xref: /wlan-dirver/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c (revision 663120a0f77ecf0340b3ac51e334fe65218a2b86)
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 /*
214  * A value of 100 (milliseconds) can be sent to FW.
215  * FW would enable Tx beamforming based on this.
216  */
217 #define TX_BFER_NDP_PERIODICITY 100
218 
219 #define g_mode_rates_size (12)
220 #define a_mode_rates_size (8)
221 
222 #define WLAN_WAIT_WLM_LATENCY_LEVEL 1000
223 
224 /*
225  * BIT map values for vdev_param_set_profile
226  * bit 0: 0 - XR SAP profile disabled
227  *        1 - XR SAP profile enabled
228  * bit 1: 0 - XPAN profile disabled
229  *        1 - XPAN profile enabled
230  */
231 #define AP_PROFILE_XR_ENABLE 0x1
232 #define AP_PROFILE_XPAN_ENABLE 0x2
233 
234 /**
235  * rtt_is_enabled - Macro to check if the bitmap has any RTT roles set
236  * @bitmap: The bitmap to be checked
237  */
238 #define rtt_is_enabled(bitmap) \
239 	((bitmap) & (WMI_FW_STA_RTT_INITR | \
240 		     WMI_FW_STA_RTT_RESPR | \
241 		     WMI_FW_AP_RTT_INITR | \
242 		     WMI_FW_AP_RTT_RESPR))
243 
244 /*
245  * Android CTS verifier needs atleast this much wait time (in msec)
246  */
247 #define MAX_REMAIN_ON_CHANNEL_DURATION (2000)
248 
249 #define HDD2GHZCHAN(freq, chan, flag)   {     \
250 		.band = HDD_NL80211_BAND_2GHZ, \
251 		.center_freq = (freq), \
252 		.hw_value = (chan), \
253 		.flags = (flag), \
254 		.max_antenna_gain = 0, \
255 		.max_power = 0, \
256 }
257 
258 #define HDD5GHZCHAN(freq, chan, flag)   {     \
259 		.band =  HDD_NL80211_BAND_5GHZ, \
260 		.center_freq = (freq), \
261 		.hw_value = (chan), \
262 		.flags = (flag), \
263 		.max_antenna_gain = 0, \
264 		.max_power = 0, \
265 }
266 
267 #define HDD_G_MODE_RATETAB(rate, rate_id, flag)	\
268 	{ \
269 		.bitrate = rate, \
270 		.hw_value = rate_id, \
271 		.flags = flag, \
272 	}
273 
274 #define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
275 			mode <= DFS_MODE_DEPRIORITIZE))
276 
277 #ifndef WLAN_CIPHER_SUITE_GCMP
278 #define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
279 #endif
280 #ifndef WLAN_CIPHER_SUITE_GCMP_256
281 #define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
282 #endif
283 
284 static const u32 hdd_gcmp_cipher_suits[] = {
285 	WLAN_CIPHER_SUITE_GCMP,
286 	WLAN_CIPHER_SUITE_GCMP_256,
287 };
288 
289 static const u32 hdd_cipher_suites[] = {
290 	WLAN_CIPHER_SUITE_WEP40,
291 	WLAN_CIPHER_SUITE_WEP104,
292 	WLAN_CIPHER_SUITE_TKIP,
293 #ifdef FEATURE_WLAN_ESE
294 #define WLAN_CIPHER_SUITE_BTK 0x004096fe        /* use for BTK */
295 #define WLAN_CIPHER_SUITE_KRK 0x004096ff        /* use for KRK */
296 	WLAN_CIPHER_SUITE_BTK,
297 	WLAN_CIPHER_SUITE_KRK,
298 	WLAN_CIPHER_SUITE_CCMP,
299 #else
300 	WLAN_CIPHER_SUITE_CCMP,
301 #endif
302 #ifdef FEATURE_WLAN_WAPI
303 	WLAN_CIPHER_SUITE_SMS4,
304 #endif
305 	WLAN_CIPHER_SUITE_AES_CMAC,
306 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
307 	WLAN_CIPHER_SUITE_BIP_GMAC_128,
308 	WLAN_CIPHER_SUITE_BIP_GMAC_256,
309 #endif
310 };
311 
312 static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
313 	HDD2GHZCHAN(2412, 1, 0),
314 	HDD2GHZCHAN(2417, 2, 0),
315 	HDD2GHZCHAN(2422, 3, 0),
316 	HDD2GHZCHAN(2427, 4, 0),
317 	HDD2GHZCHAN(2432, 5, 0),
318 	HDD2GHZCHAN(2437, 6, 0),
319 	HDD2GHZCHAN(2442, 7, 0),
320 	HDD2GHZCHAN(2447, 8, 0),
321 	HDD2GHZCHAN(2452, 9, 0),
322 	HDD2GHZCHAN(2457, 10, 0),
323 	HDD2GHZCHAN(2462, 11, 0),
324 	HDD2GHZCHAN(2467, 12, 0),
325 	HDD2GHZCHAN(2472, 13, 0),
326 	HDD2GHZCHAN(2484, 14, 0),
327 };
328 
329 static const struct ieee80211_channel hdd_channels_5_ghz[] = {
330 	HDD5GHZCHAN(5180, 36, 0),
331 	HDD5GHZCHAN(5200, 40, 0),
332 	HDD5GHZCHAN(5220, 44, 0),
333 	HDD5GHZCHAN(5240, 48, 0),
334 	HDD5GHZCHAN(5260, 52, 0),
335 	HDD5GHZCHAN(5280, 56, 0),
336 	HDD5GHZCHAN(5300, 60, 0),
337 	HDD5GHZCHAN(5320, 64, 0),
338 	HDD5GHZCHAN(5500, 100, 0),
339 	HDD5GHZCHAN(5520, 104, 0),
340 	HDD5GHZCHAN(5540, 108, 0),
341 	HDD5GHZCHAN(5560, 112, 0),
342 	HDD5GHZCHAN(5580, 116, 0),
343 	HDD5GHZCHAN(5600, 120, 0),
344 	HDD5GHZCHAN(5620, 124, 0),
345 	HDD5GHZCHAN(5640, 128, 0),
346 	HDD5GHZCHAN(5660, 132, 0),
347 	HDD5GHZCHAN(5680, 136, 0),
348 	HDD5GHZCHAN(5700, 140, 0),
349 	HDD5GHZCHAN(5720, 144, 0),
350 	HDD5GHZCHAN(5745, 149, 0),
351 	HDD5GHZCHAN(5765, 153, 0),
352 	HDD5GHZCHAN(5785, 157, 0),
353 	HDD5GHZCHAN(5805, 161, 0),
354 	HDD5GHZCHAN(5825, 165, 0),
355 };
356 
357 #ifdef WLAN_FEATURE_DSRC
358 static const struct ieee80211_channel hdd_channels_dot11p[] = {
359 	HDD5GHZCHAN(5852, 170, 0),
360 	HDD5GHZCHAN(5855, 171, 0),
361 	HDD5GHZCHAN(5860, 172, 0),
362 	HDD5GHZCHAN(5865, 173, 0),
363 	HDD5GHZCHAN(5870, 174, 0),
364 	HDD5GHZCHAN(5875, 175, 0),
365 	HDD5GHZCHAN(5880, 176, 0),
366 	HDD5GHZCHAN(5885, 177, 0),
367 	HDD5GHZCHAN(5890, 178, 0),
368 	HDD5GHZCHAN(5895, 179, 0),
369 	HDD5GHZCHAN(5900, 180, 0),
370 	HDD5GHZCHAN(5905, 181, 0),
371 	HDD5GHZCHAN(5910, 182, 0),
372 	HDD5GHZCHAN(5915, 183, 0),
373 	HDD5GHZCHAN(5920, 184, 0),
374 };
375 #else
376 static const struct ieee80211_channel hdd_5dot9_ghz_ch[] = {
377 	HDD5GHZCHAN(5845, 169, 0),
378 	HDD5GHZCHAN(5865, 173, 0),
379 	HDD5GHZCHAN(5885, 177, 0),
380 };
381 #endif
382 
383 #define band_2_ghz_channels_size sizeof(hdd_channels_2_4_ghz)
384 
385 #ifdef WLAN_FEATURE_DSRC
386 #define band_5_ghz_channels_size (sizeof(hdd_channels_5_ghz) + \
387 	sizeof(hdd_channels_dot11p))
388 #else
389 #define band_5_ghz_channels_size (sizeof(hdd_channels_5_ghz) + \
390 	sizeof(hdd_5dot9_ghz_ch))
391 #endif
392 
393 static struct ieee80211_rate g_mode_rates[] = {
394 	HDD_G_MODE_RATETAB(10, 0x1, 0),
395 	HDD_G_MODE_RATETAB(20, 0x2, 0),
396 	HDD_G_MODE_RATETAB(55, 0x4, 0),
397 	HDD_G_MODE_RATETAB(110, 0x8, 0),
398 	HDD_G_MODE_RATETAB(60, 0x10, 0),
399 	HDD_G_MODE_RATETAB(90, 0x20, 0),
400 	HDD_G_MODE_RATETAB(120, 0x40, 0),
401 	HDD_G_MODE_RATETAB(180, 0x80, 0),
402 	HDD_G_MODE_RATETAB(240, 0x100, 0),
403 	HDD_G_MODE_RATETAB(360, 0x200, 0),
404 	HDD_G_MODE_RATETAB(480, 0x400, 0),
405 	HDD_G_MODE_RATETAB(540, 0x800, 0),
406 };
407 
408 static struct ieee80211_rate a_mode_rates[] = {
409 	HDD_G_MODE_RATETAB(60, 0x10, 0),
410 	HDD_G_MODE_RATETAB(90, 0x20, 0),
411 	HDD_G_MODE_RATETAB(120, 0x40, 0),
412 	HDD_G_MODE_RATETAB(180, 0x80, 0),
413 	HDD_G_MODE_RATETAB(240, 0x100, 0),
414 	HDD_G_MODE_RATETAB(360, 0x200, 0),
415 	HDD_G_MODE_RATETAB(480, 0x400, 0),
416 	HDD_G_MODE_RATETAB(540, 0x800, 0),
417 };
418 
419 static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
420 	.channels = NULL,
421 	.n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
422 	.band = HDD_NL80211_BAND_2GHZ,
423 	.bitrates = g_mode_rates,
424 	.n_bitrates = g_mode_rates_size,
425 	.ht_cap.ht_supported = 1,
426 	.ht_cap.cap = IEEE80211_HT_CAP_SGI_20
427 		      | IEEE80211_HT_CAP_GRN_FLD
428 		      | IEEE80211_HT_CAP_DSSSCCK40
429 		      | IEEE80211_HT_CAP_LSIG_TXOP_PROT
430 		      | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
431 	.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
432 	.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
433 	.ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
434 	.ht_cap.mcs.rx_highest = cpu_to_le16(72),
435 	.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
436 };
437 
438 static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
439 	.channels = NULL,
440 	.n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
441 	.band = HDD_NL80211_BAND_5GHZ,
442 	.bitrates = a_mode_rates,
443 	.n_bitrates = a_mode_rates_size,
444 	.ht_cap.ht_supported = 1,
445 	.ht_cap.cap = IEEE80211_HT_CAP_SGI_20
446 		      | IEEE80211_HT_CAP_GRN_FLD
447 		      | IEEE80211_HT_CAP_DSSSCCK40
448 		      | IEEE80211_HT_CAP_LSIG_TXOP_PROT
449 		      | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
450 	.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
451 	.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
452 	.ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
453 	.ht_cap.mcs.rx_highest = cpu_to_le16(72),
454 	.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
455 	.vht_cap.vht_supported = 1,
456 };
457 
458 enum hdd_hw_rate_cck {
459 	HDD_HW_RATE_CCK_LP_11M = 0,
460 	HDD_HW_RATE_CCK_LP_5_5M,
461 	HDD_HW_RATE_CCK_LP_2M,
462 	HDD_HW_RATE_CCK_LP_1M,
463 	HDD_HW_RATE_CCK_SP_11M,
464 	HDD_HW_RATE_CCK_SP_5_5M,
465 	HDD_HW_RATE_CCK_SP_2M,
466 };
467 
468 enum hdd_hw_rate_ofdm {
469 	HDD_HW_RATE_OFDM_48M = 0,
470 	HDD_HW_RATE_OFDM_24M,
471 	HDD_HW_RATE_OFDM_12M,
472 	HDD_HW_RATE_OFDM_6M,
473 	HDD_HW_RATE_OFDM_54M,
474 	HDD_HW_RATE_OFDM_36M,
475 	HDD_HW_RATE_OFDM_18M,
476 	HDD_HW_RATE_OFDM_9M,
477 };
478 
479 static struct ieee80211_rate hdd_legacy_rates[] = {
480 	{ .bitrate = 10,
481 	  .hw_value = HDD_HW_RATE_CCK_LP_1M },
482 	{ .bitrate = 20,
483 	  .hw_value = HDD_HW_RATE_CCK_LP_2M },
484 	{ .bitrate = 55,
485 	  .hw_value = HDD_HW_RATE_CCK_LP_5_5M },
486 	{ .bitrate = 110,
487 	  .hw_value = HDD_HW_RATE_CCK_LP_11M },
488 	{ .bitrate = 60, .hw_value = HDD_HW_RATE_OFDM_6M },
489 	{ .bitrate = 90, .hw_value = HDD_HW_RATE_OFDM_9M },
490 	{ .bitrate = 120, .hw_value = HDD_HW_RATE_OFDM_12M },
491 	{ .bitrate = 180, .hw_value = HDD_HW_RATE_OFDM_18M },
492 	{ .bitrate = 240, .hw_value = HDD_HW_RATE_OFDM_24M },
493 	{ .bitrate = 360, .hw_value = HDD_HW_RATE_OFDM_36M },
494 	{ .bitrate = 480, .hw_value = HDD_HW_RATE_OFDM_48M },
495 	{ .bitrate = 540, .hw_value = HDD_HW_RATE_OFDM_54M },
496 };
497 
498 #if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
499 	(KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
500 
501 static struct ieee80211_channel hdd_channels_6_ghz[NUM_6GHZ_CHANNELS];
502 
503 static struct ieee80211_supported_band wlan_hdd_band_6_ghz = {
504 	.channels = NULL,
505 	.n_channels = 0,
506 	.band = HDD_NL80211_BAND_6GHZ,
507 	.bitrates = a_mode_rates,
508 	.n_bitrates = a_mode_rates_size,
509 };
510 
511 #define HDD_SET_6GHZCHAN(ch, freq, chan, flag)   {     \
512 		(ch).band =  HDD_NL80211_BAND_6GHZ; \
513 		(ch).center_freq = (freq); \
514 		(ch).hw_value = (chan); \
515 		(ch).flags = (flag); \
516 		(ch).max_antenna_gain = 0; \
517 		(ch).max_power = 0; \
518 }
519 
520 static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
521 {
522 	uint32_t i;
523 	struct wiphy *wiphy = hdd_ctx->wiphy;
524 	struct ieee80211_channel *chlist = hdd_channels_6_ghz;
525 	uint32_t num = ARRAY_SIZE(hdd_channels_6_ghz);
526 	uint16_t base_freq;
527 	QDF_STATUS status;
528 	uint32_t band_capability;
529 
530 	hdd_enter();
531 
532 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
533 	if (QDF_IS_STATUS_ERROR(status)) {
534 		hdd_err("Failed to get MLME Band Capability");
535 		return;
536 	}
537 
538 	if (!(band_capability & (BIT(REG_BAND_6G)))) {
539 		hdd_debug("6ghz band not enabled");
540 		return;
541 	}
542 
543 	qdf_mem_zero(chlist, sizeof(*chlist) * num);
544 	base_freq = wlan_reg_min_6ghz_chan_freq();
545 
546 	for (i = 0; i < num; i++)
547 		HDD_SET_6GHZCHAN(chlist[i],
548 				 base_freq + i * 20,
549 				 wlan_reg_freq_to_chan(hdd_ctx->pdev,
550 						       base_freq + i * 20),
551 				 IEEE80211_CHAN_DISABLED);
552 	wiphy->bands[HDD_NL80211_BAND_6GHZ] = &wlan_hdd_band_6_ghz;
553 	wiphy->bands[HDD_NL80211_BAND_6GHZ]->channels = chlist;
554 	wiphy->bands[HDD_NL80211_BAND_6GHZ]->n_channels = num;
555 
556 	hdd_exit();
557 }
558 
559 /**
560  * wlan_hdd_populate_6g_chan_info() - Populate 6 GHz chan info in hdd context
561  * @hdd_ctx: pointer to hdd context
562  * @index: 6 GHz channel beginning index in chan_info of @hdd_ctx
563  *
564  * Return: Number of 6 GHz channels populated
565  */
566 static uint32_t
567 wlan_hdd_populate_6g_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
568 {
569 	uint32_t num_6g, i;
570 	struct scan_chan_info *chan_info;
571 
572 	if (!hdd_ctx->wiphy->bands[HDD_NL80211_BAND_6GHZ] ||
573 	    !hdd_ctx->wiphy->bands[HDD_NL80211_BAND_6GHZ]->n_channels) {
574 		hdd_debug("6GHz channel list not populated to wiphy");
575 		return 0;
576 	}
577 
578 	num_6g = QDF_ARRAY_SIZE(hdd_channels_6_ghz);
579 	chan_info = hdd_ctx->chan_info;
580 
581 	for (i = 0; i < num_6g; i++)
582 		chan_info[index + i].freq = hdd_channels_6_ghz[i].center_freq;
583 
584 	return num_6g;
585 }
586 
587 #else
588 static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
589 {
590 }
591 
592 static inline uint32_t
593 wlan_hdd_populate_6g_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
594 {
595 	return 0;
596 }
597 #endif
598 
599 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) || \
600 	defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
601 /*akm suits supported by sta*/
602 static const u32 hdd_sta_akm_suites[] = {
603 	WLAN_AKM_SUITE_8021X,
604 	WLAN_AKM_SUITE_PSK,
605 	WLAN_AKM_SUITE_FT_8021X,
606 	WLAN_AKM_SUITE_FT_PSK,
607 	WLAN_AKM_SUITE_8021X_SHA256,
608 	WLAN_AKM_SUITE_PSK_SHA256,
609 	WLAN_AKM_SUITE_TDLS,
610 	WLAN_AKM_SUITE_SAE,
611 	WLAN_AKM_SUITE_FT_OVER_SAE,
612 	WLAN_AKM_SUITE_EAP_SHA256,
613 	WLAN_AKM_SUITE_EAP_SHA384,
614 	WLAN_AKM_SUITE_FILS_SHA256,
615 	WLAN_AKM_SUITE_FILS_SHA384,
616 	WLAN_AKM_SUITE_FT_FILS_SHA256,
617 	WLAN_AKM_SUITE_FT_FILS_SHA384,
618 	WLAN_AKM_SUITE_OWE,
619 	WLAN_AKM_SUITE_DPP_RSN,
620 	WLAN_AKM_SUITE_FT_EAP_SHA_384,
621 	RSN_AUTH_KEY_MGMT_CCKM,
622 	RSN_AUTH_KEY_MGMT_OSEN,
623 	WAPI_PSK_AKM_SUITE,
624 	WAPI_CERT_AKM_SUITE,
625 	WLAN_AKM_SUITE_SAE_EXT_KEY,
626 	WLAN_AKM_SUITE_FT_SAE_EXT_KEY,
627 };
628 
629 /*akm suits supported by AP*/
630 static const u32 hdd_ap_akm_suites[] = {
631 	WLAN_AKM_SUITE_PSK,
632 	WLAN_AKM_SUITE_SAE,
633 	WLAN_AKM_SUITE_OWE,
634 };
635 
636 /* This structure contain information what akm suits are
637  * supported for each mode
638  */
639 static const struct wiphy_iftype_akm_suites
640 	wlan_hdd_akm_suites[] = {
641 	{
642 		.iftypes_mask = BIT(NL80211_IFTYPE_STATION) |
643 				BIT(NL80211_IFTYPE_P2P_CLIENT),
644 		.akm_suites = hdd_sta_akm_suites,
645 		.n_akm_suites = (sizeof(hdd_sta_akm_suites) / sizeof(u32)),
646 	},
647 	{
648 		.iftypes_mask = BIT(NL80211_IFTYPE_AP) |
649 				BIT(NL80211_IFTYPE_P2P_GO),
650 		.akm_suites = hdd_ap_akm_suites,
651 		.n_akm_suites = (sizeof(hdd_ap_akm_suites) / sizeof(u32)),
652 	},
653 };
654 #endif
655 
656 /* This structure contain information what kind of frame are expected in
657  * TX/RX direction for each kind of interface
658  */
659 static const struct ieee80211_txrx_stypes
660 	wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
661 	[NL80211_IFTYPE_STATION] = {
662 		.tx = 0xffff,
663 		.rx = BIT(SIR_MAC_MGMT_ACTION) |
664 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
665 		      BIT(SIR_MAC_MGMT_AUTH),
666 	},
667 	[NL80211_IFTYPE_AP] = {
668 		.tx = 0xffff,
669 		.rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
670 		      BIT(SIR_MAC_MGMT_REASSOC_REQ) |
671 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
672 		      BIT(SIR_MAC_MGMT_DISASSOC) |
673 		      BIT(SIR_MAC_MGMT_AUTH) |
674 		      BIT(SIR_MAC_MGMT_DEAUTH) |
675 		      BIT(SIR_MAC_MGMT_ACTION),
676 	},
677 	[NL80211_IFTYPE_ADHOC] = {
678 		.tx = 0xffff,
679 		.rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
680 		      BIT(SIR_MAC_MGMT_REASSOC_REQ) |
681 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
682 		      BIT(SIR_MAC_MGMT_DISASSOC) |
683 		      BIT(SIR_MAC_MGMT_AUTH) |
684 		      BIT(SIR_MAC_MGMT_DEAUTH) |
685 		      BIT(SIR_MAC_MGMT_ACTION),
686 	},
687 	[NL80211_IFTYPE_P2P_CLIENT] = {
688 		.tx = 0xffff,
689 		.rx = BIT(SIR_MAC_MGMT_ACTION) |
690 		      BIT(SIR_MAC_MGMT_AUTH) |
691 		      BIT(SIR_MAC_MGMT_PROBE_REQ),
692 	},
693 	[NL80211_IFTYPE_P2P_GO] = {
694 		/* This is also same as for SoftAP */
695 		.tx = 0xffff,
696 		.rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
697 		      BIT(SIR_MAC_MGMT_REASSOC_REQ) |
698 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
699 		      BIT(SIR_MAC_MGMT_DISASSOC) |
700 		      BIT(SIR_MAC_MGMT_AUTH) |
701 		      BIT(SIR_MAC_MGMT_DEAUTH) |
702 		      BIT(SIR_MAC_MGMT_ACTION),
703 	},
704 	[NL80211_IFTYPE_NAN] = {
705 		.tx = 0xffff,
706 		.rx = BIT(SIR_MAC_MGMT_AUTH),
707 	},
708 };
709 
710 /* Interface limits and combinations registered by the driver */
711 
712 /* STA ( + STA ) combination */
713 static const struct ieee80211_iface_limit
714 	wlan_hdd_sta_iface_limit[] = {
715 	{
716 		.max = 2,
717 		.types = BIT(NL80211_IFTYPE_STATION),
718 	},
719 };
720 
721 /* AP ( + AP ) combination */
722 static const struct ieee80211_iface_limit
723 	wlan_hdd_ap_iface_limit[] = {
724 	{
725 		.max = (QDF_MAX_NO_OF_SAP_MODE),
726 		.types = BIT(NL80211_IFTYPE_AP),
727 	},
728 };
729 
730 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
731 /* P2P limit */
732 static const struct ieee80211_iface_limit
733 	wlan_hdd_p2p_iface_limit[] = {
734 	{
735 		.max = 1,
736 		.types = BIT(NL80211_IFTYPE_P2P_CLIENT),
737 	},
738 	{
739 		.max = 1,
740 		.types = BIT(NL80211_IFTYPE_P2P_GO),
741 	},
742 };
743 
744 /* STA + P2P + P2P combination */
745 static const struct ieee80211_iface_limit
746 	wlan_hdd_sta_p2p_p2p_iface_limit[] = {
747 	{
748 		.max = 1,
749 		.types = BIT(NL80211_IFTYPE_STATION)
750 	},
751 	{
752 		/* Support for two identical (GO + GO or CLI + CLI)
753 		 * or dissimilar (GO + CLI) P2P interfaces
754 		 */
755 		.max = 2,
756 		.types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
757 	},
758 };
759 
760 /* STA + AP + P2P combination */
761 static const struct ieee80211_iface_limit
762 wlan_hdd_sta_ap_p2p_iface_limit[] = {
763 	{
764 	   .max = 1,
765 	   .types = BIT(NL80211_IFTYPE_STATION)
766 	},
767 	{
768 	   .max = 1,
769 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
770 	},
771 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
772 	{
773 	   .max = 1,
774 	   .types = BIT(NL80211_IFTYPE_AP)
775 	},
776 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
777 };
778 
779 /* SAP + P2P combination */
780 static const struct ieee80211_iface_limit
781 wlan_hdd_sap_p2p_iface_limit[] = {
782 	{
783 	   /* The p2p interface in SAP+P2P can be GO/CLI.
784 	    * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
785 	    */
786 	   .max = 1,
787 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
788 	},
789 	{
790 	   /* SAP+GO to support only one SAP interface */
791 	   .max = 1,
792 	   .types = BIT(NL80211_IFTYPE_AP)
793 	}
794 };
795 
796 /* P2P + P2P combination */
797 static const struct ieee80211_iface_limit
798 wlan_hdd_p2p_p2p_iface_limit[] = {
799 	{
800 	   /* The p2p interface in P2P+P2P can be GO/CLI.
801 	    * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
802 	    */
803 	   .max = 2,
804 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
805 	},
806 };
807 #endif
808 
809 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
810 /* STA + AP combination */
811 static const struct ieee80211_iface_limit
812 wlan_hdd_sta_ap_iface_limit[] = {
813 	{
814 	   .max = 1,
815 	   .types = BIT(NL80211_IFTYPE_STATION)
816 	},
817 	{
818 	   .max = 1,
819 	   .types = BIT(NL80211_IFTYPE_AP)
820 	},
821 };
822 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
823 
824 /* STA + P2P combination */
825 static const struct ieee80211_iface_limit
826 	wlan_hdd_sta_p2p_iface_limit[] = {
827 	{
828 		.max = 1,
829 		.types = BIT(NL80211_IFTYPE_STATION)
830 	},
831 	{
832 		/* Support for either (GO or CLI) */
833 		.max = 1,
834 		.types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
835 	},
836 };
837 
838 /* Monitor interface */
839 static const struct ieee80211_iface_limit
840 	wlan_hdd_mon_iface_limit[] = {
841 	{
842 		.max = 2,
843 		.types = BIT(NL80211_IFTYPE_MONITOR),
844 	},
845 };
846 
847 #if defined(WLAN_FEATURE_NAN) && \
848 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
849 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
850 /* STA + NAN disc combination */
851 static const struct ieee80211_iface_limit
852 	wlan_hdd_sta_nan_iface_limit[] = {
853 	{
854 		/* STA */
855 		.max = 1,
856 		.types = BIT(NL80211_IFTYPE_STATION)
857 	},
858 	{
859 		/* NAN */
860 		.max = 1,
861 		.types = BIT(NL80211_IFTYPE_NAN),
862 	},
863 };
864 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
865 
866 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
867 /* SAP + NAN disc combination */
868 static const struct ieee80211_iface_limit
869 	wlan_hdd_sap_nan_iface_limit[] = {
870 	{
871 		/* SAP */
872 		.max = 1,
873 		.types = BIT(NL80211_IFTYPE_AP)
874 	},
875 	{
876 		/* NAN */
877 		.max = 1,
878 		.types = BIT(NL80211_IFTYPE_NAN),
879 	},
880 };
881 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
882 #endif /* WLAN_FEATURE_NAN */
883 
884 static struct ieee80211_iface_combination
885 	wlan_hdd_iface_combination[] = {
886 	/* STA */
887 	{
888 		.limits = wlan_hdd_sta_iface_limit,
889 		.num_different_channels = 2,
890 		.max_interfaces = 2,
891 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
892 	},
893 	/* AP */
894 	{
895 		.limits = wlan_hdd_ap_iface_limit,
896 		.num_different_channels = 2,
897 		.max_interfaces = (QDF_MAX_NO_OF_SAP_MODE),
898 		.n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
899 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
900 	defined(CFG80211_BEACON_INTERVAL_BACKPORT)
901 		.beacon_int_min_gcd = 1,
902 #endif
903 	},
904 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
905 	/* P2P */
906 	{
907 		.limits = wlan_hdd_p2p_iface_limit,
908 		.num_different_channels = 2,
909 		.max_interfaces = 2,
910 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
911 	},
912 	/* STA + P2P + P2P */
913 	{
914 		.limits = wlan_hdd_sta_p2p_p2p_iface_limit,
915 		.num_different_channels = 2,
916 		.max_interfaces = 3,
917 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_p2p_iface_limit),
918 		.beacon_int_infra_match = true,
919 	},
920 	/* STA + P2P + SAP */
921 	{
922 		.limits = wlan_hdd_sta_ap_p2p_iface_limit,
923 		/* we can allow 3 channels for three different persona
924 		 * but due to firmware limitation, allow max 2 concrnt channels.
925 		 */
926 		.num_different_channels = 2,
927 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
928 		.max_interfaces = 3,
929 #else
930 		.max_interfaces = 2,
931 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
932 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2p_iface_limit),
933 		.beacon_int_infra_match = true,
934 	},
935 	/* SAP + P2P */
936 	{
937 		.limits = wlan_hdd_sap_p2p_iface_limit,
938 		.num_different_channels = 2,
939 		/* 1-SAP + 1-P2P */
940 		.max_interfaces = 2,
941 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
942 		.beacon_int_infra_match = true,
943 	},
944 	/* P2P + P2P */
945 	{
946 		.limits = wlan_hdd_p2p_p2p_iface_limit,
947 		.num_different_channels = 2,
948 		/* 2-P2P */
949 		.max_interfaces = 2,
950 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
951 		.beacon_int_infra_match = true,
952 	},
953 #endif
954 	/* STA + P2P */
955 	{
956 		.limits = wlan_hdd_sta_p2p_iface_limit,
957 		.num_different_channels = 2,
958 		.max_interfaces = 2,
959 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
960 		.beacon_int_infra_match = true,
961 	},
962 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
963 	/* STA + SAP */
964 	{
965 		.limits = wlan_hdd_sta_ap_iface_limit,
966 		.num_different_channels = 2,
967 		.max_interfaces = 2,
968 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
969 		.beacon_int_infra_match = true,
970 	},
971 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
972 	/* Monitor */
973 	{
974 		.limits = wlan_hdd_mon_iface_limit,
975 		.max_interfaces = 2,
976 		.num_different_channels = 2,
977 		.n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
978 	},
979 #if defined(WLAN_FEATURE_NAN) && \
980 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
981 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
982 	/* NAN + STA */
983 	{
984 		.limits = wlan_hdd_sta_nan_iface_limit,
985 		.max_interfaces = 2,
986 		.num_different_channels = 2,
987 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_nan_iface_limit),
988 	},
989 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
990 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
991 	/* NAN + SAP */
992 	{
993 		.limits = wlan_hdd_sap_nan_iface_limit,
994 		.num_different_channels = 2,
995 		.max_interfaces = 2,
996 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_nan_iface_limit),
997 		.beacon_int_infra_match = true,
998 	},
999 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
1000 #endif /* WLAN_FEATURE_NAN */
1001 };
1002 
1003 /* 1 and 2 port concurrencies */
1004 static struct ieee80211_iface_combination
1005 	wlan_hdd_derived_combination[] = {
1006 	/* STA */
1007 	{
1008 		.limits = wlan_hdd_sta_iface_limit,
1009 		.num_different_channels = 2,
1010 		.max_interfaces = 2,
1011 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
1012 	},
1013 	/* AP */
1014 	{
1015 		.limits = wlan_hdd_ap_iface_limit,
1016 		.num_different_channels = 2,
1017 		.max_interfaces = (QDF_MAX_NO_OF_SAP_MODE),
1018 		.n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
1019 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
1020 	defined(CFG80211_BEACON_INTERVAL_BACKPORT)
1021 		.beacon_int_min_gcd = 1,
1022 #endif
1023 	},
1024 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
1025 	/* P2P */
1026 	{
1027 		.limits = wlan_hdd_p2p_iface_limit,
1028 		.num_different_channels = 2,
1029 		.max_interfaces = 2,
1030 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
1031 	},
1032 
1033 	/* SAP + P2P */
1034 	{
1035 		.limits = wlan_hdd_sap_p2p_iface_limit,
1036 		.num_different_channels = 2,
1037 		/* 1-SAP + 1-P2P */
1038 		.max_interfaces = 2,
1039 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
1040 		.beacon_int_infra_match = true,
1041 	},
1042 	/* P2P + P2P */
1043 	{
1044 		.limits = wlan_hdd_p2p_p2p_iface_limit,
1045 		.num_different_channels = 2,
1046 		/* 2-P2P */
1047 		.max_interfaces = 2,
1048 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
1049 		.beacon_int_infra_match = true,
1050 	},
1051 #endif
1052 	/* STA + P2P */
1053 	{
1054 		.limits = wlan_hdd_sta_p2p_iface_limit,
1055 		.num_different_channels = 2,
1056 		.max_interfaces = 2,
1057 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
1058 		.beacon_int_infra_match = true,
1059 	},
1060 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
1061 	/* STA + SAP */
1062 	{
1063 		.limits = wlan_hdd_sta_ap_iface_limit,
1064 		.num_different_channels = 2,
1065 		.max_interfaces = 2,
1066 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
1067 		.beacon_int_infra_match = true,
1068 	},
1069 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
1070 	/* Monitor */
1071 	{
1072 		.limits = wlan_hdd_mon_iface_limit,
1073 		.max_interfaces = 2,
1074 		.num_different_channels = 2,
1075 		.n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
1076 	},
1077 #if defined(WLAN_FEATURE_NAN) && \
1078 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
1079 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
1080 	/* NAN + STA */
1081 	{
1082 		.limits = wlan_hdd_sta_nan_iface_limit,
1083 		.max_interfaces = 2,
1084 		.num_different_channels = 2,
1085 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_nan_iface_limit),
1086 	},
1087 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
1088 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
1089 	/* NAN + SAP */
1090 	{
1091 		.limits = wlan_hdd_sap_nan_iface_limit,
1092 		.num_different_channels = 2,
1093 		.max_interfaces = 2,
1094 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_nan_iface_limit),
1095 		.beacon_int_infra_match = true,
1096 	},
1097 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
1098 #endif /* WLAN_FEATURE_NAN */
1099 };
1100 static struct cfg80211_ops wlan_hdd_cfg80211_ops;
1101 
1102 #ifdef WLAN_NL80211_TESTMODE
1103 enum wlan_hdd_tm_attr {
1104 	WLAN_HDD_TM_ATTR_INVALID = 0,
1105 	WLAN_HDD_TM_ATTR_CMD = 1,
1106 	WLAN_HDD_TM_ATTR_DATA = 2,
1107 	WLAN_HDD_TM_ATTR_STREAM_ID = 3,
1108 	WLAN_HDD_TM_ATTR_TYPE = 4,
1109 	/* keep last */
1110 	WLAN_HDD_TM_ATTR_AFTER_LAST,
1111 	WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
1112 };
1113 
1114 enum wlan_hdd_tm_cmd {
1115 	WLAN_HDD_TM_CMD_WLAN_FTM = 0,
1116 	WLAN_HDD_TM_CMD_WLAN_HB = 1,
1117 };
1118 
1119 #define WLAN_HDD_TM_DATA_MAX_LEN    5000
1120 
1121 static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
1122 	[WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
1123 	[WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
1124 				   .len = WLAN_HDD_TM_DATA_MAX_LEN},
1125 };
1126 #endif /* WLAN_NL80211_TESTMODE */
1127 
1128 enum wlan_hdd_vendor_ie_access_policy {
1129 	WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
1130 	WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
1131 };
1132 
1133 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
1134 static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
1135 	.flags = WIPHY_WOWLAN_MAGIC_PKT,
1136 	.n_patterns = WOWL_MAX_PTRNS_ALLOWED,
1137 	.pattern_min_len = 1,
1138 	.pattern_max_len = WOWL_PTRN_MAX_SIZE,
1139 };
1140 #endif
1141 
1142 /**
1143  * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
1144  * @flags: Pointer to the flags to Add channel switch flag.
1145  *
1146  * This Function adds Channel Switch support flag, if channel switch is
1147  * supported by kernel.
1148  * Return: void.
1149  */
1150 #ifdef CHANNEL_SWITCH_SUPPORTED
1151 static inline void hdd_add_channel_switch_support(uint32_t *flags)
1152 {
1153 	*flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
1154 }
1155 #else
1156 static inline void hdd_add_channel_switch_support(uint32_t *flags)
1157 {
1158 }
1159 #endif
1160 
1161 #ifdef FEATURE_WLAN_TDLS
1162 
1163 /* TDLS capabilities params */
1164 #define PARAM_MAX_TDLS_SESSION \
1165 		QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
1166 #define PARAM_TDLS_FEATURE_SUPPORT \
1167 		QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
1168 
1169 /**
1170  * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
1171  * @wiphy:    WIPHY structure pointer
1172  * @wdev:     Wireless device structure pointer
1173  * @data:     Pointer to the data received
1174  * @data_len: Length of the data received
1175  *
1176  * This function provides TDLS capabilities
1177  *
1178  * Return: 0 on success and errno on failure
1179  */
1180 static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
1181 						     struct wireless_dev *wdev,
1182 						     const void *data,
1183 						     int data_len)
1184 {
1185 	int status;
1186 	struct net_device *dev = wdev->netdev;
1187 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1188 	struct wlan_objmgr_vdev *vdev;
1189 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1190 	struct sk_buff *skb;
1191 	uint32_t set = 0;
1192 	uint32_t max_num_tdls_sta = 0;
1193 	bool tdls_support;
1194 	bool tdls_external_control;
1195 	bool tdls_sleep_sta_enable;
1196 	bool tdls_buffer_sta;
1197 	bool tdls_off_channel;
1198 	bool tdls_fw_wideband_cap;
1199 
1200 	hdd_enter_dev(wdev->netdev);
1201 
1202 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1203 		hdd_err("Command not allowed in FTM mode");
1204 		return -EPERM;
1205 	}
1206 
1207 	if (hdd_validate_adapter(adapter))
1208 		return -EINVAL;
1209 
1210 	status = wlan_hdd_validate_context(hdd_ctx);
1211 	if (status)
1212 		return status;
1213 
1214 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1215 						       (2 * sizeof(u32)) +
1216 						       NLMSG_HDRLEN);
1217 	if (!skb) {
1218 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1219 		goto fail;
1220 	}
1221 
1222 	if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) ==
1223 	     QDF_STATUS_SUCCESS) && !tdls_support) {
1224 		hdd_debug("TDLS feature not Enabled or Not supported in FW");
1225 		if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
1226 			nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
1227 			hdd_err("nla put fail");
1228 			goto fail;
1229 		}
1230 	} else {
1231 		cfg_tdls_get_external_control(hdd_ctx->psoc,
1232 					      &tdls_external_control);
1233 		cfg_tdls_get_sleep_sta_enable(hdd_ctx->psoc,
1234 					      &tdls_sleep_sta_enable);
1235 		cfg_tdls_get_buffer_sta_enable(hdd_ctx->psoc,
1236 					       &tdls_buffer_sta);
1237 		cfg_tdls_get_off_channel_enable(hdd_ctx->psoc,
1238 						&tdls_off_channel);
1239 		vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
1240 						   WLAN_OSIF_ID);
1241 		if (!vdev) {
1242 			hdd_err("Vdev is null return");
1243 			goto fail;
1244 		}
1245 
1246 		tdls_fw_wideband_cap =
1247 				wlan_cfg80211_tdls_is_fw_wideband_capable(vdev);
1248 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1249 
1250 		set = set | WIFI_TDLS_SUPPORT;
1251 		set = set | (tdls_external_control ?
1252 					WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
1253 		set = set | (tdls_off_channel ?
1254 					WIFI_TDLS_OFFCHANNEL_SUPPORT : 0);
1255 		set = set | (tdls_fw_wideband_cap ?
1256 					WIFI_TDLS_WIDER_BW_SUPPORT : 0);
1257 		max_num_tdls_sta = cfg_tdls_get_max_peer_count(hdd_ctx->psoc);
1258 
1259 		hdd_debug("TDLS Feature supported value %x tdls_max_peer_count:%d",
1260 			  set, max_num_tdls_sta);
1261 		if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
1262 				max_num_tdls_sta) ||
1263 		    nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
1264 			hdd_err("nla put fail");
1265 			goto fail;
1266 		}
1267 	}
1268 	return wlan_cfg80211_vendor_cmd_reply(skb);
1269 fail:
1270 	wlan_cfg80211_vendor_free_skb(skb);
1271 	return -EINVAL;
1272 }
1273 
1274 /**
1275  * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
1276  * @wiphy:    WIPHY structure pointer
1277  * @wdev:     Wireless device structure pointer
1278  * @data:     Pointer to the data received
1279  * @data_len: Length of the data received
1280  *
1281  * This function provides TDLS capabilities
1282  *
1283  * Return: 0 on success and errno on failure
1284  */
1285 static int
1286 wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
1287 					struct wireless_dev *wdev,
1288 					const void *data,
1289 					int data_len)
1290 {
1291 	struct osif_psoc_sync *psoc_sync;
1292 	int errno;
1293 
1294 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
1295 	if (errno)
1296 		return errno;
1297 
1298 	errno = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
1299 							  data, data_len);
1300 
1301 	osif_psoc_sync_op_stop(psoc_sync);
1302 
1303 	return errno;
1304 }
1305 
1306 static uint8_t hdd_get_bw_offset(uint32_t ch_width)
1307 {
1308 	uint8_t bw_offset = 0;
1309 
1310 	if (ch_width == CH_WIDTH_40MHZ)
1311 		bw_offset = 1 << BW_40_OFFSET_BIT;
1312 	else if (ch_width == CH_WIDTH_20MHZ)
1313 		bw_offset = 1 << BW_20_OFFSET_BIT;
1314 
1315 	return bw_offset;
1316 }
1317 
1318 #else /* !FEATURE_WLAN_TDLS */
1319 
1320 static inline uint8_t hdd_get_bw_offset(uint32_t ch_width)
1321 {
1322 	return 0;
1323 }
1324 
1325 #endif /* FEATURE_WLAN_TDLS */
1326 
1327 /**
1328  * wlan_vendor_bitmap_to_reg_wifi_band_bitmap() - Convert vendor bitmap to
1329  * reg_wifi_band bitmap
1330  * @psoc: PSOC pointer
1331  * @vendor_bitmap: vendor bitmap value coming via vendor command
1332  *
1333  * Return: reg_wifi_band bitmap
1334  */
1335 static uint32_t
1336 wlan_vendor_bitmap_to_reg_wifi_band_bitmap(struct wlan_objmgr_psoc *psoc,
1337 					   uint32_t vendor_bitmap)
1338 {
1339 	uint32_t reg_bitmap = 0;
1340 
1341 	if (vendor_bitmap == QCA_SETBAND_AUTO)
1342 		reg_bitmap |= REG_BAND_MASK_ALL;
1343 	if (vendor_bitmap & QCA_SETBAND_2G)
1344 		reg_bitmap |= BIT(REG_BAND_2G);
1345 	if (vendor_bitmap & QCA_SETBAND_5G)
1346 		reg_bitmap |= BIT(REG_BAND_5G);
1347 	if (vendor_bitmap & QCA_SETBAND_6G)
1348 		reg_bitmap |= BIT(REG_BAND_6G);
1349 
1350 	if (!wlan_reg_is_6ghz_supported(psoc)) {
1351 		hdd_debug("Driver doesn't support 6ghz");
1352 		reg_bitmap = (reg_bitmap & (~BIT(REG_BAND_6G)));
1353 	}
1354 
1355 	return reg_bitmap;
1356 }
1357 
1358 int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
1359 		struct ch_avoid_ind_type *srcFreqList)
1360 {
1361 	int i;
1362 	uint32_t room;
1363 	struct ch_avoid_freq_type *avoid_range =
1364 	&destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
1365 
1366 	room = CH_AVOID_MAX_RANGE - destFreqList->ch_avoid_range_cnt;
1367 	if (srcFreqList->ch_avoid_range_cnt > room) {
1368 		hdd_err("avoid freq overflow");
1369 		return -EINVAL;
1370 	}
1371 	destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
1372 
1373 	for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
1374 		avoid_range->start_freq =
1375 			srcFreqList->avoid_freq_range[i].start_freq;
1376 		avoid_range->end_freq =
1377 			srcFreqList->avoid_freq_range[i].end_freq;
1378 		avoid_range++;
1379 	}
1380 	return 0;
1381 }
1382 /*
1383  * FUNCTION: wlan_hdd_send_avoid_freq_event
1384  * This is called when wlan driver needs to send vendor specific
1385  * avoid frequency range event to userspace
1386  */
1387 int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
1388 				   struct ch_avoid_ind_type *avoid_freq_list)
1389 {
1390 	struct sk_buff *skb;
1391 	enum qca_nl80211_vendor_subcmds_index index =
1392 		QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX;
1393 
1394 	hdd_enter();
1395 
1396 	if (!hdd_ctx) {
1397 		hdd_err("HDD context is null");
1398 		return -EINVAL;
1399 	}
1400 
1401 	if (!avoid_freq_list) {
1402 		hdd_err("avoid_freq_list is null");
1403 		return -EINVAL;
1404 	}
1405 
1406 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
1407 					       sizeof(struct ch_avoid_ind_type),
1408 					       index, GFP_KERNEL);
1409 	if (!skb) {
1410 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1411 		return -EINVAL;
1412 	}
1413 
1414 	memcpy(skb_put(skb, sizeof(struct ch_avoid_ind_type)),
1415 	       (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
1416 
1417 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
1418 
1419 	hdd_exit();
1420 	return 0;
1421 }
1422 
1423 /*
1424  * define short names for the global vendor params
1425  * used by QCA_NL80211_VENDOR_SUBCMD_HANG
1426  */
1427 #define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
1428 
1429 /**
1430  * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
1431  * hang reason
1432  * @reason: cds recovery reason
1433  *
1434  * Return: Vendor specific reason code
1435  */
1436 static enum qca_wlan_vendor_hang_reason
1437 hdd_convert_hang_reason(enum qdf_hang_reason reason)
1438 {
1439 	u32 ret_val;
1440 
1441 	switch (reason) {
1442 	case QDF_RX_HASH_NO_ENTRY_FOUND:
1443 		ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
1444 		break;
1445 	case QDF_PEER_DELETION_TIMEDOUT:
1446 		ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
1447 		break;
1448 	case QDF_PEER_UNMAP_TIMEDOUT:
1449 		ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
1450 		break;
1451 	case QDF_SCAN_REQ_EXPIRED:
1452 		ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
1453 		break;
1454 	case QDF_SCAN_ATTEMPT_FAILURES:
1455 		ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
1456 		break;
1457 	case QDF_GET_MSG_BUFF_FAILURE:
1458 		ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
1459 		break;
1460 	case QDF_ACTIVE_LIST_TIMEOUT:
1461 		ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
1462 		break;
1463 	case QDF_SUSPEND_TIMEOUT:
1464 		ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
1465 		break;
1466 	case QDF_RESUME_TIMEOUT:
1467 		ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
1468 		break;
1469 	case QDF_WMI_EXCEED_MAX_PENDING_CMDS:
1470 		ret_val = QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS;
1471 		break;
1472 	case QDF_AP_STA_CONNECT_REQ_TIMEOUT:
1473 		ret_val = QCA_WLAN_HANG_AP_STA_CONNECT_REQ_TIMEOUT;
1474 		break;
1475 	case QDF_STA_AP_CONNECT_REQ_TIMEOUT:
1476 		ret_val = QCA_WLAN_HANG_STA_AP_CONNECT_REQ_TIMEOUT;
1477 		break;
1478 	case QDF_MAC_HW_MODE_CHANGE_TIMEOUT:
1479 		ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CHANGE_TIMEOUT;
1480 		break;
1481 	case QDF_MAC_HW_MODE_CONFIG_TIMEOUT:
1482 		ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CONFIG_TIMEOUT;
1483 		break;
1484 	case QDF_VDEV_START_RESPONSE_TIMED_OUT:
1485 		ret_val = QCA_WLAN_HANG_VDEV_START_RESPONSE_TIMED_OUT;
1486 		break;
1487 	case QDF_VDEV_RESTART_RESPONSE_TIMED_OUT:
1488 		ret_val = QCA_WLAN_HANG_VDEV_RESTART_RESPONSE_TIMED_OUT;
1489 		break;
1490 	case QDF_VDEV_STOP_RESPONSE_TIMED_OUT:
1491 		ret_val = QCA_WLAN_HANG_VDEV_STOP_RESPONSE_TIMED_OUT;
1492 		break;
1493 	case QDF_VDEV_DELETE_RESPONSE_TIMED_OUT:
1494 		ret_val = QCA_WLAN_HANG_VDEV_DELETE_RESPONSE_TIMED_OUT;
1495 		break;
1496 	case QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT:
1497 		ret_val = QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
1498 		break;
1499 	case QDF_WMI_BUF_SEQUENCE_MISMATCH:
1500 		ret_val = QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
1501 		break;
1502 	case QDF_HAL_REG_WRITE_FAILURE:
1503 		ret_val = QCA_WLAN_HANG_REG_WRITE_FAILURE;
1504 		break;
1505 	case QDF_SUSPEND_NO_CREDIT:
1506 		ret_val = QCA_WLAN_HANG_SUSPEND_NO_CREDIT;
1507 		break;
1508 	case QCA_HANG_BUS_FAILURE:
1509 		ret_val = QCA_WLAN_HANG_BUS_FAILURE;
1510 		break;
1511 	case QDF_TASKLET_CREDIT_LATENCY_DETECT:
1512 		ret_val = QCA_WLAN_HANG_TASKLET_CREDIT_LATENCY_DETECT;
1513 		break;
1514 	case QDF_RX_REG_PKT_ROUTE_ERR:
1515 		ret_val = QCA_WLAN_HANG_RX_MSDU_BUF_RCVD_IN_ERR_RING;
1516 		break;
1517 	case QDF_VDEV_SM_OUT_OF_SYNC:
1518 		ret_val = QCA_WLAN_HANG_VDEV_SM_OUT_OF_SYNC;
1519 		break;
1520 	case QDF_STATS_REQ_TIMEDOUT:
1521 		ret_val = QCA_WLAN_HANG_STATS_REQ_TIMEOUT;
1522 		break;
1523 	case QDF_TX_DESC_LEAK:
1524 		ret_val = QCA_WLAN_HANG_TX_DESC_LEAK;
1525 		break;
1526 	case QDF_SCHED_TIMEOUT:
1527 		ret_val = QCA_WLAN_HANG_SCHED_TIMEOUT;
1528 		break;
1529 	case QDF_SELF_PEER_DEL_FAILED:
1530 		ret_val = QCA_WLAN_HANG_SELF_PEER_DEL_FAIL;
1531 		break;
1532 	case QDF_DEL_SELF_STA_FAILED:
1533 		ret_val = QCA_WLAN_HANG_DEL_SELF_STA_FAIL;
1534 		break;
1535 	case QDF_FLUSH_LOGS:
1536 		ret_val = QCA_WLAN_HANG_FLUSH_LOGS;
1537 		break;
1538 	case QDF_HOST_WAKEUP_REASON_PAGEFAULT:
1539 		ret_val = QCA_WLAN_HANG_HOST_WAKEUP_REASON_PAGE_FAULT;
1540 		break;
1541 	case QDF_REASON_UNSPECIFIED:
1542 	default:
1543 		ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
1544 		break;
1545 	}
1546 	return ret_val;
1547 }
1548 
1549 /**
1550  * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
1551  * @hdd_ctx: Pointer to hdd context
1552  * @reason: cds recovery reason
1553  * @data: Hang Data
1554  * @data_len: length of @data
1555  *
1556  * Return: 0 on success or failure reason
1557  */
1558 int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
1559 				    enum qdf_hang_reason reason, uint8_t *data,
1560 				    size_t data_len)
1561 {
1562 	struct sk_buff *vendor_event;
1563 	enum qca_wlan_vendor_hang_reason hang_reason;
1564 
1565 	hdd_enter();
1566 
1567 	if (!hdd_ctx) {
1568 		hdd_err("HDD context is null");
1569 		return -EINVAL;
1570 	}
1571 
1572 	vendor_event = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1573 							NULL,
1574 							sizeof(uint32_t) +
1575 							data_len,
1576 							HANG_REASON_INDEX,
1577 							GFP_KERNEL);
1578 	if (!vendor_event) {
1579 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1580 		return -ENOMEM;
1581 	}
1582 
1583 	hang_reason = hdd_convert_hang_reason(reason);
1584 
1585 	if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
1586 			(uint32_t)hang_reason) ||
1587 	    nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON_DATA,
1588 		    data_len, data)) {
1589 		hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
1590 		wlan_cfg80211_vendor_free_skb(vendor_event);
1591 		return -EINVAL;
1592 	}
1593 
1594 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1595 
1596 	hdd_exit();
1597 	return 0;
1598 }
1599 
1600 #undef HANG_REASON_INDEX
1601 
1602 /**
1603  * wlan_hdd_get_adjacent_chan_freq(): Gets next/previous channel
1604  * with respect to the channel passed.
1605  * @freq: Channel frequency
1606  * @upper: If "true" then next channel is returned or else
1607  * previous channel is returned.
1608  *
1609  * This function returns the next/previous adjacent-channel to
1610  * the channel passed. If "upper = true" then next channel is
1611  * returned else previous is returned.
1612  */
1613 static qdf_freq_t wlan_hdd_get_adjacent_chan_freq(qdf_freq_t freq, bool upper)
1614 {
1615 	enum channel_enum ch_idx = wlan_reg_get_chan_enum_for_freq(freq);
1616 
1617 	if (reg_is_chan_enum_invalid(ch_idx))
1618 		return -EINVAL;
1619 
1620 	if (upper && (ch_idx < (NUM_CHANNELS - 1)))
1621 		ch_idx++;
1622 	else if (!upper && (ch_idx > CHAN_ENUM_2412))
1623 		ch_idx--;
1624 	else
1625 		return -EINVAL;
1626 
1627 	return WLAN_REG_CH_TO_FREQ(ch_idx);
1628 }
1629 
1630 /**
1631  * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
1632  * avoided when Do_Not_Break_Stream is active.
1633  * @hdd_ctx:  HDD Context
1634  * @op_freq:  AP/P2P-GO operating channel frequency
1635  *
1636  * This function sends list of frequencies to be avoided when
1637  * Do_Not_Break_Stream is active.
1638  * To clear the avoid_frequency_list in the application,
1639  * op_freq = 0 can be passed.
1640  *
1641  * Return: 0 on success and errno on failure
1642  */
1643 int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx,
1644 				      qdf_freq_t op_freq)
1645 {
1646 	struct ch_avoid_ind_type p2p_avoid_freq_list;
1647 	qdf_freq_t min_freq, max_freq;
1648 	int ret;
1649 	qdf_freq_t freq;
1650 
1651 	hdd_enter();
1652 
1653 	if (!hdd_ctx) {
1654 		hdd_err("invalid param");
1655 		return -EINVAL;
1656 	}
1657 
1658 	qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
1659 	/*
1660 	 * If channel passed is zero, clear the avoid_freq list in application.
1661 	 */
1662 	if (!op_freq) {
1663 #ifdef FEATURE_WLAN_CH_AVOID
1664 		mutex_lock(&hdd_ctx->avoid_freq_lock);
1665 		qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
1666 				sizeof(struct ch_avoid_ind_type));
1667 		if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
1668 			memcpy(&p2p_avoid_freq_list,
1669 			       &hdd_ctx->coex_avoid_freq_list,
1670 			       sizeof(struct ch_avoid_ind_type));
1671 		mutex_unlock(&hdd_ctx->avoid_freq_lock);
1672 #endif
1673 		ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
1674 						     &p2p_avoid_freq_list);
1675 		if (ret)
1676 			hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1677 				ret);
1678 
1679 		return ret;
1680 	}
1681 
1682 	if (WLAN_REG_IS_24GHZ_CH_FREQ(op_freq)) {
1683 		min_freq = WLAN_REG_MIN_24GHZ_CHAN_FREQ;
1684 		max_freq = WLAN_REG_MAX_24GHZ_CHAN_FREQ;
1685 	} else if (WLAN_REG_IS_5GHZ_CH_FREQ(op_freq)) {
1686 		min_freq = WLAN_REG_MIN_5GHZ_CHAN_FREQ;
1687 		max_freq = WLAN_REG_MAX_5GHZ_CHAN_FREQ;
1688 	} else {
1689 		hdd_err("invalid channel freq:%d", op_freq);
1690 		return -EINVAL;
1691 	}
1692 
1693 	if (op_freq > min_freq && op_freq < max_freq) {
1694 		p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1695 		p2p_avoid_freq_list.avoid_freq_range[0].start_freq = min_freq;
1696 
1697 		/* Get channel before the op_freq */
1698 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, false);
1699 		if (freq < 0)
1700 			return -EINVAL;
1701 		p2p_avoid_freq_list.avoid_freq_range[0].end_freq = freq;
1702 
1703 		/* Get channel next to the op_freq */
1704 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, true);
1705 		if (freq < 0)
1706 			return -EINVAL;
1707 		p2p_avoid_freq_list.avoid_freq_range[1].start_freq = freq;
1708 
1709 		p2p_avoid_freq_list.avoid_freq_range[1].end_freq = max_freq;
1710 	} else if (op_freq == min_freq) {
1711 		p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1712 
1713 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, true);
1714 		if (freq < 0)
1715 			return -EINVAL;
1716 		p2p_avoid_freq_list.avoid_freq_range[0].start_freq = freq;
1717 
1718 		p2p_avoid_freq_list.avoid_freq_range[0].end_freq = max_freq;
1719 	} else {
1720 		p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1721 		p2p_avoid_freq_list.avoid_freq_range[0].start_freq = min_freq;
1722 
1723 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, false);
1724 		if (freq < 0)
1725 			return -EINVAL;
1726 		p2p_avoid_freq_list.avoid_freq_range[0].end_freq = freq;
1727 	}
1728 #ifdef FEATURE_WLAN_CH_AVOID
1729 	mutex_lock(&hdd_ctx->avoid_freq_lock);
1730 	hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1731 	if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
1732 		ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
1733 				&hdd_ctx->coex_avoid_freq_list);
1734 		if (ret) {
1735 			mutex_unlock(&hdd_ctx->avoid_freq_lock);
1736 			hdd_err("avoid freq merge failed");
1737 			return ret;
1738 		}
1739 	}
1740 	mutex_unlock(&hdd_ctx->avoid_freq_lock);
1741 #endif
1742 	ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
1743 	if (ret)
1744 		hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1745 
1746 	return ret;
1747 }
1748 
1749 /* vendor specific events */
1750 static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
1751 	[QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1752 		.vendor_id =
1753 			QCA_NL80211_VENDOR_ID,
1754 		.subcmd =
1755 			QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1756 	},
1757 
1758 	[QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1759 		.vendor_id =
1760 			QCA_NL80211_VENDOR_ID,
1761 		.subcmd =
1762 			QCA_NL80211_VENDOR_SUBCMD_NAN
1763 	},
1764 
1765 #ifdef WLAN_FEATURE_STATS_EXT
1766 	[QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1767 		.vendor_id =
1768 			QCA_NL80211_VENDOR_ID,
1769 		.subcmd =
1770 			QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1771 	},
1772 #endif /* WLAN_FEATURE_STATS_EXT */
1773 	[QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS_INDEX] = {
1774 		.vendor_id =
1775 			QCA_NL80211_VENDOR_ID,
1776 		.subcmd =
1777 			QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS
1778 	},
1779 
1780 #ifdef FEATURE_WLAN_EXTSCAN
1781 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1782 		.vendor_id =
1783 			QCA_NL80211_VENDOR_ID,
1784 		.subcmd =
1785 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1786 	},
1787 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1788 		.vendor_id =
1789 			QCA_NL80211_VENDOR_ID,
1790 		.subcmd =
1791 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1792 	},
1793 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1794 		.
1795 		vendor_id
1796 			=
1797 				QCA_NL80211_VENDOR_ID,
1798 		.subcmd =
1799 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1800 	},
1801 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1802 		.
1803 		vendor_id
1804 			=
1805 				QCA_NL80211_VENDOR_ID,
1806 		.
1807 		subcmd =
1808 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1809 	},
1810 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1811 		.
1812 		vendor_id
1813 			=
1814 				QCA_NL80211_VENDOR_ID,
1815 		.
1816 		subcmd
1817 			=
1818 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1819 	},
1820 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1821 		.
1822 		vendor_id
1823 			=
1824 				QCA_NL80211_VENDOR_ID,
1825 		.subcmd =
1826 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1827 	},
1828 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1829 		.vendor_id =
1830 			QCA_NL80211_VENDOR_ID,
1831 		.subcmd =
1832 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1833 	},
1834 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1835 		.
1836 		vendor_id
1837 			=
1838 				QCA_NL80211_VENDOR_ID,
1839 		.subcmd =
1840 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1841 	},
1842 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1843 		.
1844 		vendor_id
1845 			=
1846 				QCA_NL80211_VENDOR_ID,
1847 		.subcmd =
1848 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1849 	},
1850 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1851 		.
1852 		vendor_id
1853 			=
1854 				QCA_NL80211_VENDOR_ID,
1855 		.
1856 		subcmd
1857 			=
1858 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1859 	},
1860 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1861 		.
1862 		vendor_id
1863 			=
1864 				QCA_NL80211_VENDOR_ID,
1865 		.
1866 		subcmd =
1867 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1868 	},
1869 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1870 		.
1871 		vendor_id
1872 			=
1873 				QCA_NL80211_VENDOR_ID,
1874 		.
1875 		subcmd
1876 			=
1877 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1878 	},
1879 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1880 		.
1881 		vendor_id
1882 			=
1883 				QCA_NL80211_VENDOR_ID,
1884 		.
1885 		subcmd
1886 			=
1887 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1888 	},
1889 #endif /* FEATURE_WLAN_EXTSCAN */
1890 
1891 #ifdef WLAN_FEATURE_LINK_LAYER_STATS
1892 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1893 		.vendor_id =
1894 			QCA_NL80211_VENDOR_ID,
1895 		.subcmd =
1896 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1897 	},
1898 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1899 		.vendor_id =
1900 			QCA_NL80211_VENDOR_ID,
1901 		.subcmd =
1902 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1903 	},
1904 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1905 		.vendor_id =
1906 			QCA_NL80211_VENDOR_ID,
1907 		.subcmd =
1908 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1909 	},
1910 	[QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1911 		.vendor_id =
1912 			QCA_NL80211_VENDOR_ID,
1913 		.subcmd =
1914 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1915 	},
1916 	[QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1917 		.vendor_id =
1918 			QCA_NL80211_VENDOR_ID,
1919 		.subcmd =
1920 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1921 	},
1922 	[QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1923 		.vendor_id =
1924 			QCA_NL80211_VENDOR_ID,
1925 		.subcmd =
1926 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1927 	},
1928 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1929 		.vendor_id =
1930 			QCA_NL80211_VENDOR_ID,
1931 		.subcmd =
1932 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1933 	},
1934 #endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1935 	[QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1936 		.vendor_id =
1937 			QCA_NL80211_VENDOR_ID,
1938 		.subcmd =
1939 			QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1940 	},
1941 	[QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1942 		.vendor_id = QCA_NL80211_VENDOR_ID,
1943 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1944 	},
1945 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
1946 	[QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1947 		.vendor_id =
1948 			QCA_NL80211_VENDOR_ID,
1949 		.subcmd =
1950 			QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1951 	},
1952 #endif
1953 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] =  {
1954 		.vendor_id =
1955 			QCA_NL80211_VENDOR_ID,
1956 		.subcmd =
1957 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1958 	},
1959 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] =  {
1960 		.vendor_id =
1961 			QCA_NL80211_VENDOR_ID,
1962 		.subcmd =
1963 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1964 	},
1965 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] =  {
1966 		.vendor_id =
1967 			QCA_NL80211_VENDOR_ID,
1968 		.subcmd =
1969 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1970 	},
1971 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] =  {
1972 		.vendor_id =
1973 			QCA_NL80211_VENDOR_ID,
1974 		.subcmd =
1975 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1976 	},
1977 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] =  {
1978 		.vendor_id =
1979 			QCA_NL80211_VENDOR_ID,
1980 		.subcmd =
1981 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1982 	},
1983 #ifdef FEATURE_WLAN_EXTSCAN
1984 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1985 		.vendor_id = QCA_NL80211_VENDOR_ID,
1986 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1987 	},
1988 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1989 		.vendor_id = QCA_NL80211_VENDOR_ID,
1990 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1991 	},
1992 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1993 		.vendor_id = QCA_NL80211_VENDOR_ID,
1994 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1995 	},
1996 #endif /* FEATURE_WLAN_EXTSCAN */
1997 
1998 	FEATURE_RSSI_MONITOR_VENDOR_EVENTS
1999 
2000 #ifdef WLAN_FEATURE_TSF
2001 	[QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
2002 		.vendor_id = QCA_NL80211_VENDOR_ID,
2003 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
2004 	},
2005 #endif
2006 	[QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
2007 		.vendor_id = QCA_NL80211_VENDOR_ID,
2008 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
2009 	},
2010 	[QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
2011 		.vendor_id = QCA_NL80211_VENDOR_ID,
2012 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
2013 	},
2014 	/* OCB events */
2015 	[QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
2016 		.vendor_id = QCA_NL80211_VENDOR_ID,
2017 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
2018 	},
2019 #ifdef FEATURE_LFR_SUBNET_DETECTION
2020 	[QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
2021 		.vendor_id = QCA_NL80211_VENDOR_ID,
2022 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
2023 	},
2024 #endif /*FEATURE_LFR_SUBNET_DETECTION */
2025 
2026 	FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS_INDEX
2027 
2028 	[QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
2029 		.vendor_id = QCA_NL80211_VENDOR_ID,
2030 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
2031 	},
2032 
2033 	[QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
2034 		.vendor_id = QCA_NL80211_VENDOR_ID,
2035 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
2036 	},
2037 	[QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
2038 		.vendor_id = QCA_NL80211_VENDOR_ID,
2039 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
2040 	},
2041 	[QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
2042 		.vendor_id = QCA_NL80211_VENDOR_ID,
2043 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
2044 	},
2045 	[QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
2046 		.vendor_id = QCA_NL80211_VENDOR_ID,
2047 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
2048 	},
2049 	[QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
2050 		.vendor_id = QCA_NL80211_VENDOR_ID,
2051 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
2052 	},
2053 	[QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
2054 		.vendor_id = QCA_NL80211_VENDOR_ID,
2055 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
2056 	},
2057 	[QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
2058 		.vendor_id = QCA_NL80211_VENDOR_ID,
2059 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
2060 	},
2061 	[QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX] = {
2062 		.vendor_id = QCA_NL80211_VENDOR_ID,
2063 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT,
2064 	 },
2065 	[QCA_NL80211_VENDOR_SUBCMD_NAN_EXT_INDEX] = {
2066 		.vendor_id = QCA_NL80211_VENDOR_ID,
2067 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN_EXT
2068 	},
2069 	[QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX] = {
2070 		.vendor_id = QCA_NL80211_VENDOR_ID,
2071 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
2072 	},
2073 
2074 	BCN_RECV_FEATURE_VENDOR_EVENTS
2075 	FEATURE_MEDIUM_ASSESS_VENDOR_EVENTS
2076 	[QCA_NL80211_VENDOR_SUBCMD_ROAM_INDEX] = {
2077 		.vendor_id = QCA_NL80211_VENDOR_ID,
2078 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
2079 	},
2080 	[QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX] = {
2081 		.vendor_id = QCA_NL80211_VENDOR_ID,
2082 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_OEM_DATA,
2083 	},
2084 	[QCA_NL80211_VENDOR_SUBCMD_REQUEST_SAR_LIMITS_INDEX] = {
2085 		.vendor_id = QCA_NL80211_VENDOR_ID,
2086 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS_EVENT,
2087 	},
2088 	[QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX] = {
2089 		.vendor_id = QCA_NL80211_VENDOR_ID,
2090 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO,
2091 	},
2092 	FEATURE_THERMAL_VENDOR_EVENTS
2093 	FEATURE_DRIVER_DISCONNECT_REASON
2094 #ifdef WLAN_SUPPORT_TWT
2095 	FEATURE_TWT_VENDOR_EVENTS
2096 #endif
2097 	FEATURE_CFR_DATA_VENDOR_EVENTS
2098 #ifdef WLAN_FEATURE_CONNECTIVITY_LOGGING
2099 	FEATURE_CONNECTIVITY_LOGGING_EVENT
2100 #endif
2101 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2102 	[QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS_INDEX] = {
2103 		.vendor_id = QCA_NL80211_VENDOR_ID,
2104 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS,
2105 	},
2106 #endif
2107 	FEATURE_MCC_QUOTA_VENDOR_EVENTS
2108 	[QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY_INDEX] = {
2109 		.vendor_id = QCA_NL80211_VENDOR_ID,
2110 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY,
2111 	},
2112 	FEATURE_WIFI_POS_11AZ_AUTH_EVENTS
2113 #ifdef WLAN_FEATURE_SR
2114 	[QCA_NL80211_VENDOR_SUBCMD_SR_INDEX] = {
2115 		.vendor_id = QCA_NL80211_VENDOR_ID,
2116 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_SR,
2117 	},
2118 #endif
2119 	FEATURE_GREEN_AP_LOW_LATENCY_PWR_SAVE_EVENT
2120 	FEATURE_ROAM_STATS_EVENTS
2121 #ifdef WLAN_FEATURE_11BE_MLO
2122 	[QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP_INDEX] = {
2123 		.vendor_id = QCA_NL80211_VENDOR_ID,
2124 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP,
2125 	},
2126 	[QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG_INDEX] = {
2127 		.vendor_id = QCA_NL80211_VENDOR_ID,
2128 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG,
2129 	},
2130 #endif
2131 	FEATURE_AFC_VENDOR_EVENTS
2132 };
2133 
2134 /**
2135  * __is_driver_dfs_capable() - get driver DFS capability
2136  * @wiphy:   pointer to wireless wiphy structure.
2137  * @wdev:    pointer to wireless_dev structure.
2138  * @data:    Pointer to the data to be passed via vendor interface
2139  * @data_len:Length of the data to be passed
2140  *
2141  * This function is called by userspace to indicate whether or not
2142  * the driver supports DFS offload.
2143  *
2144  * Return: 0 on success, negative errno on failure
2145  */
2146 static int __is_driver_dfs_capable(struct wiphy *wiphy,
2147 				   struct wireless_dev *wdev,
2148 				   const void *data,
2149 				   int data_len)
2150 {
2151 	u32 dfs_capability = 0;
2152 	struct sk_buff *temp_skbuff;
2153 	int ret_val;
2154 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
2155 
2156 	hdd_enter_dev(wdev->netdev);
2157 
2158 	ret_val = wlan_hdd_validate_context(hdd_ctx);
2159 	if (ret_val)
2160 		return ret_val;
2161 
2162 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2163 		hdd_err("Command not allowed in FTM mode");
2164 		return -EPERM;
2165 	}
2166 
2167 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
2168 	defined(CFG80211_DFS_OFFLOAD_BACKPORT)
2169 	dfs_capability =
2170 		wiphy_ext_feature_isset(wiphy,
2171 					NL80211_EXT_FEATURE_DFS_OFFLOAD);
2172 #else
2173 	dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
2174 #endif
2175 
2176 	temp_skbuff = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2177 							       sizeof(u32) +
2178 							       NLMSG_HDRLEN);
2179 	if (temp_skbuff) {
2180 		ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
2181 				      dfs_capability);
2182 		if (ret_val) {
2183 			hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
2184 			wlan_cfg80211_vendor_free_skb(temp_skbuff);
2185 
2186 			return ret_val;
2187 		}
2188 
2189 		return wlan_cfg80211_vendor_cmd_reply(temp_skbuff);
2190 	}
2191 
2192 	hdd_err("dfs capability: buffer alloc fail");
2193 	return -ENOMEM;
2194 }
2195 
2196 /**
2197  * is_driver_dfs_capable() - get driver DFS capability
2198  * @wiphy:   pointer to wireless wiphy structure.
2199  * @wdev:    pointer to wireless_dev structure.
2200  * @data:    Pointer to the data to be passed via vendor interface
2201  * @data_len:Length of the data to be passed
2202  *
2203  * This function is called by userspace to indicate whether or not
2204  * the driver supports DFS offload.  This is an SSR-protected
2205  * wrapper function.
2206  *
2207  * Return: 0 on success, negative errno on failure
2208  */
2209 static int is_driver_dfs_capable(struct wiphy *wiphy,
2210 				 struct wireless_dev *wdev,
2211 				 const void *data,
2212 				 int data_len)
2213 {
2214 	struct osif_psoc_sync *psoc_sync;
2215 	int errno;
2216 
2217 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
2218 	if (errno)
2219 		return errno;
2220 
2221 	errno = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
2222 
2223 	osif_psoc_sync_op_stop(psoc_sync);
2224 
2225 	return errno;
2226 }
2227 
2228 /**
2229  * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
2230  *
2231  * @adapter: SAP adapter pointer
2232  *
2233  * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
2234  * radio. So in case of DFS MCC scenario override current SAP given config
2235  * to follow concurrent SAP DFS config
2236  *
2237  * Return: 0 - No DFS issue, 1 - Override done and negative error codes
2238  */
2239 int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
2240 {
2241 	struct hdd_adapter *con_sap_adapter;
2242 	struct sap_config *sap_config, *con_sap_config;
2243 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2244 	uint32_t con_ch_freq;
2245 
2246 	if (!hdd_ctx) {
2247 		hdd_err("hdd context is NULL");
2248 		return 0;
2249 	}
2250 
2251 	/*
2252 	 * Check if AP+AP case, once primary AP chooses a DFS
2253 	 * channel secondary AP should always follow primary APs channel
2254 	 */
2255 	if (!policy_mgr_concurrent_beaconing_sessions_running(
2256 		hdd_ctx->psoc))
2257 		return 0;
2258 
2259 	con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
2260 	if (!con_sap_adapter)
2261 		return 0;
2262 
2263 	sap_config = &adapter->deflink->session.ap.sap_config;
2264 	con_sap_config = &con_sap_adapter->deflink->session.ap.sap_config;
2265 	con_ch_freq = con_sap_adapter->deflink->session.ap.operating_chan_freq;
2266 
2267 	if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, con_ch_freq))
2268 		return 0;
2269 
2270 	hdd_debug("Only SCC AP-AP DFS Permitted (ch_freq=%d, con_ch_freq=%d)",
2271 		  sap_config->chan_freq, con_ch_freq);
2272 	hdd_debug("Overriding guest AP's channel");
2273 	sap_config->chan_freq = con_ch_freq;
2274 
2275 	if (con_sap_config->acs_cfg.acs_mode == true) {
2276 		if (con_ch_freq != con_sap_config->acs_cfg.pri_ch_freq &&
2277 		    con_ch_freq != con_sap_config->acs_cfg.ht_sec_ch_freq) {
2278 			hdd_err("Primary AP channel config error");
2279 			hdd_err("Operating ch: %d ACS ch freq: %d Sec Freq %d",
2280 				con_ch_freq,
2281 				con_sap_config->acs_cfg.pri_ch_freq,
2282 				con_sap_config->acs_cfg.ht_sec_ch_freq);
2283 			return -EINVAL;
2284 		}
2285 		/* Sec AP ACS info is overwritten with Pri AP due to DFS
2286 		 * MCC restriction. So free ch list allocated in do_acs
2287 		 * func for Sec AP and realloc for Pri AP ch list size
2288 		 */
2289 		if (sap_config->acs_cfg.freq_list) {
2290 			qdf_mem_free(sap_config->acs_cfg.freq_list);
2291 			sap_config->acs_cfg.freq_list = NULL;
2292 		}
2293 		if (sap_config->acs_cfg.master_freq_list) {
2294 			qdf_mem_free(sap_config->acs_cfg.master_freq_list);
2295 			sap_config->acs_cfg.master_freq_list = NULL;
2296 		}
2297 
2298 		qdf_mem_copy(&sap_config->acs_cfg,
2299 			     &con_sap_config->acs_cfg,
2300 			     sizeof(struct sap_acs_cfg));
2301 
2302 		sap_config->acs_cfg.freq_list =
2303 			qdf_mem_malloc(sizeof(uint32_t) *
2304 				con_sap_config->acs_cfg.ch_list_count);
2305 		if (!sap_config->acs_cfg.freq_list) {
2306 			sap_config->acs_cfg.ch_list_count = 0;
2307 			return -ENOMEM;
2308 		}
2309 		qdf_mem_copy(sap_config->acs_cfg.freq_list,
2310 			     con_sap_config->acs_cfg.freq_list,
2311 			     con_sap_config->acs_cfg.ch_list_count *
2312 				sizeof(uint32_t));
2313 
2314 		sap_config->acs_cfg.master_freq_list =
2315 			qdf_mem_malloc(sizeof(uint32_t) *
2316 				con_sap_config->acs_cfg.master_ch_list_count);
2317 		if (!sap_config->acs_cfg.master_freq_list) {
2318 			sap_config->acs_cfg.master_ch_list_count = 0;
2319 			qdf_mem_free(sap_config->acs_cfg.freq_list);
2320 			sap_config->acs_cfg.freq_list = NULL;
2321 			return -ENOMEM;
2322 		}
2323 		qdf_mem_copy(sap_config->acs_cfg.master_freq_list,
2324 			     con_sap_config->acs_cfg.master_freq_list,
2325 			     con_sap_config->acs_cfg.master_ch_list_count *
2326 				sizeof(uint32_t));
2327 	} else {
2328 		sap_config->acs_cfg.pri_ch_freq = con_ch_freq;
2329 		if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
2330 			sap_config->acs_cfg.ht_sec_ch_freq =
2331 						con_sap_config->sec_ch_freq;
2332 	}
2333 
2334 	return con_ch_freq;
2335 }
2336 
2337 /**
2338  * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
2339  * @sap_cfg: pointer to SAP config struct
2340  * @hw_mode: hw mode retrieved from vendor command buffer
2341  * @ht_enabled: whether HT phy mode is enabled
2342  * @vht_enabled: whether VHT phy mode is enabled
2343  *
2344  * This function populates the ACS hw mode based on the configuration retrieved
2345  * from the vendor command buffer; and sets ACS start and end channel for the
2346  * given band.
2347  *
2348  * Return: 0 if success; -EINVAL if ACS channel list is NULL
2349  */
2350 static int wlan_hdd_set_acs_ch_range(
2351 	struct sap_config *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
2352 	bool ht_enabled, bool vht_enabled)
2353 {
2354 	int i;
2355 
2356 	if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
2357 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
2358 		sap_cfg->acs_cfg.start_ch_freq =
2359 				wlan_reg_ch_to_freq(CHAN_ENUM_2412);
2360 		sap_cfg->acs_cfg.end_ch_freq =
2361 				wlan_reg_ch_to_freq(CHAN_ENUM_2484);
2362 	} else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
2363 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
2364 		sap_cfg->acs_cfg.start_ch_freq =
2365 				wlan_reg_ch_to_freq(CHAN_ENUM_2412);
2366 		sap_cfg->acs_cfg.end_ch_freq =
2367 				wlan_reg_ch_to_freq(CHAN_ENUM_2472);
2368 	} else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
2369 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
2370 		sap_cfg->acs_cfg.start_ch_freq =
2371 				wlan_reg_ch_to_freq(CHAN_ENUM_5180);
2372 		sap_cfg->acs_cfg.end_ch_freq =
2373 				wlan_reg_ch_to_freq(CHAN_ENUM_5885);
2374 	} else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
2375 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
2376 		sap_cfg->acs_cfg.start_ch_freq =
2377 				wlan_reg_ch_to_freq(CHAN_ENUM_2412);
2378 		sap_cfg->acs_cfg.end_ch_freq =
2379 				wlan_reg_ch_to_freq(CHAN_ENUM_5885);
2380 	}
2381 
2382 	if (ht_enabled)
2383 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
2384 
2385 	if (vht_enabled)
2386 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2387 
2388 	/* Parse ACS Chan list from hostapd */
2389 	if (!sap_cfg->acs_cfg.freq_list)
2390 		return -EINVAL;
2391 
2392 	sap_cfg->acs_cfg.start_ch_freq = sap_cfg->acs_cfg.freq_list[0];
2393 	sap_cfg->acs_cfg.end_ch_freq =
2394 		sap_cfg->acs_cfg.freq_list[sap_cfg->acs_cfg.ch_list_count - 1];
2395 	for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
2396 		/* avoid channel as start channel */
2397 		if (sap_cfg->acs_cfg.start_ch_freq >
2398 		    sap_cfg->acs_cfg.freq_list[i] &&
2399 		    sap_cfg->acs_cfg.freq_list[i] != 0)
2400 			sap_cfg->acs_cfg.start_ch_freq =
2401 			    sap_cfg->acs_cfg.freq_list[i];
2402 		if (sap_cfg->acs_cfg.end_ch_freq <
2403 				sap_cfg->acs_cfg.freq_list[i])
2404 			sap_cfg->acs_cfg.end_ch_freq =
2405 			    sap_cfg->acs_cfg.freq_list[i];
2406 	}
2407 
2408 	return 0;
2409 }
2410 
2411 static void hdd_update_acs_channel_list(struct sap_config *sap_config,
2412 					enum band_info band)
2413 {
2414 	int i, temp_count = 0;
2415 	int acs_list_count = sap_config->acs_cfg.ch_list_count;
2416 
2417 	for (i = 0; i < acs_list_count; i++) {
2418 		if (BAND_2G == band) {
2419 			if (WLAN_REG_IS_24GHZ_CH_FREQ(
2420 				sap_config->acs_cfg.freq_list[i])) {
2421 				sap_config->acs_cfg.freq_list[temp_count] =
2422 					sap_config->acs_cfg.freq_list[i];
2423 				temp_count++;
2424 			}
2425 		} else if (BAND_5G == band) {
2426 			if (WLAN_REG_IS_5GHZ_CH_FREQ(
2427 				sap_config->acs_cfg.freq_list[i]) ||
2428 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(
2429 				sap_config->acs_cfg.freq_list[i])) {
2430 				sap_config->acs_cfg.freq_list[temp_count] =
2431 					sap_config->acs_cfg.freq_list[i];
2432 				temp_count++;
2433 			}
2434 		}
2435 	}
2436 	sap_config->acs_cfg.ch_list_count = temp_count;
2437 }
2438 
2439 /**
2440  * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
2441  * @link_info: Link info pointer in SAP HDD adapter
2442  *
2443  * This function starts the ACS procedure if there are no
2444  * constraints like MBSSID DFS restrictions.
2445  *
2446  * Return: Status of ACS Start procedure
2447  */
2448 int wlan_hdd_cfg80211_start_acs(struct wlan_hdd_link_info *link_info)
2449 {
2450 	struct hdd_context *hdd_ctx;
2451 	struct sap_config *sap_config;
2452 	struct sap_context *sap_ctx;
2453 	struct hdd_ap_ctx *ap_ctx;
2454 	sap_event_cb acs_event_callback;
2455 	uint8_t mcc_to_scc_switch = 0;
2456 	int status;
2457 	QDF_STATUS qdf_status;
2458 	struct hdd_adapter *adapter = link_info->adapter;
2459 
2460 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2461 	status = wlan_hdd_validate_context(hdd_ctx);
2462 	if (0 != status)
2463 		return status;
2464 
2465 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
2466 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
2467 	sap_config = &ap_ctx->sap_config;
2468 
2469 	if (hdd_ctx->acs_policy.acs_chan_freq)
2470 		sap_config->chan_freq = hdd_ctx->acs_policy.acs_chan_freq;
2471 	else
2472 		sap_config->chan_freq = AUTO_CHANNEL_SELECT;
2473 	ucfg_policy_mgr_get_mcc_scc_switch(hdd_ctx->psoc,
2474 					   &mcc_to_scc_switch);
2475 	/*
2476 	 * No DFS SCC is allowed in Auto use case. Hence not
2477 	 * calling DFS override
2478 	 */
2479 	if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
2480 	    mcc_to_scc_switch &&
2481 	    !(policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) &&
2482 	    WLAN_REG_IS_24GHZ_CH_FREQ(sap_config->acs_cfg.end_ch_freq)) &&
2483 	    !wlansap_dcs_is_wlan_interference_mitigation_enabled(sap_ctx)) {
2484 		status = wlan_hdd_sap_cfg_dfs_override(adapter);
2485 		if (status < 0)
2486 			return status;
2487 
2488 		if (status > 0) {
2489 			/*notify hostapd about channel override */
2490 			wlan_hdd_cfg80211_acs_ch_select_evt(link_info, true);
2491 			wlansap_dcs_set_wlan_interference_mitigation_on_band(sap_ctx,
2492 									     sap_config);
2493 			return 0;
2494 		}
2495 	}
2496 	/* When first 2 connections are on the same frequency band,
2497 	 * then PCL would include only channels from the other
2498 	 * frequency band on which no connections are active
2499 	 */
2500 	if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
2501 		(sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2502 		struct policy_mgr_conc_connection_info *conc_connection_info;
2503 		uint32_t i;
2504 
2505 		conc_connection_info = policy_mgr_get_conn_info(&i);
2506 		if (policy_mgr_are_2_freq_on_same_mac(hdd_ctx->psoc,
2507 			conc_connection_info[0].freq,
2508 			conc_connection_info[1].freq)) {
2509 			if (!WLAN_REG_IS_24GHZ_CH_FREQ(
2510 				sap_config->acs_cfg.pcl_chan_freq[0])) {
2511 				sap_config->acs_cfg.band =
2512 					QCA_ACS_MODE_IEEE80211A;
2513 				hdd_update_acs_channel_list(sap_config,
2514 					BAND_5G);
2515 			} else {
2516 				sap_config->acs_cfg.band =
2517 					QCA_ACS_MODE_IEEE80211G;
2518 				hdd_update_acs_channel_list(sap_config,
2519 					BAND_2G);
2520 			}
2521 		}
2522 	}
2523 	status = wlan_hdd_config_acs(hdd_ctx, adapter);
2524 	if (status) {
2525 		hdd_err("ACS config failed");
2526 		return -EINVAL;
2527 	}
2528 
2529 	acs_event_callback = hdd_hostapd_sap_event_cb;
2530 
2531 	qdf_mem_copy(sap_config->self_macaddr.bytes,
2532 		adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
2533 
2534 	qdf_status = wlansap_acs_chselect(sap_ctx, acs_event_callback,
2535 					  sap_config, adapter->dev);
2536 
2537 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
2538 		hdd_err("ACS channel select failed");
2539 		return -EINVAL;
2540 	}
2541 	if (sap_is_auto_channel_select(sap_ctx))
2542 		sap_config->acs_cfg.acs_mode = true;
2543 
2544 	/* If ACS scan is skipped then ACS request would be completed by now,
2545 	 * so no need to set acs in progress
2546 	 */
2547 	if (!sap_config->acs_cfg.skip_acs_scan)
2548 		qdf_atomic_set(&ap_ctx->acs_in_progress, 1);
2549 
2550 	return 0;
2551 }
2552 
2553 /**
2554  * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
2555  * @hdd_ctx: hdd context
2556  * @acs_chan_params: external acs channel params
2557  * @sap_config: SAP config
2558  *
2559  * This API provides unsorted pcl list.
2560  * this list is a subset of the valid channel list given by hostapd.
2561  * if channel is not present in pcl, weightage will be given as zero
2562  *
2563  * Return: Zero on success, non-zero on failure
2564  */
2565 static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
2566 		struct hdd_vendor_acs_chan_params *acs_chan_params,
2567 		struct sap_config *sap_config)
2568 {
2569 	int i, j;
2570 	/*
2571 	 * PCL shall contain only the preferred channels from the
2572 	 * application. If those channels are not present in the
2573 	 * driver PCL, then set the weight to zero
2574 	 */
2575 	for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
2576 		acs_chan_params->vendor_pcl_list[i] =
2577 				sap_config->acs_cfg.freq_list[i];
2578 		acs_chan_params->vendor_weight_list[i] = 0;
2579 		for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
2580 			if (sap_config->acs_cfg.freq_list[i] ==
2581 			    sap_config->acs_cfg.pcl_chan_freq[j]) {
2582 				acs_chan_params->vendor_weight_list[i] =
2583 				sap_config->acs_cfg.pcl_channels_weight_list[j];
2584 				break;
2585 			}
2586 		}
2587 	}
2588 	acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
2589 }
2590 
2591 /**
2592  * hdd_update_reg_chan_info : This API constructs channel info
2593  * for all the given channel
2594  * @adapter: pointer to SAP adapter struct
2595  * @channel_count: channel count
2596  * @freq_list: channel frequency (MHz) list
2597  *
2598  * Return: Status of of channel information updation
2599  */
2600 static int
2601 hdd_update_reg_chan_info(struct hdd_adapter *adapter,
2602 			 uint32_t channel_count, uint32_t *freq_list)
2603 {
2604 	int i;
2605 	struct hdd_channel_info *icv;
2606 	struct ch_params ch_params = {0};
2607 	uint8_t bw_offset = 0, chan = 0;
2608 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2609 	struct sap_config *sap_config =
2610 				&adapter->deflink->session.ap.sap_config;
2611 	mac_handle_t mac_handle;
2612 	uint8_t sub_20_chan_width = 0;
2613 	QDF_STATUS status;
2614 
2615 	mac_handle = hdd_ctx->mac_handle;
2616 	sap_config->channel_info_count = channel_count;
2617 
2618 	status = ucfg_mlme_get_sub_20_chan_width(hdd_ctx->psoc,
2619 						 &sub_20_chan_width);
2620 	if (QDF_IS_STATUS_ERROR(status))
2621 		hdd_err("Failed to get sub_20_chan_width config");
2622 
2623 	for (i = 0; i < channel_count; i++) {
2624 		icv = &sap_config->channel_info[i];
2625 		chan = wlan_reg_freq_to_chan(hdd_ctx->pdev,
2626 					     freq_list[i]);
2627 		if (chan == 0)
2628 			continue;
2629 
2630 		icv->freq = freq_list[i];
2631 		icv->ieee_chan_number = chan;
2632 		icv->max_reg_power = wlan_reg_get_channel_reg_power_for_freq(
2633 				hdd_ctx->pdev, freq_list[i]);
2634 
2635 		/* filling demo values */
2636 		icv->max_radio_power = HDD_MAX_TX_POWER;
2637 		icv->min_radio_power = HDD_MIN_TX_POWER;
2638 		/* not supported in current driver */
2639 		icv->max_antenna_gain = 0;
2640 
2641 		bw_offset = hdd_get_bw_offset(sap_config->acs_cfg.ch_width);
2642 		icv->reg_class_id =
2643 			wlan_hdd_find_opclass(mac_handle, chan, bw_offset);
2644 
2645 		if (WLAN_REG_IS_5GHZ_CH_FREQ(freq_list[i])) {
2646 			if (sap_phymode_is_eht(sap_config->SapHw_mode))
2647 				wlan_reg_set_create_punc_bitmap(&ch_params,
2648 								true);
2649 			ch_params.ch_width = sap_config->acs_cfg.ch_width;
2650 			wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
2651 								icv->freq,
2652 								0, &ch_params,
2653 								REG_CURRENT_PWR_MODE);
2654 			icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
2655 			icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
2656 		}
2657 
2658 		icv->flags = 0;
2659 		icv->flags = cds_get_vendor_reg_flags(hdd_ctx->pdev,
2660 				icv->freq,
2661 				sap_config->acs_cfg.ch_width,
2662 				sap_config->acs_cfg.is_ht_enabled,
2663 				sap_config->acs_cfg.is_vht_enabled,
2664 				sub_20_chan_width);
2665 		if (icv->flags & IEEE80211_CHAN_PASSIVE)
2666 			icv->flagext |= IEEE80211_CHAN_DFS;
2667 
2668 		hdd_debug("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
2669 			icv->freq, icv->flags,
2670 			icv->flagext, icv->ieee_chan_number,
2671 			icv->max_reg_power, icv->max_radio_power,
2672 			icv->min_radio_power, icv->reg_class_id,
2673 			icv->max_antenna_gain, icv->vht_center_freq_seg0,
2674 			icv->vht_center_freq_seg1);
2675 	}
2676 	return 0;
2677 }
2678 
2679 /* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
2680 #define CHAN_INFO_ATTR_FLAGS \
2681 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
2682 #define CHAN_INFO_ATTR_FLAG_EXT \
2683 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
2684 #define CHAN_INFO_ATTR_FREQ \
2685 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
2686 #define CHAN_INFO_ATTR_MAX_REG_POWER \
2687 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
2688 #define CHAN_INFO_ATTR_MAX_POWER \
2689 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
2690 #define CHAN_INFO_ATTR_MIN_POWER \
2691 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
2692 #define CHAN_INFO_ATTR_REG_CLASS_ID \
2693 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
2694 #define CHAN_INFO_ATTR_ANTENNA_GAIN \
2695 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
2696 #define CHAN_INFO_ATTR_VHT_SEG_0 \
2697 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
2698 #define CHAN_INFO_ATTR_VHT_SEG_1 \
2699 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
2700 
2701 #define CHAN_INFO_ATTR_FREQ_VHT_SEG_0 \
2702 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2703 #define CHAN_INFO_ATTR_FREQ_VHT_SEG_1 \
2704 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2705 
2706 /**
2707  * hdd_cfg80211_update_channel_info() - add channel info attributes
2708  * @hdd_ctx: pointer to hdd context
2709  * @skb: pointer to sk buff
2710  * @sap_config: pointer to SAP configuration
2711  * @idx: attribute index
2712  *
2713  * Return: Success(0) or reason code for failure
2714  */
2715 static int32_t
2716 hdd_cfg80211_update_channel_info(struct hdd_context *hdd_ctx,
2717 				 struct sk_buff *skb,
2718 				 struct sap_config *sap_config, int idx)
2719 {
2720 	struct nlattr *nla_attr, *channel;
2721 	struct hdd_channel_info *icv;
2722 	int i;
2723 	uint32_t freq_seg_0 = 0, freq_seg_1 = 0;
2724 	enum reg_wifi_band band;
2725 	uint8_t band_mask;
2726 
2727 	nla_attr = nla_nest_start(skb, idx);
2728 	if (!nla_attr)
2729 		goto fail;
2730 
2731 	for (i = 0; i < sap_config->channel_info_count; i++) {
2732 		channel = nla_nest_start(skb, i);
2733 		if (!channel)
2734 			goto fail;
2735 
2736 		icv = &sap_config->channel_info[i];
2737 		if (!icv) {
2738 			hdd_err("channel info not found");
2739 			goto fail;
2740 		}
2741 
2742 		band = wlan_reg_freq_to_band(icv->freq);
2743 		band_mask = 1 << band;
2744 
2745 		if (icv->vht_center_freq_seg0)
2746 			freq_seg_0 = wlan_reg_chan_band_to_freq(hdd_ctx->pdev,
2747 						    icv->vht_center_freq_seg0,
2748 						    band_mask);
2749 		if (icv->vht_center_freq_seg1)
2750 			freq_seg_1 = wlan_reg_chan_band_to_freq(hdd_ctx->pdev,
2751 						    icv->vht_center_freq_seg1,
2752 						    band_mask);
2753 
2754 		if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
2755 				icv->freq) ||
2756 		    nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
2757 				icv->flags) ||
2758 		    nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
2759 				icv->flagext) ||
2760 		    nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
2761 				icv->max_reg_power) ||
2762 		    nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
2763 				icv->max_radio_power) ||
2764 		    nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
2765 				icv->min_radio_power) ||
2766 		    nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
2767 				icv->reg_class_id) ||
2768 		    nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
2769 				icv->max_antenna_gain) ||
2770 		    nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
2771 				icv->vht_center_freq_seg0) ||
2772 		    nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
2773 				icv->vht_center_freq_seg1) ||
2774 		    nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_0,
2775 				freq_seg_0) ||
2776 		    nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_1,
2777 				freq_seg_1)) {
2778 			hdd_err("put fail");
2779 			goto fail;
2780 		}
2781 		nla_nest_end(skb, channel);
2782 	}
2783 	nla_nest_end(skb, nla_attr);
2784 	return 0;
2785 fail:
2786 	hdd_err("nl channel update failed");
2787 	return -EINVAL;
2788 }
2789 #undef CHAN_INFO_ATTR_FLAGS
2790 #undef CHAN_INFO_ATTR_FLAG_EXT
2791 #undef CHAN_INFO_ATTR_FREQ
2792 #undef CHAN_INFO_ATTR_MAX_REG_POWER
2793 #undef CHAN_INFO_ATTR_MAX_POWER
2794 #undef CHAN_INFO_ATTR_MIN_POWER
2795 #undef CHAN_INFO_ATTR_REG_CLASS_ID
2796 #undef CHAN_INFO_ATTR_ANTENNA_GAIN
2797 #undef CHAN_INFO_ATTR_VHT_SEG_0
2798 #undef CHAN_INFO_ATTR_VHT_SEG_1
2799 
2800 #undef CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2801 #undef CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2802 
2803 /**
2804  * hdd_cfg80211_update_pcl() - add pcl info attributes
2805  * @hdd_ctx: pointer to hdd context
2806  * @skb: pointer to sk buff
2807  * @ch_list_count: number of channels to add
2808  * @idx: attribute index
2809  * @vendor_pcl_list: PCL list
2810  * @vendor_weight_list: PCL weights
2811  *
2812  * Return: Success(0) or reason code for failure
2813  */
2814 static int32_t
2815 hdd_cfg80211_update_pcl(struct hdd_context *hdd_ctx,
2816 			struct sk_buff *skb,
2817 			uint8_t ch_list_count, int idx,
2818 			uint32_t *vendor_pcl_list, uint8_t *vendor_weight_list)
2819 {
2820 	struct nlattr *nla_attr, *channel;
2821 	int i;
2822 	uint8_t chan;
2823 
2824 	nla_attr = nla_nest_start(skb, idx);
2825 	if (!nla_attr)
2826 		goto fail;
2827 
2828 	for (i = 0; i < ch_list_count; i++) {
2829 		channel = nla_nest_start(skb, i);
2830 		if (!channel)
2831 			goto fail;
2832 
2833 		chan = (uint8_t)wlan_reg_freq_to_chan(hdd_ctx->pdev,
2834 						      vendor_pcl_list[i]);
2835 
2836 		if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL, chan) ||
2837 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
2838 				vendor_pcl_list[i]) ||
2839 		    nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
2840 			       vendor_weight_list[i])) {
2841 			hdd_err("put fail");
2842 			goto fail;
2843 		}
2844 		nla_nest_end(skb, channel);
2845 	}
2846 	nla_nest_end(skb, nla_attr);
2847 
2848 	return 0;
2849 fail:
2850 	hdd_err("updating pcl list failed");
2851 	return -EINVAL;
2852 }
2853 
2854 static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
2855 			      struct sap_config *sap_config,
2856 			      enum band_info *band)
2857 {
2858 	/* Get scan band */
2859 	if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2860 	   (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
2861 		*band = BAND_2G;
2862 	} else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
2863 		*band = BAND_5G;
2864 	} else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
2865 		*band = BAND_ALL;
2866 	}
2867 }
2868 
2869 /**
2870  * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
2871  * @adapter: adapter
2872  * @channel_count: valid channel count
2873  * @freq_list: valid channel frequency (MHz) list
2874  * @band: frequency band
2875  *
2876  * This API returns valid channel list for SAP after removing nol and
2877  * channel which lies outside of configuration.
2878  *
2879  * Return: Zero on success, non-zero on failure
2880  */
2881 static int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
2882 					      uint32_t *channel_count,
2883 					      uint32_t *freq_list,
2884 					      enum band_info band)
2885 {
2886 	struct sap_config *sap_config;
2887 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2888 	uint32_t pcl_freqs[NUM_CHANNELS] = {0};
2889 	uint32_t chan_count;
2890 	uint32_t i;
2891 	QDF_STATUS status;
2892 	struct wlan_objmgr_pdev *pdev = hdd_ctx->pdev;
2893 
2894 	sap_config = &adapter->deflink->session.ap.sap_config;
2895 
2896 	status = policy_mgr_get_valid_chans(hdd_ctx->psoc,
2897 					    pcl_freqs,
2898 					    &chan_count);
2899 	if (QDF_IS_STATUS_ERROR(status)) {
2900 		hdd_err("Failed to get channel list");
2901 		return -EINVAL;
2902 	}
2903 
2904 	*channel_count = 0;
2905 	for (i = 0; i < chan_count; i++) {
2906 		if (*channel_count >= NUM_CHANNELS)
2907 			break;
2908 
2909 		if (band == BAND_2G &&
2910 		    WLAN_REG_IS_24GHZ_CH_FREQ(pcl_freqs[i]) &&
2911 		    !wlan_reg_is_disable_for_pwrmode(pdev, pcl_freqs[i],
2912 						     REG_CURRENT_PWR_MODE)) {
2913 			freq_list[*channel_count] = pcl_freqs[i];
2914 			*channel_count += 1;
2915 		} else if (band == BAND_5G &&
2916 			   (WLAN_REG_IS_5GHZ_CH_FREQ(pcl_freqs[i]) ||
2917 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(pcl_freqs[i])) &&
2918 			   !wlan_reg_is_disable_for_pwrmode(
2919 							pdev, pcl_freqs[i],
2920 							REG_CURRENT_PWR_MODE)) {
2921 			freq_list[*channel_count] = pcl_freqs[i];
2922 			*channel_count += 1;
2923 		}
2924 	}
2925 
2926 	if (*channel_count == 0) {
2927 		hdd_err("no valid channel found");
2928 		return -EINVAL;
2929 	}
2930 
2931 	return 0;
2932 }
2933 
2934 /**
2935  * hdd_get_external_acs_event_len() - Get event buffer length for external ACS
2936  * @channel_count: number of channels for ACS operation
2937  *
2938  * Return: External ACS event (SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG) buffer length.
2939  */
2940 static int hdd_get_external_acs_event_len(uint32_t channel_count)
2941 {
2942 	uint32_t len = NLMSG_HDRLEN;
2943 	uint32_t i;
2944 
2945 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON */
2946 	len += nla_total_size(sizeof(u8));
2947 
2948 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED */
2949 	len += nla_total_size(sizeof(u32));
2950 
2951 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT */
2952 	len += nla_total_size(sizeof(u32));
2953 
2954 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH */
2955 	len += nla_total_size(sizeof(u8));
2956 
2957 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND */
2958 	len += nla_total_size(sizeof(u8));
2959 
2960 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE */
2961 	len += nla_total_size(sizeof(u32));
2962 
2963 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST */
2964 	len += nla_total_size(channel_count * sizeof(u32));
2965 
2966 	for (i = 0; i < channel_count; i++) {
2967 		/* QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL */
2968 		len += nla_total_size(sizeof(u8));
2969 
2970 		/* QCA_WLAN_VENDOR_ATTR_PCL_FREQ */
2971 		len += nla_total_size(sizeof(u32));
2972 
2973 		/* QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT */
2974 		len += nla_total_size(sizeof(u8));
2975 	}
2976 
2977 	for (i = 0; i < channel_count; i++) {
2978 		/* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ */
2979 		len += nla_total_size(sizeof(u16));
2980 
2981 		/* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS */
2982 		len += nla_total_size(sizeof(u32));
2983 
2984 		/* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT */
2985 		len += nla_total_size(sizeof(u32));
2986 
2987 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER */
2988 		len += nla_total_size(sizeof(u8));
2989 
2990 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER */
2991 		len += nla_total_size(sizeof(u8));
2992 
2993 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER */
2994 		len += nla_total_size(sizeof(u8));
2995 
2996 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID */
2997 		len += nla_total_size(sizeof(u8));
2998 
2999 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN */
3000 		len += nla_total_size(sizeof(u8));
3001 
3002 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 */
3003 		len += nla_total_size(sizeof(u8));
3004 
3005 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 */
3006 		len += nla_total_size(sizeof(u8));
3007 
3008 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 */
3009 		len += nla_total_size(sizeof(u32));
3010 
3011 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 */
3012 		len += nla_total_size(sizeof(u32));
3013 	}
3014 
3015 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY */
3016 	len += nla_total_size(sizeof(u32));
3017 
3018 	return len;
3019 }
3020 
3021 int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
3022 				   uint8_t reason)
3023 {
3024 	struct sk_buff *skb = NULL;
3025 	struct sap_config *sap_config;
3026 	uint32_t channel_count = 0, status = -EINVAL;
3027 	uint32_t *freq_list;
3028 	uint32_t vendor_pcl_list[NUM_CHANNELS] = {0};
3029 	uint8_t vendor_weight_list[NUM_CHANNELS] = {0};
3030 	struct hdd_vendor_acs_chan_params acs_chan_params;
3031 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3032 	enum band_info band = BAND_2G;
3033 	eCsrPhyMode phy_mode;
3034 	enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
3035 	uint32_t i, id;
3036 	QDF_STATUS qdf_status;
3037 	bool is_external_acs_policy = cfg_default(CFG_EXTERNAL_ACS_POLICY);
3038 	uint32_t len;
3039 
3040 	if (!hdd_ctx) {
3041 		hdd_err("HDD context is NULL");
3042 		return -EINVAL;
3043 	}
3044 
3045 	hdd_enter();
3046 	sap_config = &adapter->deflink->session.ap.sap_config;
3047 	/* When first 2 connections are on the same frequency band,
3048 	 * then PCL would include only channels from the other
3049 	 * frequency band on which no connections are active
3050 	 */
3051 	if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
3052 	    (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
3053 		struct policy_mgr_conc_connection_info	*conc_connection_info;
3054 
3055 		conc_connection_info = policy_mgr_get_conn_info(&i);
3056 		if (policy_mgr_are_2_freq_on_same_mac(hdd_ctx->psoc,
3057 			conc_connection_info[0].freq,
3058 			conc_connection_info[1].freq)) {
3059 			if (!WLAN_REG_IS_24GHZ_CH_FREQ(
3060 				sap_config->acs_cfg.pcl_chan_freq[0])) {
3061 				sap_config->acs_cfg.band =
3062 					QCA_ACS_MODE_IEEE80211A;
3063 				hdd_update_acs_channel_list(sap_config,
3064 					BAND_5G);
3065 			} else {
3066 				sap_config->acs_cfg.band =
3067 					QCA_ACS_MODE_IEEE80211G;
3068 				hdd_update_acs_channel_list(sap_config,
3069 					BAND_2G);
3070 			}
3071 		}
3072 	}
3073 
3074 	hdd_get_scan_band(hdd_ctx, &adapter->deflink->session.ap.sap_config,
3075 			  &band);
3076 
3077 	freq_list = qdf_mem_malloc(sizeof(uint32_t) * NUM_CHANNELS);
3078 	if (!freq_list)
3079 		return -ENOMEM;
3080 
3081 	if (sap_config->acs_cfg.freq_list) {
3082 		/* Copy INI or hostapd provided ACS channel range*/
3083 		for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
3084 			freq_list[i] = sap_config->acs_cfg.freq_list[i];
3085 		channel_count = sap_config->acs_cfg.ch_list_count;
3086 	} else {
3087 		/* No channel list provided, copy all valid channels */
3088 		wlan_hdd_sap_get_valid_channellist(adapter,
3089 			&channel_count,
3090 			freq_list,
3091 			band);
3092 	}
3093 
3094 	sap_config->channel_info = qdf_mem_malloc(
3095 					sizeof(struct hdd_channel_info) *
3096 					channel_count);
3097 	if (!sap_config->channel_info) {
3098 		status = -ENOMEM;
3099 		goto fail;
3100 	}
3101 
3102 	hdd_update_reg_chan_info(adapter, channel_count, freq_list);
3103 
3104 	/* Get phymode */
3105 	phy_mode = adapter->deflink->session.ap.sap_config.acs_cfg.hw_mode;
3106 
3107 	len = hdd_get_external_acs_event_len(channel_count);
3108 	id = QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG;
3109 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, &adapter->wdev,
3110 					       len, id, GFP_KERNEL);
3111 	if (!skb) {
3112 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
3113 		status = -ENOMEM;
3114 		goto fail;
3115 	}
3116 	/*
3117 	 * Application expects pcl to be a subset of channel list
3118 	 * Remove all channels which are not in channel list from pcl
3119 	 * and add weight as zero
3120 	 */
3121 	acs_chan_params.vendor_pcl_list = vendor_pcl_list;
3122 	acs_chan_params.vendor_weight_list = vendor_weight_list;
3123 
3124 	hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
3125 				   sap_config);
3126 
3127 	if (acs_chan_params.pcl_count) {
3128 		hdd_debug("ACS PCL list: len: %d",
3129 			  acs_chan_params.pcl_count);
3130 		for (i = 0; i < acs_chan_params.pcl_count; i++)
3131 			hdd_debug("channel_frequency: %u, weight: %u",
3132 				  acs_chan_params.
3133 				  vendor_pcl_list[i],
3134 				  acs_chan_params.
3135 				  vendor_weight_list[i]);
3136 	}
3137 
3138 	qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
3139 						       &is_external_acs_policy);
3140 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3141 		hdd_err("get_external_acs_policy failed, set default");
3142 
3143 	if (is_external_acs_policy) {
3144 		acs_policy =
3145 			QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
3146 	} else {
3147 		acs_policy =
3148 			QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
3149 	}
3150 	/* Update values in NL buffer */
3151 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
3152 		       reason) ||
3153 	    nla_put_flag(skb,
3154 		QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
3155 	    nla_put_flag(skb,
3156 		QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
3157 		||
3158 	    nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
3159 		       sap_config->acs_cfg.ch_width) ||
3160 	    nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
3161 		       band) ||
3162 	    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
3163 		       phy_mode) ||
3164 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
3165 		    channel_count * sizeof(uint32_t), freq_list)) {
3166 		hdd_err("nla put fail");
3167 		goto fail;
3168 	}
3169 	status =
3170 	hdd_cfg80211_update_pcl(hdd_ctx, skb,
3171 				acs_chan_params.pcl_count,
3172 				QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
3173 				vendor_pcl_list,
3174 				vendor_weight_list);
3175 
3176 	if (status != 0)
3177 		goto fail;
3178 
3179 	id = QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO;
3180 
3181 	status = hdd_cfg80211_update_channel_info(hdd_ctx, skb, sap_config, id);
3182 	if (status != 0)
3183 		goto fail;
3184 
3185 	status = nla_put_u32(skb,
3186 			     QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
3187 			     acs_policy);
3188 
3189 	if (status != 0)
3190 		goto fail;
3191 
3192 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
3193 	qdf_mem_free(freq_list);
3194 	qdf_mem_free(sap_config->channel_info);
3195 
3196 	return 0;
3197 fail:
3198 	qdf_mem_free(freq_list);
3199 	if (sap_config->channel_info)
3200 		qdf_mem_free(sap_config->channel_info);
3201 	wlan_cfg80211_vendor_free_skb(skb);
3202 	return status;
3203 }
3204 
3205 /**
3206  * hdd_create_acs_timer(): Initialize vendor ACS timer
3207  * @adapter: pointer to SAP adapter struct
3208  *
3209  * This function initializes the vendor ACS timer.
3210  *
3211  * Return: Status of create vendor ACS timer
3212  */
3213 static int hdd_create_acs_timer(struct hdd_adapter *adapter)
3214 {
3215 	struct hdd_external_acs_timer_context *timer_context;
3216 	QDF_STATUS status;
3217 
3218 	if (adapter->deflink->session.ap.vendor_acs_timer_initialized)
3219 		return 0;
3220 
3221 	hdd_debug("Starting vendor app based ACS");
3222 	timer_context = qdf_mem_malloc(sizeof(*timer_context));
3223 	if (!timer_context)
3224 		return -ENOMEM;
3225 
3226 	timer_context->adapter = adapter;
3227 
3228 	set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->deflink->link_flags);
3229 	status = qdf_mc_timer_init(
3230 		  &adapter->deflink->session.ap.vendor_acs_timer,
3231 		  QDF_TIMER_TYPE_SW,
3232 		  hdd_acs_response_timeout_handler, timer_context);
3233 	if (status != QDF_STATUS_SUCCESS) {
3234 		hdd_err("Failed to initialize acs response timeout timer");
3235 		return -EFAULT;
3236 	}
3237 	adapter->deflink->session.ap.vendor_acs_timer_initialized = true;
3238 	return 0;
3239 }
3240 
3241 static const struct nla_policy
3242 wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1] = {
3243 	[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
3244 	[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
3245 	[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
3246 	[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
3247 	[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
3248 	[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_BINARY,
3249 				.len = sizeof(NLA_U8) * NUM_CHANNELS },
3250 	[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_BINARY,
3251 				.len = sizeof(NLA_U32) * NUM_CHANNELS },
3252 	[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED] = { .type = NLA_FLAG },
3253 	[QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP] = { .type = NLA_U16 },
3254 	[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED] = { .type = NLA_FLAG },
3255 	[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL] = { .type = NLA_U8 },
3256 	[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME] = { .type = NLA_U32 },
3257 };
3258 
3259 int hdd_start_vendor_acs(struct hdd_adapter *adapter)
3260 {
3261 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3262 	int status;
3263 	QDF_STATUS qdf_status;
3264 	bool is_acs_support_for_dfs_ltecoex = cfg_default(CFG_USER_ACS_DFS_LTE);
3265 
3266 	status = hdd_create_acs_timer(adapter);
3267 	if (status != 0) {
3268 		hdd_err("failed to create acs timer");
3269 		return status;
3270 	}
3271 	status = hdd_update_acs_timer_reason(adapter,
3272 		QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
3273 	if (status != 0) {
3274 		hdd_err("failed to update acs timer reason");
3275 		return status;
3276 	}
3277 	qdf_status = ucfg_mlme_get_acs_support_for_dfs_ltecoex(
3278 				hdd_ctx->psoc,
3279 				&is_acs_support_for_dfs_ltecoex);
3280 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3281 		hdd_err("get_acs_support_for_dfs_ltecoex failed, set def");
3282 
3283 	if (is_acs_support_for_dfs_ltecoex)
3284 		status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
3285 				WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
3286 				true));
3287 	else
3288 		status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
3289 				WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
3290 				false));
3291 
3292 	return status;
3293 }
3294 
3295 /**
3296  * hdd_avoid_acs_channels() - Avoid acs channels
3297  * @hdd_ctx: Pointer to the hdd context
3298  * @sap_config: Sap config structure pointer
3299  *
3300  * This function avoids channels from the acs corresponding to
3301  * the frequencies configured in the ini sap_avoid_acs_freq_list
3302  *
3303  * Return: None
3304  */
3305 
3306 #ifdef SAP_AVOID_ACS_FREQ_LIST
3307 static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
3308 				   struct sap_config *sap_config)
3309 {
3310 	int i, j, ch_cnt = 0;
3311 	uint16_t avoid_acs_freq_list[CFG_VALID_CHANNEL_LIST_LEN];
3312 	uint8_t avoid_acs_freq_list_num;
3313 
3314 	ucfg_mlme_get_acs_avoid_freq_list(hdd_ctx->psoc,
3315 					  avoid_acs_freq_list,
3316 					  &avoid_acs_freq_list_num);
3317 
3318 	for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
3319 		for (j = 0; j < avoid_acs_freq_list_num; j++) {
3320 			if (sap_config->acs_cfg.freq_list[i] ==
3321 						avoid_acs_freq_list[j]) {
3322 				hdd_debug("skip freq %d",
3323 					  sap_config->acs_cfg.freq_list[i]);
3324 				break;
3325 			}
3326 		}
3327 		if (j == avoid_acs_freq_list_num)
3328 			sap_config->acs_cfg.freq_list[ch_cnt++] =
3329 					sap_config->acs_cfg.freq_list[i];
3330 	}
3331 	sap_config->acs_cfg.ch_list_count = ch_cnt;
3332 }
3333 #else
3334 static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
3335 				   struct sap_config *sap_config)
3336 {
3337 }
3338 #endif
3339 
3340 void wlan_hdd_trim_acs_channel_list(uint32_t *pcl, uint8_t pcl_count,
3341 				    uint32_t *org_freq_list,
3342 				    uint8_t *org_ch_list_count)
3343 {
3344 	uint16_t i, j, ch_list_count = 0;
3345 
3346 	if (*org_ch_list_count >= NUM_CHANNELS) {
3347 		hdd_err("org_ch_list_count too big %d",
3348 			*org_ch_list_count);
3349 		return;
3350 	}
3351 
3352 	if (pcl_count >= NUM_CHANNELS) {
3353 		hdd_err("pcl_count is too big %d", pcl_count);
3354 		return;
3355 	}
3356 
3357 	hdd_debug("Update ACS chan freq with PCL");
3358 	for (j = 0; j < *org_ch_list_count; j++)
3359 		for (i = 0; i < pcl_count; i++)
3360 			if (pcl[i] == org_freq_list[j]) {
3361 				org_freq_list[ch_list_count++] = pcl[i];
3362 				break;
3363 			}
3364 
3365 	*org_ch_list_count = ch_list_count;
3366 }
3367 
3368 /* wlan_hdd_dump_freq_list() - Dump the ACS master frequency list
3369  *
3370  * @freq_list: Frequency list
3371  * @num_freq: num of frequencies in list
3372  *
3373  * Dump the ACS master frequency list.
3374  */
3375 static inline
3376 void wlan_hdd_dump_freq_list(uint32_t *freq_list, uint8_t num_freq)
3377 {
3378 	uint32_t buf_len = 0;
3379 	uint32_t i = 0, j = 0;
3380 	uint8_t *master_chlist;
3381 
3382 	if (num_freq >= NUM_CHANNELS)
3383 		return;
3384 
3385 	buf_len = NUM_CHANNELS * 4;
3386 	master_chlist = qdf_mem_malloc(buf_len);
3387 
3388 	if (!master_chlist)
3389 		return;
3390 
3391 	for (i = 0; i < num_freq && j < buf_len; i++) {
3392 		j += qdf_scnprintf(master_chlist + j, buf_len - j,
3393 				   "%d ", freq_list[i]);
3394 	}
3395 
3396 	hdd_debug("Master channel list: %s", master_chlist);
3397 	qdf_mem_free(master_chlist);
3398 }
3399 
3400 void wlan_hdd_handle_zero_acs_list(struct hdd_context *hdd_ctx,
3401 				   uint32_t *acs_freq_list,
3402 				   uint8_t *acs_ch_list_count,
3403 				   uint32_t *org_freq_list,
3404 				   uint8_t org_ch_list_count)
3405 {
3406 	uint16_t i, sta_count;
3407 	uint32_t acs_chan_default = 0, acs_dfs_chan = 0;
3408 	bool force_sap_allowed = false;
3409 	enum channel_state state;
3410 
3411 	if (!acs_ch_list_count || *acs_ch_list_count > 0 ||
3412 	    !acs_freq_list) {
3413 		return;
3414 	}
3415 	if (!org_ch_list_count || !org_freq_list)
3416 		return;
3417 
3418 	if (!policy_mgr_is_force_scc(hdd_ctx->psoc))
3419 		return;
3420 	sta_count = policy_mgr_mode_specific_connection_count
3421 			(hdd_ctx->psoc, PM_STA_MODE, NULL);
3422 	sta_count += policy_mgr_mode_specific_connection_count
3423 			(hdd_ctx->psoc, PM_P2P_CLIENT_MODE, NULL);
3424 
3425 	ucfg_mlme_get_force_sap_enabled(hdd_ctx->psoc, &force_sap_allowed);
3426 	if (!sta_count && !force_sap_allowed)
3427 		return;
3428 
3429 	wlan_hdd_dump_freq_list(org_freq_list, org_ch_list_count);
3430 
3431 	for (i = 0; i < org_ch_list_count; i++) {
3432 		state = wlan_reg_get_channel_state_for_pwrmode(
3433 				hdd_ctx->pdev, org_freq_list[i],
3434 				REG_CURRENT_PWR_MODE);
3435 		if (state == CHANNEL_STATE_DISABLE ||
3436 		    state == CHANNEL_STATE_INVALID)
3437 			continue;
3438 
3439 		if (wlan_reg_is_6ghz_chan_freq(org_freq_list[i]) &&
3440 		    !wlan_reg_is_6ghz_psc_chan_freq(org_freq_list[i]))
3441 			continue;
3442 
3443 		if (!policy_mgr_is_safe_channel(hdd_ctx->psoc,
3444 						org_freq_list[i]))
3445 			continue;
3446 		/* Make dfs channel as last choice */
3447 		if (state == CHANNEL_STATE_DFS ||
3448 		    state == CHANNEL_STATE_PASSIVE) {
3449 			acs_dfs_chan = org_freq_list[i];
3450 			continue;
3451 		}
3452 		acs_chan_default = org_freq_list[i];
3453 		break;
3454 	}
3455 	if (!acs_chan_default) {
3456 		if (acs_dfs_chan)
3457 			acs_chan_default = acs_dfs_chan;
3458 		else
3459 			acs_chan_default = org_freq_list[0];
3460 	}
3461 
3462 	acs_freq_list[0] = acs_chan_default;
3463 	*acs_ch_list_count = 1;
3464 	hdd_debug("restore acs chan list to single freq %d", acs_chan_default);
3465 }
3466 
3467 /**
3468  * wlan_hdd_handle_single_ch_in_acs_list() - Handle acs list with single channel
3469  * @link_info: Link info pointer in HDD adapter
3470  *
3471  * If only one acs channel is left after filter, driver will return the channel
3472  * to hostapd without ACS scan.
3473  *
3474  * Return: None
3475  */
3476 static void
3477 wlan_hdd_handle_single_ch_in_acs_list(struct wlan_hdd_link_info *link_info)
3478 {
3479 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
3480 	uint32_t channel_bonding_mode_2g;
3481 	struct sap_config *sap_config;
3482 
3483 	sap_config = &link_info->session.ap.sap_config;
3484 	ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
3485 					    &channel_bonding_mode_2g);
3486 	sap_config->acs_cfg.start_ch_freq =
3487 		sap_config->acs_cfg.freq_list[0];
3488 	sap_config->acs_cfg.end_ch_freq =
3489 		sap_config->acs_cfg.freq_list[0];
3490 	sap_config->acs_cfg.pri_ch_freq =
3491 			      sap_config->acs_cfg.freq_list[0];
3492 	if (sap_config->acs_cfg.pri_ch_freq <=
3493 	    WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484) &&
3494 	    sap_config->acs_cfg.ch_width >=
3495 				CH_WIDTH_40MHZ &&
3496 	    !channel_bonding_mode_2g) {
3497 		sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
3498 		hdd_debug("2.4ghz channel resetting BW to %d 2.4 cbmode %d",
3499 			  sap_config->acs_cfg.ch_width,
3500 			  channel_bonding_mode_2g);
3501 	}
3502 
3503 	wlan_sap_set_sap_ctx_acs_cfg(
3504 		WLAN_HDD_GET_SAP_CTX_PTR(link_info), sap_config);
3505 	sap_config_acs_result(hdd_ctx->mac_handle,
3506 			      WLAN_HDD_GET_SAP_CTX_PTR(link_info),
3507 			    sap_config->acs_cfg.ht_sec_ch_freq);
3508 	sap_config->ch_params.ch_width =
3509 			sap_config->acs_cfg.ch_width;
3510 	sap_config->ch_params.sec_ch_offset =
3511 			wlan_reg_freq_to_chan(
3512 			hdd_ctx->pdev,
3513 			sap_config->acs_cfg.ht_sec_ch_freq);
3514 	sap_config->ch_params.center_freq_seg0 =
3515 	wlan_reg_freq_to_chan(
3516 		hdd_ctx->pdev,
3517 		sap_config->acs_cfg.vht_seg0_center_ch_freq);
3518 	sap_config->ch_params.center_freq_seg1 =
3519 	wlan_reg_freq_to_chan(
3520 		hdd_ctx->pdev,
3521 		sap_config->acs_cfg.vht_seg1_center_ch_freq);
3522 	sap_config->ch_params.mhz_freq_seg0 =
3523 		sap_config->acs_cfg.vht_seg0_center_ch_freq;
3524 	sap_config->ch_params.mhz_freq_seg1 =
3525 		sap_config->acs_cfg.vht_seg1_center_ch_freq;
3526 	/*notify hostapd about channel override */
3527 	wlan_hdd_cfg80211_acs_ch_select_evt(link_info, true);
3528 	wlansap_dcs_set_wlan_interference_mitigation_on_band(
3529 		WLAN_HDD_GET_SAP_CTX_PTR(link_info),
3530 		sap_config);
3531 }
3532 
3533 #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC)
3534 static void wlan_hdd_set_sap_acs_ch_width_320(struct sap_config *sap_config)
3535 {
3536 	sap_config->acs_cfg.ch_width = CH_WIDTH_320MHZ;
3537 }
3538 
3539 static bool wlan_hdd_is_sap_acs_ch_width_320(struct sap_config *sap_config)
3540 {
3541 	return sap_config->acs_cfg.ch_width == CH_WIDTH_320MHZ;
3542 }
3543 
3544 static void wlan_hdd_set_chandef(struct wlan_objmgr_vdev *vdev,
3545 				 struct cfg80211_chan_def *chandef)
3546 {
3547 	if (vdev->vdev_mlme.des_chan->ch_width != CH_WIDTH_320MHZ)
3548 		return;
3549 
3550 	chandef->width = NL80211_CHAN_WIDTH_320;
3551 	/* Set center_freq1 to center frequency of complete 320MHz */
3552 	chandef->center_freq1 = vdev->vdev_mlme.des_chan->ch_cfreq2;
3553 }
3554 #else /* !WLAN_FEATURE_11BE */
3555 static inline
3556 void wlan_hdd_set_sap_acs_ch_width_320(struct sap_config *sap_config)
3557 {
3558 }
3559 
3560 static inline
3561 bool wlan_hdd_is_sap_acs_ch_width_320(struct sap_config *sap_config)
3562 {
3563 	return false;
3564 }
3565 
3566 static inline void wlan_hdd_set_chandef(struct wlan_objmgr_vdev *vdev,
3567 					struct cfg80211_chan_def *chandef)
3568 {
3569 }
3570 #endif /* WLAN_FEATURE_11BE */
3571 
3572 #ifdef WLAN_FEATURE_11BE
3573 /**
3574  * wlan_hdd_acs_set_eht_enabled() - set is_eht_enabled of acs config
3575  * @sap_config: pointer to sap_config
3576  * @eht_enabled: eht is enabled
3577  *
3578  * Return: void
3579  */
3580 static void wlan_hdd_acs_set_eht_enabled(struct sap_config *sap_config,
3581 					 bool eht_enabled)
3582 {
3583 	if (!sap_config) {
3584 		hdd_err("Invalid sap_config");
3585 		return;
3586 	}
3587 
3588 	sap_config->acs_cfg.is_eht_enabled = eht_enabled;
3589 }
3590 #else
3591 static void wlan_hdd_acs_set_eht_enabled(struct sap_config *sap_config,
3592 					 bool eht_enabled)
3593 {
3594 }
3595 #endif /* WLAN_FEATURE_11BE */
3596 
3597 static uint16_t wlan_hdd_update_bw_from_mlme(struct hdd_context *hdd_ctx,
3598 					     struct sap_config *sap_config)
3599 {
3600 	uint16_t ch_width, temp_ch_width = 0;
3601 	QDF_STATUS status;
3602 	uint8_t hw_mode = HW_MODE_DBS;
3603 	struct wma_caps_per_phy caps_per_phy = {0};
3604 
3605 	ch_width = sap_config->acs_cfg.ch_width;
3606 
3607 	if (ch_width > CH_WIDTH_80P80MHZ)
3608 		return ch_width;
3609 
3610 	/* 2.4ghz is already handled for acs */
3611 	if (sap_config->acs_cfg.end_ch_freq <=
3612 	    WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484))
3613 		return ch_width;
3614 
3615 	if (!policy_mgr_is_dbs_enable(hdd_ctx->psoc))
3616 		hw_mode = HW_MODE_DBS_NONE;
3617 
3618 	status = wma_get_caps_for_phyidx_hwmode(&caps_per_phy, hw_mode,
3619 						CDS_BAND_5GHZ);
3620 	if (!QDF_IS_STATUS_SUCCESS(status))
3621 		return ch_width;
3622 
3623 	switch (ch_width) {
3624 	case CH_WIDTH_80P80MHZ:
3625 		if (!(caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ))
3626 		{
3627 			if (caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_160MHZ)
3628 				temp_ch_width = CH_WIDTH_160MHZ;
3629 			else
3630 				temp_ch_width = CH_WIDTH_80MHZ;
3631 		}
3632 		break;
3633 	case CH_WIDTH_160MHZ:
3634 		if (!((caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
3635 		      || (caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_160MHZ)))
3636 				temp_ch_width = CH_WIDTH_80MHZ;
3637 		break;
3638 	default:
3639 		break;
3640 	}
3641 
3642 	if (!temp_ch_width)
3643 		return ch_width;
3644 
3645 	hdd_debug("ch_width updated from %d to %d vht_5g: %x", ch_width,
3646 		  temp_ch_width, caps_per_phy.vht_5g);
3647 	return temp_ch_width;
3648 }
3649 
3650 /**
3651  *  wlan_hdd_check_is_acs_request_same() - API to compare ongoing ACS and
3652  *					current received ACS request
3653  * @adapter: hdd adapter
3654  * @data: ACS data
3655  * @data_len: ACS data length
3656  *
3657  * This function is used to compare ongoing ACS params with current received
3658  * ACS request on same interface.
3659  *
3660  * Return: true only if ACS request received is same as ongoing ACS
3661  */
3662 static bool wlan_hdd_check_is_acs_request_same(struct hdd_adapter *adapter,
3663 					       const void *data, int data_len)
3664 {
3665 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
3666 	uint8_t hw_mode, ht_enabled, ht40_enabled, vht_enabled, eht_enabled;
3667 	struct sap_config *sap_config;
3668 	uint32_t last_scan_ageout_time = 0;
3669 	uint8_t ch_list_count;
3670 	uint16_t ch_width;
3671 	int ret, i, j;
3672 	struct wlan_objmgr_psoc *psoc;
3673 
3674 	ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
3675 				      data_len,
3676 				      wlan_hdd_cfg80211_do_acs_policy);
3677 	if (ret) {
3678 		hdd_err("Invalid ATTR");
3679 		return false;
3680 	}
3681 
3682 	if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE])
3683 		return false;
3684 
3685 	sap_config = &adapter->deflink->session.ap.sap_config;
3686 
3687 	hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
3688 	if (sap_config->acs_cfg.master_acs_cfg.hw_mode != hw_mode)
3689 		return false;
3690 
3691 	ht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
3692 	if (sap_config->acs_cfg.master_acs_cfg.ht != ht_enabled)
3693 		return false;
3694 
3695 	ht40_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
3696 	if (sap_config->acs_cfg.master_acs_cfg.ht40 != ht40_enabled)
3697 		return false;
3698 
3699 	vht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
3700 	if (sap_config->acs_cfg.master_acs_cfg.vht != vht_enabled)
3701 		return false;
3702 
3703 	eht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED]);
3704 	if (sap_config->acs_cfg.master_acs_cfg.eht != eht_enabled)
3705 		return false;
3706 
3707 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH])
3708 		ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
3709 	else
3710 		ch_width = 0;
3711 	if (sap_config->acs_cfg.master_acs_cfg.ch_width != ch_width)
3712 		return false;
3713 
3714 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME]) {
3715 		last_scan_ageout_time =
3716 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME]);
3717 	} else {
3718 		psoc = wlan_vdev_get_psoc(adapter->deflink->vdev);
3719 		if (psoc)
3720 			wlan_scan_get_last_scan_ageout_time(
3721 							psoc,
3722 							&last_scan_ageout_time);
3723 	}
3724 	if (sap_config->acs_cfg.last_scan_ageout_time != last_scan_ageout_time)
3725 		return false;
3726 
3727 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
3728 		uint32_t *freq =
3729 			nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
3730 
3731 		ch_list_count = nla_len(
3732 				tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
3733 				sizeof(uint32_t);
3734 		if (sap_config->acs_cfg.master_ch_list_count != ch_list_count)
3735 			return false;
3736 		for (i = 0; i < ch_list_count; i++) {
3737 			j = 0;
3738 			while (j < ch_list_count && freq[i] !=
3739 			       sap_config->acs_cfg.master_freq_list[j])
3740 				j++;
3741 			if (j == ch_list_count)
3742 				return false;
3743 		}
3744 	} else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
3745 		uint8_t *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3746 
3747 		ch_list_count = nla_len(
3748 					tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3749 		if (sap_config->acs_cfg.master_ch_list_count != ch_list_count)
3750 			return false;
3751 		for (i = 0; i < ch_list_count; i++) {
3752 			j = 0;
3753 			while (j < ch_list_count &&
3754 			       wlan_reg_legacy_chan_to_freq(
3755 			       adapter->hdd_ctx->pdev, tmp[i]) !=
3756 			       sap_config->acs_cfg.master_freq_list[j])
3757 				j++;
3758 			if (j == ch_list_count)
3759 				return false;
3760 		}
3761 	}
3762 
3763 	return true;
3764 }
3765 
3766 #ifndef WLAN_FEATURE_LL_LT_SAP
3767 /**
3768  * hdd_remove_passive_dfs_acs_channel_for_ll_sap(): Remove passive/dfs channel
3769  * for LL SAP
3770  * @sap_config: Pointer to sap_config
3771  * @psoc: Pointer to psoc
3772  * @pdev: Pointer to pdev
3773  * @vdev_id: Vdev Id
3774  *
3775  * This function will remove passive/dfs acs channel for low latency SAP
3776  * which are configured through userspace.
3777  *
3778  * Return: void
3779  */
3780 static void hdd_remove_passive_dfs_acs_channel_for_ll_sap(
3781 					struct sap_config *sap_config,
3782 					struct wlan_objmgr_psoc *psoc,
3783 					struct wlan_objmgr_pdev *pdev,
3784 					uint8_t vdev_id)
3785 {
3786 	uint32_t i, ch_cnt = 0;
3787 	uint32_t freq = 0;
3788 
3789 	if (!policy_mgr_is_vdev_ll_sap(psoc, vdev_id))
3790 		return;
3791 
3792 	for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
3793 		freq = sap_config->acs_cfg.freq_list[i];
3794 
3795 		/* Remove passive/dfs channel for LL SAP */
3796 		if (wlan_reg_is_passive_for_freq(pdev, freq) ||
3797 		    wlan_reg_is_dfs_for_freq(pdev, freq))
3798 			continue;
3799 
3800 		sap_config->acs_cfg.freq_list[ch_cnt++] = freq;
3801 	}
3802 
3803 	if (ch_cnt != sap_config->acs_cfg.ch_list_count) {
3804 		hdd_debug("New count after modification %d", ch_cnt);
3805 		sap_config->acs_cfg.ch_list_count = ch_cnt;
3806 		sap_dump_acs_channel(&sap_config->acs_cfg);
3807 	}
3808 }
3809 #else
3810 static inline void
3811 hdd_remove_passive_dfs_acs_channel_for_ll_sap(struct sap_config *sap_config,
3812 					      struct wlan_objmgr_psoc *psoc,
3813 					      struct wlan_objmgr_pdev *pdev,
3814 					      uint8_t vdev_id)
3815 {
3816 }
3817 #endif
3818 
3819 /* Stored ACS Frequency timeout in msec */
3820 #define STORED_ACS_FREQ_TIMEOUT 500
3821 static bool
3822 wlan_hdd_is_prev_acs_freq_present_in_acs_config(struct sap_config *sap_cfg)
3823 {
3824 	uint32_t i = 0;
3825 	bool prev_acs_freq_found = false;
3826 
3827 	if (!qdf_system_time_before(
3828 		qdf_get_time_of_the_day_ms(),
3829 		sap_cfg->last_acs_complete_time + STORED_ACS_FREQ_TIMEOUT))
3830 		return prev_acs_freq_found;
3831 
3832 	for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
3833 		if (sap_cfg->acs_cfg.freq_list[i] == sap_cfg->last_acs_freq) {
3834 			prev_acs_freq_found = true;
3835 			break;
3836 		}
3837 	}
3838 
3839 	return prev_acs_freq_found;
3840 }
3841 
3842 static bool
3843 wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(struct hdd_adapter *adapter)
3844 {
3845 	struct hdd_context *hdd_ctx;
3846 	struct sap_config *sap_config;
3847 	int status;
3848 	bool prev_acs_freq_valid = false;
3849 	struct sap_context *sap_ctx;
3850 
3851 	if (!adapter) {
3852 		hdd_err("adapter is NULL");
3853 		return prev_acs_freq_valid;
3854 	}
3855 
3856 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3857 	status = wlan_hdd_validate_context(hdd_ctx);
3858 	if (0 != status) {
3859 		hdd_err("Invalid HDD context");
3860 		return prev_acs_freq_valid;
3861 	}
3862 
3863 	sap_config = &adapter->deflink->session.ap.sap_config;
3864 	if (!sap_config) {
3865 		hdd_err("SAP config is NULL");
3866 		return prev_acs_freq_valid;
3867 	}
3868 
3869 	if (!sap_config->last_acs_freq || !sap_config->last_acs_complete_time)
3870 		return prev_acs_freq_valid;
3871 
3872 	if (!policy_mgr_is_vdev_ll_lt_sap(
3873 				hdd_ctx->psoc,
3874 				adapter->deflink->vdev_id))
3875 		return prev_acs_freq_valid;
3876 
3877 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink);
3878 	if (wlan_hdd_is_prev_acs_freq_present_in_acs_config(sap_config)) {
3879 		wlansap_update_ll_lt_sap_acs_result(sap_ctx,
3880 						    sap_config->last_acs_freq);
3881 
3882 		hdd_debug("vdev %d, return prev ACS freq %d stored at %lu, current time %lu",
3883 			  adapter->deflink->vdev_id, sap_config->last_acs_freq,
3884 			  sap_config->last_acs_complete_time,
3885 			  qdf_get_time_of_the_day_ms());
3886 
3887 		/* Notify to hostapd without storing the last acs frequency.
3888 		 * Reason for not storing the last acs frequency is to avoid
3889 		 * storing the same freq again and again
3890 		 */
3891 		wlan_hdd_cfg80211_acs_ch_select_evt(adapter->deflink, false);
3892 		wlansap_dcs_set_wlan_interference_mitigation_on_band(sap_ctx,
3893 								    sap_config);
3894 
3895 		prev_acs_freq_valid = true;
3896 	}
3897 
3898 	return prev_acs_freq_valid;
3899 }
3900 
3901 /**
3902  * hdd_remove_6ghz_freq_from_acs_list(): Removed 6 GHz frequecies from ACS list
3903  * @org_freq_list: ACS frequecny list
3904  * @org_ch_list_count: Number of frequencies in ACS list
3905  *
3906  * Return: None
3907  */
3908 static void hdd_remove_6ghz_freq_from_acs_list(uint32_t *org_freq_list,
3909 					       uint8_t *org_ch_list_count)
3910 {
3911 	uint16_t i, ch_list_count = 0;
3912 
3913 	hdd_debug("Remove 6 GHz channels from ACS list");
3914 	for (i = 0; i < *org_ch_list_count; i++) {
3915 		if (wlan_reg_is_6ghz_chan_freq(org_freq_list[i]))
3916 			continue;
3917 		org_freq_list[ch_list_count++] = org_freq_list[i];
3918 	}
3919 	*org_ch_list_count = ch_list_count;
3920 }
3921 
3922 /**
3923  * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
3924  * @wiphy:  Linux wiphy struct pointer
3925  * @wdev:   Linux wireless device struct pointer
3926  * @data:   ACS information from hostapd
3927  * @data_len: ACS information length
3928  *
3929  * This function handle DO_ACS Vendor command from hostapd, parses ACS config
3930  * and starts ACS procedure.
3931  *
3932  * Return: ACS procedure start status
3933  */
3934 static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
3935 					struct wireless_dev *wdev,
3936 					const void *data, int data_len)
3937 {
3938 	struct net_device *ndev = wdev->netdev;
3939 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
3940 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
3941 	struct sap_config *sap_config;
3942 	struct sap_context *sap_ctx;
3943 	struct hdd_ap_ctx *ap_ctx;
3944 	struct sk_buff *temp_skbuff;
3945 	int ret, i;
3946 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
3947 	bool ht_enabled, ht40_enabled, vht_enabled, eht_enabled;
3948 	uint16_t ch_width;
3949 	enum qca_wlan_vendor_acs_hw_mode hw_mode;
3950 	enum policy_mgr_con_mode pm_mode;
3951 	QDF_STATUS qdf_status;
3952 	bool is_vendor_acs_support = false;
3953 	bool is_external_acs_policy = false;
3954 	bool is_vendor_unsafe_ch_present = false;
3955 	bool sap_force_11n_for_11ac = 0;
3956 	bool go_force_11n_for_11ac = 0;
3957 	bool is_ll_lt_sap = false;
3958 	bool sap_force_11n;
3959 	bool go_11ac_override = 0;
3960 	bool sap_11ac_override = 0;
3961 	uint8_t vht_ch_width;
3962 	uint32_t channel_bonding_mode_2g;
3963 	uint32_t last_scan_ageout_time;
3964 	bool ll_lt_sap = false;
3965 	struct wlan_hdd_link_info *link_info = adapter->deflink;
3966 
3967 	/* ***Note*** Donot set SME config related to ACS operation here because
3968 	 * ACS operation is not synchronouse and ACS for Second AP may come when
3969 	 * ACS operation for first AP is going on. So only do_acs is split to
3970 	 * separate start_acs routine. Also SME-PMAC struct that is used to
3971 	 * pass parameters from HDD to SAP is global. Thus All ACS related SME
3972 	 * config shall be set only from start_acs.
3973 	 */
3974 
3975 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3976 		hdd_err("Command not allowed in FTM mode");
3977 		return -EPERM;
3978 	}
3979 
3980 	ret = wlan_hdd_validate_context(hdd_ctx);
3981 	if (ret)
3982 		return ret;
3983 
3984 	ucfg_mlme_get_sap_force_11n_for_11ac(hdd_ctx->psoc,
3985 					     &sap_force_11n_for_11ac);
3986 	ucfg_mlme_get_go_force_11n_for_11ac(hdd_ctx->psoc,
3987 					    &go_force_11n_for_11ac);
3988 	ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
3989 					    &channel_bonding_mode_2g);
3990 
3991 	if (policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc, link_info->vdev_id))
3992 		is_ll_lt_sap = true;
3993 
3994 	if (is_ll_lt_sap || sap_force_11n_for_11ac)
3995 		sap_force_11n = true;
3996 
3997 	if (!((adapter->device_mode == QDF_SAP_MODE) ||
3998 	      (adapter->device_mode == QDF_P2P_GO_MODE))) {
3999 		hdd_err("Invalid device mode %d", adapter->device_mode);
4000 		return -EINVAL;
4001 	}
4002 
4003 	if (cds_is_sub_20_mhz_enabled()) {
4004 		hdd_err("ACS not supported in sub 20 MHz ch wd.");
4005 		return -EINVAL;
4006 	}
4007 
4008 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
4009 
4010 	if (qdf_atomic_read(&ap_ctx->acs_in_progress) > 0) {
4011 		if (wlan_hdd_check_is_acs_request_same(adapter,
4012 						       data, data_len)) {
4013 			hdd_debug("Same ACS req as ongoing is received, return success");
4014 			ret = 0;
4015 			goto out;
4016 		}
4017 		hdd_err("ACS rejected as previous ACS req already in progress");
4018 		return -EINVAL;
4019 	} else {
4020 		qdf_atomic_set(&ap_ctx->acs_in_progress, 1);
4021 		qdf_event_reset(&link_info->acs_complete_event);
4022 	}
4023 
4024 	hdd_reg_wait_for_country_change(hdd_ctx);
4025 
4026 	ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
4027 					 data_len,
4028 					 wlan_hdd_cfg80211_do_acs_policy);
4029 	if (ret) {
4030 		hdd_err("Invalid ATTR");
4031 		goto out;
4032 	}
4033 
4034 	if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
4035 		hdd_err("Attr hw_mode failed");
4036 		ret = -EINVAL;
4037 		goto out;
4038 	}
4039 
4040 	sap_config = &ap_ctx->sap_config;
4041 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
4042 
4043 	/* Check and free if memory is already allocated for acs channel list */
4044 	wlan_hdd_undo_acs(link_info);
4045 
4046 	qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
4047 
4048 	hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
4049 	hdd_nofl_info("ACS request vid %d hw mode %d",
4050 		      link_info->vdev_id, hw_mode);
4051 	ht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
4052 	ht40_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
4053 	vht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
4054 	eht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED]);
4055 
4056 	sap_config->acs_cfg.master_acs_cfg.hw_mode = hw_mode;
4057 	sap_config->acs_cfg.master_acs_cfg.ht = ht_enabled;
4058 	sap_config->acs_cfg.master_acs_cfg.ht40 = ht40_enabled;
4059 	sap_config->acs_cfg.master_acs_cfg.vht = vht_enabled;
4060 	sap_config->acs_cfg.master_acs_cfg.eht = eht_enabled;
4061 
4062 	if (((adapter->device_mode == QDF_SAP_MODE) &&
4063 	      sap_force_11n) ||
4064 	    ((adapter->device_mode == QDF_P2P_GO_MODE) &&
4065 	      go_force_11n_for_11ac)) {
4066 		vht_enabled = 0;
4067 		hdd_info("VHT is Disabled in ACS");
4068 	}
4069 
4070 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
4071 		ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
4072 		sap_config->acs_cfg.master_acs_cfg.ch_width = ch_width;
4073 	} else {
4074 		if (ht_enabled && ht40_enabled)
4075 			ch_width = 40;
4076 		else
4077 			ch_width = 20;
4078 		sap_config->acs_cfg.master_acs_cfg.ch_width = 0;
4079 	}
4080 
4081 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED])
4082 		eht_enabled =
4083 			nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED]);
4084 	else
4085 		eht_enabled = 0;
4086 
4087 	if (ch_width == 320 && !eht_enabled)
4088 		ch_width = 160;
4089 
4090 	/* this may be possible, when sap_force_11n_for_11ac or
4091 	 * go_force_11n_for_11ac is set
4092 	 */
4093 	if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
4094 		if (ht_enabled && ht40_enabled)
4095 			ch_width = 40;
4096 		else
4097 			ch_width = 20;
4098 	}
4099 	if (is_ll_lt_sap)
4100 		ch_width = 20;
4101 
4102 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME])
4103 		last_scan_ageout_time =
4104 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME]);
4105 	else
4106 		wlan_scan_get_last_scan_ageout_time(hdd_ctx->psoc,
4107 						    &last_scan_ageout_time);
4108 
4109 	if (ch_width == 320)
4110 		wlan_hdd_set_sap_acs_ch_width_320(sap_config);
4111 	else if (ch_width == 160)
4112 		sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
4113 	else if (ch_width == 80)
4114 		sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
4115 	else if (ch_width == 40)
4116 		sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
4117 	else
4118 		sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
4119 
4120 	/* Firstly try to get channel frequencies */
4121 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
4122 		uint32_t *freq =
4123 			nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
4124 		sap_config->acs_cfg.ch_list_count = nla_len(
4125 			tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
4126 				sizeof(uint32_t);
4127 		if (sap_config->acs_cfg.ch_list_count) {
4128 			sap_config->acs_cfg.freq_list = qdf_mem_malloc(
4129 				sap_config->acs_cfg.ch_list_count *
4130 				sizeof(uint32_t));
4131 			sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
4132 				sap_config->acs_cfg.ch_list_count *
4133 				sizeof(uint32_t));
4134 			if (!sap_config->acs_cfg.freq_list ||
4135 			    !sap_config->acs_cfg.master_freq_list) {
4136 				ret = -ENOMEM;
4137 				goto out;
4138 			}
4139 
4140 			for (i = 0; i < sap_config->acs_cfg.ch_list_count;
4141 			     i++) {
4142 				sap_config->acs_cfg.master_freq_list[i] =
4143 									freq[i];
4144 				sap_config->acs_cfg.freq_list[i] = freq[i];
4145 			}
4146 			sap_config->acs_cfg.master_ch_list_count =
4147 					sap_config->acs_cfg.ch_list_count;
4148 		}
4149 	} else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
4150 		uint8_t *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
4151 
4152 		sap_config->acs_cfg.ch_list_count = nla_len(
4153 					tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
4154 		if (sap_config->acs_cfg.ch_list_count) {
4155 			sap_config->acs_cfg.freq_list = qdf_mem_malloc(
4156 					sap_config->acs_cfg.ch_list_count *
4157 					sizeof(uint32_t));
4158 			sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
4159 					sap_config->acs_cfg.ch_list_count *
4160 					sizeof(uint32_t));
4161 			if (!sap_config->acs_cfg.freq_list ||
4162 			    !sap_config->acs_cfg.master_freq_list) {
4163 				ret = -ENOMEM;
4164 				goto out;
4165 			}
4166 
4167 			/* convert channel to frequency */
4168 			for (i = 0; i < sap_config->acs_cfg.ch_list_count;
4169 			     i++) {
4170 				sap_config->acs_cfg.freq_list[i] =
4171 					wlan_reg_legacy_chan_to_freq(
4172 								hdd_ctx->pdev,
4173 								tmp[i]);
4174 				sap_config->acs_cfg.master_freq_list[i] =
4175 					sap_config->acs_cfg.freq_list[i];
4176 			}
4177 			sap_config->acs_cfg.master_ch_list_count =
4178 					sap_config->acs_cfg.ch_list_count;
4179 		}
4180 	}
4181 
4182 	if (!sap_config->acs_cfg.ch_list_count) {
4183 		hdd_err("acs config chan count 0");
4184 		ret = -EINVAL;
4185 		goto out;
4186 	} else {
4187 		hdd_nofl_debug("Dump raw ACS chanlist - ");
4188 		sap_dump_acs_channel(&sap_config->acs_cfg);
4189 	}
4190 
4191 	hdd_handle_acs_2g_preferred_sap_conc(hdd_ctx->psoc, adapter,
4192 					     sap_config);
4193 	hdd_avoid_acs_channels(hdd_ctx, sap_config);
4194 
4195 	pm_mode =
4196 		policy_mgr_qdf_opmode_to_pm_con_mode(hdd_ctx->psoc,
4197 						     adapter->device_mode,
4198 						     adapter->deflink->vdev_id);
4199 
4200 	/* Remove passive/dfs acs channel for ll sap */
4201 	hdd_remove_passive_dfs_acs_channel_for_ll_sap(
4202 						sap_config, hdd_ctx->psoc,
4203 						hdd_ctx->pdev,
4204 						link_info->vdev_id);
4205 
4206 	/* consult policy manager to get PCL */
4207 	qdf_status = policy_mgr_get_pcl(hdd_ctx->psoc, pm_mode,
4208 					sap_config->acs_cfg.pcl_chan_freq,
4209 					&sap_config->acs_cfg.pcl_ch_count,
4210 					sap_config->acs_cfg.
4211 					pcl_channels_weight_list,
4212 					NUM_CHANNELS,
4213 					link_info->vdev_id);
4214 
4215 	policy_mgr_get_pcl_channel_for_ll_sap_concurrency(
4216 				hdd_ctx->psoc,
4217 				link_info->vdev_id,
4218 				sap_config->acs_cfg.pcl_chan_freq,
4219 				sap_config->acs_cfg.pcl_channels_weight_list,
4220 				&sap_config->acs_cfg.pcl_ch_count);
4221 
4222 	sap_config->acs_cfg.band = hw_mode;
4223 
4224 	qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
4225 						       &is_external_acs_policy);
4226 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
4227 		hdd_err("get_external_acs_policy failed");
4228 
4229 	sap_config->acs_cfg.acs_mode = true;
4230 
4231 	ll_lt_sap = policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc,
4232 						 link_info->vdev_id);
4233 
4234 	if (wlan_reg_get_keep_6ghz_sta_cli_connection(hdd_ctx->pdev))
4235 		hdd_remove_6ghz_freq_from_acs_list(
4236 					sap_config->acs_cfg.freq_list,
4237 					&sap_config->acs_cfg.ch_list_count);
4238 
4239 	if ((is_external_acs_policy &&
4240 	    policy_mgr_is_force_scc(hdd_ctx->psoc) &&
4241 	    policy_mgr_get_connection_count(hdd_ctx->psoc)) || ll_lt_sap) {
4242 		if (adapter->device_mode == QDF_SAP_MODE)
4243 			is_vendor_unsafe_ch_present =
4244 				wlansap_filter_vendor_unsafe_ch_freq(sap_ctx,
4245 								     sap_config);
4246 		wlan_hdd_trim_acs_channel_list(
4247 					sap_config->acs_cfg.pcl_chan_freq,
4248 					sap_config->acs_cfg.pcl_ch_count,
4249 					sap_config->acs_cfg.freq_list,
4250 					&sap_config->acs_cfg.ch_list_count);
4251 		if (!sap_config->acs_cfg.ch_list_count &&
4252 		    sap_config->acs_cfg.master_ch_list_count &&
4253 		    !is_vendor_unsafe_ch_present &&
4254 		    !ll_lt_sap)
4255 			wlan_hdd_handle_zero_acs_list(
4256 				hdd_ctx,
4257 				sap_config->acs_cfg.freq_list,
4258 				&sap_config->acs_cfg.ch_list_count,
4259 				sap_config->acs_cfg.master_freq_list,
4260 				sap_config->acs_cfg.master_ch_list_count);
4261 		/* if it is only one channel, send ACS event to upper layer */
4262 		if (sap_config->acs_cfg.ch_list_count == 1) {
4263 			wlan_hdd_handle_single_ch_in_acs_list(link_info);
4264 			ret = 0;
4265 			goto out;
4266 		} else if (!sap_config->acs_cfg.ch_list_count) {
4267 			hdd_err("channel list count 0");
4268 			ret = -EINVAL;
4269 			goto out;
4270 		}
4271 	} else if (adapter->device_mode == QDF_SAP_MODE) {
4272 		wlansap_filter_vendor_unsafe_ch_freq(sap_ctx, sap_config);
4273 		if (sap_config->acs_cfg.ch_list_count == 1) {
4274 			wlan_hdd_handle_single_ch_in_acs_list(link_info);
4275 			ret = 0;
4276 			goto out;
4277 		} else if (!sap_config->acs_cfg.ch_list_count) {
4278 			hdd_err("channel count 0 after vendor unsafe filter");
4279 			ret = -EINVAL;
4280 			goto out;
4281 		}
4282 	}
4283 
4284 	ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
4285 					ht_enabled, vht_enabled);
4286 	if (ret) {
4287 		hdd_err("set acs channel range failed");
4288 		goto out;
4289 	}
4290 
4291 	ucfg_mlme_is_go_11ac_override(hdd_ctx->psoc, &go_11ac_override);
4292 	ucfg_mlme_is_sap_11ac_override(hdd_ctx->psoc, &sap_11ac_override);
4293 	/* ACS override for android */
4294 	if (ht_enabled &&
4295 	    sap_config->acs_cfg.end_ch_freq >=
4296 		WLAN_REG_CH_TO_FREQ(CHAN_ENUM_5180) &&
4297 	    ((adapter->device_mode == QDF_SAP_MODE &&
4298 	      !sap_force_11n &&
4299 	      sap_11ac_override) ||
4300 	      (adapter->device_mode == QDF_P2P_GO_MODE &&
4301 	      !go_force_11n_for_11ac &&
4302 	      go_11ac_override))) {
4303 		vht_enabled = 1;
4304 		sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
4305 		qdf_status =
4306 			ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
4307 							&vht_ch_width);
4308 		ch_width = vht_ch_width;
4309 		sap_config->acs_cfg.ch_width = ch_width;
4310 	}
4311 
4312 	/* Check 2.4ghz cbmode and update BW if only 2.4 channels are present */
4313 	if (sap_config->acs_cfg.end_ch_freq <=
4314 	    WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484) &&
4315 	    sap_config->acs_cfg.ch_width >= eHT_CHANNEL_WIDTH_40MHZ) {
4316 
4317 		sap_config->acs_cfg.ch_width = channel_bonding_mode_2g ?
4318 			eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ;
4319 
4320 		hdd_debug("Only 2.4ghz channels, resetting BW to %d 2.4 cbmode %d",
4321 			  sap_config->acs_cfg.ch_width,
4322 			  channel_bonding_mode_2g);
4323 	}
4324 
4325 	sap_config->acs_cfg.ch_width = wlan_hdd_update_bw_from_mlme(hdd_ctx,
4326 								    sap_config);
4327 
4328 	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",
4329 		       hdd_ctx->reg.alpha2, ch_width,
4330 		       sap_config->acs_cfg.hw_mode, sap_config->acs_cfg.ch_width,
4331 		       ht_enabled, vht_enabled, eht_enabled,
4332 		       sap_config->acs_cfg.start_ch_freq,
4333 		       sap_config->acs_cfg.end_ch_freq,
4334 		       sap_config->acs_cfg.band, last_scan_ageout_time);
4335 	host_log_acs_req_event(adapter->dev->name,
4336 			  csr_phy_mode_str(sap_config->acs_cfg.hw_mode),
4337 			  ch_width, ht_enabled, vht_enabled,
4338 			  sap_config->acs_cfg.start_ch_freq,
4339 			  sap_config->acs_cfg.end_ch_freq);
4340 
4341 	sap_config->acs_cfg.is_ht_enabled = ht_enabled;
4342 	sap_config->acs_cfg.is_vht_enabled = vht_enabled;
4343 	wlan_hdd_acs_set_eht_enabled(sap_config, eht_enabled);
4344 	sap_config->acs_cfg.last_scan_ageout_time = last_scan_ageout_time;
4345 
4346 	sap_dump_acs_channel(&sap_config->acs_cfg);
4347 
4348 	if (wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(adapter)) {
4349 		ret = 0;
4350 		goto out;
4351 	}
4352 
4353 	qdf_status = ucfg_mlme_get_vendor_acs_support(hdd_ctx->psoc,
4354 						      &is_vendor_acs_support);
4355 	if (QDF_IS_STATUS_ERROR(qdf_status))
4356 		hdd_err("get_vendor_acs_support failed, set default");
4357 
4358 	/* Check if vendor specific acs is enabled */
4359 	if (is_vendor_acs_support)
4360 		ret = hdd_start_vendor_acs(adapter);
4361 	else
4362 		ret = wlan_hdd_cfg80211_start_acs(link_info);
4363 
4364 out:
4365 	if (ret == 0) {
4366 		temp_skbuff =
4367 			wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4368 								 NLMSG_HDRLEN);
4369 		if (temp_skbuff)
4370 			return wlan_cfg80211_vendor_cmd_reply(temp_skbuff);
4371 	}
4372 	qdf_atomic_set(&ap_ctx->acs_in_progress, 0);
4373 
4374 	return ret;
4375 }
4376 
4377 /**
4378  * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
4379  * @wiphy:  Linux wiphy struct pointer
4380  * @wdev:   Linux wireless device struct pointer
4381  * @data:   ACS information from hostapd
4382  * @data_len: ACS information len
4383  *
4384  * This function handle DO_ACS Vendor command from hostapd, parses ACS config
4385  * and starts ACS procedure.
4386  *
4387  * Return: ACS procedure start status
4388  */
4389 
4390 static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
4391 				    struct wireless_dev *wdev,
4392 				    const void *data, int data_len)
4393 {
4394 	int errno;
4395 	struct osif_vdev_sync *vdev_sync;
4396 
4397 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
4398 	if (errno)
4399 		return errno;
4400 
4401 	errno = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
4402 
4403 	osif_vdev_sync_op_stop(vdev_sync);
4404 
4405 	return errno;
4406 }
4407 
4408 void wlan_hdd_undo_acs(struct wlan_hdd_link_info *link_info)
4409 {
4410 	sap_undo_acs(WLAN_HDD_GET_SAP_CTX_PTR(link_info),
4411 		     &link_info->session.ap.sap_config);
4412 }
4413 
4414 /**
4415  * hdd_fill_acs_chan_freq() - Populate channel frequencies (MHz) selected in ACS
4416  * @hdd_ctx: pointer to hdd context
4417  * @sap_cfg: sap acs configuration
4418  * @vendor_event: output pointer to populate channel frequencies (MHz)
4419  *
4420  * Return: If populated successfully return 0 else negative value.
4421  */
4422 static int hdd_fill_acs_chan_freq(struct hdd_context *hdd_ctx,
4423 				  struct sap_config *sap_cfg,
4424 				  struct sk_buff *vendor_event)
4425 {
4426 	uint32_t id;
4427 	int errno;
4428 
4429 	id = QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY;
4430 	errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.pri_ch_freq);
4431 	if (errno) {
4432 		hdd_err("VENDOR_ATTR_ACS_PRIMARY_FREQUENCY put fail");
4433 		return errno;
4434 	}
4435 
4436 	id = QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY;
4437 	errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.ht_sec_ch_freq);
4438 	if (errno) {
4439 		hdd_err("VENDOR_ATTR_ACS_SECONDARY_FREQUENCY put fail");
4440 		return errno;
4441 	}
4442 
4443 	id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY;
4444 	errno = nla_put_u32(vendor_event, id,
4445 			    sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
4446 	if (errno) {
4447 		hdd_err("VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY put fail");
4448 		return errno;
4449 	}
4450 
4451 	id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY;
4452 	errno = nla_put_u32(vendor_event, id,
4453 			    sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
4454 	if (errno) {
4455 		hdd_err("VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY put fail");
4456 		return errno;
4457 	}
4458 
4459 	return 0;
4460 }
4461 
4462 static int hdd_get_acs_evt_data_len(struct sap_config *sap_cfg)
4463 {
4464 	uint32_t len = NLMSG_HDRLEN;
4465 
4466 	/* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL */
4467 	len += nla_total_size(sizeof(u8));
4468 
4469 	/* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL */
4470 	len += nla_total_size(sizeof(u8));
4471 
4472 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL */
4473 	len += nla_total_size(sizeof(u8));
4474 
4475 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL */
4476 	len += nla_total_size(sizeof(u8));
4477 
4478 	/* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY */
4479 	len += nla_total_size(sizeof(u32));
4480 
4481 	/* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY */
4482 	len += nla_total_size(sizeof(u32));
4483 
4484 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY */
4485 	len += nla_total_size(sizeof(u32));
4486 
4487 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY */
4488 	len += nla_total_size(sizeof(u32));
4489 
4490 	/* QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH */
4491 	len += nla_total_size(sizeof(u16));
4492 
4493 	/* QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE */
4494 	len += nla_total_size(sizeof(u8));
4495 
4496 	/* QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP */
4497 	if (sap_acs_is_puncture_applicable(&sap_cfg->acs_cfg))
4498 		len += nla_total_size(sizeof(u16));
4499 
4500 	return len;
4501 }
4502 
4503 #ifdef WLAN_FEATURE_11BE
4504 /**
4505  * wlan_hdd_acs_get_puncture_bitmap() - get puncture_bitmap for acs result
4506  * @acs_cfg: pointer to struct sap_acs_cfg
4507  *
4508  * Return: acs puncture bitmap
4509  */
4510 static uint16_t wlan_hdd_acs_get_puncture_bitmap(struct sap_acs_cfg *acs_cfg)
4511 {
4512 	if (sap_acs_is_puncture_applicable(acs_cfg))
4513 		return acs_cfg->acs_puncture_bitmap;
4514 
4515 	return 0;
4516 }
4517 #else
4518 static uint16_t wlan_hdd_acs_get_puncture_bitmap(struct sap_acs_cfg *acs_cfg)
4519 {
4520 	return 0;
4521 }
4522 #endif /* WLAN_FEATURE_11BE */
4523 
4524 void wlan_hdd_cfg80211_acs_ch_select_evt(struct wlan_hdd_link_info *link_info,
4525 					 bool store_acs_freq)
4526 {
4527 	struct hdd_adapter *adapter = link_info->adapter;
4528 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4529 	struct sap_config *sap_cfg;
4530 	struct sk_buff *vendor_event;
4531 	int ret_val;
4532 	uint16_t ch_width;
4533 	uint8_t pri_channel;
4534 	uint8_t ht_sec_channel;
4535 	uint8_t vht_seg0_center_ch, vht_seg1_center_ch;
4536 	uint32_t id = QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX;
4537 	uint32_t len;
4538 	uint16_t puncture_bitmap;
4539 
4540 	qdf_atomic_set(&link_info->session.ap.acs_in_progress, 0);
4541 	qdf_event_set(&link_info->acs_complete_event);
4542 
4543 	sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(link_info))->sap_config;
4544 	len = hdd_get_acs_evt_data_len(sap_cfg);
4545 
4546 	if (store_acs_freq &&
4547 	    policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc,
4548 					 link_info->vdev_id)) {
4549 		sap_cfg->last_acs_freq = sap_cfg->acs_cfg.pri_ch_freq;
4550 		sap_cfg->last_acs_complete_time = qdf_get_time_of_the_day_ms();
4551 	}
4552 
4553 	vendor_event = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4554 							&adapter->wdev, len, id,
4555 							GFP_KERNEL);
4556 
4557 	if (!vendor_event) {
4558 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
4559 		return;
4560 	}
4561 
4562 	ret_val = hdd_fill_acs_chan_freq(hdd_ctx, sap_cfg, vendor_event);
4563 	if (ret_val) {
4564 		hdd_err("failed to put frequencies");
4565 		wlan_cfg80211_vendor_free_skb(vendor_event);
4566 		return;
4567 	}
4568 
4569 	pri_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
4570 					    sap_cfg->acs_cfg.pri_ch_freq);
4571 
4572 	ht_sec_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
4573 					       sap_cfg->acs_cfg.ht_sec_ch_freq);
4574 
4575 	ret_val = nla_put_u8(vendor_event,
4576 				QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
4577 				pri_channel);
4578 	if (ret_val) {
4579 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
4580 		wlan_cfg80211_vendor_free_skb(vendor_event);
4581 		return;
4582 	}
4583 
4584 	ret_val = nla_put_u8(vendor_event,
4585 			     QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
4586 			     ht_sec_channel);
4587 	if (ret_val) {
4588 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
4589 		wlan_cfg80211_vendor_free_skb(vendor_event);
4590 		return;
4591 	}
4592 	vht_seg0_center_ch = wlan_reg_freq_to_chan(
4593 				hdd_ctx->pdev,
4594 				sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
4595 	ret_val = nla_put_u8(vendor_event,
4596 			QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
4597 			vht_seg0_center_ch);
4598 	if (ret_val) {
4599 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
4600 		wlan_cfg80211_vendor_free_skb(vendor_event);
4601 		return;
4602 	}
4603 	vht_seg1_center_ch = wlan_reg_freq_to_chan(
4604 				hdd_ctx->pdev,
4605 				sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
4606 	ret_val = nla_put_u8(vendor_event,
4607 			QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
4608 			vht_seg1_center_ch);
4609 	if (ret_val) {
4610 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
4611 		wlan_cfg80211_vendor_free_skb(vendor_event);
4612 		return;
4613 	}
4614 
4615 	if (wlan_hdd_is_sap_acs_ch_width_320(sap_cfg))
4616 		ch_width = 320;
4617 	else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
4618 		ch_width = 160;
4619 	else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
4620 		ch_width = 80;
4621 	else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
4622 		ch_width = 40;
4623 	else
4624 		ch_width = 20;
4625 
4626 	ret_val = nla_put_u16(vendor_event,
4627 				QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
4628 				ch_width);
4629 	if (ret_val) {
4630 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
4631 		wlan_cfg80211_vendor_free_skb(vendor_event);
4632 		return;
4633 	}
4634 	if (WLAN_REG_IS_24GHZ_CH_FREQ(sap_cfg->acs_cfg.pri_ch_freq))
4635 		ret_val = nla_put_u8(vendor_event,
4636 					QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
4637 					QCA_ACS_MODE_IEEE80211G);
4638 	else
4639 		ret_val = nla_put_u8(vendor_event,
4640 					QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
4641 					QCA_ACS_MODE_IEEE80211A);
4642 
4643 	if (ret_val) {
4644 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
4645 		wlan_cfg80211_vendor_free_skb(vendor_event);
4646 		return;
4647 	}
4648 
4649 	puncture_bitmap = wlan_hdd_acs_get_puncture_bitmap(&sap_cfg->acs_cfg);
4650 	if (sap_acs_is_puncture_applicable(&sap_cfg->acs_cfg)) {
4651 		ret_val = nla_put_u16(vendor_event,
4652 				      QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP,
4653 				      puncture_bitmap);
4654 		if (ret_val) {
4655 			hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP put fail");
4656 			wlan_cfg80211_vendor_free_skb(vendor_event);
4657 			return;
4658 		}
4659 	}
4660 
4661 	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",
4662 		  adapter->dev->name, sap_cfg->acs_cfg.pri_ch_freq,
4663 		  sap_cfg->acs_cfg.ht_sec_ch_freq,
4664 		  sap_cfg->acs_cfg.vht_seg0_center_ch_freq,
4665 		  sap_cfg->acs_cfg.vht_seg1_center_ch_freq, ch_width,
4666 		  sap_acs_is_puncture_applicable(&sap_cfg->acs_cfg),
4667 		  puncture_bitmap);
4668 
4669 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
4670 }
4671 
4672 /**
4673  * hdd_is_wlm_latency_manager_supported - Checks if WLM Latency manager is
4674  *                                        supported
4675  * @hdd_ctx: The HDD context
4676  *
4677  * Return: True if supported, false otherwise
4678  */
4679 static inline
4680 bool hdd_is_wlm_latency_manager_supported(struct hdd_context *hdd_ctx)
4681 {
4682 	bool latency_enable;
4683 
4684 	if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_latency_enable
4685 				(hdd_ctx->psoc, &latency_enable)))
4686 		return false;
4687 
4688 	if (latency_enable &&
4689 	    sme_is_feature_supported_by_fw(VDEV_LATENCY_CONFIG))
4690 		return true;
4691 	else
4692 		return false;
4693 }
4694 
4695 static int
4696 __wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
4697 					 struct wireless_dev *wdev,
4698 					 const void *data,
4699 					 int data_len)
4700 {
4701 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
4702 	struct sk_buff *skb = NULL;
4703 	uint32_t fset = 0;
4704 	int ret;
4705 #ifdef FEATURE_WLAN_TDLS
4706 	bool bvalue;
4707 #endif
4708 	uint32_t fine_time_meas_cap;
4709 
4710 	/* ENTER_DEV() intentionally not used in a frequently invoked API */
4711 
4712 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4713 		hdd_err("Command not allowed in FTM mode");
4714 		return -EPERM;
4715 	}
4716 
4717 	ret = wlan_hdd_validate_context(hdd_ctx);
4718 	if (ret)
4719 		return ret;
4720 
4721 	if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
4722 		hdd_debug("Infra Station mode is supported by driver");
4723 		fset |= WIFI_FEATURE_INFRA;
4724 	}
4725 	if (true == hdd_is_5g_supported(hdd_ctx)) {
4726 		hdd_debug("INFRA_5G is supported by firmware");
4727 		fset |= WIFI_FEATURE_INFRA_5G;
4728 	}
4729 #ifdef WLAN_FEATURE_P2P
4730 	if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
4731 	    (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
4732 		hdd_debug("WiFi-Direct is supported by driver");
4733 		fset |= WIFI_FEATURE_P2P;
4734 	}
4735 #endif
4736 	fset |= WIFI_FEATURE_SOFT_AP;
4737 
4738 	/* HOTSPOT is a supplicant feature, enable it by default */
4739 	fset |= WIFI_FEATURE_HOTSPOT;
4740 
4741 	if (ucfg_extscan_get_enable(hdd_ctx->psoc) &&
4742 	    sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
4743 		hdd_debug("EXTScan is supported by firmware");
4744 		fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
4745 	}
4746 	if (wlan_hdd_nan_is_supported(hdd_ctx)) {
4747 		hdd_debug("NAN is supported by firmware");
4748 		fset |= WIFI_FEATURE_NAN;
4749 	}
4750 
4751 	ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, &fine_time_meas_cap);
4752 
4753 	if (sme_is_feature_supported_by_fw(RTT) &&
4754 	    rtt_is_enabled(fine_time_meas_cap)) {
4755 		hdd_debug("RTT is supported by firmware and driver: %x",
4756 			  fine_time_meas_cap);
4757 		fset |= WIFI_FEATURE_D2D_RTT;
4758 		fset |= WIFI_FEATURE_D2AP_RTT;
4759 	}
4760 #ifdef FEATURE_WLAN_SCAN_PNO
4761 	if (ucfg_scan_get_pno_scan_support(hdd_ctx->psoc) &&
4762 	    sme_is_feature_supported_by_fw(PNO)) {
4763 		hdd_debug("PNO is supported by firmware");
4764 		fset |= WIFI_FEATURE_PNO;
4765 	}
4766 #endif
4767 	if (ucfg_policy_mgr_get_dual_sta_feature(hdd_ctx->psoc))
4768 		fset |= WIFI_FEATURE_ADDITIONAL_STA;
4769 
4770 #ifdef FEATURE_WLAN_TDLS
4771 	cfg_tdls_get_support_enable(hdd_ctx->psoc, &bvalue);
4772 	if ((bvalue) && sme_is_feature_supported_by_fw(TDLS)) {
4773 		hdd_debug("TDLS is supported by firmware");
4774 		fset |= WIFI_FEATURE_TDLS;
4775 	}
4776 
4777 	cfg_tdls_get_off_channel_enable(hdd_ctx->psoc, &bvalue);
4778 	if (sme_is_feature_supported_by_fw(TDLS) &&
4779 	    bvalue && sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
4780 		hdd_debug("TDLS off-channel is supported by firmware");
4781 		fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
4782 	}
4783 #endif
4784 	fset |= WIFI_FEATURE_AP_STA;
4785 	fset |= WIFI_FEATURE_RSSI_MONITOR;
4786 	fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
4787 	fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
4788 	fset |= WIFI_FEATURE_CONFIG_NDO;
4789 
4790 	if (hdd_link_layer_stats_supported())
4791 		fset |= WIFI_FEATURE_LINK_LAYER_STATS;
4792 
4793 	if (hdd_roaming_supported(hdd_ctx))
4794 		fset |= WIFI_FEATURE_CONTROL_ROAMING;
4795 
4796 	if (hdd_scan_random_mac_addr_supported())
4797 		fset |= WIFI_FEATURE_SCAN_RAND;
4798 
4799 	if (hdd_is_wlm_latency_manager_supported(hdd_ctx))
4800 		fset |= WIFI_FEATURE_SET_LATENCY_MODE;
4801 
4802 	if (hdd_dynamic_mac_addr_supported(hdd_ctx))
4803 		fset |= WIFI_FEATURE_DYNAMIC_SET_MAC;
4804 
4805 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
4806 						       NLMSG_HDRLEN);
4807 	if (!skb) {
4808 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
4809 		return -EINVAL;
4810 	}
4811 	hdd_debug("Supported Features : 0x%x", fset);
4812 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
4813 		hdd_err("nla put fail");
4814 		goto nla_put_failure;
4815 	}
4816 	ret = wlan_cfg80211_vendor_cmd_reply(skb);
4817 	return ret;
4818 nla_put_failure:
4819 	wlan_cfg80211_vendor_free_skb(skb);
4820 	return -EINVAL;
4821 }
4822 
4823 /**
4824  * wlan_hdd_cfg80211_get_supported_features() - get supported features
4825  * @wiphy:   pointer to wireless wiphy structure.
4826  * @wdev:    pointer to wireless_dev structure.
4827  * @data:    Pointer to the data to be passed via vendor interface
4828  * @data_len:Length of the data to be passed
4829  *
4830  * Return:   Return the Success or Failure code.
4831  */
4832 static int
4833 wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
4834 					struct wireless_dev *wdev,
4835 					const void *data, int data_len)
4836 {
4837 	struct osif_psoc_sync *psoc_sync;
4838 	int errno;
4839 
4840 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
4841 	if (errno)
4842 		return errno;
4843 
4844 	errno = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
4845 							   data, data_len);
4846 
4847 	osif_psoc_sync_op_stop(psoc_sync);
4848 
4849 	return errno;
4850 }
4851 
4852 /**
4853  * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
4854  * @wiphy:   pointer to wireless wiphy structure.
4855  * @wdev:    pointer to wireless_dev structure.
4856  * @data:    Pointer to the data to be passed via vendor interface
4857  * @data_len:Length of the data to be passed
4858  *
4859  * Set the MAC address that is to be used for scanning.
4860  *
4861  * Return:   Return the Success or Failure code.
4862  */
4863 static int
4864 __wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
4865 					 struct wireless_dev *wdev,
4866 					 const void *data,
4867 					 int data_len)
4868 {
4869 	struct scan_mac_oui scan_mac_oui = { {0} };
4870 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
4871 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
4872 	QDF_STATUS status;
4873 	int ret, len;
4874 	struct net_device *ndev = wdev->netdev;
4875 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
4876 	mac_handle_t mac_handle;
4877 	bool mac_spoofing_enabled;
4878 
4879 	hdd_enter_dev(wdev->netdev);
4880 
4881 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4882 		hdd_err("Command not allowed in FTM mode");
4883 		return -EPERM;
4884 	}
4885 
4886 	ret = wlan_hdd_validate_context(hdd_ctx);
4887 	if (ret)
4888 		return ret;
4889 
4890 	mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
4891 	if (!mac_spoofing_enabled) {
4892 		hdd_debug("MAC address spoofing is not enabled");
4893 		return -ENOTSUPP;
4894 	}
4895 
4896 	/*
4897 	 * audit note: it is ok to pass a NULL policy here since only
4898 	 * one attribute is parsed and it is explicitly validated
4899 	 */
4900 	if (wlan_cfg80211_nla_parse(tb,
4901 				  QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
4902 				  data, data_len, NULL)) {
4903 		hdd_err("Invalid ATTR");
4904 		return -EINVAL;
4905 	}
4906 
4907 	if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
4908 		hdd_err("attr mac oui failed");
4909 		return -EINVAL;
4910 	}
4911 
4912 	len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
4913 	if (len != sizeof(scan_mac_oui.oui)) {
4914 		hdd_err("attr mac oui invalid size %d expected %zu",
4915 			len, sizeof(scan_mac_oui.oui));
4916 		return -EINVAL;
4917 	}
4918 
4919 	nla_memcpy(scan_mac_oui.oui,
4920 		   tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
4921 		   sizeof(scan_mac_oui.oui));
4922 
4923 	/* populate rest of scan_mac_oui for mac addr randomization */
4924 	scan_mac_oui.vdev_id = adapter->deflink->vdev_id;
4925 	scan_mac_oui.enb_probe_req_sno_randomization = true;
4926 
4927 	hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d",
4928 		  scan_mac_oui.oui[0], scan_mac_oui.oui[1],
4929 		  scan_mac_oui.oui[2], scan_mac_oui.vdev_id);
4930 
4931 	hdd_update_ie_allowlist_attr(&scan_mac_oui.ie_allowlist, hdd_ctx);
4932 
4933 	mac_handle = hdd_ctx->mac_handle;
4934 	status = sme_set_scanning_mac_oui(mac_handle, &scan_mac_oui);
4935 	if (!QDF_IS_STATUS_SUCCESS(status))
4936 		hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
4937 
4938 	return qdf_status_to_os_return(status);
4939 }
4940 
4941 /**
4942  * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
4943  * @wiphy:   pointer to wireless wiphy structure.
4944  * @wdev:    pointer to wireless_dev structure.
4945  * @data:    Pointer to the data to be passed via vendor interface
4946  * @data_len:Length of the data to be passed
4947  *
4948  * Set the MAC address that is to be used for scanning.  This is an
4949  * SSR-protecting wrapper function.
4950  *
4951  * Return:   Return the Success or Failure code.
4952  */
4953 static int
4954 wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
4955 				       struct wireless_dev *wdev,
4956 				       const void *data,
4957 				       int data_len)
4958 {
4959 	int errno;
4960 	struct osif_vdev_sync *vdev_sync;
4961 
4962 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
4963 	if (errno)
4964 		return errno;
4965 
4966 	errno = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
4967 							 data, data_len);
4968 
4969 	osif_vdev_sync_op_stop(vdev_sync);
4970 
4971 	return errno;
4972 }
4973 
4974 #define NUM_BITS_IN_BYTE       8
4975 
4976 /**
4977  * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
4978  * @feature_flags: pointer to the byte array of features.
4979  * @feature: Feature to be turned ON in the byte array.
4980  *
4981  * Return: None
4982  *
4983  * This is called to turn ON or SET the feature flag for the requested feature.
4984  **/
4985 static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
4986 					  uint8_t feature)
4987 {
4988 	uint32_t index;
4989 	uint8_t bit_mask;
4990 
4991 	index = feature / NUM_BITS_IN_BYTE;
4992 	bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
4993 	feature_flags[index] |= bit_mask;
4994 }
4995 
4996 /**
4997  * wlan_hdd_set_ndi_feature() - Set NDI related features
4998  * @feature_flags: pointer to the byte array of features.
4999  *
5000  * Return: None
5001  **/
5002 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0))
5003 static void wlan_hdd_set_ndi_feature(uint8_t *feature_flags)
5004 {
5005 	wlan_hdd_cfg80211_set_feature(feature_flags,
5006 				      QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI);
5007 }
5008 #else
5009 static inline void wlan_hdd_set_ndi_feature(uint8_t *feature_flags)
5010 {
5011 }
5012 #endif
5013 
5014 static inline void wlan_hdd_set_ll_lt_sap_feature(uint8_t *feature_flags)
5015 {
5016 	/* To Do: Once FW feature capability changes for ll_lt_sap feature are
5017 	 * merged, then this feature will be set based on that feature set
5018 	 * capability
5019 	 */
5020 	wlan_hdd_cfg80211_set_feature(feature_flags,
5021 				      QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN);
5022 }
5023 
5024 #define MAX_CONCURRENT_CHAN_ON_24G    2
5025 #define MAX_CONCURRENT_CHAN_ON_5G     2
5026 
5027 /**
5028  * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
5029  * @wiphy: pointer to wireless wiphy structure.
5030  * @wdev: pointer to wireless_dev structure.
5031  * @data: Pointer to the data to be passed via vendor interface
5032  * @data_len:Length of the data to be passed
5033  *
5034  * This is called when wlan driver needs to send supported feature set to
5035  * supplicant upon a request/query from the supplicant.
5036  *
5037  * Return: Return the Success or Failure code.
5038  **/
5039 static int
5040 __wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
5041 				 struct wireless_dev *wdev,
5042 				 const void *data, int data_len)
5043 {
5044 	struct sk_buff *skb = NULL;
5045 	uint32_t dbs_capability = 0;
5046 	bool one_by_one_dbs, two_by_two_dbs;
5047 	bool value, twt_req, twt_res;
5048 	QDF_STATUS ret = QDF_STATUS_E_FAILURE;
5049 	QDF_STATUS status;
5050 	int ret_val;
5051 
5052 	uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
5053 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
5054 
5055 	hdd_enter_dev(wdev->netdev);
5056 
5057 	ret_val = wlan_hdd_validate_context(hdd_ctx);
5058 	if (ret_val)
5059 		return ret_val;
5060 
5061 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5062 		hdd_err("Command not allowed in FTM mode");
5063 		return -EPERM;
5064 	}
5065 
5066 	if (roaming_offload_enabled(hdd_ctx)) {
5067 		hdd_debug("Key Mgmt Offload is supported");
5068 		wlan_hdd_cfg80211_set_feature(feature_flags,
5069 				QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
5070 	}
5071 
5072 	wlan_hdd_cfg80211_set_feature(feature_flags,
5073 				QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
5074 	if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx->psoc))
5075 		wlan_hdd_cfg80211_set_feature(feature_flags,
5076 			QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
5077 
5078 	if (policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc))
5079 		wlan_hdd_cfg80211_set_feature(feature_flags,
5080 			QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS);
5081 
5082 	if (wma_is_p2p_lo_capable())
5083 		wlan_hdd_cfg80211_set_feature(feature_flags,
5084 			QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
5085 
5086 	value = false;
5087 	status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc, &value);
5088 	if (QDF_IS_STATUS_ERROR(status))
5089 		hdd_err("could not get OCE STA enable info");
5090 	if (value)
5091 		wlan_hdd_cfg80211_set_feature(feature_flags,
5092 					      QCA_WLAN_VENDOR_FEATURE_OCE_STA);
5093 
5094 	value = false;
5095 	status = ucfg_mlme_get_oce_sap_enabled_info(hdd_ctx->psoc, &value);
5096 	if (QDF_IS_STATUS_ERROR(status))
5097 		hdd_err("could not get OCE SAP enable info");
5098 	if (value)
5099 		wlan_hdd_cfg80211_set_feature(feature_flags,
5100 					  QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
5101 
5102 	value = false;
5103 	status = ucfg_mlme_get_adaptive11r_enabled(hdd_ctx->psoc, &value);
5104 	if (QDF_IS_STATUS_ERROR(status))
5105 		hdd_err("could not get FT-Adaptive 11R info");
5106 	if (value) {
5107 		hdd_debug("FT-Adaptive 11R is Enabled");
5108 		wlan_hdd_cfg80211_set_feature(feature_flags,
5109 					  QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R);
5110 	}
5111 
5112 	hdd_get_twt_requestor(hdd_ctx->psoc, &twt_req);
5113 	hdd_get_twt_responder(hdd_ctx->psoc, &twt_res);
5114 	hdd_debug("twt_req:%d twt_res:%d", twt_req, twt_res);
5115 
5116 	if (twt_req || twt_res) {
5117 		wlan_hdd_cfg80211_set_feature(feature_flags,
5118 					      QCA_WLAN_VENDOR_FEATURE_TWT);
5119 
5120 		wlan_hdd_cfg80211_set_feature(
5121 				feature_flags,
5122 				QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT);
5123 	}
5124 
5125 	/* Check the kernel version for upstream commit aced43ce780dc5 that
5126 	 * has support for processing user cell_base hints when wiphy is
5127 	 * self managed or check the backport flag for the same.
5128 	 */
5129 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
5130 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
5131 	wlan_hdd_cfg80211_set_feature(feature_flags,
5132 			QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY);
5133 #endif
5134 
5135 	if (wlan_hdd_thermal_config_support())
5136 		wlan_hdd_cfg80211_set_feature(feature_flags,
5137 					QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG);
5138 
5139 	wlan_hdd_set_ndi_feature(feature_flags);
5140 	wlan_hdd_cfg80211_set_feature(
5141 				feature_flags,
5142 				QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST);
5143 	wlan_wifi_pos_cfg80211_set_features(hdd_ctx->psoc, feature_flags);
5144 	wlan_hdd_set_ll_lt_sap_feature(feature_flags);
5145 
5146 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5147 						       sizeof(feature_flags) +
5148 						       NLMSG_HDRLEN);
5149 
5150 	if (!skb) {
5151 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
5152 		return -ENOMEM;
5153 	}
5154 
5155 	if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
5156 			sizeof(feature_flags), feature_flags))
5157 		goto nla_put_failure;
5158 
5159 	ret = policy_mgr_get_dbs_hw_modes(hdd_ctx->psoc,
5160 					  &one_by_one_dbs, &two_by_two_dbs);
5161 	if (QDF_STATUS_SUCCESS == ret) {
5162 		if (one_by_one_dbs)
5163 			dbs_capability = DRV_DBS_CAPABILITY_1X1;
5164 
5165 		if (two_by_two_dbs)
5166 			dbs_capability = DRV_DBS_CAPABILITY_2X2;
5167 
5168 		if (!one_by_one_dbs && !two_by_two_dbs)
5169 			dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
5170 	} else {
5171 		hdd_err("wma_get_dbs_hw_mode failed");
5172 		dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
5173 	}
5174 
5175 	hdd_debug("dbs_capability is %d", dbs_capability);
5176 
5177 	if (nla_put_u32(skb,
5178 			QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
5179 			dbs_capability))
5180 		goto nla_put_failure;
5181 
5182 
5183 	if (nla_put_u32(skb,
5184 			QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
5185 			MAX_CONCURRENT_CHAN_ON_24G))
5186 		goto nla_put_failure;
5187 
5188 	if (nla_put_u32(skb,
5189 			QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
5190 			MAX_CONCURRENT_CHAN_ON_5G))
5191 		goto nla_put_failure;
5192 
5193 	hdd_debug("feature flags:");
5194 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
5195 			   feature_flags, sizeof(feature_flags));
5196 
5197 	return wlan_cfg80211_vendor_cmd_reply(skb);
5198 
5199 nla_put_failure:
5200 	wlan_cfg80211_vendor_free_skb(skb);
5201 	return -EINVAL;
5202 }
5203 
5204 /**
5205  * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
5206  * @wiphy:   pointer to wireless wiphy structure.
5207  * @wdev:    pointer to wireless_dev structure.
5208  * @data:    Pointer to the data to be passed via vendor interface
5209  * @data_len:Length of the data to be passed
5210  *
5211  * This is called when wlan driver needs to send supported feature set to
5212  * supplicant upon a request/query from the supplicant.
5213  *
5214  * Return:   Return the Success or Failure code.
5215  */
5216 static int
5217 wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
5218 		struct wireless_dev *wdev,
5219 		const void *data, int data_len)
5220 {
5221 	struct osif_psoc_sync *psoc_sync;
5222 	int errno;
5223 
5224 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
5225 	if (errno)
5226 		return errno;
5227 
5228 	errno = __wlan_hdd_cfg80211_get_features(wiphy, wdev, data, data_len);
5229 
5230 	osif_psoc_sync_op_stop(psoc_sync);
5231 
5232 	return errno;
5233 }
5234 
5235 #define PARAM_NUM_NW \
5236 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
5237 #define PARAM_SET_BSSID \
5238 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
5239 #define PARAM_SET_BSSID_HINT \
5240 		QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT
5241 #define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
5242 #define PARAM_LIST_SSID  QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
5243 #define MAX_ROAMING_PARAM \
5244 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
5245 #define PARAM_NUM_BSSID \
5246 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
5247 #define PARAM_BSSID_PREFS \
5248 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
5249 #define PARAM_ROAM_BSSID \
5250 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
5251 #define PARAM_RSSI_MODIFIER \
5252 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
5253 #define PARAMS_NUM_BSSID \
5254 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
5255 #define PARAM_BSSID_PARAMS \
5256 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
5257 #define PARAM_A_BAND_BOOST_THLD \
5258 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
5259 #define PARAM_A_BAND_PELT_THLD \
5260 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
5261 #define PARAM_A_BAND_BOOST_FACTOR \
5262 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
5263 #define PARAM_A_BAND_PELT_FACTOR \
5264 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
5265 #define PARAM_A_BAND_MAX_BOOST \
5266 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
5267 #define PARAM_ROAM_HISTERESYS \
5268 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
5269 #define PARAM_RSSI_TRIGGER \
5270 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
5271 #define PARAM_ROAM_ENABLE \
5272 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
5273 #define PARAM_ROAM_CONTROL_CONFIG \
5274 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL
5275 #define PARAM_FREQ_LIST_SCHEME \
5276 	QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME
5277 #define PARAM_FREQ_LIST_SCHEME_MAX \
5278 	QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_MAX
5279 #define PARAM_SCAN_FREQ_LIST \
5280 	QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
5281 #define PARAM_SCAN_FREQ_LIST_TYPE \
5282 	QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE
5283 #define PARAM_CAND_SEL_CRITERIA_MAX \
5284 	QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_MAX
5285 #define PARAM_CAND_SEL_SCORE_RSSI \
5286 	QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_RSSI
5287 
5288 const struct nla_policy wlan_hdd_set_roam_param_policy[
5289 			MAX_ROAMING_PARAM + 1] = {
5290 	[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
5291 	[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
5292 	[PARAM_NUM_NW] = {.type = NLA_U32},
5293 	[PARAM_SSID_LIST] = { .type = NLA_NESTED },
5294 	[PARAM_LIST_SSID] = { .type = NLA_BINARY },
5295 	[PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
5296 	[PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
5297 	[PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
5298 	[PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
5299 	[PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
5300 	[PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
5301 	[PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
5302 	[PARAM_ROAM_ENABLE] = {	.type = NLA_S32},
5303 	[PARAM_BSSID_PREFS] = { .type = NLA_NESTED },
5304 	[PARAM_NUM_BSSID] = {.type = NLA_U32},
5305 	[PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
5306 	[PARAM_BSSID_PARAMS] = {.type = NLA_NESTED},
5307 	[PARAMS_NUM_BSSID] = {.type = NLA_U32},
5308 	[PARAM_ROAM_BSSID] = VENDOR_NLA_POLICY_MAC_ADDR,
5309 	[PARAM_SET_BSSID] = VENDOR_NLA_POLICY_MAC_ADDR,
5310 	[PARAM_SET_BSSID_HINT] = {.type = NLA_FLAG},
5311 	[PARAM_ROAM_CONTROL_CONFIG] = {.type = NLA_NESTED},
5312 };
5313 
5314 /**
5315  * hdd_set_allow_list() - parse allow list
5316  * @hdd_ctx: HDD context
5317  * @rso_config: rso config
5318  * @tb: list of attributes
5319  * @vdev_id: vdev id
5320  * @rso_usr_cfg: roam userspace params
5321  *
5322  * Return: 0 on success; error number on failure
5323  */
5324 static int hdd_set_allow_list(struct hdd_context *hdd_ctx,
5325 			      struct rso_config_params *rso_config,
5326 			      struct nlattr **tb, uint8_t vdev_id,
5327 			      struct rso_user_config *rso_usr_cfg)
5328 {
5329 	int rem, i;
5330 	uint32_t buf_len = 0, count;
5331 	struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
5332 	struct nlattr *curr_attr = NULL;
5333 	mac_handle_t mac_handle;
5334 	struct wlan_ssid *ssid;
5335 
5336 	i = 0;
5337 	if (tb[PARAM_NUM_NW]) {
5338 		count = nla_get_u32(tb[PARAM_NUM_NW]);
5339 	} else {
5340 		hdd_err("Number of networks is not provided");
5341 		goto fail;
5342 	}
5343 
5344 	if (count && tb[PARAM_SSID_LIST]) {
5345 		nla_for_each_nested(curr_attr,
5346 				    tb[PARAM_SSID_LIST], rem) {
5347 			if (i == MAX_SSID_ALLOWED_LIST) {
5348 				hdd_err("Excess MAX_SSID_ALLOWED_LIST");
5349 				goto fail;
5350 			}
5351 			if (wlan_cfg80211_nla_parse(tb2,
5352 					QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
5353 					nla_data(curr_attr),
5354 					nla_len(curr_attr),
5355 					wlan_hdd_set_roam_param_policy)) {
5356 				hdd_err("nla_parse failed");
5357 				goto fail;
5358 			}
5359 			/* Parse and Fetch allowed SSID list*/
5360 			if (!tb2[PARAM_LIST_SSID]) {
5361 				hdd_err("attr allowed ssid failed");
5362 				goto fail;
5363 			}
5364 			buf_len = nla_len(tb2[PARAM_LIST_SSID]);
5365 			/*
5366 			 * Upper Layers include a null termination
5367 			 * character. Check for the actual permissible
5368 			 * length of SSID and also ensure not to copy
5369 			 * the NULL termination character to the driver
5370 			 * buffer.
5371 			 */
5372 			if (buf_len <= 1 || (buf_len - 1) > WLAN_SSID_MAX_LEN) {
5373 				hdd_err("Invalid buffer length");
5374 				continue;
5375 			}
5376 
5377 			ssid = &rso_usr_cfg->ssid_allowed_list[i];
5378 			nla_memcpy(ssid->ssid,
5379 				   tb2[PARAM_LIST_SSID], buf_len - 1);
5380 			ssid->length = buf_len - 1;
5381 			hdd_debug("SSID[%d]: " QDF_SSID_FMT ",length = %d", i,
5382 				  QDF_SSID_REF(ssid->length, ssid->ssid),
5383 				  rso_usr_cfg->ssid_allowed_list[i].length);
5384 			i++;
5385 		}
5386 	}
5387 
5388 	if (i != count) {
5389 		hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
5390 		goto fail;
5391 	}
5392 
5393 	rso_usr_cfg->num_ssid_allowed_list = i;
5394 	hdd_debug("Num of Allowed SSID %d", rso_usr_cfg->num_ssid_allowed_list);
5395 	mac_handle = hdd_ctx->mac_handle;
5396 	sme_update_roam_params(mac_handle, vdev_id, rso_config, rso_usr_cfg,
5397 			       REASON_ROAM_SET_SSID_ALLOWED);
5398 	return 0;
5399 
5400 fail:
5401 	return -EINVAL;
5402 }
5403 
5404 /**
5405  * hdd_set_bssid_prefs() - parse set bssid prefs
5406  * @hdd_ctx:        HDD context
5407  * @rso_config: rso config
5408  * @tb:            list of attributes
5409  * @vdev_id:    vdev id
5410  *
5411  * Return: 0 on success; error number on failure
5412  */
5413 static int hdd_set_bssid_prefs(struct hdd_context *hdd_ctx,
5414 			       struct rso_config_params *rso_config,
5415 			       struct nlattr **tb, uint8_t vdev_id)
5416 {
5417 	int rem, i;
5418 	uint32_t count;
5419 	struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
5420 	struct nlattr *curr_attr = NULL;
5421 	mac_handle_t mac_handle;
5422 
5423 	/* Parse and fetch number of preferred BSSID */
5424 	if (!tb[PARAM_NUM_BSSID]) {
5425 		hdd_err("attr num of preferred bssid failed");
5426 		goto fail;
5427 	}
5428 	count = nla_get_u32(tb[PARAM_NUM_BSSID]);
5429 	if (count > MAX_BSSID_FAVORED) {
5430 		hdd_err("Preferred BSSID count %u exceeds max %u",
5431 			count, MAX_BSSID_FAVORED);
5432 		goto fail;
5433 	}
5434 	hdd_debug("Num of Preferred BSSID (%d)", count);
5435 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
5436 		hdd_err("attr Preferred BSSID failed");
5437 		goto fail;
5438 	}
5439 
5440 	i = 0;
5441 	nla_for_each_nested(curr_attr,
5442 		tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
5443 		rem) {
5444 		if (i == count) {
5445 			hdd_warn("Ignoring excess Preferred BSSID");
5446 			break;
5447 		}
5448 
5449 		if (wlan_cfg80211_nla_parse(tb2,
5450 					 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
5451 					 nla_data(curr_attr),
5452 					 nla_len(curr_attr),
5453 					 wlan_hdd_set_roam_param_policy)) {
5454 			hdd_err("nla_parse failed");
5455 			goto fail;
5456 		}
5457 		/* Parse and fetch MAC address */
5458 		if (!tb2[PARAM_ROAM_BSSID]) {
5459 			hdd_err("attr mac address failed");
5460 			goto fail;
5461 		}
5462 		nla_memcpy(rso_config->bssid_favored[i].bytes,
5463 			  tb2[PARAM_ROAM_BSSID],
5464 			  QDF_MAC_ADDR_SIZE);
5465 		hdd_debug(QDF_MAC_ADDR_FMT,
5466 			  QDF_MAC_ADDR_REF(rso_config->bssid_favored[i].bytes));
5467 		/* Parse and fetch preference factor*/
5468 		if (!tb2[PARAM_RSSI_MODIFIER]) {
5469 			hdd_err("BSSID Preference score failed");
5470 			goto fail;
5471 		}
5472 		rso_config->bssid_favored_factor[i] = nla_get_u32(
5473 			tb2[PARAM_RSSI_MODIFIER]);
5474 		hdd_debug("BSSID Preference score (%d)",
5475 			  rso_config->bssid_favored_factor[i]);
5476 		i++;
5477 	}
5478 	if (i < count)
5479 		hdd_warn("Num Preferred BSSID %u less than expected %u",
5480 				 i, count);
5481 
5482 	rso_config->num_bssid_favored = i;
5483 	mac_handle = hdd_ctx->mac_handle;
5484 	sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
5485 			       REASON_ROAM_SET_FAVORED_BSSID);
5486 
5487 	return 0;
5488 
5489 fail:
5490 	return -EINVAL;
5491 }
5492 
5493 /**
5494  * hdd_set_denylist_bssid() - parse set denylist bssid
5495  * @hdd_ctx:        HDD context
5496  * @rso_config:   roam params
5497  * @tb:            list of attributes
5498  * @vdev_id:    vdev id
5499  *
5500  * Return: 0 on success; error number on failure
5501  */
5502 static int hdd_set_denylist_bssid(struct hdd_context *hdd_ctx,
5503 				  struct rso_config_params *rso_config,
5504 				  struct nlattr **tb,
5505 				  uint8_t vdev_id)
5506 {
5507 	int rem, i;
5508 	uint32_t count;
5509 	uint8_t j = 0;
5510 	struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
5511 	struct nlattr *curr_attr = NULL;
5512 	struct qdf_mac_addr *deny_list_bssid;
5513 	mac_handle_t mac_handle;
5514 
5515 	/* Parse and fetch number of denylist BSSID */
5516 	if (!tb[PARAMS_NUM_BSSID]) {
5517 		hdd_err("attr num of denylist bssid failed");
5518 		goto fail;
5519 	}
5520 	count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
5521 	if (count > MAX_BSSID_AVOID_LIST) {
5522 		hdd_err("Denylist BSSID count %u exceeds max %u",
5523 			count, MAX_BSSID_AVOID_LIST);
5524 		goto fail;
5525 	}
5526 	hdd_debug("Num of denylist BSSID (%d)", count);
5527 	deny_list_bssid = qdf_mem_malloc(sizeof(*deny_list_bssid) *
5528 					  MAX_BSSID_AVOID_LIST);
5529 	if (!deny_list_bssid)
5530 		goto fail;
5531 
5532 	i = 0;
5533 	if (count && tb[PARAM_BSSID_PARAMS]) {
5534 		nla_for_each_nested(curr_attr,
5535 			tb[PARAM_BSSID_PARAMS],
5536 			rem) {
5537 			if (i == count) {
5538 				hdd_warn("Ignoring excess Denylist BSSID");
5539 				break;
5540 			}
5541 
5542 			if (wlan_cfg80211_nla_parse(tb2,
5543 					 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
5544 					 nla_data(curr_attr),
5545 					 nla_len(curr_attr),
5546 					 wlan_hdd_set_roam_param_policy)) {
5547 				hdd_err("nla_parse failed");
5548 				qdf_mem_free(deny_list_bssid);
5549 				goto fail;
5550 			}
5551 			/* Parse and fetch MAC address */
5552 			if (!tb2[PARAM_SET_BSSID]) {
5553 				hdd_err("attr denylist addr failed");
5554 				qdf_mem_free(deny_list_bssid);
5555 				goto fail;
5556 			}
5557 			if (tb2[PARAM_SET_BSSID_HINT]) {
5558 				struct reject_ap_info ap_info;
5559 
5560 				qdf_mem_zero(&ap_info,
5561 					     sizeof(struct reject_ap_info));
5562 				nla_memcpy(ap_info.bssid.bytes,
5563 					   tb2[PARAM_SET_BSSID],
5564 					   QDF_MAC_ADDR_SIZE);
5565 				ap_info.reject_ap_type = USERSPACE_AVOID_TYPE;
5566 				ap_info.reject_reason =
5567 						REASON_USERSPACE_AVOID_LIST;
5568 				ap_info.source = ADDED_BY_DRIVER;
5569 
5570 				/* This BSSID is avoided and not denylisted */
5571 				ucfg_dlm_add_bssid_to_reject_list(hdd_ctx->pdev,
5572 								  &ap_info);
5573 				i++;
5574 				continue;
5575 			}
5576 			nla_memcpy(deny_list_bssid[j].bytes,
5577 				   tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
5578 			hdd_debug(QDF_MAC_ADDR_FMT,
5579 				  QDF_MAC_ADDR_REF(deny_list_bssid[j].bytes));
5580 			i++;
5581 			j++;
5582 		}
5583 	}
5584 
5585 	if (i < count)
5586 		hdd_warn("Num Denylist BSSID %u less than expected %u",
5587 			 i, count);
5588 
5589 	/* Send the denylist to the denylist mgr component */
5590 	ucfg_dlm_add_userspace_deny_list(hdd_ctx->pdev, deny_list_bssid, j);
5591 	qdf_mem_free(deny_list_bssid);
5592 	mac_handle = hdd_ctx->mac_handle;
5593 	sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
5594 			       REASON_ROAM_SET_DENYLIST_BSSID);
5595 
5596 	return 0;
5597 fail:
5598 	return -EINVAL;
5599 }
5600 
5601 static const struct nla_policy
5602 roam_scan_freq_list_scheme_policy[PARAM_FREQ_LIST_SCHEME_MAX + 1] = {
5603 	[PARAM_SCAN_FREQ_LIST_TYPE] = {.type = NLA_U32},
5604 	[PARAM_SCAN_FREQ_LIST] = {.type = NLA_NESTED},
5605 };
5606 
5607 /**
5608  * hdd_send_roam_scan_channel_freq_list_to_sme() - Send control roam scan freqs
5609  * @hdd_ctx: HDD context
5610  * @vdev_id: vdev id
5611  * @tb: Nested attribute carrying frequency list scheme
5612  *
5613  * Extracts the frequency list and frequency list type from the frequency
5614  * list scheme and send the frequencies to SME.
5615  *
5616  * Return: QDF_STATUS
5617  */
5618 static QDF_STATUS
5619 hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context *hdd_ctx,
5620 					    uint8_t vdev_id, struct nlattr *tb)
5621 {
5622 	QDF_STATUS status;
5623 	struct nlattr *tb2[PARAM_FREQ_LIST_SCHEME_MAX + 1], *curr_attr;
5624 	uint8_t num_chan = 0;
5625 	uint32_t freq_list[SIR_MAX_SUPPORTED_CHANNEL_LIST] = {0};
5626 	uint32_t list_type;
5627 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
5628 	int rem;
5629 
5630 	if (wlan_cfg80211_nla_parse_nested(tb2, PARAM_FREQ_LIST_SCHEME_MAX,
5631 					   tb,
5632 					   roam_scan_freq_list_scheme_policy)) {
5633 		hdd_err("nla_parse failed");
5634 		return QDF_STATUS_E_INVAL;
5635 	}
5636 
5637 	if (!tb2[PARAM_SCAN_FREQ_LIST] || !tb2[PARAM_SCAN_FREQ_LIST_TYPE]) {
5638 		hdd_err("ROAM_CONTROL_SCAN_FREQ_LIST or type are not present");
5639 		return QDF_STATUS_E_INVAL;
5640 	}
5641 
5642 	list_type = nla_get_u32(tb2[PARAM_SCAN_FREQ_LIST_TYPE]);
5643 	if (list_type != QCA_PREFERRED_SCAN_FREQ_LIST &&
5644 	    list_type != QCA_SPECIFIC_SCAN_FREQ_LIST) {
5645 		hdd_err("Invalid freq list type received: %u", list_type);
5646 		return QDF_STATUS_E_INVAL;
5647 	}
5648 
5649 	nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
5650 		if (num_chan >= SIR_MAX_SUPPORTED_CHANNEL_LIST) {
5651 			hdd_err("number of channels (%d) supported exceeded max (%d)",
5652 				num_chan, SIR_MAX_SUPPORTED_CHANNEL_LIST);
5653 			return QDF_STATUS_E_INVAL;
5654 		}
5655 		num_chan++;
5656 	}
5657 	num_chan = 0;
5658 
5659 	nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
5660 		if (nla_len(curr_attr) != sizeof(uint32_t)) {
5661 			hdd_err("len is not correct for frequency %d",
5662 				num_chan);
5663 			return QDF_STATUS_E_INVAL;
5664 		}
5665 		freq_list[num_chan++] = nla_get_u32(curr_attr);
5666 	}
5667 
5668 	status = sme_update_roam_scan_freq_list(mac_handle, vdev_id, freq_list,
5669 						num_chan, list_type);
5670 	if (QDF_IS_STATUS_ERROR(status))
5671 		hdd_err("Failed to update channel list information");
5672 
5673 	return status;
5674 }
5675 
5676 static const struct nla_policy
5677 roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = {
5678 	[QCA_ATTR_ROAM_CONTROL_ENABLE] = {.type = NLA_U8},
5679 	[QCA_ATTR_ROAM_CONTROL_STATUS] = {.type = NLA_U8},
5680 	[PARAM_FREQ_LIST_SCHEME] = {.type = NLA_NESTED},
5681 	[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD] = {.type = NLA_U32},
5682 	[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL] = {.type = NLA_FLAG},
5683 	[QCA_ATTR_ROAM_CONTROL_TRIGGERS] = {.type = NLA_U32},
5684 	[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA] = {.type = NLA_NESTED},
5685 	[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD] = {.type = NLA_U32},
5686 	[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME] = {.type = NLA_U32},
5687 	[QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD] = {.type = NLA_U32},
5688 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD] = {.type = NLA_U32},
5689 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ] = {
5690 			.type = NLA_U32},
5691 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ] = {
5692 			.type = NLA_U32},
5693 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ] = {
5694 			.type = NLA_U32},
5695 	[QCA_ATTR_ROAM_CONTROL_USER_REASON] = {.type = NLA_U32},
5696 	[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS] = {.type = NLA_U32},
5697 	[QCA_ATTR_ROAM_CONTROL_BAND_MASK] = {.type = NLA_U32},
5698 	[QCA_ATTR_ROAM_CONTROL_RX_LINKSPEED_THRESHOLD] = {.type = NLA_U16},
5699 	[QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX] = {.type = NLA_U16},
5700 	[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_NO_REUSE_PARTIAL_SCAN_FREQ] = {
5701 			.type = NLA_U8},
5702 	[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_6GHZ_ONLY_ON_PRIOR_DISCOVERY] = {
5703 			.type = NLA_U8},
5704 };
5705 
5706 /**
5707  * hdd_send_roam_full_scan_period_to_sme() - Send full roam scan period to SME
5708  * @hdd_ctx: HDD context
5709  * @vdev_id: vdev id
5710  * @full_roam_scan_period: Idle period in seconds between two successive
5711  *			   full channel roam scans
5712  * @check_and_update: If this is true/set, update the value only if the current
5713  *		      configured value is not same as global value read from
5714  *		      ini param. This is to give priority to the user configured
5715  *		      values and retain the value, if updated already.
5716  *		      If this is not set, update the value without any check.
5717  *
5718  * Validate the full roam scan period and send it to firmware
5719  *
5720  * Return: QDF_STATUS
5721  */
5722 static QDF_STATUS
5723 hdd_send_roam_full_scan_period_to_sme(struct hdd_context *hdd_ctx,
5724 				      uint8_t vdev_id,
5725 				      uint32_t full_roam_scan_period,
5726 				      bool check_and_update)
5727 {
5728 	QDF_STATUS status;
5729 	uint32_t full_roam_scan_period_current, full_roam_scan_period_global;
5730 
5731 	if (!ucfg_mlme_validate_full_roam_scan_period(full_roam_scan_period))
5732 		return QDF_STATUS_E_INVAL;
5733 
5734 	hdd_debug("Received Command to Set full roam scan period = %u",
5735 		  full_roam_scan_period);
5736 
5737 	status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
5738 					       &full_roam_scan_period_current);
5739 	if (QDF_IS_STATUS_ERROR(status))
5740 		return status;
5741 
5742 	full_roam_scan_period_global =
5743 		sme_get_full_roam_scan_period_global(hdd_ctx->mac_handle);
5744 	if (check_and_update &&
5745 	    full_roam_scan_period_current != full_roam_scan_period_global) {
5746 		hdd_debug("Full roam scan period is already updated, value: %u",
5747 			  full_roam_scan_period_current);
5748 		return QDF_STATUS_SUCCESS;
5749 	}
5750 	status = sme_update_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
5751 						  full_roam_scan_period);
5752 	if (QDF_IS_STATUS_ERROR(status))
5753 		hdd_err("Failed to set full scan period");
5754 
5755 	return status;
5756 }
5757 
5758 /**
5759  * wlan_hdd_convert_control_roam_trigger_bitmap  - Convert the
5760  * vendor specific reason code to internal reason code.
5761  * @trigger_reason_bitmap: Vendor specific roam trigger bitmap
5762  *
5763  * Return: Internal roam trigger bitmap
5764  */
5765 static uint32_t
5766 wlan_hdd_convert_control_roam_trigger_bitmap(uint32_t trigger_reason_bitmap)
5767 {
5768 	uint32_t drv_trigger_bitmap = 0, all_bitmap;
5769 
5770 	/* Enable the complete trigger bitmap when all bits are set in
5771 	 * the control config bitmap
5772 	 */
5773 	all_bitmap = (QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN << 1) - 1;
5774 	if (trigger_reason_bitmap == all_bitmap)
5775 		return BIT(ROAM_TRIGGER_REASON_MAX) - 1;
5776 
5777 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PER)
5778 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PER);
5779 
5780 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BEACON_MISS)
5781 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BMISS);
5782 
5783 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_POOR_RSSI)
5784 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_LOW_RSSI);
5785 
5786 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BETTER_RSSI)
5787 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_HIGH_RSSI);
5788 
5789 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PERIODIC)
5790 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PERIODIC);
5791 
5792 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DENSE)
5793 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_DENSE);
5794 
5795 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BTM)
5796 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BTM);
5797 
5798 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
5799 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BSS_LOAD);
5800 
5801 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_USER_TRIGGER)
5802 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_FORCED);
5803 
5804 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DEAUTH)
5805 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_DEAUTH);
5806 
5807 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_IDLE)
5808 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_IDLE);
5809 
5810 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_TX_FAILURES)
5811 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_STA_KICKOUT);
5812 
5813 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN)
5814 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BACKGROUND);
5815 
5816 	return drv_trigger_bitmap;
5817 }
5818 
5819 /**
5820  * wlan_hdd_convert_control_roam_scan_scheme_bitmap()  - Convert the
5821  * vendor specific roam scan scheme for roam triggers to internal roam trigger
5822  * bitmap for partial scan.
5823  * @trigger_reason_bitmap: Vendor specific roam trigger bitmap
5824  *
5825  * Return: Internal roam scan scheme bitmap
5826  */
5827 static uint32_t
5828 wlan_hdd_convert_control_roam_scan_scheme_bitmap(uint32_t trigger_reason_bitmap)
5829 {
5830 	uint32_t drv_scan_scheme_bitmap = 0;
5831 
5832 	/*
5833 	 * Partial scan scheme override over default scan scheme only for
5834 	 * the PER, BMISS, Low RSSI, BTM, BSS_LOAD Triggers
5835 	 */
5836 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PER)
5837 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_PER);
5838 
5839 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BEACON_MISS)
5840 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BMISS);
5841 
5842 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_POOR_RSSI)
5843 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_LOW_RSSI);
5844 
5845 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BTM)
5846 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BTM);
5847 
5848 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
5849 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BSS_LOAD);
5850 
5851 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_USER_TRIGGER)
5852 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_FORCED);
5853 
5854 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DEAUTH)
5855 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_DEAUTH);
5856 
5857 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_IDLE)
5858 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_IDLE);
5859 
5860 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_TX_FAILURES)
5861 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_STA_KICKOUT);
5862 
5863 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN)
5864 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BACKGROUND);
5865 
5866 	return drv_scan_scheme_bitmap;
5867 }
5868 
5869 /**
5870  * hdd_send_roam_triggers_to_sme() - Send roam trigger bitmap to SME
5871  * @hdd_ctx: HDD context
5872  * @vdev_id: vdev id
5873  * @roam_trigger_bitmap: Vendor configured roam trigger bitmap to be configured
5874  *			 to firmware
5875  *
5876  * Send the roam trigger bitmap received to SME
5877  *
5878  * Return: QDF_STATUS
5879  */
5880 static QDF_STATUS
5881 hdd_send_roam_triggers_to_sme(struct hdd_context *hdd_ctx,
5882 			      uint8_t vdev_id,
5883 			      uint32_t roam_trigger_bitmap)
5884 {
5885 	QDF_STATUS status;
5886 	struct wlan_roam_triggers triggers;
5887 	struct wlan_hdd_link_info *link_info;
5888 
5889 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
5890 	if (!link_info) {
5891 		hdd_err("Invalid vdev");
5892 		return QDF_STATUS_E_FAILURE;
5893 	}
5894 
5895 	if (link_info->adapter->device_mode != QDF_STA_MODE) {
5896 		hdd_err("Roam trigger bitmap supported only in STA mode");
5897 		return QDF_STATUS_E_FAILURE;
5898 	}
5899 
5900 	triggers.vdev_id = vdev_id;
5901 	triggers.trigger_bitmap =
5902 	    wlan_hdd_convert_control_roam_trigger_bitmap(roam_trigger_bitmap);
5903 	hdd_debug("trigger bitmap: 0x%x converted trigger_bitmap: 0x%x",
5904 		  roam_trigger_bitmap, triggers.trigger_bitmap);
5905 	/*
5906 	 * In standalone STA, if this vendor command is received between
5907 	 * ROAM_START and roam synch indication, it is better to reject
5908 	 * roam disable since driver would send vdev_params command to
5909 	 * de-initialize roaming structures in fw.
5910 	 * In STA+STA mode, if this vendor command to enable roaming is
5911 	 * received for one STA vdev and ROAM_START was received for other
5912 	 * STA vdev, then also driver would be send vdev_params command to
5913 	 * de-initialize roaming structures in fw on the roaming enabled
5914 	 * vdev.
5915 	 */
5916 	if (hdd_is_roaming_in_progress(hdd_ctx)) {
5917 		mlme_set_roam_trigger_bitmap(hdd_ctx->psoc,
5918 					     link_info->vdev_id,
5919 					     triggers.trigger_bitmap);
5920 		hdd_err("Reject set roam trigger as roaming is in progress");
5921 
5922 		return QDF_STATUS_E_BUSY;
5923 	}
5924 
5925 	/*
5926 	 * roam trigger bitmap is > 0 - Roam triggers are set.
5927 	 * roam trigger bitmap is 0 - Disable roaming
5928 	 *
5929 	 * For both the above modes, reset the roam scan scheme bitmap to
5930 	 * 0.
5931 	 */
5932 	status = ucfg_cm_update_roam_scan_scheme_bitmap(hdd_ctx->psoc,
5933 							vdev_id, 0);
5934 
5935 	status = ucfg_cm_rso_set_roam_trigger(hdd_ctx->pdev, vdev_id,
5936 					      &triggers);
5937 	if (QDF_IS_STATUS_ERROR(status))
5938 		hdd_err("Failed to set roam control trigger bitmap");
5939 
5940 	return status;
5941 }
5942 
5943 /*
5944  * Disable default scoring algorithm. This is intended to set all bits of the
5945  * disable_bitmap in struct scoring_param.
5946  */
5947 #define DISABLE_SCORING 0
5948 
5949 /*
5950  * Enable scoring algorithm. This is intended to clear all bits of the
5951  * disable_bitmap in struct scoring_param.
5952  */
5953 #define ENABLE_SCORING 1
5954 
5955 /*
5956  * Controlled roam candidate selection is enabled from userspace.
5957  * Driver/firmware should honor the selection criteria
5958  */
5959 #define CONTROL_ROAM_CAND_SEL_ENABLE 1
5960 
5961 /*
5962  * Controlled roam candidate selection is disabled from userspace.
5963  * Driver/firmware can use its internal candidate selection criteria
5964  */
5965 #define CONTROL_ROAM_CAND_SEL_DISABLE 0
5966 
5967 static const struct nla_policy
5968 roam_scan_cand_sel_policy[PARAM_CAND_SEL_CRITERIA_MAX + 1] = {
5969 	[PARAM_CAND_SEL_SCORE_RSSI] = {.type = NLA_U8},
5970 };
5971 
5972 /**
5973  * hdd_send_roam_cand_sel_criteria_to_sme() - Send candidate sel criteria to SME
5974  * @hdd_ctx: HDD context
5975  * @vdev_id: vdev id
5976  * @attr: Nested attribute carrying candidate selection criteria
5977  *
5978  * Extract different candidate sel criteria mentioned and convert it to
5979  * driver/firmware understable format.
5980  *
5981  * Return: QDF_STATUS
5982  */
5983 static QDF_STATUS
5984 hdd_send_roam_cand_sel_criteria_to_sme(struct hdd_context *hdd_ctx,
5985 				       uint8_t vdev_id,
5986 				       struct nlattr *attr)
5987 {
5988 	QDF_STATUS status;
5989 	struct nlattr *tb2[PARAM_CAND_SEL_CRITERIA_MAX + 1];
5990 	struct nlattr *curr_attr;
5991 	uint8_t sel_criteria = 0, rssi_score = 0, scoring;
5992 	int rem;
5993 
5994 	hdd_debug("Received Command to Set candidate selection criteria ");
5995 	nla_for_each_nested(curr_attr, attr, rem) {
5996 		sel_criteria++;
5997 		break;
5998 	}
5999 
6000 	if (sel_criteria &&
6001 	    wlan_cfg80211_nla_parse_nested(tb2, PARAM_CAND_SEL_CRITERIA_MAX,
6002 					   attr, roam_scan_cand_sel_policy)) {
6003 		hdd_err("nla_parse failed");
6004 		return QDF_STATUS_E_INVAL;
6005 	}
6006 
6007 	/*
6008 	 * Firmware supports the below configurations currently,
6009 	 * 1. Default selection criteria where all scoring params
6010 	 *    are enabled and different weightages/scores are given to
6011 	 *    different parameters.
6012 	 *    When userspace doesn't specify any candidate selection criteria,
6013 	 *    this will be enabled.
6014 	 * 2. Legacy candidate selection criteria where scoring
6015 	 *    algorithm is disabled and only RSSI is considered for
6016 	 *    roam candidate selection.
6017 	 *    When userspace specify 100% weightage for RSSI, this will
6018 	 *    be enabled.
6019 	 * Rest of the combinations are not supported for now.
6020 	 */
6021 	if (sel_criteria == CONTROL_ROAM_CAND_SEL_ENABLE) {
6022 		/* Legacy selection criteria: 100% weightage to RSSI */
6023 		if (tb2[PARAM_CAND_SEL_SCORE_RSSI])
6024 			rssi_score = nla_get_u8(tb2[PARAM_CAND_SEL_SCORE_RSSI]);
6025 
6026 		if (rssi_score != 100) {
6027 			hdd_debug("Ignore the candidate selection criteria");
6028 			return QDF_STATUS_E_INVAL;
6029 		}
6030 		scoring = DISABLE_SCORING;
6031 	} else {
6032 		/* Default selection criteria */
6033 		scoring = ENABLE_SCORING;
6034 	}
6035 
6036 	status = sme_modify_roam_cand_sel_criteria(hdd_ctx->mac_handle, vdev_id,
6037 						   !!scoring);
6038 	if (QDF_IS_STATUS_ERROR(status))
6039 		hdd_err("Failed to disable scoring");
6040 
6041 	return status;
6042 }
6043 
6044 /**
6045  * hdd_send_roam_scan_period_to_sme() - Send roam scan period to SME
6046  * @hdd_ctx: HDD context
6047  * @vdev_id: vdev id
6048  * @roam_scan_period: Roam scan period in seconds
6049  * @check_and_update: If this is true/set, update the value only if the current
6050  *		      configured value is not same as global value read from
6051  *		      ini param. This is to give priority to the user configured
6052  *		      values and retain the value, if updated already.
6053  *		      If this is not set, update the value without any check.
6054  *
6055  * Validate the roam scan period and send it to firmware if valid.
6056  *
6057  * Return: QDF_STATUS
6058  */
6059 static QDF_STATUS
6060 hdd_send_roam_scan_period_to_sme(struct hdd_context *hdd_ctx,
6061 				 uint8_t vdev_id,
6062 				 uint32_t roam_scan_period,
6063 				 bool check_and_update)
6064 {
6065 	QDF_STATUS status;
6066 	uint16_t roam_scan_period_current, roam_scan_period_global = 0;
6067 
6068 	if (!ucfg_mlme_validate_scan_period(hdd_ctx->psoc,
6069 					    roam_scan_period * 1000))
6070 		return QDF_STATUS_E_INVAL;
6071 
6072 	hdd_debug("Received Command to Set roam scan period (Empty Scan refresh period) = %d",
6073 		  roam_scan_period);
6074 
6075 	status = ucfg_cm_get_empty_scan_refresh_period(
6076 						hdd_ctx->psoc, vdev_id,
6077 						&roam_scan_period_current);
6078 	if (QDF_IS_STATUS_ERROR(status))
6079 		return status;
6080 
6081 	ucfg_cm_get_empty_scan_refresh_period_global(hdd_ctx->psoc,
6082 						     &roam_scan_period_global);
6083 	if (check_and_update &&
6084 	    roam_scan_period_current != roam_scan_period_global) {
6085 		hdd_debug("roam scan period is already updated, value: %u",
6086 			  roam_scan_period_current / 1000);
6087 		return QDF_STATUS_SUCCESS;
6088 	}
6089 	status = sme_update_empty_scan_refresh_period(hdd_ctx->mac_handle,
6090 						      vdev_id,
6091 						      roam_scan_period * 1000);
6092 	if (QDF_IS_STATUS_ERROR(status))
6093 		hdd_err("Failed to set scan period");
6094 
6095 	return status;
6096 }
6097 
6098 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && \
6099 defined(FEATURE_RX_LINKSPEED_ROAM_TRIGGER)
6100 /**
6101  * hdd_set_roam_rx_linkspeed_threshold() - Set rx link speed threshold
6102  * @psoc: Pointer to psoc
6103  * @vdev: vdev
6104  * @linkspeed_threshold: threshold value to set
6105  *
6106  * Return: none
6107  */
6108 static QDF_STATUS
6109 hdd_set_roam_rx_linkspeed_threshold(struct wlan_objmgr_psoc *psoc,
6110 				    struct wlan_objmgr_vdev *vdev,
6111 				    uint32_t linkspeed_threshold)
6112 {
6113 	if (!ucfg_cm_is_linkspeed_roam_trigger_supported(psoc))
6114 		return QDF_STATUS_E_NOSUPPORT;
6115 
6116 	if (linkspeed_threshold) {
6117 		dp_ucfg_enable_link_monitoring(psoc, vdev,
6118 					       linkspeed_threshold);
6119 	} else {
6120 		dp_ucfg_disable_link_monitoring(psoc, vdev);
6121 		wlan_hdd_link_speed_update(psoc, wlan_vdev_get_id(vdev),
6122 					   false);
6123 	}
6124 
6125 	return QDF_STATUS_SUCCESS;
6126 }
6127 #else
6128 static inline QDF_STATUS
6129 hdd_set_roam_rx_linkspeed_threshold(struct wlan_objmgr_psoc *psoc,
6130 				    struct wlan_objmgr_vdev *vdev,
6131 				    uint32_t linkspeed_threshold)
6132 {
6133 	return QDF_STATUS_E_NOSUPPORT;
6134 }
6135 #endif
6136 
6137 /* Roam Hand-off delay range is 20 to 1000 msec */
6138 #define MIN_ROAM_HO_DELAY 20
6139 #define MAX_ROAM_HO_DELAY 1000
6140 
6141 /* Include/Exclude roam partial scan channels in full scan */
6142 #define INCLUDE_ROAM_PARTIAL_SCAN_FREQ 0
6143 #define EXCLUDE_ROAM_PARTIAL_SCAN_FREQ 1
6144 
6145 /* Include the supported 6 GHz PSC channels in full scan by default */
6146 #define INCLUDE_6GHZ_IN_FULL_SCAN_BY_DEF	0
6147 /* Include the 6 GHz channels in roam full scan only on prior discovery */
6148 #define INCLUDE_6GHZ_IN_FULL_SCAN_IF_DISC	1
6149 
6150 #ifdef WLAN_VENDOR_HANDOFF_CONTROL
6151 /**
6152  * hdd_get_handoff_param() - get vendor handoff parameters
6153  * @hdd_ctx: HDD context
6154  * @vdev_id: vdev id
6155  *
6156  * Wrapper function for hdd_cm_get_handoff_param
6157  *
6158  * Return: QDF_STATUS
6159  */
6160 static QDF_STATUS hdd_get_handoff_param(struct hdd_context *hdd_ctx,
6161 					uint8_t vdev_id)
6162 {
6163 	return hdd_cm_get_handoff_param(hdd_ctx->psoc, vdev_id,
6164 					VENDOR_CONTROL_PARAM_ROAM_ALL);
6165 }
6166 #else
6167 static inline QDF_STATUS
6168 hdd_get_handoff_param(struct hdd_context *hdd_ctx, uint8_t vdev_id)
6169 {
6170 	return QDF_STATUS_SUCCESS;
6171 }
6172 #endif
6173 
6174 /**
6175  * hdd_set_roam_with_control_config() - Set roam control configuration
6176  * @hdd_ctx: HDD context
6177  * @tb: List of attributes carrying roam subcmd data
6178  * @vdev_id: vdev id
6179  *
6180  * Extracts the attribute PARAM_ROAM_CONTROL_CONFIG from the attributes list tb
6181  * and sends the corresponding roam control configuration to driver/firmware.
6182  *
6183  * Return: 0 on success; error number on failure
6184  */
6185 static int
6186 hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx,
6187 				 struct nlattr **tb,
6188 				 uint8_t vdev_id)
6189 {
6190 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6191 	struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1], *attr;
6192 	uint32_t value;
6193 	struct wlan_cm_roam_vendor_btm_params param = {0};
6194 	bool is_wtc_param_updated = false;
6195 	uint32_t band_mask;
6196 	uint16_t threshold;
6197 	struct wlan_hdd_link_info *link_info;
6198 	uint8_t roam_control_enable = false;
6199 
6200 	hdd_enter();
6201 
6202 	/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
6203 	if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
6204 		hdd_err("Attribute CONTROL_CONFIG is not present");
6205 		return -EINVAL;
6206 	}
6207 
6208 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6209 	if (!link_info || hdd_validate_adapter(link_info->adapter))
6210 		return QDF_STATUS_E_FAILURE;
6211 
6212 	if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
6213 					   tb[PARAM_ROAM_CONTROL_CONFIG],
6214 					   roam_control_policy)) {
6215 		hdd_err("nla_parse failed");
6216 		return -EINVAL;
6217 	}
6218 
6219 	attr = tb2[PARAM_FREQ_LIST_SCHEME];
6220 	if (attr) {
6221 		status = hdd_send_roam_scan_channel_freq_list_to_sme(hdd_ctx,
6222 								     vdev_id,
6223 								     attr);
6224 		if (QDF_IS_STATUS_ERROR(status))
6225 			hdd_err("failed to config roam control");
6226 	}
6227 
6228 	if (tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]) {
6229 		value = nla_get_u32(tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]);
6230 		hdd_debug("Received roam trigger bitmap: 0x%x", value);
6231 		status = hdd_send_roam_triggers_to_sme(hdd_ctx,
6232 						       vdev_id,
6233 						       value);
6234 		if (status)
6235 			hdd_err("failed to config roam triggers");
6236 	}
6237 
6238 	attr = tb2[QCA_ATTR_ROAM_CONTROL_ENABLE];
6239 	if (attr) {
6240 		roam_control_enable = nla_get_u8(attr);
6241 		if (roam_control_enable &&
6242 		    ucfg_cm_roam_is_vendor_handoff_control_enable(
6243 			hdd_ctx->psoc)) {
6244 			status = hdd_get_handoff_param(hdd_ctx, vdev_id);
6245 			if (QDF_IS_STATUS_ERROR(status)) {
6246 				hdd_err("failed to get vendor handoff params");
6247 				return qdf_status_to_os_return(status);
6248 			}
6249 		}
6250 
6251 		hdd_debug("Parse and send roam control to FW: %s",
6252 			  roam_control_enable ? "Enable" : "Disable");
6253 
6254 		status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
6255 						    vdev_id,
6256 						    roam_control_enable);
6257 		if (QDF_IS_STATUS_ERROR(status))
6258 			hdd_err("failed to enable/disable roam control config");
6259 
6260 		attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
6261 		if (attr) {
6262 			/* Default value received as part of Roam control enable
6263 			 * Set this only if user hasn't configured any value so
6264 			 * far.
6265 			 */
6266 			value = nla_get_u32(attr);
6267 			status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
6268 								  vdev_id,
6269 								  value, true);
6270 			if (QDF_IS_STATUS_ERROR(status))
6271 				hdd_err("failed to send scan period to firmware");
6272 		}
6273 
6274 		attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
6275 		if (attr) {
6276 			value = nla_get_u32(attr);
6277 			/* Default value received as part of Roam control enable
6278 			 * Set this only if user hasn't configured any value so
6279 			 * far.
6280 			 */
6281 			status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
6282 								       vdev_id,
6283 								       value,
6284 								       true);
6285 			if (status)
6286 				hdd_err("failed to config full scan period");
6287 		}
6288 	} else {
6289 		attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
6290 		if (attr) {
6291 			/* User configured value, cache the value directly */
6292 			value = nla_get_u32(attr);
6293 			status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
6294 								  vdev_id,
6295 								  value, false);
6296 			if (QDF_IS_STATUS_ERROR(status))
6297 				hdd_err("failed to send scan period to firmware");
6298 		}
6299 
6300 		attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
6301 		if (attr) {
6302 			value = nla_get_u32(attr);
6303 			/* User configured value, cache the value directly */
6304 			status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
6305 								       vdev_id,
6306 								       value,
6307 								       false);
6308 			if (status)
6309 				hdd_err("failed to config full scan period");
6310 		}
6311 	}
6312 
6313 	attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS];
6314 	if (attr) {
6315 		value = wlan_hdd_convert_control_roam_scan_scheme_bitmap(
6316 							nla_get_u32(attr));
6317 		status = ucfg_cm_update_roam_scan_scheme_bitmap(hdd_ctx->psoc,
6318 								vdev_id,
6319 								value);
6320 	}
6321 
6322 	/* Scoring and roam candidate selection criteria */
6323 	attr = tb2[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA];
6324 	if (attr) {
6325 		status = hdd_send_roam_cand_sel_criteria_to_sme(hdd_ctx,
6326 								vdev_id, attr);
6327 		if (QDF_IS_STATUS_ERROR(status))
6328 			hdd_err("failed to set candidate selection criteria");
6329 	}
6330 
6331 	attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME];
6332 	if (attr) {
6333 		param.scan_freq_scheme = nla_get_u32(attr);
6334 		is_wtc_param_updated = true;
6335 	}
6336 
6337 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD];
6338 	if (attr) {
6339 		param.connected_rssi_threshold = nla_get_u32(attr);
6340 		is_wtc_param_updated = true;
6341 	}
6342 
6343 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD];
6344 	if (attr) {
6345 		param.candidate_rssi_threshold_2g = nla_get_u32(attr);
6346 		is_wtc_param_updated = true;
6347 	}
6348 
6349 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ];
6350 	if (attr) {
6351 		param.candidate_rssi_threshold_2g = nla_get_u32(attr);
6352 		is_wtc_param_updated = true;
6353 	}
6354 
6355 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ];
6356 	if (attr) {
6357 		param.candidate_rssi_threshold_5g = nla_get_u32(attr);
6358 		is_wtc_param_updated = true;
6359 	} else {
6360 		param.candidate_rssi_threshold_5g =
6361 					param.candidate_rssi_threshold_2g;
6362 	}
6363 
6364 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ];
6365 	if (attr) {
6366 		param.candidate_rssi_threshold_6g = nla_get_u32(attr);
6367 		is_wtc_param_updated = true;
6368 	} else {
6369 		param.candidate_rssi_threshold_6g =
6370 					param.candidate_rssi_threshold_2g;
6371 	}
6372 
6373 	attr = tb2[QCA_ATTR_ROAM_CONTROL_USER_REASON];
6374 	if (attr) {
6375 		param.user_roam_reason = nla_get_u32(attr);
6376 		is_wtc_param_updated = true;
6377 	} else {
6378 		param.user_roam_reason = DISABLE_VENDOR_BTM_CONFIG;
6379 	}
6380 
6381 	if (tb2[QCA_ATTR_ROAM_CONTROL_BAND_MASK]) {
6382 		band_mask =
6383 			nla_get_u32(tb2[QCA_ATTR_ROAM_CONTROL_BAND_MASK]);
6384 		band_mask =
6385 			wlan_vendor_bitmap_to_reg_wifi_band_bitmap(hdd_ctx->psoc,
6386 								   band_mask);
6387 		hdd_debug("[ROAM BAND] set roam band mask:%d", band_mask);
6388 		if (band_mask) {
6389 			ucfg_cm_set_roam_band_mask(hdd_ctx->psoc, vdev_id,
6390 						   band_mask);
6391 		} else {
6392 			hdd_debug("Invalid roam BAND_MASK");
6393 			return -EINVAL;
6394 		}
6395 
6396 		if (ucfg_cm_is_change_in_band_allowed(hdd_ctx->psoc, vdev_id,
6397 						      band_mask)) {
6398 
6399 			/* Disable roaming on Vdev before setting PCL */
6400 			sme_stop_roaming(hdd_ctx->mac_handle, vdev_id,
6401 					 REASON_DRIVER_DISABLED, RSO_SET_PCL);
6402 
6403 			policy_mgr_set_pcl_for_existing_combo(hdd_ctx->psoc,
6404 							      PM_STA_MODE,
6405 							      vdev_id);
6406 
6407 			/* Enable roaming once SET pcl is done */
6408 			sme_start_roaming(hdd_ctx->mac_handle, vdev_id,
6409 					  REASON_DRIVER_ENABLED, RSO_SET_PCL);
6410 		}
6411 	}
6412 
6413 	attr = tb2[QCA_ATTR_ROAM_CONTROL_RX_LINKSPEED_THRESHOLD];
6414 	if (attr) {
6415 		threshold = nla_get_u16(attr);
6416 		status = hdd_set_roam_rx_linkspeed_threshold(hdd_ctx->psoc,
6417 							     link_info->vdev,
6418 							     threshold);
6419 	}
6420 
6421 	if (is_wtc_param_updated) {
6422 		wlan_cm_roam_set_vendor_btm_params(hdd_ctx->psoc, &param);
6423 		/* Sends RSO update */
6424 		sme_send_vendor_btm_params(hdd_ctx->mac_handle, vdev_id);
6425 	}
6426 
6427 	attr = tb2[QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX];
6428 	if (attr) {
6429 		value = nla_get_u16(attr);
6430 		if (value < MIN_ROAM_HO_DELAY || value > MAX_ROAM_HO_DELAY) {
6431 			hdd_err("Invalid roam HO delay value: %d", value);
6432 			return -EINVAL;
6433 		}
6434 
6435 		hdd_debug("Received roam HO delay value: %d", value);
6436 
6437 		status = ucfg_cm_roam_send_ho_delay_config(hdd_ctx->pdev,
6438 							   vdev_id, value);
6439 		if (QDF_IS_STATUS_ERROR(status))
6440 			hdd_err("failed to set hand-off delay");
6441 	}
6442 
6443 	attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_NO_REUSE_PARTIAL_SCAN_FREQ];
6444 	if (attr) {
6445 		value = nla_get_u8(attr);
6446 		if (value < INCLUDE_ROAM_PARTIAL_SCAN_FREQ ||
6447 		    value > EXCLUDE_ROAM_PARTIAL_SCAN_FREQ) {
6448 			hdd_err("Invalid value %d to exclude partial scan freq",
6449 				value);
6450 			return -EINVAL;
6451 		}
6452 
6453 		hdd_debug("%s partial scan channels in roam full scan",
6454 			  value ? "Exclude" : "Include");
6455 
6456 		status = ucfg_cm_exclude_rm_partial_scan_freq(hdd_ctx->pdev,
6457 							      vdev_id, value);
6458 		if (QDF_IS_STATUS_ERROR(status))
6459 			hdd_err("Fail to exclude roam partial scan channels");
6460 	}
6461 
6462 	attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_6GHZ_ONLY_ON_PRIOR_DISCOVERY];
6463 	if (attr) {
6464 		value = nla_get_u8(attr);
6465 		if (value < INCLUDE_6GHZ_IN_FULL_SCAN_BY_DEF ||
6466 		    value > INCLUDE_6GHZ_IN_FULL_SCAN_IF_DISC) {
6467 			hdd_err("Invalid value %d to decide inclusion of 6 GHz channels",
6468 				value);
6469 			return -EINVAL;
6470 		}
6471 
6472 		hdd_debug("Include 6 GHz channels in roam full scan by %s",
6473 			  value ? "prior discovery" : "default");
6474 
6475 		status = ucfg_cm_roam_full_scan_6ghz_on_disc(hdd_ctx->pdev,
6476 							     vdev_id, value);
6477 		if (QDF_IS_STATUS_ERROR(status))
6478 			hdd_err("Fail to decide inclusion of 6 GHz channels");
6479 	}
6480 
6481 	return qdf_status_to_os_return(status);
6482 }
6483 
6484 #define ENABLE_ROAM_TRIGGERS_ALL (QCA_ROAM_TRIGGER_REASON_PER | \
6485 				  QCA_ROAM_TRIGGER_REASON_BEACON_MISS | \
6486 				  QCA_ROAM_TRIGGER_REASON_POOR_RSSI | \
6487 				  QCA_ROAM_TRIGGER_REASON_BETTER_RSSI | \
6488 				  QCA_ROAM_TRIGGER_REASON_PERIODIC | \
6489 				  QCA_ROAM_TRIGGER_REASON_DENSE | \
6490 				  QCA_ROAM_TRIGGER_REASON_BTM | \
6491 				  QCA_ROAM_TRIGGER_REASON_BSS_LOAD | \
6492 				  QCA_ROAM_TRIGGER_REASON_USER_TRIGGER | \
6493 				  QCA_ROAM_TRIGGER_REASON_DEAUTH | \
6494 				  QCA_ROAM_TRIGGER_REASON_IDLE | \
6495 				  QCA_ROAM_TRIGGER_REASON_TX_FAILURES | \
6496 				  QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN)
6497 
6498 static int
6499 hdd_clear_roam_control_config(struct hdd_context *hdd_ctx,
6500 			      struct nlattr **tb,
6501 			      uint8_t vdev_id)
6502 {
6503 	QDF_STATUS status;
6504 	struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
6505 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
6506 	uint32_t value;
6507 
6508 	/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
6509 	if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
6510 		hdd_err("Attribute CONTROL_CONFIG is not present");
6511 		return -EINVAL;
6512 	}
6513 
6514 	if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
6515 					   tb[PARAM_ROAM_CONTROL_CONFIG],
6516 					   roam_control_policy)) {
6517 		hdd_err("nla_parse failed");
6518 		return -EINVAL;
6519 	}
6520 
6521 	hdd_debug("Clear the control config done through SET");
6522 	if (tb2[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL]) {
6523 		hdd_debug("Disable roam control config done through SET");
6524 		status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
6525 						    vdev_id, 0);
6526 		if (QDF_IS_STATUS_ERROR(status)) {
6527 			hdd_err("failed to enable/disable roam control config");
6528 			return qdf_status_to_os_return(status);
6529 		}
6530 
6531 		value = ENABLE_ROAM_TRIGGERS_ALL;
6532 		hdd_debug("Reset roam trigger bitmap to 0x%x", value);
6533 		status = hdd_send_roam_triggers_to_sme(hdd_ctx, vdev_id, value);
6534 		if (QDF_IS_STATUS_ERROR(status)) {
6535 			hdd_err("failed to restore roam trigger bitmap");
6536 			return qdf_status_to_os_return(status);
6537 		}
6538 
6539 		status = sme_roam_control_restore_default_config(mac_handle,
6540 								 vdev_id);
6541 		if (QDF_IS_STATUS_ERROR(status)) {
6542 			hdd_err("failed to config roam control");
6543 			return qdf_status_to_os_return(status);
6544 		}
6545 	}
6546 
6547 	return 0;
6548 }
6549 
6550 /**
6551  * hdd_roam_control_config_buf_size() - Calculate the skb size to be allocated
6552  * @hdd_ctx: HDD context
6553  * @tb: List of attributes to be populated
6554  *
6555  * Calculate the buffer size to be allocated based on the attributes
6556  * mentioned in tb.
6557  *
6558  * Return: buffer size to be allocated
6559  */
6560 static uint16_t
6561 hdd_roam_control_config_buf_size(struct hdd_context *hdd_ctx,
6562 				 struct nlattr **tb)
6563 {
6564 	uint16_t skb_len = 0;
6565 
6566 	if (tb[QCA_ATTR_ROAM_CONTROL_STATUS])
6567 		skb_len += NLA_HDRLEN + sizeof(uint8_t);
6568 
6569 	if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD])
6570 		skb_len += NLA_HDRLEN + sizeof(uint32_t);
6571 
6572 	if (tb[QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME])
6573 		/*
6574 		 * Response has 3 nests, 1 atrribure value and a
6575 		 * attribute list of frequencies.
6576 		 */
6577 		skb_len += 3 * nla_total_size(0) +
6578 			nla_total_size(sizeof(uint32_t)) +
6579 			(nla_total_size(sizeof(uint32_t)) *
6580 			NUM_CHANNELS);
6581 
6582 	if (tb[QCA_ATTR_ROAM_CONTROL_BAND_MASK])
6583 		skb_len += NLA_HDRLEN + sizeof(uint32_t);
6584 
6585 	return skb_len;
6586 }
6587 
6588 /**
6589  * wlan_reg_wifi_band_bitmap_to_vendor_bitmap() - Convert enum reg_wifi_band
6590  * to enum qca_set_band
6591  * @reg_wifi_band_bitmap: enum reg_wifi_band
6592  *
6593  * Return: qca_set_band value
6594  */
6595 static uint32_t
6596 wlan_reg_wifi_band_bitmap_to_vendor_bitmap(uint32_t reg_wifi_band_bitmap)
6597 {
6598 	uint32_t vendor_mask = 0;
6599 
6600 	if (reg_wifi_band_bitmap & BIT(REG_BAND_2G))
6601 		vendor_mask |= QCA_SETBAND_2G;
6602 	if (reg_wifi_band_bitmap & BIT(REG_BAND_5G))
6603 		vendor_mask |= QCA_SETBAND_5G;
6604 	if (reg_wifi_band_bitmap & BIT(REG_BAND_6G))
6605 		vendor_mask |= QCA_SETBAND_6G;
6606 
6607 	return vendor_mask;
6608 }
6609 
6610 /**
6611  * hdd_roam_control_config_fill_data() - Fill the data requested by userspace
6612  * @hdd_ctx: HDD context
6613  * @vdev_id: vdev id
6614  * @skb: SK buffer
6615  * @tb: List of attributes
6616  *
6617  * Get the data corresponding to the attribute list specified in tb and
6618  * update the same to skb by populating the same attributes.
6619  *
6620  * Return: 0 on success; error number on failure
6621  */
6622 static int
6623 hdd_roam_control_config_fill_data(struct hdd_context *hdd_ctx, uint8_t vdev_id,
6624 				  struct sk_buff *skb, struct nlattr **tb)
6625 {
6626 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6627 	uint8_t roam_control;
6628 	struct nlattr *config, *get_freq_scheme, *get_freq;
6629 	uint32_t full_roam_scan_period, roam_band, vendor_band_mask;
6630 	uint8_t num_channels = 0;
6631 	uint32_t i = 0, freq_list[NUM_CHANNELS] = { 0 };
6632 	struct wlan_hdd_link_info *link_info;
6633 
6634 	config = nla_nest_start(skb, PARAM_ROAM_CONTROL_CONFIG);
6635 	if (!config) {
6636 		hdd_err("nla nest start failure");
6637 		return -EINVAL;
6638 	}
6639 
6640 	if (tb[QCA_ATTR_ROAM_CONTROL_STATUS]) {
6641 		status = sme_get_roam_config_status(hdd_ctx->mac_handle,
6642 						    vdev_id,
6643 						    &roam_control);
6644 		if (QDF_IS_STATUS_ERROR(status))
6645 			goto out;
6646 		hdd_debug("Roam control: %s",
6647 			  roam_control ? "Enabled" : "Disabled");
6648 		if (nla_put_u8(skb, QCA_ATTR_ROAM_CONTROL_STATUS,
6649 			       roam_control)) {
6650 			hdd_info("failed to put vendor_roam_control");
6651 			return -ENOMEM;
6652 		}
6653 	}
6654 
6655 	if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD]) {
6656 		status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle,
6657 						       vdev_id,
6658 						       &full_roam_scan_period);
6659 		if (QDF_IS_STATUS_ERROR(status))
6660 			goto out;
6661 		hdd_debug("full_roam_scan_period: %u", full_roam_scan_period);
6662 
6663 		if (nla_put_u32(skb, QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD,
6664 				full_roam_scan_period)) {
6665 			hdd_info("failed to put full_roam_scan_period");
6666 			return -EINVAL;
6667 		}
6668 	}
6669 
6670 	if (tb[QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME]) {
6671 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6672 		if (!link_info) {
6673 			hdd_info("Invalid vdev");
6674 			return -EINVAL;
6675 		}
6676 
6677 		hdd_debug("Get roam scan frequencies req received");
6678 		status = hdd_get_roam_scan_freq(link_info->adapter,
6679 						hdd_ctx->mac_handle,
6680 						freq_list, &num_channels);
6681 		if (QDF_IS_STATUS_ERROR(status)) {
6682 			hdd_info("failed to get roam scan freq");
6683 			goto out;
6684 		}
6685 
6686 		hdd_debug("num_channels %d", num_channels);
6687 		get_freq_scheme = nla_nest_start(
6688 				skb, QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME);
6689 		if (!get_freq_scheme) {
6690 			hdd_info("failed to nest start for roam scan freq");
6691 			return -EINVAL;
6692 		}
6693 
6694 		if (nla_put_u32(skb, PARAM_SCAN_FREQ_LIST_TYPE, 0)) {
6695 			hdd_info("failed to put list type");
6696 			return -EINVAL;
6697 		}
6698 
6699 		get_freq = nla_nest_start(
6700 				skb, QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST);
6701 		if (!get_freq) {
6702 			hdd_info("failed to nest start for roam scan freq");
6703 			return -EINVAL;
6704 		}
6705 
6706 		for (i = 0; i < num_channels; i++) {
6707 			if (nla_put_u32(skb, PARAM_SCAN_FREQ_LIST,
6708 					freq_list[i])) {
6709 				hdd_info("failed to put freq at index %d", i);
6710 				return -EINVAL;
6711 			}
6712 		}
6713 		nla_nest_end(skb, get_freq);
6714 		nla_nest_end(skb, get_freq_scheme);
6715 	}
6716 
6717 	if (tb[QCA_ATTR_ROAM_CONTROL_BAND_MASK]) {
6718 		status = ucfg_cm_get_roam_band(hdd_ctx->psoc, vdev_id,
6719 					       &roam_band);
6720 		if (QDF_IS_STATUS_ERROR(status))
6721 			goto out;
6722 		vendor_band_mask =
6723 			wlan_reg_wifi_band_bitmap_to_vendor_bitmap(roam_band);
6724 		if (nla_put_u32(skb, QCA_ATTR_ROAM_CONTROL_BAND_MASK,
6725 				vendor_band_mask)) {
6726 			hdd_info("failed to put roam_band");
6727 			return -EINVAL;
6728 		}
6729 		hdd_debug("sending vendor_band_mask: %d reg band:%d",
6730 			  vendor_band_mask, roam_band);
6731 	}
6732 
6733 	nla_nest_end(skb, config);
6734 
6735 out:
6736 	return qdf_status_to_os_return(status);
6737 }
6738 
6739 /**
6740  * hdd_send_roam_control_config() - Send the roam config as vendor cmd reply
6741  * @hdd_ctx: HDD context
6742  * @vdev_id: vdev id
6743  * @tb: List of attributes
6744  *
6745  * Parse the attributes list tb and  get the data corresponding to the
6746  * attributes specified in tb. Send them as a vendor response.
6747  *
6748  * Return: 0 on success; error number on failure
6749  */
6750 static int
6751 hdd_send_roam_control_config(struct hdd_context *hdd_ctx,
6752 			     uint8_t vdev_id,
6753 			     struct nlattr **tb)
6754 {
6755 	struct sk_buff *skb;
6756 	uint16_t skb_len;
6757 	int status;
6758 
6759 	skb_len = hdd_roam_control_config_buf_size(hdd_ctx, tb);
6760 	if (!skb_len) {
6761 		hdd_err("No data requested");
6762 		return -EINVAL;
6763 	}
6764 
6765 	skb_len += NLMSG_HDRLEN;
6766 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
6767 	if (!skb) {
6768 		hdd_info("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
6769 		return -ENOMEM;
6770 	}
6771 
6772 	status = hdd_roam_control_config_fill_data(hdd_ctx, vdev_id, skb, tb);
6773 	if (status)
6774 		goto fail;
6775 
6776 	return wlan_cfg80211_vendor_cmd_reply(skb);
6777 
6778 fail:
6779 	hdd_err("nla put fail");
6780 	wlan_cfg80211_vendor_free_skb(skb);
6781 	return status;
6782 }
6783 
6784 /**
6785  * hdd_get_roam_control_config() - Send requested roam config to userspace
6786  * @hdd_ctx: HDD context
6787  * @tb: list of attributes
6788  * @vdev_id: vdev id
6789  *
6790  * Return: 0 on success; error number on failure
6791  */
6792 static int hdd_get_roam_control_config(struct hdd_context *hdd_ctx,
6793 				       struct nlattr **tb,
6794 				       uint8_t vdev_id)
6795 {
6796 	QDF_STATUS status;
6797 	struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
6798 
6799 	/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
6800 	if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
6801 		hdd_err("Attribute CONTROL_CONFIG is not present");
6802 		return -EINVAL;
6803 	}
6804 
6805 	if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
6806 					   tb[PARAM_ROAM_CONTROL_CONFIG],
6807 					   roam_control_policy)) {
6808 		hdd_err("nla_parse failed");
6809 		return -EINVAL;
6810 	}
6811 
6812 	status = hdd_send_roam_control_config(hdd_ctx, vdev_id, tb2);
6813 	if (status) {
6814 		hdd_err("failed to enable/disable roam control");
6815 		return status;
6816 	}
6817 
6818 	return qdf_status_to_os_return(status);
6819 }
6820 
6821 #undef PARAM_ROAM_CONTROL_CONFIG
6822 #undef PARAM_FREQ_LIST_SCHEME_MAX
6823 #undef PARAM_FREQ_LIST_SCHEME
6824 #undef PARAM_SCAN_FREQ_LIST
6825 #undef PARAM_SCAN_FREQ_LIST_TYPE
6826 #undef PARAM_CAND_SEL_CRITERIA_MAX
6827 #undef PARAM_CAND_SEL_SCORE_RSSI
6828 
6829 /**
6830  * hdd_set_ext_roam_params() - parse ext roam params
6831  * @hdd_ctx: HDD context
6832  * @data: ext roam params attribute payload
6833  * @data_len: length of @data
6834  * @vdev_id: vdev id
6835  * @rso_config: roam params
6836  * @rso_usr_cfg: roam userspace params
6837  *
6838  * Return: 0 on success; error number on failure
6839  */
6840 static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
6841 				   const void *data, int data_len,
6842 				   uint8_t vdev_id,
6843 				   struct rso_config_params *rso_config,
6844 				   struct rso_user_config *rso_usr_cfg)
6845 {
6846 	uint32_t cmd_type, req_id;
6847 	struct nlattr *tb[MAX_ROAMING_PARAM + 1];
6848 	int ret;
6849 	mac_handle_t mac_handle;
6850 
6851 	if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
6852 				    wlan_hdd_set_roam_param_policy)) {
6853 		hdd_err("Invalid ATTR");
6854 		return -EINVAL;
6855 	}
6856 	/* Parse and fetch Command Type */
6857 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
6858 		hdd_err("roam cmd type failed");
6859 		goto fail;
6860 	}
6861 
6862 	cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
6863 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
6864 		hdd_err("attr request id failed");
6865 		goto fail;
6866 	}
6867 	mac_handle = hdd_ctx->mac_handle;
6868 	req_id = nla_get_u32(
6869 		tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
6870 	hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
6871 	switch (cmd_type) {
6872 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST:
6873 		ret = hdd_set_allow_list(hdd_ctx, rso_config, tb, vdev_id,
6874 					 rso_usr_cfg);
6875 		if (ret)
6876 			goto fail;
6877 		break;
6878 
6879 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
6880 		/* Parse and fetch 5G Boost Threshold */
6881 		if (!tb[PARAM_A_BAND_BOOST_THLD]) {
6882 			hdd_err("5G boost threshold failed");
6883 			goto fail;
6884 		}
6885 		rso_config->raise_rssi_thresh_5g = nla_get_s32(
6886 			tb[PARAM_A_BAND_BOOST_THLD]);
6887 		hdd_debug("5G Boost Threshold (%d)",
6888 			rso_config->raise_rssi_thresh_5g);
6889 		/* Parse and fetch 5G Penalty Threshold */
6890 		if (!tb[PARAM_A_BAND_PELT_THLD]) {
6891 			hdd_err("5G penalty threshold failed");
6892 			goto fail;
6893 		}
6894 		rso_config->drop_rssi_thresh_5g = nla_get_s32(
6895 			tb[PARAM_A_BAND_PELT_THLD]);
6896 		hdd_debug("5G Penalty Threshold (%d)",
6897 			rso_config->drop_rssi_thresh_5g);
6898 		/* Parse and fetch 5G Boost Factor */
6899 		if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
6900 			hdd_err("5G boost Factor failed");
6901 			goto fail;
6902 		}
6903 		rso_config->raise_factor_5g = nla_get_u32(
6904 			tb[PARAM_A_BAND_BOOST_FACTOR]);
6905 		hdd_debug("5G Boost Factor (%d)",
6906 			rso_config->raise_factor_5g);
6907 		/* Parse and fetch 5G Penalty factor */
6908 		if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
6909 			hdd_err("5G Penalty Factor failed");
6910 			goto fail;
6911 		}
6912 		rso_config->drop_factor_5g = nla_get_u32(
6913 			tb[PARAM_A_BAND_PELT_FACTOR]);
6914 		hdd_debug("5G Penalty factor (%d)",
6915 			rso_config->drop_factor_5g);
6916 		/* Parse and fetch 5G Max Boost */
6917 		if (!tb[PARAM_A_BAND_MAX_BOOST]) {
6918 			hdd_err("5G Max Boost failed");
6919 			goto fail;
6920 		}
6921 		rso_config->max_raise_rssi_5g = nla_get_u32(
6922 			tb[PARAM_A_BAND_MAX_BOOST]);
6923 		hdd_debug("5G Max Boost (%d)",
6924 			rso_config->max_raise_rssi_5g);
6925 		/* Parse and fetch Rssi Diff */
6926 		if (!tb[PARAM_ROAM_HISTERESYS]) {
6927 			hdd_err("Rssi Diff failed");
6928 			goto fail;
6929 		}
6930 		rso_config->rssi_diff = nla_get_s32(
6931 			tb[PARAM_ROAM_HISTERESYS]);
6932 		hdd_debug("RSSI Diff (%d)",
6933 			rso_config->rssi_diff);
6934 		/* Parse and fetch Alert Rssi Threshold */
6935 		if (!tb[PARAM_RSSI_TRIGGER]) {
6936 			hdd_err("Alert Rssi Threshold failed");
6937 			goto fail;
6938 		}
6939 		rso_config->alert_rssi_threshold = nla_get_u32(
6940 			tb[PARAM_RSSI_TRIGGER]);
6941 		hdd_debug("Alert RSSI Threshold (%d)",
6942 			rso_config->alert_rssi_threshold);
6943 		sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
6944 				       REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
6945 		break;
6946 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM:
6947 		/* Parse and fetch Activate Good Rssi Roam */
6948 		if (!tb[PARAM_ROAM_ENABLE]) {
6949 			hdd_err("Activate Good Rssi Roam failed");
6950 			goto fail;
6951 		}
6952 		rso_config->good_rssi_roam = nla_get_s32(
6953 			tb[PARAM_ROAM_ENABLE]);
6954 		hdd_debug("Activate Good Rssi Roam (%d)",
6955 			  rso_config->good_rssi_roam);
6956 		sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
6957 				       REASON_ROAM_GOOD_RSSI_CHANGED);
6958 		break;
6959 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS:
6960 		ret = hdd_set_bssid_prefs(hdd_ctx, rso_config, tb, vdev_id);
6961 		if (ret)
6962 			goto fail;
6963 		break;
6964 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID:
6965 		ret = hdd_set_denylist_bssid(hdd_ctx, rso_config, tb, vdev_id);
6966 		if (ret)
6967 			goto fail;
6968 		break;
6969 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET:
6970 		ret = hdd_set_roam_with_control_config(hdd_ctx, tb, vdev_id);
6971 		if (ret)
6972 			goto fail;
6973 		break;
6974 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR:
6975 		ret = hdd_clear_roam_control_config(hdd_ctx, tb, vdev_id);
6976 		if (ret)
6977 			goto fail;
6978 		break;
6979 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET:
6980 		ret = hdd_get_roam_control_config(hdd_ctx, tb, vdev_id);
6981 		if (ret)
6982 			goto fail;
6983 		break;
6984 	}
6985 
6986 	return 0;
6987 
6988 fail:
6989 	return -EINVAL;
6990 }
6991 
6992 /**
6993  * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
6994  * @wiphy:                 The wiphy structure
6995  * @wdev:                  The wireless device
6996  * @data:                  Data passed by framework
6997  * @data_len:              Parameters to be configured passed as data
6998  *
6999  * The roaming related parameters are configured by the framework
7000  * using this interface.
7001  *
7002  * Return: Return either success or failure code.
7003  */
7004 static int
7005 __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
7006 	struct wireless_dev *wdev, const void *data, int data_len)
7007 {
7008 	struct net_device *dev = wdev->netdev;
7009 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7010 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7011 	struct rso_config_params *rso_config;
7012 	struct rso_user_config *rso_usr_cfg = NULL;
7013 
7014 	int ret;
7015 
7016 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7017 		hdd_err("Command not allowed in FTM mode");
7018 		return -EPERM;
7019 	}
7020 
7021 	ret = wlan_hdd_validate_context(hdd_ctx);
7022 	if (ret)
7023 		return ret;
7024 
7025 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7026 		hdd_err("Driver Modules are closed");
7027 		return -EINVAL;
7028 	}
7029 
7030 	rso_config = qdf_mem_malloc(sizeof(*rso_config));
7031 	if (!rso_config)
7032 		return -ENOMEM;
7033 
7034 	rso_usr_cfg = qdf_mem_malloc(sizeof(*rso_usr_cfg));
7035 	if (!rso_usr_cfg)
7036 		return -ENOMEM;
7037 
7038 	ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
7039 				      adapter->deflink->vdev_id, rso_config,
7040 				      rso_usr_cfg);
7041 	qdf_mem_free(rso_config);
7042 	qdf_mem_free(rso_usr_cfg);
7043 
7044 	if (ret)
7045 		goto fail;
7046 
7047 	return 0;
7048 fail:
7049 	return ret;
7050 }
7051 #undef PARAM_NUM_NW
7052 #undef PARAM_SET_BSSID
7053 #undef PARAM_SET_BSSID_HINT
7054 #undef PARAM_SSID_LIST
7055 #undef PARAM_LIST_SSID
7056 #undef MAX_ROAMING_PARAM
7057 #undef PARAM_NUM_BSSID
7058 #undef PARAM_BSSID_PREFS
7059 #undef PARAM_ROAM_BSSID
7060 #undef PARAM_RSSI_MODIFIER
7061 #undef PARAMS_NUM_BSSID
7062 #undef PARAM_BSSID_PARAMS
7063 #undef PARAM_A_BAND_BOOST_THLD
7064 #undef PARAM_A_BAND_PELT_THLD
7065 #undef PARAM_A_BAND_BOOST_FACTOR
7066 #undef PARAM_A_BAND_PELT_FACTOR
7067 #undef PARAM_A_BAND_MAX_BOOST
7068 #undef PARAM_ROAM_HISTERESYS
7069 #undef PARAM_RSSI_TRIGGER
7070 #undef PARAM_ROAM_ENABLE
7071 
7072 
7073 /**
7074  * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
7075  * @wiphy:   pointer to wireless wiphy structure.
7076  * @wdev:    pointer to wireless_dev structure.
7077  * @data:    Pointer to the data to be passed via vendor interface
7078  * @data_len:Length of the data to be passed
7079  *
7080  * Return:   Return the Success or Failure code.
7081  */
7082 static int
7083 wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
7084 				struct wireless_dev *wdev,
7085 				const void *data,
7086 				int data_len)
7087 {
7088 	int errno;
7089 	struct osif_vdev_sync *vdev_sync;
7090 
7091 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7092 	if (errno)
7093 		return errno;
7094 
7095 	errno = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
7096 							data, data_len);
7097 
7098 	osif_vdev_sync_op_stop(vdev_sync);
7099 
7100 	return errno;
7101 }
7102 
7103 #define RATEMASK_PARAMS_TYPE_MAX 4
7104 #define RATEMASK_PARAMS_BITMAP_MAX 16
7105 #define RATEMASK_PARAMS_MAX QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX
7106 const struct nla_policy wlan_hdd_set_ratemask_param_policy[
7107 			RATEMASK_PARAMS_MAX + 1] = {
7108 	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST] = {.type = NLA_NESTED},
7109 	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE] = {.type = NLA_U8},
7110 	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP] = {.type = NLA_BINARY,
7111 					.len = RATEMASK_PARAMS_BITMAP_MAX},
7112 };
7113 
7114 /**
7115  * hdd_set_ratemask_params() - parse ratemask params
7116  * @hdd_ctx: HDD context
7117  * @data: ratemask attribute payload
7118  * @data_len: length of @data
7119  * @vdev: vdev to modify
7120  *
7121  * Return: 0 on success; error number on failure
7122  */
7123 static int hdd_set_ratemask_params(struct hdd_context *hdd_ctx,
7124 				   const void *data, int data_len,
7125 				   struct wlan_objmgr_vdev *vdev)
7126 {
7127 	struct nlattr *tb[RATEMASK_PARAMS_MAX + 1];
7128 	struct nlattr *tb2[RATEMASK_PARAMS_MAX + 1];
7129 	struct nlattr *curr_attr;
7130 	int ret, rem;
7131 	struct config_ratemask_params rate_params[RATEMASK_PARAMS_TYPE_MAX];
7132 	uint8_t ratemask_type, num_ratemask = 0, len;
7133 	uint32_t bitmap[RATEMASK_PARAMS_BITMAP_MAX / 4];
7134 
7135 	ret = wlan_cfg80211_nla_parse(tb,
7136 				      RATEMASK_PARAMS_MAX,
7137 				      data, data_len,
7138 				      wlan_hdd_set_ratemask_param_policy);
7139 	if (ret) {
7140 		hdd_err("Invalid ATTR");
7141 		return -EINVAL;
7142 	}
7143 
7144 	if (!tb[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST]) {
7145 		hdd_err("ratemask array attribute not present");
7146 		return -EINVAL;
7147 	}
7148 
7149 	memset(rate_params, 0, (RATEMASK_PARAMS_TYPE_MAX *
7150 				sizeof(struct config_ratemask_params)));
7151 
7152 	nla_for_each_nested(curr_attr,
7153 			    tb[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST],
7154 			    rem) {
7155 		if (num_ratemask >= RATEMASK_PARAMS_TYPE_MAX) {
7156 			hdd_err("Exceeding ratemask_list_param_num value");
7157 			return -EINVAL;
7158 		}
7159 
7160 		if (wlan_cfg80211_nla_parse(
7161 				tb2, RATEMASK_PARAMS_MAX,
7162 				nla_data(curr_attr), nla_len(curr_attr),
7163 				wlan_hdd_set_ratemask_param_policy)) {
7164 			hdd_err("nla_parse failed");
7165 			return -EINVAL;
7166 		}
7167 
7168 		if (!tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE]) {
7169 			hdd_err("type attribute not present");
7170 			return -EINVAL;
7171 		}
7172 
7173 		if (!tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP]) {
7174 			hdd_err("bitmap attribute not present");
7175 			return -EINVAL;
7176 		}
7177 
7178 		ratemask_type =
7179 		 nla_get_u8(tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE]);
7180 		if (ratemask_type >= RATEMASK_PARAMS_TYPE_MAX) {
7181 			hdd_err("invalid ratemask type");
7182 			return -EINVAL;
7183 		}
7184 
7185 		len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP]);
7186 		qdf_mem_zero(bitmap, sizeof(bitmap));
7187 		nla_memcpy(bitmap,
7188 			   tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP],
7189 			   len);
7190 
7191 		hdd_debug("rate_type:%d, lower32 0x%x, lower32_2 0x%x, higher32 0x%x, higher32_2 0x%x",
7192 			  ratemask_type, bitmap[0], bitmap[1],
7193 			  bitmap[2], bitmap[3]);
7194 
7195 		rate_params[num_ratemask].type = ratemask_type;
7196 		rate_params[num_ratemask].lower32 = bitmap[0];
7197 		rate_params[num_ratemask].lower32_2 = bitmap[1];
7198 		rate_params[num_ratemask].higher32 = bitmap[2];
7199 		rate_params[num_ratemask].higher32_2 = bitmap[3];
7200 
7201 		num_ratemask += 1;
7202 	}
7203 
7204 	ret = ucfg_set_ratemask_params(vdev, num_ratemask, rate_params);
7205 	if (ret)
7206 		hdd_err("ucfg_set_ratemask_params failed");
7207 	return ret;
7208 }
7209 
7210 /**
7211  * __wlan_hdd_cfg80211_set_ratemask_config() - Ratemask parameters
7212  * @wiphy:                 The wiphy structure
7213  * @wdev:                  The wireless device
7214  * @data:                  Data passed by framework
7215  * @data_len:              Parameters to be configured passed as data
7216  *
7217  * The ratemask parameters are configured by the framework
7218  * using this interface.
7219  *
7220  * Return: Return either success or failure code.
7221  */
7222 static int
7223 __wlan_hdd_cfg80211_set_ratemask_config(struct wiphy *wiphy,
7224 					struct wireless_dev *wdev,
7225 					const void *data, int data_len)
7226 {
7227 	struct net_device *dev = wdev->netdev;
7228 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7229 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7230 	struct wlan_objmgr_vdev *vdev;
7231 	int ret;
7232 
7233 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7234 		hdd_err("Command not allowed in FTM mode");
7235 		return -EPERM;
7236 	}
7237 
7238 	ret = wlan_hdd_validate_context(hdd_ctx);
7239 	if (ret)
7240 		return ret;
7241 
7242 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7243 		hdd_err("Driver Modules are closed");
7244 		return -EINVAL;
7245 	}
7246 
7247 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
7248 					   WLAN_OSIF_POWER_ID);
7249 	if (!vdev) {
7250 		hdd_err("vdev not present");
7251 		return -EINVAL;
7252 	}
7253 
7254 	ret = hdd_set_ratemask_params(hdd_ctx, data, data_len, vdev);
7255 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
7256 	if (ret)
7257 		goto fail;
7258 
7259 	return 0;
7260 fail:
7261 	return ret;
7262 }
7263 
7264 /**
7265  * wlan_hdd_cfg80211_set_ratemask_config() - set ratemask config
7266  * @wiphy:   pointer to wireless wiphy structure.
7267  * @wdev:    pointer to wireless_dev structure.
7268  * @data:    Pointer to the data to be passed via vendor interface
7269  * @data_len:Length of the data to be passed
7270  *
7271  * Return:   Return the Success or Failure code.
7272  */
7273 static int
7274 wlan_hdd_cfg80211_set_ratemask_config(struct wiphy *wiphy,
7275 				      struct wireless_dev *wdev,
7276 				      const void *data,
7277 				      int data_len)
7278 {
7279 	int errno;
7280 	struct osif_vdev_sync *vdev_sync;
7281 
7282 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7283 	if (errno)
7284 		return errno;
7285 
7286 	errno = __wlan_hdd_cfg80211_set_ratemask_config(wiphy, wdev,
7287 							data, data_len);
7288 
7289 	osif_vdev_sync_op_stop(vdev_sync);
7290 
7291 	return errno;
7292 }
7293 
7294 #define PWR_SAVE_FAIL_CMD_INDEX \
7295 	QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
7296 
7297 void hdd_chip_pwr_save_fail_detected_cb(hdd_handle_t hdd_handle,
7298 			struct chip_pwr_save_fail_detected_params
7299 			*data)
7300 {
7301 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
7302 	struct sk_buff *skb;
7303 	int flags = cds_get_gfp_flags();
7304 
7305 	hdd_enter();
7306 
7307 	if (wlan_hdd_validate_context(hdd_ctx))
7308 		return;
7309 
7310 	if (!data) {
7311 		hdd_debug("data is null");
7312 		return;
7313 	}
7314 
7315 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
7316 					       NLMSG_HDRLEN +
7317 					       sizeof(uint32_t) +
7318 					       NLMSG_HDRLEN,
7319 					       PWR_SAVE_FAIL_CMD_INDEX, flags);
7320 	if (!skb) {
7321 		hdd_info("wlan_cfg80211_vendor_event_alloc failed");
7322 		return;
7323 	}
7324 
7325 	hdd_debug("failure reason code: %u", data->failure_reason_code);
7326 
7327 	if (nla_put_u32(skb,
7328 		QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
7329 		data->failure_reason_code))
7330 		goto fail;
7331 
7332 	wlan_cfg80211_vendor_event(skb, flags);
7333 	hdd_exit();
7334 	return;
7335 
7336 fail:
7337 	wlan_cfg80211_vendor_free_skb(skb);
7338 }
7339 #undef PWR_SAVE_FAIL_CMD_INDEX
7340 
7341 const struct nla_policy
7342 wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
7343 				       +1] = {
7344 	[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
7345 };
7346 
7347 /**
7348  *  wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
7349  *  @hdd_ctx:      HDD context
7350  *  @device_mode:    device mode
7351  *  Return:         bool
7352  */
7353 static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
7354 						   enum QDF_OPMODE device_mode)
7355 {
7356 	struct hdd_adapter *adapter, *next_adapter = NULL;
7357 	struct hdd_ap_ctx *ap_ctx;
7358 	struct hdd_station_ctx *sta_ctx;
7359 	wlan_net_dev_ref_dbgid dbgid =
7360 				NET_DEV_HOLD_CHECK_DFS_CHANNEL_FOR_ADAPTER;
7361 	struct wlan_hdd_link_info *link_info;
7362 
7363 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
7364 					   dbgid) {
7365 		if (adapter->device_mode != device_mode)
7366 			goto next_adapter;
7367 
7368 		hdd_adapter_for_each_active_link_info(adapter, link_info) {
7369 			if (device_mode == QDF_SAP_MODE) {
7370 				ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
7371 				/*
7372 				 *  if there is SAP already running on
7373 				 *  DFS channel, do not disable scan on
7374 				 *  dfs channels. Note that with SAP on DFS,
7375 				 *  there cannot be conurrency on single radio.
7376 				 *  But then we can have multiple radios !!
7377 				 *
7378 				 *  Indoor channels are also marked DFS,
7379 				 *  therefore check if the channel has
7380 				 *  REGULATORY_CHAN_RADAR channel flag to
7381 				 *  identify if the channel is DFS
7382 				 */
7383 				if (wlan_reg_is_dfs_for_freq(
7384 						hdd_ctx->pdev,
7385 						ap_ctx->operating_chan_freq)) {
7386 					hdd_err("SAP running on DFS channel");
7387 					hdd_adapter_dev_put_debug(adapter,
7388 								  dbgid);
7389 					if (next_adapter)
7390 						hdd_adapter_dev_put_debug(
7391 								next_adapter,
7392 								dbgid);
7393 					return true;
7394 				}
7395 			}
7396 
7397 			if (device_mode == QDF_STA_MODE) {
7398 				sta_ctx =
7399 					WLAN_HDD_GET_STATION_CTX_PTR(link_info);
7400 				/*
7401 				 *  if STA is already connected on DFS channel,
7402 				 *  do not disable scan on dfs channels.
7403 				 *
7404 				 *  Indoor channels are also marked DFS,
7405 				 *  therefore check if the channel has
7406 				 *  REGULATORY_CHAN_RADAR channel flag to
7407 				 *  identify if the channel is DFS
7408 				 */
7409 				if (hdd_cm_is_vdev_associated(link_info) &&
7410 				    wlan_reg_is_dfs_for_freq(
7411 					    hdd_ctx->pdev,
7412 					    sta_ctx->conn_info.chan_freq)) {
7413 					hdd_err("client connected on DFS channel");
7414 					hdd_adapter_dev_put_debug(adapter,
7415 								  dbgid);
7416 					if (next_adapter)
7417 						hdd_adapter_dev_put_debug(
7418 								next_adapter,
7419 								dbgid);
7420 					return true;
7421 				}
7422 			}
7423 		}
7424 next_adapter:
7425 		hdd_adapter_dev_put_debug(adapter, dbgid);
7426 	}
7427 
7428 	return false;
7429 }
7430 
7431 /**
7432  * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
7433  * @hdd_ctx: HDD context within host driver
7434  * @enable_dfs_channels: If true, DFS channels can be used for scanning
7435  *
7436  * Loops through devices to see who is operating on DFS channels
7437  * and then disables/enables DFS channels.
7438  * Fails the disable request if any device is active on a DFS channel.
7439  *
7440  * Return: 0 or other error codes.
7441  */
7442 
7443 int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
7444 				  bool enable_dfs_channels)
7445 {
7446 	QDF_STATUS status;
7447 	bool err;
7448 	mac_handle_t mac_handle;
7449 	bool enable_dfs_scan = true;
7450 
7451 	ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
7452 						&enable_dfs_scan);
7453 
7454 	if (enable_dfs_channels == enable_dfs_scan) {
7455 		hdd_debug("DFS channels are already %s",
7456 			  enable_dfs_channels ? "enabled" : "disabled");
7457 		return 0;
7458 	}
7459 
7460 	if (!enable_dfs_channels) {
7461 		err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
7462 							     QDF_STA_MODE);
7463 		if (err)
7464 			return -EOPNOTSUPP;
7465 
7466 		err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
7467 							     QDF_SAP_MODE);
7468 		if (err)
7469 			return -EOPNOTSUPP;
7470 	}
7471 
7472 	ucfg_scan_cfg_set_dfs_chan_scan_allowed(hdd_ctx->psoc,
7473 						enable_dfs_channels);
7474 
7475 	mac_handle = hdd_ctx->mac_handle;
7476 	status = sme_enable_dfs_chan_scan(mac_handle, enable_dfs_channels);
7477 	if (QDF_IS_STATUS_ERROR(status)) {
7478 		hdd_err("Failed to set DFS channel scan flag to %d",
7479 			enable_dfs_channels);
7480 		return qdf_status_to_os_return(status);
7481 	}
7482 
7483 	hdd_abort_mac_scan_all_adapters(hdd_ctx);
7484 
7485 	/* pass dfs channel status to regulatory component */
7486 	status = ucfg_reg_enable_dfs_channels(hdd_ctx->pdev,
7487 					      enable_dfs_channels);
7488 
7489 	if (QDF_IS_STATUS_ERROR(status))
7490 		hdd_err("Failed to %s DFS channels",
7491 			enable_dfs_channels ? "enable" : "disable");
7492 
7493 	return qdf_status_to_os_return(status);
7494 }
7495 
7496 /**
7497  *  __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
7498  *  @wiphy:          corestack handler
7499  *  @wdev:           wireless device
7500  *  @data:           data
7501  *  @data_len:       data length
7502  *  Return:         success(0) or reason code for failure
7503  */
7504 static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
7505 						     struct wireless_dev *wdev,
7506 						     const void *data,
7507 						     int data_len)
7508 {
7509 	struct net_device *dev = wdev->netdev;
7510 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
7511 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
7512 	int ret_val;
7513 	uint32_t no_dfs_flag = 0;
7514 	bool enable_dfs_scan = true;
7515 	hdd_enter_dev(dev);
7516 
7517 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7518 		hdd_err("Command not allowed in FTM mode");
7519 		return -EPERM;
7520 	}
7521 
7522 	ret_val = wlan_hdd_validate_context(hdd_ctx);
7523 	if (ret_val)
7524 		return ret_val;
7525 
7526 	if (wlan_cfg80211_nla_parse(tb,
7527 				    QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
7528 				    data, data_len,
7529 				    wlan_hdd_set_no_dfs_flag_config_policy)) {
7530 		hdd_err("invalid attr");
7531 		return -EINVAL;
7532 	}
7533 
7534 	if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
7535 		hdd_err("attr dfs flag failed");
7536 		return -EINVAL;
7537 	}
7538 
7539 	no_dfs_flag = nla_get_u32(
7540 		tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
7541 
7542 	hdd_debug("DFS flag: %d", no_dfs_flag);
7543 
7544 	if (no_dfs_flag > 1) {
7545 		hdd_err("invalid value of dfs flag");
7546 		return -EINVAL;
7547 	}
7548 	ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
7549 						&enable_dfs_scan);
7550 
7551 	if (enable_dfs_scan) {
7552 		ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
7553 	} else {
7554 		if ((!no_dfs_flag) != enable_dfs_scan) {
7555 			hdd_err("DFS chan ini configured %d, no dfs flag: %d",
7556 				enable_dfs_scan,
7557 				no_dfs_flag);
7558 			return -EINVAL;
7559 		}
7560 	}
7561 
7562 	return ret_val;
7563 }
7564 
7565 /**
7566  * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
7567  *
7568  * @wiphy: wiphy device pointer
7569  * @wdev: wireless device pointer
7570  * @data: Vendor command data buffer
7571  * @data_len: Buffer length
7572  *
7573  * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
7574  * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
7575  *
7576  * Return: EOK or other error codes.
7577  */
7578 
7579 static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
7580 						   struct wireless_dev *wdev,
7581 						   const void *data,
7582 						   int data_len)
7583 {
7584 	struct osif_psoc_sync *psoc_sync;
7585 	int errno;
7586 
7587 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
7588 	if (errno)
7589 		return errno;
7590 
7591 	errno = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
7592 							  data, data_len);
7593 
7594 	osif_psoc_sync_op_stop(psoc_sync);
7595 
7596 	return errno;
7597 }
7598 
7599 const struct nla_policy
7600 wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
7601 	[QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
7602 };
7603 
7604 /**
7605  * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
7606  * @wiphy: wiphy device pointer
7607  * @wdev: wireless device pointer
7608  * @data: Vendor command data buffer
7609  * @data_len: Buffer length
7610  *
7611  * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
7612  * setup WISA Mode features.
7613  *
7614  * Return: Success(0) or reason code for failure
7615  */
7616 static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
7617 		struct wireless_dev *wdev, const void *data, int data_len)
7618 {
7619 	struct net_device *dev = wdev->netdev;
7620 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7621 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
7622 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
7623 	struct sir_wisa_params wisa;
7624 	int ret_val;
7625 	QDF_STATUS status;
7626 	bool wisa_mode;
7627 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
7628 	mac_handle_t mac_handle;
7629 
7630 	hdd_enter_dev(dev);
7631 	ret_val = wlan_hdd_validate_context(hdd_ctx);
7632 	if (ret_val)
7633 		goto err;
7634 
7635 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7636 		hdd_err("Command not allowed in FTM mode");
7637 		return -EPERM;
7638 	}
7639 
7640 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
7641 				    data_len, wlan_hdd_wisa_cmd_policy)) {
7642 		hdd_err("Invalid WISA cmd attributes");
7643 		ret_val = -EINVAL;
7644 		goto err;
7645 	}
7646 	if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
7647 		hdd_err("Invalid WISA mode");
7648 		ret_val = -EINVAL;
7649 		goto err;
7650 	}
7651 
7652 	wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
7653 	hdd_debug("WISA Mode: %d", wisa_mode);
7654 	wisa.mode = wisa_mode;
7655 	wisa.vdev_id = adapter->deflink->vdev_id;
7656 	mac_handle = hdd_ctx->mac_handle;
7657 	status = sme_set_wisa_params(mac_handle, &wisa);
7658 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7659 		hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
7660 		ret_val = -EINVAL;
7661 	}
7662 	if (QDF_IS_STATUS_SUCCESS(status) || !wisa_mode)
7663 		cdp_set_wisa_mode(soc, adapter->deflink->vdev_id, wisa_mode);
7664 err:
7665 	hdd_exit();
7666 	return ret_val;
7667 }
7668 
7669 /**
7670  * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
7671  * @wiphy:          corestack handler
7672  * @wdev:           wireless device
7673  * @data:           data
7674  * @data_len:       data length
7675  *
7676  * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
7677  * setup WISA mode features.
7678  *
7679  * Return: Success(0) or reason code for failure
7680  */
7681 static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
7682 						   struct wireless_dev *wdev,
7683 						   const void *data,
7684 						   int data_len)
7685 {
7686 	int errno;
7687 	struct osif_vdev_sync *vdev_sync;
7688 
7689 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7690 	if (errno)
7691 		return errno;
7692 
7693 	errno = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev,
7694 						    data, data_len);
7695 
7696 	osif_vdev_sync_op_stop(vdev_sync);
7697 
7698 	return errno;
7699 }
7700 
7701 struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
7702 					 struct qdf_mac_addr mac_addr)
7703 {
7704 	struct hdd_station_info *stainfo = NULL;
7705 	int i;
7706 
7707 	for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
7708 		if (!qdf_mem_cmp(&astainfo[i].sta_mac,
7709 				 &mac_addr,
7710 				 QDF_MAC_ADDR_SIZE)) {
7711 			stainfo = &astainfo[i];
7712 			break;
7713 		}
7714 	}
7715 
7716 	return stainfo;
7717 }
7718 
7719 /*
7720  * undef short names defined for get station command
7721  * used by __wlan_hdd_cfg80211_get_station_cmd()
7722  */
7723 #undef STATION_INVALID
7724 #undef STATION_INFO
7725 #undef STATION_ASSOC_FAIL_REASON
7726 #undef STATION_REMOTE
7727 #undef STATION_MAX
7728 #undef LINK_INFO_STANDARD_NL80211_ATTR
7729 #undef AP_INFO_STANDARD_NL80211_ATTR
7730 #undef INFO_ROAM_COUNT
7731 #undef INFO_AKM
7732 #undef WLAN802_11_MODE
7733 #undef AP_INFO_HS20_INDICATION
7734 #undef HT_OPERATION
7735 #undef VHT_OPERATION
7736 #undef INFO_ASSOC_FAIL_REASON
7737 #undef REMOTE_MAX_PHY_RATE
7738 #undef REMOTE_TX_PACKETS
7739 #undef REMOTE_TX_BYTES
7740 #undef REMOTE_RX_PACKETS
7741 #undef REMOTE_RX_BYTES
7742 #undef REMOTE_LAST_TX_RATE
7743 #undef REMOTE_LAST_RX_RATE
7744 #undef REMOTE_WMM
7745 #undef REMOTE_SUPPORTED_MODE
7746 #undef REMOTE_AMPDU
7747 #undef REMOTE_TX_STBC
7748 #undef REMOTE_RX_STBC
7749 #undef REMOTE_CH_WIDTH
7750 #undef REMOTE_SGI_ENABLE
7751 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
7752 #undef REMOTE_PAD
7753 #endif
7754 
7755 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
7756 /**
7757  * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
7758  * @wiphy: pointer to wireless wiphy structure.
7759  * @wdev: pointer to wireless_dev structure.
7760  * @data: Pointer to the Key data
7761  * @data_len:Length of the data passed
7762  *
7763  * This is called when wlan driver needs to save the keys received via
7764  * vendor specific command.
7765  *
7766  * Return: Return the Success or Failure code.
7767  */
7768 static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
7769 					       struct wireless_dev *wdev,
7770 					       const void *data, int data_len)
7771 {
7772 	struct net_device *dev = wdev->netdev;
7773 	struct hdd_adapter *hdd_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7774 	struct hdd_context *hdd_ctx;
7775 	struct hdd_station_ctx *sta_ctx =
7776 			WLAN_HDD_GET_STATION_CTX_PTR(hdd_adapter->deflink);
7777 	struct wlan_crypto_pmksa pmksa;
7778 	int status;
7779 	mac_handle_t mac_handle;
7780 
7781 	hdd_enter_dev(dev);
7782 
7783 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7784 		hdd_err("Command not allowed in FTM mode");
7785 		return -EPERM;
7786 	}
7787 
7788 	if ((!data) || (data_len <= 0) ||
7789 	    (data_len > MAX_PMK_LEN)) {
7790 		hdd_err("Invalid data");
7791 		return -EINVAL;
7792 	}
7793 
7794 	hdd_ctx = WLAN_HDD_GET_CTX(hdd_adapter);
7795 	if (!hdd_ctx) {
7796 		hdd_err("HDD context is null");
7797 		return -EINVAL;
7798 	}
7799 
7800 	status = wlan_hdd_validate_context(hdd_ctx);
7801 	if (status)
7802 		return status;
7803 
7804 	mac_handle = hdd_ctx->mac_handle;
7805 	qdf_mem_zero(&pmksa, sizeof(pmksa));
7806 	pmksa.pmk_len = data_len;
7807 	qdf_mem_copy(pmksa.pmk, data, data_len);
7808 
7809 	qdf_mem_copy(&pmksa.bssid, &sta_ctx->conn_info.bssid,
7810 		     QDF_MAC_ADDR_SIZE);
7811 
7812 	sme_roam_set_psk_pmk(mac_handle, &pmksa,
7813 			     hdd_adapter->deflink->vdev_id, true);
7814 	qdf_mem_zero(&pmksa, sizeof(pmksa));
7815 	return 0;
7816 }
7817 
7818 /**
7819  * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
7820  * @wiphy:   pointer to wireless wiphy structure.
7821  * @wdev:    pointer to wireless_dev structure.
7822  * @data:    Pointer to the Key data
7823  * @data_len:Length of the data passed
7824  *
7825  * This is called when wlan driver needs to save the keys received via
7826  * vendor specific command.
7827  *
7828  * Return:   Return the Success or Failure code.
7829  */
7830 static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
7831 					     struct wireless_dev *wdev,
7832 					     const void *data, int data_len)
7833 {
7834 	int errno;
7835 	struct osif_vdev_sync *vdev_sync;
7836 
7837 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7838 	if (errno)
7839 		return errno;
7840 
7841 	errno = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev,
7842 						    data, data_len);
7843 
7844 	osif_vdev_sync_op_stop(vdev_sync);
7845 
7846 	return errno;
7847 }
7848 #endif
7849 
7850 const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
7851 			QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
7852 	[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
7853 	[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
7854 	[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
7855 };
7856 
7857 /**
7858  * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
7859  * @wiphy:   pointer to wireless wiphy structure.
7860  * @wdev:    pointer to wireless_dev structure.
7861  * @data:    Pointer to the data to be passed via vendor interface
7862  * @data_len:Length of the data to be passed
7863  *
7864  * This is called when wlan driver needs to send wifi driver related info
7865  * (driver/fw version) to the user space application upon request.
7866  *
7867  * Return:   Return the Success or Failure code.
7868  */
7869 static int
7870 __wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
7871 				  struct wireless_dev *wdev,
7872 				  const void *data, int data_len)
7873 {
7874 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7875 	struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
7876 	uint8_t *firmware_version = NULL;
7877 	int status;
7878 	struct sk_buff *reply_skb;
7879 	uint32_t skb_len = 0;
7880 	struct pld_soc_info info;
7881 	bool stt_flag = false;
7882 
7883 	hdd_enter_dev(wdev->netdev);
7884 
7885 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7886 		hdd_err("Command not allowed in FTM mode");
7887 		return -EPERM;
7888 	}
7889 
7890 	status = wlan_hdd_validate_context(hdd_ctx);
7891 	if (status)
7892 		return status;
7893 
7894 	if (wlan_cfg80211_nla_parse(tb_vendor,
7895 				    QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
7896 				    data, data_len,
7897 				    qca_wlan_vendor_get_wifi_info_policy)) {
7898 		hdd_err("WIFI_INFO_GET NL CMD parsing failed");
7899 		return -EINVAL;
7900 	}
7901 
7902 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
7903 		hdd_debug("Rcvd req for Driver version");
7904 		skb_len += nla_total_size(strlen(QWLAN_VERSIONSTR) + 1);
7905 	}
7906 
7907 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
7908 		hdd_debug("Rcvd req for FW version");
7909 		if (!pld_get_soc_info(hdd_ctx->parent_dev, &info))
7910 			stt_flag = true;
7911 
7912 		firmware_version = qdf_mem_malloc(SIR_VERSION_STRING_LEN);
7913 		if (!firmware_version)
7914 			return -ENOMEM;
7915 
7916 		snprintf(firmware_version, SIR_VERSION_STRING_LEN,
7917 			 "FW:%d.%d.%d.%d.%d.%d HW:%s STT:%s",
7918 			 hdd_ctx->fw_version_info.major_spid,
7919 			 hdd_ctx->fw_version_info.minor_spid,
7920 			 hdd_ctx->fw_version_info.siid,
7921 			 hdd_ctx->fw_version_info.rel_id,
7922 			 hdd_ctx->fw_version_info.crmid,
7923 			 hdd_ctx->fw_version_info.sub_id,
7924 			 hdd_ctx->target_hw_name,
7925 			 (stt_flag ? info.fw_build_id : " "));
7926 		skb_len += nla_total_size(strlen(firmware_version) + 1);
7927 	}
7928 
7929 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
7930 		hdd_debug("Rcvd req for Radio index");
7931 		skb_len += nla_total_size(sizeof(uint32_t));
7932 	}
7933 
7934 	if (!skb_len) {
7935 		hdd_err("unknown attribute in get_wifi_info request");
7936 		qdf_mem_free(firmware_version);
7937 		return -EINVAL;
7938 	}
7939 
7940 	skb_len += NLMSG_HDRLEN;
7941 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
7942 	if (!reply_skb) {
7943 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
7944 		qdf_mem_free(firmware_version);
7945 		return -ENOMEM;
7946 	}
7947 
7948 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
7949 		if (nla_put_string(reply_skb,
7950 			    QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
7951 			    QWLAN_VERSIONSTR))
7952 			goto error_nla_fail;
7953 	}
7954 
7955 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
7956 		if (nla_put_string(reply_skb,
7957 			    QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
7958 			    firmware_version))
7959 			goto error_nla_fail;
7960 	}
7961 
7962 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
7963 		if (nla_put_u32(reply_skb,
7964 				QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
7965 				hdd_ctx->radio_index))
7966 			goto error_nla_fail;
7967 	}
7968 
7969 	qdf_mem_free(firmware_version);
7970 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
7971 
7972 error_nla_fail:
7973 	hdd_err("nla put fail");
7974 	qdf_mem_free(firmware_version);
7975 	wlan_cfg80211_vendor_free_skb(reply_skb);
7976 	return -EINVAL;
7977 }
7978 
7979 /**
7980  * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
7981  * @wiphy:   pointer to wireless wiphy structure.
7982  * @wdev:    pointer to wireless_dev structure.
7983  * @data:    Pointer to the data to be passed via vendor interface
7984  * @data_len:Length of the data to be passed
7985  *
7986  * This is called when wlan driver needs to send wifi driver related info
7987  * (driver/fw version) to the user space application upon request.
7988  *
7989  * Return:   Return the Success or Failure code.
7990  */
7991 static int
7992 wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
7993 		struct wireless_dev *wdev,
7994 		const void *data, int data_len)
7995 {
7996 	struct osif_psoc_sync *psoc_sync;
7997 	int errno;
7998 
7999 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
8000 	if (errno)
8001 		return errno;
8002 
8003 	errno = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
8004 
8005 	osif_psoc_sync_op_stop(psoc_sync);
8006 
8007 	return errno;
8008 }
8009 
8010 const struct nla_policy get_logger_set_policy[
8011 			QCA_WLAN_VENDOR_ATTR_LOGGER_MAX + 1] = {
8012 	[QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED] = {.type = NLA_U32},
8013 };
8014 
8015 /**
8016  * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
8017  * @wiphy:   pointer to wireless wiphy structure.
8018  * @wdev:    pointer to wireless_dev structure.
8019  * @data:    Pointer to the data to be passed via vendor interface
8020  * @data_len:Length of the data to be passed
8021  *
8022  * This is called by userspace to know the supported logger features
8023  *
8024  * Return:   Return the Success or Failure code.
8025  */
8026 static int
8027 __wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
8028 		struct wireless_dev *wdev,
8029 		const void *data, int data_len)
8030 {
8031 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
8032 	int status;
8033 	uint32_t features;
8034 	struct sk_buff *reply_skb = NULL;
8035 	bool enable_ring_buffer;
8036 
8037 	hdd_enter_dev(wdev->netdev);
8038 
8039 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8040 		hdd_err("Command not allowed in FTM mode");
8041 		return -EPERM;
8042 	}
8043 
8044 	status = wlan_hdd_validate_context(hdd_ctx);
8045 	if (status)
8046 		return status;
8047 
8048 	features = 0;
8049 	wlan_mlme_get_status_ring_buffer(hdd_ctx->psoc, &enable_ring_buffer);
8050 	if (enable_ring_buffer) {
8051 		features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
8052 		features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
8053 		features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
8054 		features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
8055 		features |= WIFI_LOGGER_PACKET_FATE_SUPPORTED;
8056 		hdd_debug("Supported logger features: 0x%0x", features);
8057 	} else {
8058 		hdd_info("Ring buffer disable");
8059 	}
8060 
8061 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
8062 							     sizeof(uint32_t) +
8063 							     NLA_HDRLEN +
8064 							     NLMSG_HDRLEN);
8065 	if (!reply_skb) {
8066 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
8067 		return -ENOMEM;
8068 	}
8069 
8070 	if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
8071 				   features)) {
8072 		hdd_err("nla put fail");
8073 		wlan_cfg80211_vendor_free_skb(reply_skb);
8074 		return -EINVAL;
8075 	}
8076 
8077 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
8078 }
8079 
8080 /**
8081  * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
8082  * @wiphy:   pointer to wireless wiphy structure.
8083  * @wdev:    pointer to wireless_dev structure.
8084  * @data:    Pointer to the data to be passed via vendor interface
8085  * @data_len:Length of the data to be passed
8086  *
8087  * This is called by userspace to know the supported logger features
8088  *
8089  * Return:   Return the Success or Failure code.
8090  */
8091 static int
8092 wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
8093 		struct wireless_dev *wdev,
8094 		const void *data, int data_len)
8095 {
8096 	struct osif_psoc_sync *psoc_sync;
8097 	int errno;
8098 
8099 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
8100 	if (errno)
8101 		return errno;
8102 
8103 	errno = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
8104 							    data, data_len);
8105 
8106 	osif_psoc_sync_op_stop(psoc_sync);
8107 
8108 	return errno;
8109 }
8110 
8111 #ifdef WLAN_FEATURE_GTK_OFFLOAD
8112 void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
8113 				      uint8_t *kck_ptr, uint8_t kck_len,
8114 				      uint8_t *kek_ptr, uint32_t kek_len,
8115 				      uint8_t *replay_ctr, bool big_endian)
8116 {
8117 	struct hdd_station_ctx *hdd_sta_ctx;
8118 	uint8_t *buf;
8119 	int i;
8120 	struct pmo_gtk_req *gtk_req = NULL;
8121 	struct wlan_objmgr_vdev *vdev;
8122 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
8123 	struct hdd_context *hdd_ctx =  WLAN_HDD_GET_CTX(adapter);
8124 
8125 	gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
8126 	if (!gtk_req)
8127 		return;
8128 
8129 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
8130 	if (kck_ptr) {
8131 		if (kck_len > sizeof(gtk_req->kck)) {
8132 			kck_len = sizeof(gtk_req->kck);
8133 			QDF_ASSERT(0);
8134 		}
8135 		qdf_mem_copy(gtk_req->kck, kck_ptr, kck_len);
8136 		gtk_req->kck_len = kck_len;
8137 	}
8138 
8139 	if (kek_ptr) {
8140 		/* paranoia */
8141 		if (kek_len > sizeof(gtk_req->kek)) {
8142 			kek_len = sizeof(gtk_req->kek);
8143 			QDF_ASSERT(0);
8144 		}
8145 		qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
8146 	}
8147 
8148 	qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssid);
8149 
8150 	gtk_req->kek_len = kek_len;
8151 	gtk_req->is_fils_connection = hdd_is_fils_connection(hdd_ctx, adapter);
8152 
8153 	/* convert big to little endian since driver work on little endian */
8154 	buf = (uint8_t *)&gtk_req->replay_counter;
8155 	for (i = 0; i < 8; i++)
8156 		buf[7 - i] = replay_ctr[i];
8157 
8158 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
8159 					   WLAN_OSIF_POWER_ID);
8160 	if (!vdev)
8161 		goto end;
8162 	status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
8163 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
8164 	if (status != QDF_STATUS_SUCCESS)
8165 		hdd_err("Failed to cache GTK Offload");
8166 
8167 end:
8168 	qdf_mem_free(gtk_req);
8169 }
8170 #endif
8171 
8172 #ifdef WLAN_CFR_ENABLE
8173 void hdd_cfr_data_send_nl_event(uint8_t vdev_id, uint32_t pid,
8174 				const void *data, uint32_t data_len)
8175 {
8176 	uint32_t len, ret;
8177 	struct sk_buff *vendor_event;
8178 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8179 	struct wlan_hdd_link_info *link_info;
8180 	struct nlmsghdr *nlhdr;
8181 
8182 	if (!hdd_ctx) {
8183 		hdd_err("HDD context is NULL");
8184 		return;
8185 	}
8186 
8187 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
8188 	if (!link_info) {
8189 		hdd_err("adapter NULL for vdev id %d", vdev_id);
8190 		return;
8191 	}
8192 
8193 	hdd_debug("vdev id %d pid %d data len %d", vdev_id, pid, data_len);
8194 	len = nla_total_size(data_len) + NLMSG_HDRLEN;
8195 	vendor_event = wlan_cfg80211_vendor_event_alloc(
8196 			hdd_ctx->wiphy, &link_info->adapter->wdev, len,
8197 			QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG_INDEX,
8198 			GFP_KERNEL);
8199 
8200 	if (!vendor_event) {
8201 		hdd_err("wlan_cfg80211_vendor_event_alloc failed vdev id %d, data len %d",
8202 			vdev_id, data_len);
8203 		return;
8204 	}
8205 
8206 	ret = nla_put(vendor_event,
8207 		      QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA,
8208 		      data_len, data);
8209 	if (ret) {
8210 		hdd_err("CFR event put fails status %d", ret);
8211 		wlan_cfg80211_vendor_free_skb(vendor_event);
8212 		return;
8213 	}
8214 
8215 	if (pid) {
8216 		nlhdr = nlmsg_hdr(vendor_event);
8217 		if (nlhdr)
8218 			nlhdr->nlmsg_pid = pid;
8219 		else
8220 			hdd_err_rl("nlhdr is null");
8221 	}
8222 
8223 	wlan_cfg80211_vendor_event(vendor_event, GFP_ATOMIC);
8224 }
8225 #endif
8226 
8227 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
8228 void hdd_send_roam_scan_ch_list_event(struct hdd_context *hdd_ctx,
8229 				      uint8_t vdev_id, uint16_t buf_len,
8230 				      uint8_t *buf)
8231 {
8232 	struct sk_buff *vendor_event;
8233 	uint32_t len, ret;
8234 	struct wlan_hdd_link_info *link_info;
8235 
8236 	if (!hdd_ctx) {
8237 		hdd_err_rl("hdd context is null");
8238 		return;
8239 	}
8240 
8241 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
8242 	if (!link_info)
8243 		return;
8244 
8245 	len = nla_total_size(buf_len) + NLMSG_HDRLEN;
8246 	vendor_event =
8247 		wlan_cfg80211_vendor_event_alloc(
8248 			hdd_ctx->wiphy, &link_info->adapter->wdev, len,
8249 			QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX,
8250 			GFP_KERNEL);
8251 
8252 	if (!vendor_event) {
8253 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
8254 		return;
8255 	}
8256 
8257 	ret = nla_put(vendor_event,
8258 		      QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_CONNECT_CHANNELS,
8259 		      buf_len, buf);
8260 	if (ret) {
8261 		hdd_err("OEM event put fails status %d", ret);
8262 		wlan_cfg80211_vendor_free_skb(vendor_event);
8263 		return;
8264 	}
8265 
8266 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8267 }
8268 #endif
8269 
8270 #define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
8271 	((1 << 26) | \
8272 	 (((probe_period) & 0x1fff) << 13) | \
8273 	 ((stay_period) & 0x1fff))
8274 
8275 #define ANT_DIV_SET_SNR_DIFF(snr_diff) \
8276 	((1 << 27) | \
8277 	 ((snr_diff) & 0x1fff))
8278 
8279 #define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
8280 	((1 << 28) | \
8281 	 ((probe_dwell_time) & 0x1fff))
8282 
8283 #define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
8284 	((1 << 29) | \
8285 	 (((mgmt_snr_weight) & 0xff) << 16) | \
8286 	 (((data_snr_weight) & 0xff) << 8) | \
8287 	 ((ack_snr_weight) & 0xff))
8288 
8289 #define RX_REORDER_TIMEOUT_VOICE \
8290 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
8291 #define RX_REORDER_TIMEOUT_VIDEO \
8292 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
8293 #define RX_REORDER_TIMEOUT_BESTEFFORT \
8294 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
8295 #define RX_REORDER_TIMEOUT_BACKGROUND \
8296 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
8297 #define RX_BLOCKSIZE_PEER_MAC \
8298 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
8299 #define RX_BLOCKSIZE_WINLIMIT \
8300 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
8301 
8302 #define CONFIG_CHANNEL_WIDTH \
8303 	QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH
8304 #define CONFIG_MLO_LINK_ID \
8305 	QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID
8306 #define CONFIG_MLO_LINKS \
8307 	QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS
8308 
8309 const struct nla_policy wlan_hdd_wifi_config_policy[
8310 			QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
8311 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS] = {
8312 							.type = NLA_U32},
8313 	[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES] = {.type = NLA_BINARY},
8314 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND] = {.type = NLA_U32},
8315 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_VALUE] = {.type = NLA_U32},
8316 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA] = {.type = NLA_BINARY,
8317 						      .len = 5000 },
8318 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH] = {.type = NLA_U32},
8319 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS] = {.type = NLA_U32},
8320 	[QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX] = {.type = NLA_U32},
8321 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE] = {
8322 		.type = NLA_U32},
8323 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO] = {
8324 		.type = NLA_U32},
8325 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT] = {
8326 		.type = NLA_U32},
8327 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND] = {
8328 		.type = NLA_U32},
8329 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC] =
8330 		VENDOR_NLA_POLICY_MAC_ADDR,
8331 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT] = {
8332 		.type = NLA_U32},
8333 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24] = {
8334 		.type = NLA_U8},
8335 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5] = {
8336 		.type = NLA_U8},
8337 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {
8338 		.type = NLA_U8},
8339 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL] = {.type = NLA_U8},
8340 	[QCA_WLAN_VENDOR_ATTR_CONF_TX_RATE] = {.type = NLA_U16},
8341 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
8342 	[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED] = {
8343 		.type = NLA_U8},
8344 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS] = {.type = NLA_U8 },
8345 	[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
8346 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
8347 	[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
8348 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
8349 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
8350 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
8351 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
8352 	[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
8353 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
8354 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
8355 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
8356 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY] = {
8357 		.type = NLA_U32 },
8358 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
8359 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
8360 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
8361 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
8362 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME] = {
8363 		.type = NLA_U32},
8364 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT] = {
8365 		.type = NLA_U32},
8366 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT] = {
8367 		.type = NLA_U32},
8368 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT] = {
8369 		.type = NLA_U32},
8370 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
8371 	[RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
8372 	[RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
8373 	[RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
8374 	[RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
8375 	[RX_BLOCKSIZE_PEER_MAC] = VENDOR_NLA_POLICY_MAC_ADDR,
8376 	[RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
8377 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
8378 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
8379 	[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER] = {.type = NLA_U8 },
8380 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
8381 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
8382 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
8383 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {
8384 						.type = NLA_U32 },
8385 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
8386 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {
8387 						.type = NLA_U8},
8388 	[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
8389 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
8390 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_U8},
8391 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS] = {.type = NLA_U8},
8392 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY] = {.type = NLA_U32 },
8393 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST] = {
8394 		.type = NLA_BINARY,
8395 		.len = WLAN_MAX_IE_LEN + 2},
8396 	[QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES] = {
8397 		.type = NLA_BINARY,
8398 		.len = SIR_MAC_MAX_ADD_IE_LENGTH + 2},
8399 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON] = {.type = NLA_U8 },
8400 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION] = {.type = NLA_U8 },
8401 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION] = {.type = NLA_U8 },
8402 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC] = {.type = NLA_U8 },
8403 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC] = {.type = NLA_U8 },
8404 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC] = {.type = NLA_U8 },
8405 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE] = {.type = NLA_U32 },
8406 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH] = {.type = NLA_U8 },
8407 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW] = {.type = NLA_U8 },
8408 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NSS] = {.type = NLA_U8 },
8409 	[QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT] = {
8410 		.type = NLA_U8 },
8411 	[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_ITO] = {.type = NLA_U16 },
8412 	[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_SPEC_WAKE_INTERVAL] = {
8413 		.type = NLA_U16 },
8414 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE] = {
8415 		.type = NLA_U8 },
8416 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS] = {.type = NLA_U8 },
8417 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS] = {.type = NLA_U8 },
8418 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING] = {.type = NLA_U8 },
8419 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL] = {.type = NLA_S32 },
8420 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS] = {.type = NLA_U8 },
8421 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS] = {.type = NLA_U8 },
8422 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY] = {
8423 							.type = NLA_U8 },
8424 	[QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS] = {.type = NLA_U8 },
8425 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD] = {.type = NLA_U8 },
8426 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DBAM] = {.type = NLA_U8 },
8427 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE_FOR_BE_BK] = {
8428 		.type = NLA_U8 },
8429 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEAMFORMER_PERIODIC_SOUNDING] = {
8430 		.type = NLA_U8 },
8431 	[QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE] = {
8432 		.type = NLA_U8 },
8433 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_EML_CAPABILITY] = {
8434 		.type = NLA_U8},
8435 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_SIMULTANEOUS_LINKS] = {
8436 		.type = NLA_U8},
8437 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_CAPABILITY] = {
8438 		.type = NLA_U8},
8439 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_FUNCTION] = {
8440 		.type = NLA_U8},
8441 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_NUM_LINKS] = {
8442 		.type = NLA_U8},
8443 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MODE] = {
8444 		.type = NLA_U8},
8445 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_ACTIVE_LINKS] = {
8446 		.type = NLA_NESTED},
8447 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EMLSR_MODE_SWITCH] = {
8448 		.type = NLA_U8},
8449 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UL_MU_CONFIG] = {.type = NLA_U8},
8450 	[QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST] = {
8451 		.type = NLA_NESTED},
8452 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS] = {
8453 		.type = NLA_NESTED },
8454 };
8455 
8456 #define WLAN_MAX_LINK_ID 15
8457 
8458 static const struct nla_policy bandwidth_mlo_policy[
8459 			QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
8460 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH] = {
8461 		.type = NLA_U8 },
8462 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID] = {
8463 		.type = NLA_U8 },
8464 };
8465 
8466 static const struct nla_policy
8467 qca_wlan_vendor_attr_omi_tx_policy [QCA_WLAN_VENDOR_ATTR_OMI_MAX + 1] = {
8468 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS] =       {.type = NLA_U8 },
8469 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW] =        {.type = NLA_U8 },
8470 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE] = {.type = NLA_U8 },
8471 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS] =      {.type = NLA_U8 },
8472 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE] = {.type = NLA_U8 },
8473 	[QCA_WLAN_VENDOR_ATTR_EHT_OMI_RX_NSS_EXTN] = {.type = NLA_U8 },
8474 	[QCA_WLAN_VENDOR_ATTR_EHT_OMI_CH_BW_EXTN] =  {.type = NLA_U8 },
8475 	[QCA_WLAN_VENDOR_ATTR_EHT_OMI_TX_NSS_EXTN] = {.type = NLA_U8 },
8476 };
8477 
8478 static const struct nla_policy
8479 wlan_oci_override_policy [QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX + 1] = {
8480 	[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE] = {.type = NLA_U8 },
8481 	[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY] = {.type = NLA_U32 },
8482 };
8483 
8484 const struct nla_policy
8485 wlan_hdd_wifi_test_config_policy[
8486 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
8487 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
8488 			.type = NLA_U8},
8489 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
8490 			.type = NLA_U8},
8491 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
8492 			.type = NLA_U8},
8493 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
8494 			.type = NLA_U8},
8495 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
8496 			.type = NLA_U8},
8497 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
8498 			.type = NLA_U8},
8499 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
8500 			.type = NLA_U8},
8501 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE] = {
8502 			.type = NLA_U8},
8503 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
8504 			.type = NLA_U8},
8505 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
8506 			.type = NLA_U16},
8507 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
8508 			.type = NLA_U8},
8509 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
8510 			.type = NLA_U8},
8511 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF] = {
8512 			.type = NLA_U8},
8513 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE] = {
8514 			.type = NLA_U8},
8515 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS] = {
8516 			.type = NLA_U8},
8517 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT] = {
8518 			.type = NLA_U8},
8519 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS] = {
8520 			.type = NLA_U8},
8521 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR] = {
8522 			.type = NLA_U8},
8523 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC] = {
8524 			.type = NLA_U8},
8525 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA] = {
8526 			.type = NLA_U8},
8527 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP] = {
8528 			.type = NLA_U8},
8529 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW] = {
8530 			.type = NLA_U8},
8531 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS] = {
8532 			.type = NLA_U8},
8533 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG] = {
8534 			.type = NLA_FLAG},
8535 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU] = {
8536 			.type = NLA_U8},
8537 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA] = {
8538 			.type = NLA_U8},
8539 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP] = {
8540 			.type = NLA_U8},
8541 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX] = {
8542 			.type = NLA_NESTED},
8543 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU] = {
8544 			.type = NLA_U8},
8545 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS]
8546 			= {.type = NLA_U8},
8547 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT] = {
8548 			.type = NLA_U8},
8549 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP] = {
8550 			.type = NLA_NESTED},
8551 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE] = {
8552 			.type = NLA_NESTED},
8553 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT] = {
8554 			.type = NLA_U8},
8555 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE] = {
8556 			.type = NLA_U8},
8557 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION] = {
8558 			.type = NLA_U8},
8559 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX]
8560 			= {.type = NLA_U8},
8561 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD] = {
8562 			.type = NLA_U16},
8563 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE] = {
8564 			.type = NLA_U8},
8565 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX] = {
8566 			.type = NLA_U8},
8567 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX] = {
8568 			.type = NLA_FLAG},
8569 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED] = {
8570 			.type = NLA_U8},
8571 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA] = {
8572 			.type = NLA_U8},
8573 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE] = {
8574 			.type = NLA_NESTED},
8575 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT] = {
8576 			.type = NLA_U8},
8577 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX] = {
8578 			.type = NLA_U8},
8579 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO] = {
8580 			.type = NLA_U8},
8581 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX] = {
8582 			.type = NLA_U8},
8583 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE]
8584 			= {.type = NLA_U8},
8585 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE]
8586 			= {.type = NLA_U8},
8587 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_11BE_EMLSR_MODE] = {
8588 			.type = NLA_U8},
8589 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BEAMFORMER_PERIODIC_SOUNDING] = {
8590 			.type = NLA_U8},
8591 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_80MHZ] = {
8592 			.type = NLA_U8},
8593 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_160MHZ] = {
8594 			.type = NLA_U8},
8595 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_320MHZ] = {
8596 			.type = NLA_U8},
8597 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EXCLUDE_STA_PROF_IN_PROBE_REQ] = {
8598 			.type = NLA_U8},
8599 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_EHT_TESTBED_DEFAULTS] = {
8600 			.type = NLA_U8},
8601 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MCS] = {
8602 			.type = NLA_U8},
8603 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_TB_SOUNDING_FB_RL] = {
8604 			.type = NLA_U8},
8605 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_OM_CTRL_SUPPORT] = {
8606 			.type = NLA_U8},
8607 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EMLSR_PADDING_DELAY] = {
8608 			.type = NLA_U8},
8609 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FORCE_MLO_POWER_SAVE_BCN_PERIOD] = {
8610 			.type = NLA_U8},
8611 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_STR_TX] = {
8612 			.type = NLA_U8},
8613 };
8614 
8615 /**
8616  * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
8617  * @hdd_ctx: HDD context
8618  * @adapter: Pointer to HDD adapter
8619  * @ie_data: Pointer to Scan IEs buffer
8620  * @ie_len: Length of Scan IEs
8621  *
8622  * This API is used to store the default scan ies received from
8623  * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
8624  *
8625  * Return: 0 on success; error number otherwise
8626  */
8627 static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
8628 					  struct hdd_adapter *adapter,
8629 					  uint8_t *ie_data, uint16_t ie_len)
8630 {
8631 	struct hdd_scan_info *scan_info = &adapter->scan_info;
8632 	bool add_qcn_ie;
8633 
8634 	if (!scan_info)
8635 		return -EINVAL;
8636 
8637 	if (scan_info->default_scan_ies) {
8638 		qdf_mem_free(scan_info->default_scan_ies);
8639 		scan_info->default_scan_ies = NULL;
8640 	}
8641 
8642 	scan_info->default_scan_ies_len = ie_len;
8643 	ucfg_mlme_get_qcn_ie_support(hdd_ctx->psoc, &add_qcn_ie);
8644 	if (add_qcn_ie)
8645 		ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
8646 
8647 	scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
8648 	if (!scan_info->default_scan_ies) {
8649 		scan_info->default_scan_ies_len = 0;
8650 		return -ENOMEM;
8651 	}
8652 
8653 	qdf_mem_copy(scan_info->default_scan_ies, ie_data,
8654 			  scan_info->default_scan_ies_len);
8655 
8656 	/* Add QCN IE if g_qcn_ie_support INI is enabled */
8657 	if (add_qcn_ie)
8658 		sme_add_qcn_ie(hdd_ctx->mac_handle,
8659 			       scan_info->default_scan_ies,
8660 			       &scan_info->default_scan_ies_len);
8661 
8662 	hdd_debug("Saved default scan IE:len %d",
8663 		  scan_info->default_scan_ies_len);
8664 	qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
8665 				(uint8_t *) scan_info->default_scan_ies,
8666 				scan_info->default_scan_ies_len);
8667 
8668 	return 0;
8669 }
8670 
8671 /**
8672  * wlan_hdd_handle_restrict_offchan_config() -
8673  * Handle wifi configuration attribute :
8674  * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
8675  * @adapter: Pointer to HDD adapter
8676  * @restrict_offchan: Restrict offchannel setting done by
8677  * application
8678  *
8679  * Return: 0 on success; error number otherwise
8680  */
8681 static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
8682 						   u8 restrict_offchan)
8683 {
8684 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8685 	enum QDF_OPMODE dev_mode = adapter->device_mode;
8686 	struct wlan_objmgr_vdev *vdev;
8687 	int ret_val = 0;
8688 
8689 	if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
8690 		hdd_err("Invalid interface type:%d", dev_mode);
8691 		return -EINVAL;
8692 	}
8693 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
8694 	if (!vdev)
8695 		return -EINVAL;
8696 	if (restrict_offchan == 1) {
8697 		u32 vdev_id = wlan_vdev_get_id(vdev);
8698 		enum policy_mgr_con_mode pmode =
8699 		policy_mgr_qdf_opmode_to_pm_con_mode(hdd_ctx->psoc, dev_mode,
8700 						     vdev_id);
8701 		uint32_t freq;
8702 
8703 		wlan_vdev_obj_lock(vdev);
8704 		wlan_vdev_mlme_cap_set(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
8705 		wlan_vdev_obj_unlock(vdev);
8706 		freq = policy_mgr_get_channel(hdd_ctx->psoc, pmode, &vdev_id);
8707 		if (!freq ||
8708 		    wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, freq)) {
8709 			hdd_err("unable to send avoid_freq");
8710 			ret_val = -EINVAL;
8711 		}
8712 		hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
8713 	} else if (restrict_offchan == 0) {
8714 		wlan_vdev_obj_lock(vdev);
8715 		wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
8716 		wlan_vdev_obj_unlock(vdev);
8717 		if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
8718 			hdd_err("unable to clear avoid_freq");
8719 			ret_val = -EINVAL;
8720 		}
8721 		hdd_info("vdev mode %d dnbs disabled", dev_mode);
8722 	} else {
8723 		ret_val = -EINVAL;
8724 		hdd_err("Invalid RESTRICT_OFFCHAN setting");
8725 	}
8726 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
8727 	return ret_val;
8728 }
8729 
8730 /**
8731  * wlan_hdd_cfg80211_wifi_set_reorder_timeout() - set reorder timeout
8732  * @link_info: link info pointer in HDD adapter
8733  * @tb: array of pointer to struct nlattr
8734  *
8735  * Return: 0 on success; error number otherwise
8736  */
8737 static int
8738 wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct wlan_hdd_link_info *link_info,
8739 					   struct nlattr *tb[])
8740 {
8741 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
8742 	int ret_val = 0;
8743 	QDF_STATUS qdf_status;
8744 	struct sir_set_rx_reorder_timeout_val reorder_timeout;
8745 	mac_handle_t mac_handle;
8746 
8747 #define RX_TIMEOUT_VAL_MIN 10
8748 #define RX_TIMEOUT_VAL_MAX 1000
8749 
8750 	if (tb[RX_REORDER_TIMEOUT_VOICE] ||
8751 	    tb[RX_REORDER_TIMEOUT_VIDEO] ||
8752 	    tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
8753 	    tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
8754 
8755 		/* if one is specified, all must be specified */
8756 		if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
8757 		    !tb[RX_REORDER_TIMEOUT_VIDEO] ||
8758 		    !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
8759 		    !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
8760 			hdd_err("four AC timeout val are required MAC");
8761 			return -EINVAL;
8762 		}
8763 
8764 		reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
8765 			tb[RX_REORDER_TIMEOUT_VOICE]);
8766 		reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
8767 			tb[RX_REORDER_TIMEOUT_VIDEO]);
8768 		reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
8769 			tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
8770 		reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
8771 			tb[RX_REORDER_TIMEOUT_BACKGROUND]);
8772 		/* timeout value is required to be in the rang 10 to 1000ms */
8773 		if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
8774 		    reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
8775 		    reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
8776 		    reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
8777 		    reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
8778 		    reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
8779 		    reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
8780 		    reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
8781 			mac_handle = hdd_ctx->mac_handle;
8782 			qdf_status = sme_set_reorder_timeout(mac_handle,
8783 							     &reorder_timeout);
8784 			if (qdf_status != QDF_STATUS_SUCCESS) {
8785 				hdd_err("failed to set reorder timeout err %d",
8786 					qdf_status);
8787 				ret_val = -EPERM;
8788 			}
8789 		} else {
8790 			hdd_err("one of the timeout value is not in range");
8791 			ret_val = -EINVAL;
8792 		}
8793 	}
8794 
8795 	return ret_val;
8796 }
8797 
8798 /**
8799  * wlan_hdd_cfg80211_wifi_set_rx_blocksize() - set rx blocksize
8800  * @link_info: Link info pointer in HDD adapter
8801  * @tb: array of pointer to struct nlattr
8802  *
8803  * Return: 0 on success; error number otherwise
8804  */
8805 static int
8806 wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct wlan_hdd_link_info *link_info,
8807 					struct nlattr *tb[])
8808 {
8809 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
8810 	int ret_val = 0;
8811 	uint32_t set_value;
8812 	QDF_STATUS qdf_status;
8813 	struct sir_peer_set_rx_blocksize rx_blocksize;
8814 	mac_handle_t mac_handle;
8815 
8816 #define WINDOW_SIZE_VAL_MIN 1
8817 #define WINDOW_SIZE_VAL_MAX 64
8818 
8819 	if (tb[RX_BLOCKSIZE_PEER_MAC] ||
8820 	    tb[RX_BLOCKSIZE_WINLIMIT]) {
8821 
8822 		/* if one is specified, both must be specified */
8823 		if (!tb[RX_BLOCKSIZE_PEER_MAC] ||
8824 		    !tb[RX_BLOCKSIZE_WINLIMIT]) {
8825 			hdd_err("Both Peer MAC and windows limit required");
8826 			return -EINVAL;
8827 		}
8828 
8829 		memcpy(&rx_blocksize.peer_macaddr,
8830 		       nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
8831 		       sizeof(rx_blocksize.peer_macaddr)),
8832 
8833 		rx_blocksize.vdev_id = link_info->vdev_id;
8834 		set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
8835 		/* maximum window size is 64 */
8836 		if (set_value >= WINDOW_SIZE_VAL_MIN &&
8837 		    set_value <= WINDOW_SIZE_VAL_MAX) {
8838 			rx_blocksize.rx_block_ack_win_limit = set_value;
8839 			mac_handle = hdd_ctx->mac_handle;
8840 			qdf_status = sme_set_rx_set_blocksize(mac_handle,
8841 							      &rx_blocksize);
8842 			if (qdf_status != QDF_STATUS_SUCCESS) {
8843 				hdd_err("failed to set aggr sizes err %d",
8844 					qdf_status);
8845 				ret_val = -EPERM;
8846 			}
8847 		} else {
8848 			hdd_err("window size val is not in range");
8849 			ret_val = -EINVAL;
8850 		}
8851 	}
8852 
8853 	return ret_val;
8854 }
8855 
8856 int hdd_set_vdev_phy_mode(struct hdd_adapter *adapter,
8857 			  enum qca_wlan_vendor_phy_mode vendor_phy_mode)
8858 {
8859 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8860 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
8861 	struct wlan_hdd_link_info *link_info = adapter->deflink;
8862 	eCsrPhyMode phymode;
8863 	WMI_HOST_WIFI_STANDARD std;
8864 	enum hdd_dot11_mode dot11_mode;
8865 	uint8_t supported_band;
8866 	int ret;
8867 
8868 	if (hdd_cm_is_vdev_connected(link_info)) {
8869 		hdd_err("Station is connected, command is not supported");
8870 		return -EINVAL;
8871 	}
8872 
8873 	adapter->user_phy_mode = vendor_phy_mode;
8874 
8875 	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &phymode);
8876 	if (ret)
8877 		return ret;
8878 
8879 	ret = hdd_phymode_to_dot11_mode(phymode, &dot11_mode);
8880 	if (ret)
8881 		return ret;
8882 
8883 	ret = hdd_vendor_mode_to_band(vendor_phy_mode, &supported_band,
8884 				      wlan_reg_is_6ghz_supported(psoc));
8885 	if (ret)
8886 		return ret;
8887 
8888 	std = hdd_get_wifi_standard(hdd_ctx, dot11_mode, supported_band);
8889 	hdd_debug("wifi_standard %d, vendor_phy_mode %d", std, vendor_phy_mode);
8890 
8891 	ret = sme_cli_set_command(link_info->vdev_id,
8892 				  wmi_vdev_param_wifi_standard_version,
8893 				  std, VDEV_CMD);
8894 	if (ret) {
8895 		hdd_err("Failed to set standard version to fw");
8896 		return ret;
8897 	}
8898 
8899 	ucfg_mlme_set_vdev_wifi_std(hdd_ctx->psoc, link_info->vdev_id, std);
8900 
8901 	return 0;
8902 }
8903 
8904 int hdd_set_phy_mode(struct hdd_adapter *adapter,
8905 		     enum qca_wlan_vendor_phy_mode vendor_phy_mode)
8906 {
8907 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8908 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
8909 	eCsrPhyMode phymode;
8910 	uint8_t supported_band;
8911 	uint32_t bonding_mode;
8912 	int ret = 0;
8913 
8914 	if (!psoc) {
8915 		hdd_err("psoc is NULL");
8916 		return -EINVAL;
8917 	}
8918 
8919 	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &phymode);
8920 	if (ret < 0)
8921 		return ret;
8922 
8923 	ret = hdd_vendor_mode_to_band(vendor_phy_mode, &supported_band,
8924 				      wlan_reg_is_6ghz_supported(psoc));
8925 	if (ret < 0)
8926 		return ret;
8927 
8928 	ret = hdd_vendor_mode_to_bonding_mode(vendor_phy_mode, &bonding_mode);
8929 	if (ret < 0)
8930 		return ret;
8931 
8932 	return hdd_update_phymode(adapter, phymode, supported_band,
8933 				  bonding_mode);
8934 }
8935 
8936 /**
8937  * hdd_config_phy_mode() - set PHY mode
8938  * @link_info: Link info pointer in HDD adapter
8939  * @tb: nla attr sent from userspace
8940  *
8941  * Return: 0 on success; error number otherwise
8942  */
8943 static int hdd_config_phy_mode(struct wlan_hdd_link_info *link_info,
8944 			       struct nlattr *tb[])
8945 {
8946 	enum qca_wlan_vendor_phy_mode vendor_phy_mode;
8947 	uint32_t ifindex;
8948 	struct nlattr *phy_mode_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE];
8949 	struct nlattr *ifindex_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX];
8950 
8951 	if (!phy_mode_attr)
8952 		return 0;
8953 
8954 	vendor_phy_mode = nla_get_u32(phy_mode_attr);
8955 	if (!ifindex_attr)
8956 		return hdd_set_phy_mode(link_info->adapter, vendor_phy_mode);
8957 
8958 	ifindex = nla_get_u32(ifindex_attr);
8959 	if (ifindex == link_info->adapter->dev->ifindex)
8960 		return hdd_set_vdev_phy_mode(link_info->adapter,
8961 					     vendor_phy_mode);
8962 
8963 	hdd_err_rl("ifindex %d, expected ifindex %d", ifindex,
8964 		   link_info->adapter->dev->ifindex);
8965 	return -EINVAL;
8966 }
8967 
8968 /**
8969  * hdd_set_roam_reason_vsie_status() - enable/disable inclusion of
8970  * roam reason vsie in Reassoc
8971  * @link_info: Link info pointer in adapter
8972  * @attr: nla attr sent by supplicant
8973  *
8974  * Return: 0 on success, negative errno on failure
8975  */
8976 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
8977 static int hdd_set_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
8978 					   const struct nlattr *attr)
8979 {
8980 	uint8_t roam_reason_vsie_enabled;
8981 	int errno;
8982 	QDF_STATUS status = QDF_STATUS_SUCCESS;
8983 	struct hdd_adapter *adapter = link_info->adapter;
8984 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8985 
8986 	if (!hdd_ctx) {
8987 		hdd_err("hdd_ctx failure");
8988 		return -EINVAL;
8989 	}
8990 
8991 	roam_reason_vsie_enabled = nla_get_u8(attr);
8992 	if (roam_reason_vsie_enabled > 1)
8993 		roam_reason_vsie_enabled = 1;
8994 
8995 	status =
8996 		ucfg_mlme_set_roam_reason_vsie_status(hdd_ctx->psoc,
8997 						      roam_reason_vsie_enabled);
8998 	if (QDF_IS_STATUS_ERROR(status)) {
8999 		hdd_err("set roam reason vsie failed");
9000 		return -EINVAL;
9001 	}
9002 
9003 	errno = sme_cli_set_command
9004 			(link_info->vdev_id,
9005 			 wmi_vdev_param_enable_disable_roam_reason_vsie,
9006 			 roam_reason_vsie_enabled, VDEV_CMD);
9007 	if (errno) {
9008 		hdd_err("Failed to set beacon report error vsie");
9009 		status = QDF_STATUS_E_FAILURE;
9010 	}
9011 
9012 	return qdf_status_to_os_return(status);
9013 }
9014 #else
9015 static inline int
9016 hdd_set_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
9017 				const struct nlattr *attr)
9018 {
9019 	return -ENOTSUPP;
9020 }
9021 #endif
9022 
9023 static int hdd_set_ft_over_ds(struct wlan_hdd_link_info *link_info,
9024 			      const struct nlattr *attr)
9025 {
9026 	uint8_t ft_over_ds_enable;
9027 	QDF_STATUS status = QDF_STATUS_SUCCESS;
9028 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9029 
9030 	if (!hdd_ctx) {
9031 		hdd_err("hdd_ctx failure");
9032 		return -EINVAL;
9033 	}
9034 
9035 	ft_over_ds_enable = nla_get_u8(attr);
9036 
9037 	if (ft_over_ds_enable != 0 && ft_over_ds_enable != 1) {
9038 		hdd_err_rl("Invalid ft_over_ds_enable: %d", ft_over_ds_enable);
9039 		return -EINVAL;
9040 	}
9041 
9042 	status = ucfg_mlme_set_ft_over_ds(hdd_ctx->psoc, ft_over_ds_enable);
9043 	if (QDF_IS_STATUS_ERROR(status)) {
9044 		hdd_err("set ft_over_ds failed");
9045 		return -EINVAL;
9046 	}
9047 
9048 	return status;
9049 }
9050 
9051 static int hdd_config_ldpc(struct wlan_hdd_link_info *link_info,
9052 			   const struct nlattr *attr)
9053 {
9054 	uint8_t ldpc;
9055 	int ret;
9056 
9057 	ldpc = nla_get_u8(attr);
9058 
9059 	ret = hdd_set_ldpc(link_info, ldpc);
9060 
9061 	return ret;
9062 }
9063 
9064 static int hdd_config_tx_stbc(struct wlan_hdd_link_info *link_info,
9065 			      const struct nlattr *attr)
9066 {
9067 	uint8_t tx_stbc;
9068 	int ret;
9069 
9070 	tx_stbc = nla_get_u8(attr);
9071 
9072 	ret = hdd_set_tx_stbc(link_info, tx_stbc);
9073 
9074 	return ret;
9075 }
9076 
9077 static int hdd_config_rx_stbc(struct wlan_hdd_link_info *link_info,
9078 			      const struct nlattr *attr)
9079 {
9080 	uint8_t rx_stbc;
9081 	int ret;
9082 
9083 	rx_stbc = nla_get_u8(attr);
9084 
9085 	ret = hdd_set_rx_stbc(link_info, rx_stbc);
9086 
9087 	return ret;
9088 }
9089 
9090 static int hdd_config_access_policy(struct wlan_hdd_link_info *link_info,
9091 				    struct nlattr *tb[])
9092 {
9093 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9094 	struct nlattr *policy_attr =
9095 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY];
9096 	struct nlattr *ielist_attr =
9097 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST];
9098 	uint32_t access_policy;
9099 	uint8_t ie[WLAN_MAX_IE_LEN + 2];
9100 	QDF_STATUS status;
9101 
9102 	/* nothing to do if neither attribute is present */
9103 	if (!ielist_attr && !policy_attr)
9104 		return 0;
9105 
9106 	/* if one is present, both must be present */
9107 	if (!ielist_attr || !policy_attr) {
9108 		hdd_err("Missing attribute for %s",
9109 			policy_attr ?
9110 				"ACCESS_POLICY_IE_LIST" : "ACCESS_POLICY");
9111 		return -EINVAL;
9112 	}
9113 
9114 	/* validate the access policy */
9115 	access_policy = nla_get_u32(policy_attr);
9116 	switch (access_policy) {
9117 	case QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED:
9118 	case QCA_ACCESS_POLICY_DENY_UNLESS_LISTED:
9119 		/* valid */
9120 		break;
9121 	default:
9122 		hdd_err("Invalid value. access_policy %u", access_policy);
9123 		return -EINVAL;
9124 	}
9125 
9126 	/*
9127 	 * ie length is validated by the nla_policy.  need to make a
9128 	 * copy since SME will always read WLAN_MAX_IE_LEN+2 bytes
9129 	 */
9130 	nla_memcpy(ie, ielist_attr, sizeof(ie));
9131 
9132 	hdd_debug("calling sme_update_access_policy_vendor_ie");
9133 	status = sme_update_access_policy_vendor_ie(hdd_ctx->mac_handle,
9134 						    link_info->vdev_id,
9135 						    ie, access_policy);
9136 	if (QDF_IS_STATUS_ERROR(status))
9137 		hdd_err("Failed to set vendor ie and access policy, %d",
9138 			status);
9139 
9140 	return qdf_status_to_os_return(status);
9141 }
9142 
9143 static int hdd_config_mpdu_aggregation(struct wlan_hdd_link_info *link_info,
9144 				       struct nlattr *tb[])
9145 {
9146 	struct nlattr *tx_attr =
9147 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION];
9148 	struct nlattr *rx_attr =
9149 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION];
9150 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9151 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
9152 	uint8_t tx_size, rx_size;
9153 	QDF_STATUS status;
9154 
9155 	if (!mac_handle) {
9156 		hdd_err("NULL Mac handle");
9157 		return -EINVAL;
9158 	}
9159 
9160 	/* nothing to do if neither attribute is present */
9161 	if (!tx_attr && !rx_attr)
9162 		return 0;
9163 
9164 	/* if one is present, both must be present */
9165 	if (!tx_attr || !rx_attr) {
9166 		hdd_err("Missing attribute for %s",
9167 			tx_attr ? "RX" : "TX");
9168 		return -EINVAL;
9169 	}
9170 
9171 	tx_size = nla_get_u8(tx_attr);
9172 	rx_size = nla_get_u8(rx_attr);
9173 	if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
9174 	    !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
9175 		hdd_err("TX %d RX %d MPDU aggr size not in range",
9176 			tx_size, rx_size);
9177 
9178 		return -EINVAL;
9179 	}
9180 
9181 	if (tx_size > 1)
9182 		sme_set_amsdu(mac_handle, true);
9183 	else
9184 		sme_set_amsdu(mac_handle, false);
9185 
9186 	hdd_debug("tx size: %d", tx_size);
9187 	status = wma_cli_set_command(link_info->vdev_id,
9188 				     GEN_VDEV_PARAM_AMSDU,
9189 				     tx_size, GEN_CMD);
9190 	if (status) {
9191 		hdd_err("Failed to set AMSDU param to FW, status %d", status);
9192 		return qdf_status_to_os_return(status);
9193 	}
9194 
9195 	status = wma_set_tx_rx_aggr_size(link_info->vdev_id,
9196 					 tx_size, rx_size,
9197 					 WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU);
9198 
9199 	return qdf_status_to_os_return(status);
9200 }
9201 
9202 static int hdd_config_msdu_aggregation(struct wlan_hdd_link_info *link_info,
9203 				       struct nlattr *tb[])
9204 {
9205 	struct nlattr *tx_attr =
9206 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION];
9207 	struct nlattr *rx_attr =
9208 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION];
9209 	uint8_t tx_size, rx_size;
9210 	QDF_STATUS status;
9211 
9212 	/* nothing to do if neither attribute is present */
9213 	if (!tx_attr && !rx_attr)
9214 		return 0;
9215 
9216 	/* if one is present, both must be present */
9217 	if (!tx_attr || !rx_attr) {
9218 		hdd_err("Missing attribute for %s",
9219 			tx_attr ? "RX" : "TX");
9220 		return -EINVAL;
9221 	}
9222 
9223 	tx_size = nla_get_u8(tx_attr);
9224 	rx_size = nla_get_u8(rx_attr);
9225 	if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
9226 	    !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
9227 		hdd_err("TX %d RX %d MSDU aggr size not in range",
9228 			tx_size, rx_size);
9229 
9230 		return -EINVAL;
9231 	}
9232 
9233 	status = wma_set_tx_rx_aggr_size(link_info->vdev_id,
9234 					 tx_size,
9235 					 rx_size,
9236 					 WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU);
9237 
9238 	return qdf_status_to_os_return(status);
9239 }
9240 
9241 static QDF_STATUS
9242 hdd_populate_vdev_chains(struct wlan_mlme_nss_chains *nss_chains_cfg,
9243 			 uint8_t tx_chains,
9244 			 uint8_t rx_chains,
9245 			 enum nss_chains_band_info band,
9246 			 struct wlan_objmgr_vdev *vdev)
9247 {
9248 	struct wlan_mlme_nss_chains *dynamic_cfg;
9249 
9250 	nss_chains_cfg->num_rx_chains[band] = rx_chains;
9251 	nss_chains_cfg->num_tx_chains[band] = tx_chains;
9252 
9253 	dynamic_cfg = ucfg_mlme_get_dynamic_vdev_config(vdev);
9254 	if (!dynamic_cfg) {
9255 		hdd_err("nss chain dynamic config NULL");
9256 		return QDF_STATUS_E_FAILURE;
9257 	}
9258 	/*
9259 	 * If user gives any nss value, then chains will be adjusted based on
9260 	 * nss (in SME func sme_validate_user_nss_chain_params).
9261 	 * If Chains are not suitable as per current NSS then, we need to
9262 	 * return, and the below logic is added for the same.
9263 	 */
9264 
9265 	if ((dynamic_cfg->rx_nss[band] > rx_chains) ||
9266 	    (dynamic_cfg->tx_nss[band] > tx_chains)) {
9267 		hdd_err("Chains less than nss, configure correct nss first.");
9268 		return QDF_STATUS_E_FAILURE;
9269 	}
9270 
9271 	return QDF_STATUS_SUCCESS;
9272 }
9273 
9274 int
9275 hdd_set_dynamic_antenna_mode(struct wlan_hdd_link_info *link_info,
9276 			     uint8_t num_rx_chains, uint8_t num_tx_chains)
9277 {
9278 	enum nss_chains_band_info band;
9279 	struct wlan_mlme_nss_chains user_cfg;
9280 	QDF_STATUS status;
9281 	mac_handle_t mac_handle;
9282 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9283 	struct wlan_objmgr_vdev *vdev;
9284 	int ret;
9285 
9286 	ret = wlan_hdd_validate_context(hdd_ctx);
9287 	if (0 != ret)
9288 		return ret;
9289 
9290 	mac_handle = hdd_ctx->mac_handle;
9291 	if (!mac_handle) {
9292 		hdd_err("NULL MAC handle");
9293 		return -EINVAL;
9294 	}
9295 
9296 	if (!hdd_is_vdev_in_conn_state(link_info)) {
9297 		hdd_debug("Vdev (id %d) not in connected/started state, cannot accept command",
9298 			  link_info->vdev_id);
9299 		return -EINVAL;
9300 	}
9301 
9302 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
9303 	if (!vdev) {
9304 		hdd_err("vdev is NULL");
9305 		return -EINVAL;
9306 	}
9307 
9308 	qdf_mem_zero(&user_cfg, sizeof(user_cfg));
9309 	for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++) {
9310 		status = hdd_populate_vdev_chains(&user_cfg,
9311 						  num_tx_chains,
9312 						  num_rx_chains, band, vdev);
9313 		if (QDF_IS_STATUS_ERROR(status)) {
9314 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9315 			return -EINVAL;
9316 		}
9317 	}
9318 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9319 
9320 	status = sme_nss_chains_update(mac_handle,
9321 				       &user_cfg,
9322 				       link_info->vdev_id);
9323 	if (QDF_IS_STATUS_ERROR(status))
9324 		return -EINVAL;
9325 
9326 	return 0;
9327 }
9328 
9329 static int hdd_config_vdev_chains(struct wlan_hdd_link_info *link_info,
9330 				  struct nlattr *tb[])
9331 {
9332 	struct hdd_adapter *adapter = link_info->adapter;
9333 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9334 	uint8_t tx_chains, rx_chains;
9335 	struct nlattr *tx_attr =
9336 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS];
9337 	struct nlattr *rx_attr =
9338 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS];
9339 
9340 	if (!tx_attr && !rx_attr)
9341 		return 0;
9342 
9343 	/* if one is present, both must be present */
9344 	if (!tx_attr || !rx_attr) {
9345 		hdd_err("Missing attribute for %s",
9346 			tx_attr ? "RX" : "TX");
9347 		return -EINVAL;
9348 	}
9349 
9350 	tx_chains = nla_get_u8(tx_attr);
9351 	rx_chains = nla_get_u8(rx_attr);
9352 
9353 	if (hdd_ctx->dynamic_nss_chains_support)
9354 		return hdd_set_dynamic_antenna_mode(link_info,
9355 						    rx_chains, tx_chains);
9356 	return 0;
9357 }
9358 
9359 static int hdd_config_tx_rx_nss(struct wlan_hdd_link_info *link_info,
9360 				struct nlattr *tb[])
9361 {
9362 	uint8_t tx_nss, rx_nss;
9363 	QDF_STATUS status;
9364 
9365 	struct nlattr *tx_attr =
9366 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS];
9367 	struct nlattr *rx_attr =
9368 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS];
9369 
9370 	if (!tx_attr && !rx_attr)
9371 		return 0;
9372 
9373 	/* if one is present, both must be present */
9374 	if (!tx_attr || !rx_attr) {
9375 		hdd_err("Missing attribute for %s",
9376 			tx_attr ? "RX" : "TX");
9377 		return -EINVAL;
9378 	}
9379 
9380 	tx_nss = nla_get_u8(tx_attr);
9381 	rx_nss = nla_get_u8(rx_attr);
9382 	hdd_debug("tx_nss %d rx_nss %d", tx_nss, rx_nss);
9383 	/* Only allow NSS for tx_rx_nss for 1x1, 1x2, 2x2 */
9384 	if (!((tx_nss == 1 && rx_nss == 2) || (tx_nss == 1 && rx_nss == 1) ||
9385 	      (tx_nss == 2 && rx_nss == 2))) {
9386 		hdd_err("Setting tx_nss %d rx_nss %d not allowed", tx_nss,
9387 			rx_nss);
9388 		return -EINVAL;
9389 	}
9390 	status = hdd_update_nss(link_info, tx_nss, rx_nss);
9391 	if (status != QDF_STATUS_SUCCESS) {
9392 		hdd_debug("Can't set tx_nss %d rx_nss %d", tx_nss, rx_nss);
9393 		return -EINVAL;
9394 	}
9395 
9396 	return 0;
9397 }
9398 
9399 #ifdef WLAN_FEATURE_SON
9400 static int hdd_process_generic_set_cmd(struct wlan_hdd_link_info *link_info,
9401 				       struct nlattr *tb[])
9402 {
9403 	struct wireless_dev *wdev;
9404 	struct wiphy *wiphy;
9405 	struct hdd_adapter *adapter = link_info->adapter;
9406 
9407 	if (!adapter)
9408 		return 0;
9409 
9410 	wdev = &adapter->wdev;
9411 	if (!wdev || !wdev->wiphy)
9412 		return 0;
9413 	wiphy = wdev->wiphy;
9414 
9415 	/* Generic command is used by EasyMesh,
9416 	 * route the command to SON module if it is Generic
9417 	 */
9418 	if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND])
9419 		return hdd_son_send_set_wifi_generic_command(wiphy, wdev, tb);
9420 
9421 	return 0;
9422 }
9423 #else
9424 static inline int
9425 hdd_process_generic_set_cmd(struct wlan_hdd_link_info *link_info,
9426 			    struct nlattr *tb[])
9427 {
9428 	return 0;
9429 }
9430 #endif
9431 
9432 static int hdd_config_ani(struct wlan_hdd_link_info *link_info,
9433 			  struct nlattr *tb[])
9434 {
9435 	int errno;
9436 	uint8_t ani_setting_type;
9437 	int32_t ani_level = 0, enable_ani;
9438 	struct nlattr *ani_setting_attr =
9439 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING];
9440 	struct nlattr *ani_level_attr =
9441 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL];
9442 
9443 	if (!ani_setting_attr)
9444 		return 0;
9445 
9446 	ani_setting_type = nla_get_u8(ani_setting_attr);
9447 	if (ani_setting_type != QCA_WLAN_ANI_SETTING_AUTO &&
9448 	    ani_setting_type != QCA_WLAN_ANI_SETTING_FIXED) {
9449 		hdd_err("invalid ani_setting_type %d", ani_setting_type);
9450 		return -EINVAL;
9451 	}
9452 
9453 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_AUTO &&
9454 	    ani_level_attr) {
9455 		hdd_err("Not support to set ani level in QCA_WLAN_ANI_SETTING_AUTO");
9456 		return -EINVAL;
9457 	}
9458 
9459 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_FIXED) {
9460 		if (!ani_level_attr) {
9461 			hdd_err("invalid ani_level_attr");
9462 			return -EINVAL;
9463 		}
9464 		ani_level = nla_get_s32(ani_level_attr);
9465 	}
9466 	hdd_debug("ani_setting_type %u, ani_level %d",
9467 		  ani_setting_type, ani_level);
9468 
9469 	/* ANI (Adaptive noise immunity) */
9470 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_AUTO)
9471 		enable_ani = 1;
9472 	else
9473 		enable_ani = 0;
9474 
9475 	errno = wma_cli_set_command(link_info->vdev_id,
9476 				    wmi_pdev_param_ani_enable,
9477 				    enable_ani, PDEV_CMD);
9478 	if (errno) {
9479 		hdd_err("Failed to set ani enable, errno %d", errno);
9480 		return errno;
9481 	}
9482 
9483 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_FIXED) {
9484 		errno = wma_cli_set_command(link_info->vdev_id,
9485 					    wmi_pdev_param_ani_ofdm_level,
9486 					    ani_level, PDEV_CMD);
9487 		if (errno) {
9488 			hdd_err("Failed to set ani level, errno %d", errno);
9489 			return errno;
9490 		}
9491 	}
9492 
9493 	return 0;
9494 }
9495 
9496 static int hdd_config_ant_div_period(struct wlan_hdd_link_info *link_info,
9497 				     struct nlattr *tb[])
9498 {
9499 	struct nlattr *probe_attr =
9500 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD];
9501 	struct nlattr *stay_attr =
9502 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD];
9503 	uint32_t probe_period, stay_period, ant_div_usrcfg;
9504 	int errno;
9505 
9506 	/* nothing to do if neither attribute is present */
9507 	if (!probe_attr && !stay_attr)
9508 		return 0;
9509 
9510 	/* if one is present, both must be present */
9511 	if (!probe_attr || !stay_attr) {
9512 		hdd_err("Missing attribute for %s",
9513 			probe_attr ? "STAY" : "PROBE");
9514 		return -EINVAL;
9515 	}
9516 
9517 	probe_period = nla_get_u32(probe_attr);
9518 	stay_period = nla_get_u32(stay_attr);
9519 	ant_div_usrcfg = ANT_DIV_SET_PERIOD(probe_period, stay_period);
9520 	hdd_debug("ant div set period: %x", ant_div_usrcfg);
9521 	errno = wma_cli_set_command(link_info->vdev_id,
9522 				    wmi_pdev_param_ant_div_usrcfg,
9523 				    ant_div_usrcfg, PDEV_CMD);
9524 	if (errno)
9525 		hdd_err("Failed to set ant div period, %d", errno);
9526 
9527 	return errno;
9528 }
9529 
9530 static int hdd_config_ant_div_snr_weight(struct wlan_hdd_link_info *link_info,
9531 					 struct nlattr *tb[])
9532 {
9533 	struct nlattr *mgmt_attr =
9534 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT];
9535 	struct nlattr *data_attr =
9536 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT];
9537 	struct nlattr *ack_attr =
9538 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT];
9539 	uint32_t mgmt_snr, data_snr, ack_snr, ant_div_usrcfg;
9540 	int errno;
9541 
9542 	/* nothing to do if none of the attributes are present */
9543 	if (!mgmt_attr && !data_attr && !ack_attr)
9544 		return 0;
9545 
9546 	/* if one is present, all must be present */
9547 	if (!mgmt_attr || !data_attr || !ack_attr) {
9548 		hdd_err("Missing attribute");
9549 		return -EINVAL;
9550 	}
9551 
9552 	mgmt_snr = nla_get_u32(mgmt_attr);
9553 	data_snr = nla_get_u32(data_attr);
9554 	ack_snr = nla_get_u32(ack_attr);
9555 	ant_div_usrcfg = ANT_DIV_SET_WEIGHT(mgmt_snr, data_snr, ack_snr);
9556 	hdd_debug("ant div set weight: %x", ant_div_usrcfg);
9557 	errno = wma_cli_set_command(link_info->vdev_id,
9558 				    wmi_pdev_param_ant_div_usrcfg,
9559 				    ant_div_usrcfg, PDEV_CMD);
9560 	if (errno)
9561 		hdd_err("Failed to set ant div weight, %d", errno);
9562 
9563 	return errno;
9564 }
9565 
9566 static int
9567 hdd_config_fine_time_measurement(struct wlan_hdd_link_info *link_info,
9568 				 const struct nlattr *attr)
9569 {
9570 	struct hdd_adapter *adapter = link_info->adapter;
9571 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9572 	uint32_t user_capability;
9573 	uint32_t target_capability;
9574 	uint32_t final_capability;
9575 	QDF_STATUS status;
9576 
9577 	user_capability = nla_get_u32(attr);
9578 	target_capability = hdd_ctx->fine_time_meas_cap_target;
9579 	final_capability = user_capability & target_capability;
9580 
9581 	status = ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
9582 						  final_capability);
9583 	if (QDF_IS_STATUS_ERROR(status)) {
9584 		hdd_err("Unable to set value, status %d", status);
9585 		return -EINVAL;
9586 	}
9587 
9588 	sme_update_fine_time_measurement_capab(hdd_ctx->mac_handle,
9589 					       link_info->vdev_id,
9590 					       final_capability);
9591 	ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, final_capability);
9592 
9593 	hdd_debug("user: 0x%x, target: 0x%x, final: 0x%x",
9594 		  user_capability, target_capability, final_capability);
9595 
9596 	return 0;
9597 }
9598 
9599 static int hdd_config_modulated_dtim(struct wlan_hdd_link_info *link_info,
9600 				     const struct nlattr *attr)
9601 {
9602 	struct wlan_objmgr_vdev *vdev;
9603 	uint32_t modulated_dtim;
9604 	QDF_STATUS status;
9605 
9606 	modulated_dtim = nla_get_u32(attr);
9607 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
9608 	if (!vdev)
9609 		return -EINVAL;
9610 
9611 	status = ucfg_pmo_config_modulated_dtim(vdev, modulated_dtim);
9612 
9613 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9614 
9615 	return qdf_status_to_os_return(status);
9616 }
9617 
9618 static int hdd_config_listen_interval(struct wlan_hdd_link_info *link_info,
9619 				      const struct nlattr *attr)
9620 {
9621 	struct wlan_objmgr_vdev *vdev;
9622 	uint32_t listen_interval;
9623 	QDF_STATUS status;
9624 
9625 	listen_interval = nla_get_u32(attr);
9626 	if (listen_interval > cfg_max(CFG_PMO_ENABLE_DYNAMIC_DTIM)) {
9627 		hdd_err_rl("Invalid value for listen interval - %d",
9628 			   listen_interval);
9629 		return -EINVAL;
9630 	}
9631 
9632 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_PMO_ID);
9633 	if (!vdev)
9634 		return -EINVAL;
9635 
9636 	status = ucfg_pmo_config_listen_interval(vdev, listen_interval);
9637 
9638 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_PMO_ID);
9639 
9640 	return qdf_status_to_os_return(status);
9641 }
9642 
9643 static int hdd_config_lro(struct wlan_hdd_link_info *link_info,
9644 			  const struct nlattr *attr)
9645 {
9646 	struct wlan_objmgr_vdev *vdev;
9647 	uint8_t enable_flag;
9648 	QDF_STATUS status = QDF_STATUS_E_FAULT;
9649 
9650 	enable_flag = nla_get_u8(attr);
9651 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_DP_ID);
9652 	if (vdev) {
9653 		status = osif_dp_lro_set_reset(vdev, enable_flag);
9654 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
9655 	}
9656 
9657 	return qdf_status_to_os_return(status);
9658 }
9659 
9660 static int hdd_config_scan_enable(struct wlan_hdd_link_info *link_info,
9661 				  const struct nlattr *attr)
9662 {
9663 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9664 	uint8_t enable_flag;
9665 
9666 	enable_flag = nla_get_u8(attr);
9667 	if (enable_flag)
9668 		ucfg_scan_psoc_set_enable(hdd_ctx->psoc, REASON_USER_SPACE);
9669 	else
9670 		ucfg_scan_psoc_set_disable(hdd_ctx->psoc, REASON_USER_SPACE);
9671 
9672 	return 0;
9673 }
9674 
9675 /**
9676  * hdd_config_udp_qos_upgrade_be_bk() - Set UDP QoS threshold for BE/BK AC.
9677  * @link_info: Link info pointer in HDD adapter
9678  * @attr: NL attribute
9679  *
9680  * Returns: 0 on success, -EINVAL on failure
9681  */
9682 static int
9683 hdd_config_udp_qos_upgrade_be_bk(struct wlan_hdd_link_info *link_info,
9684 				 const struct nlattr *attr)
9685 {
9686 	struct hdd_adapter *adapter = link_info->adapter;
9687 	uint8_t priority = nla_get_u8(attr);
9688 
9689 	adapter->udp_qos_upgrade_type = UDP_QOS_UPGRADE_BK_BE;
9690 	return hdd_set_udp_qos_upgrade_config(adapter, priority);
9691 }
9692 
9693 /**
9694  * hdd_config_udp_qos_upgrade_threshold() - NL attribute handler to parse
9695  *					    priority upgrade threshold value.
9696  * @link_info: Link info pointer in adapter
9697  * @attr: NL attribute
9698  *
9699  * Returns: 0 on success, -EINVAL on failure
9700  */
9701 static int
9702 hdd_config_udp_qos_upgrade_threshold(struct wlan_hdd_link_info *link_info,
9703 				     const struct nlattr *attr)
9704 {
9705 	struct hdd_adapter *adapter = link_info->adapter;
9706 	uint8_t priority = nla_get_u8(attr);
9707 
9708 	adapter->udp_qos_upgrade_type = UDP_QOS_UPGRADE_ALL;
9709 	return hdd_set_udp_qos_upgrade_config(adapter, priority);
9710 }
9711 
9712 static enum powersave_mode
9713 hdd_vendor_opm_to_pmo_opm(enum qca_wlan_vendor_opm_mode opm_mode)
9714 {
9715 	switch (opm_mode) {
9716 	case QCA_WLAN_VENDOR_OPM_MODE_DISABLE:
9717 		return PMO_PS_ADVANCED_POWER_SAVE_DISABLE;
9718 	case QCA_WLAN_VENDOR_OPM_MODE_ENABLE:
9719 		return PMO_PS_ADVANCED_POWER_SAVE_ENABLE;
9720 	case QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED:
9721 		return PMO_PS_ADVANCED_POWER_SAVE_USER_DEFINED;
9722 	default:
9723 		hdd_debug("Invalid opm_mode: %d", opm_mode);
9724 		return PMO_PS_ADVANCED_POWER_SAVE_DISABLE;
9725 	}
9726 }
9727 
9728 static int hdd_config_power(struct wlan_hdd_link_info *link_info,
9729 			    struct nlattr *tb[])
9730 {
9731 	struct hdd_adapter *adapter = link_info->adapter;
9732 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9733 	struct wlan_objmgr_vdev *vdev;
9734 	enum qca_wlan_vendor_opm_mode opm_mode;
9735 	struct pmo_ps_params ps_params = {0};
9736 	struct nlattr *power_attr =
9737 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER];
9738 	struct nlattr *opm_attr =
9739 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT];
9740 	struct nlattr *ps_ito_attr =
9741 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_ITO];
9742 	struct nlattr *spec_wake_attr =
9743 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_SPEC_WAKE_INTERVAL];
9744 	int ret;
9745 
9746 	if (!power_attr && !opm_attr)
9747 		return 0;
9748 
9749 	if (power_attr && opm_attr) {
9750 		hdd_err_rl("Invalid OPM set attribute");
9751 		return -EINVAL;
9752 	}
9753 
9754 	if (!ucfg_pmo_get_default_power_save_mode(hdd_ctx->psoc)) {
9755 		hdd_err_rl("OPM power save is disabled in ini");
9756 		return -EINVAL;
9757 	}
9758 
9759 	opm_mode = power_attr ? nla_get_u8(power_attr) : nla_get_u8(opm_attr);
9760 	if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED)
9761 		if (!ps_ito_attr || !spec_wake_attr) {
9762 			hdd_err_rl("Invalid User defined OPM attributes");
9763 			return -EINVAL;
9764 		}
9765 
9766 	ret = hdd_set_power_config(hdd_ctx, adapter, &opm_mode);
9767 	if (ret)
9768 		return ret;
9769 
9770 	ps_params.opm_mode = hdd_vendor_opm_to_pmo_opm(opm_mode);
9771 	if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) {
9772 		ps_params.ps_ito = nla_get_u16(ps_ito_attr);
9773 		ps_params.spec_wake = nla_get_u16(spec_wake_attr);
9774 		ret = hdd_set_power_config_params(hdd_ctx, adapter,
9775 						  ps_params.ps_ito,
9776 						  ps_params.spec_wake);
9777 		if (ret)
9778 			return ret;
9779 	}
9780 
9781 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_POWER_ID);
9782 	if (vdev) {
9783 		ucfg_pmo_set_ps_params(vdev, &ps_params);
9784 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
9785 	}
9786 
9787 	return 0;
9788 }
9789 
9790 static int hdd_config_stats_avg_factor(struct wlan_hdd_link_info *link_info,
9791 				       const struct nlattr *attr)
9792 {
9793 	struct hdd_adapter *adapter = link_info->adapter;
9794 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9795 	uint16_t stats_avg_factor;
9796 	QDF_STATUS status;
9797 
9798 	stats_avg_factor = nla_get_u16(attr);
9799 	status = sme_configure_stats_avg_factor(hdd_ctx->mac_handle,
9800 						link_info->vdev_id,
9801 						stats_avg_factor);
9802 
9803 	return qdf_status_to_os_return(status);
9804 }
9805 
9806 static int hdd_config_non_agg_retry(struct wlan_hdd_link_info *link_info,
9807 				    const struct nlattr *attr)
9808 {
9809 	uint8_t retry;
9810 
9811 	retry = nla_get_u8(attr);
9812 	/* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
9813 	retry = (retry > CFG_NON_AGG_RETRY_MAX) ? CFG_NON_AGG_RETRY_MAX :
9814 		((retry < CFG_NON_AGG_RETRY_MIN) ? CFG_NON_AGG_RETRY_MIN :
9815 		  retry);
9816 	hdd_debug("sending Non-Agg Retry Th: %d", retry);
9817 
9818 	return sme_set_vdev_sw_retry(link_info->vdev_id, retry,
9819 				     WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR);
9820 }
9821 
9822 static int hdd_config_agg_retry(struct wlan_hdd_link_info *link_info,
9823 				const struct nlattr *attr)
9824 {
9825 	uint8_t retry;
9826 
9827 	retry = nla_get_u8(attr);
9828 	/* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
9829 	retry = (retry > CFG_AGG_RETRY_MAX) ? CFG_AGG_RETRY_MAX :
9830 		((retry < CFG_AGG_RETRY_MIN) ? CFG_AGG_RETRY_MIN :
9831 		  retry);
9832 	hdd_debug("sending Agg Retry Th: %d", retry);
9833 
9834 	return sme_set_vdev_sw_retry(link_info->vdev_id, retry,
9835 				     WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR);
9836 }
9837 
9838 static int hdd_config_mgmt_retry(struct wlan_hdd_link_info *link_info,
9839 				 const struct nlattr *attr)
9840 {
9841 	uint8_t retry;
9842 	int param_id;
9843 	uint8_t max_mgmt_retry;
9844 
9845 	retry = nla_get_u8(attr);
9846 	max_mgmt_retry = (cfg_max(CFG_MGMT_RETRY_MAX));
9847 	retry = retry > max_mgmt_retry ?
9848 		max_mgmt_retry : retry;
9849 	param_id = wmi_pdev_param_mgmt_retry_limit;
9850 
9851 	return wma_cli_set_command(link_info->vdev_id, param_id,
9852 				   retry, PDEV_CMD);
9853 }
9854 
9855 static int hdd_config_ctrl_retry(struct wlan_hdd_link_info *link_info,
9856 				 const struct nlattr *attr)
9857 {
9858 	uint8_t retry;
9859 	int param_id;
9860 
9861 	retry = nla_get_u8(attr);
9862 	retry = retry > CFG_CTRL_RETRY_MAX ?
9863 		CFG_CTRL_RETRY_MAX : retry;
9864 	param_id = wmi_pdev_param_ctrl_retry_limit;
9865 
9866 	return wma_cli_set_command(link_info->vdev_id, param_id,
9867 				   retry, PDEV_CMD);
9868 }
9869 
9870 static int hdd_config_propagation_delay(struct wlan_hdd_link_info *link_info,
9871 					const struct nlattr *attr)
9872 {
9873 	uint8_t delay;
9874 	uint32_t abs_delay;
9875 	int param_id;
9876 
9877 	delay = nla_get_u8(attr);
9878 	delay = delay > CFG_PROPAGATION_DELAY_MAX ?
9879 				CFG_PROPAGATION_DELAY_MAX : delay;
9880 	abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
9881 	param_id = wmi_pdev_param_propagation_delay;
9882 
9883 	return  wma_cli_set_command(link_info->vdev_id, param_id,
9884 				    abs_delay, PDEV_CMD);
9885 }
9886 
9887 static int
9888 hdd_config_propagation_abs_delay(struct wlan_hdd_link_info *link_info,
9889 				 const struct nlattr *attr)
9890 {
9891 	uint32_t abs_delay;
9892 	int param_id;
9893 
9894 	abs_delay = nla_get_u32(attr);
9895 	param_id = wmi_pdev_param_propagation_delay;
9896 
9897 	return wma_cli_set_command(link_info->vdev_id, param_id,
9898 				   abs_delay, PDEV_CMD);
9899 }
9900 
9901 static int hdd_config_tx_fail_count(struct wlan_hdd_link_info *link_info,
9902 				    const struct nlattr *attr)
9903 {
9904 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9905 	uint32_t tx_fail_count;
9906 	QDF_STATUS status;
9907 
9908 	tx_fail_count = nla_get_u32(attr);
9909 	if (!tx_fail_count)
9910 		return 0;
9911 
9912 	status = sme_update_tx_fail_cnt_threshold(hdd_ctx->mac_handle,
9913 						  link_info->vdev_id,
9914 						  tx_fail_count);
9915 	if (QDF_IS_STATUS_ERROR(status))
9916 		hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
9917 			status);
9918 
9919 	return qdf_status_to_os_return(status);
9920 }
9921 
9922 static int
9923 hdd_config_channel_avoidance_ind(struct wlan_hdd_link_info *link_info,
9924 				 const struct nlattr *attr)
9925 {
9926 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9927 	uint8_t set_value;
9928 
9929 	set_value = nla_get_u8(attr);
9930 	hdd_debug("set_value: %d", set_value);
9931 
9932 	return hdd_enable_disable_ca_event(hdd_ctx, set_value);
9933 }
9934 
9935 static int hdd_config_guard_time(struct wlan_hdd_link_info *link_info,
9936 				 const struct nlattr *attr)
9937 {
9938 	struct hdd_adapter *adapter = link_info->adapter;
9939 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9940 	uint32_t guard_time;
9941 	QDF_STATUS status;
9942 
9943 	guard_time = nla_get_u32(attr);
9944 	status = sme_configure_guard_time(hdd_ctx->mac_handle,
9945 					  link_info->vdev_id, guard_time);
9946 
9947 	return qdf_status_to_os_return(status);
9948 }
9949 
9950 static int
9951 hdd_config_scan_default_ies(struct wlan_hdd_link_info *link_info,
9952 			    const struct nlattr *attr)
9953 {
9954 	struct hdd_adapter *adapter = link_info->adapter;
9955 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9956 	uint8_t *scan_ie;
9957 	uint16_t scan_ie_len;
9958 	QDF_STATUS status;
9959 	mac_handle_t mac_handle;
9960 
9961 	scan_ie_len = nla_len(attr);
9962 	hdd_debug("IE len %d session %d device mode %d",
9963 		  scan_ie_len, link_info->vdev_id, adapter->device_mode);
9964 
9965 	if (!scan_ie_len) {
9966 		hdd_err("zero-length IE prohibited");
9967 		return -EINVAL;
9968 	}
9969 
9970 	if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
9971 		hdd_err("IE length %d exceeds max of %d",
9972 			scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
9973 		return -EINVAL;
9974 	}
9975 
9976 	scan_ie = nla_data(attr);
9977 	if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
9978 		hdd_err("Invalid default scan IEs");
9979 		return -EINVAL;
9980 	}
9981 
9982 	if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
9983 					   scan_ie, scan_ie_len))
9984 		hdd_err("Failed to save default scan IEs");
9985 
9986 	if (adapter->device_mode == QDF_STA_MODE) {
9987 		mac_handle = hdd_ctx->mac_handle;
9988 		status = sme_set_default_scan_ie(mac_handle,
9989 						 link_info->vdev_id,
9990 						 scan_ie, scan_ie_len);
9991 		if (QDF_STATUS_SUCCESS != status) {
9992 			hdd_err("failed to set default scan IEs in sme: %d",
9993 				status);
9994 			return -EPERM;
9995 		}
9996 	}
9997 
9998 	return 0;
9999 }
10000 
10001 static int hdd_config_ant_div_ena(struct wlan_hdd_link_info *link_info,
10002 				  const struct nlattr *attr)
10003 {
10004 	uint32_t antdiv_enable;
10005 	int errno;
10006 
10007 	antdiv_enable = nla_get_u32(attr);
10008 	hdd_debug("antdiv_enable: %d", antdiv_enable);
10009 	errno = wma_cli_set_command(link_info->vdev_id,
10010 				    wmi_pdev_param_ena_ant_div,
10011 				    antdiv_enable, PDEV_CMD);
10012 	if (errno)
10013 		hdd_err("Failed to set antdiv_enable, %d", errno);
10014 
10015 	return errno;
10016 }
10017 
10018 static int hdd_config_ant_div_snr_diff(struct wlan_hdd_link_info *link_info,
10019 				       const struct nlattr *attr)
10020 {
10021 	uint32_t ant_div_snr_diff;
10022 	uint32_t ant_div_usrcfg;
10023 	int errno;
10024 
10025 	ant_div_snr_diff = nla_get_u32(attr);
10026 	hdd_debug("snr diff: %x", ant_div_snr_diff);
10027 
10028 	ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(ant_div_snr_diff);
10029 	hdd_debug("usrcfg: %x", ant_div_usrcfg);
10030 
10031 	errno = wma_cli_set_command(link_info->vdev_id,
10032 				    wmi_pdev_param_ant_div_usrcfg,
10033 				    ant_div_usrcfg, PDEV_CMD);
10034 	if (errno)
10035 		hdd_err("Failed to set snr diff, %d", errno);
10036 
10037 	return errno;
10038 }
10039 
10040 static int
10041 hdd_config_ant_div_probe_dwell_time(struct wlan_hdd_link_info *link_info,
10042 				    const struct nlattr *attr)
10043 {
10044 	uint32_t dwell_time;
10045 	uint32_t ant_div_usrcfg;
10046 	int errno;
10047 
10048 	dwell_time = nla_get_u32(attr);
10049 	hdd_debug("dwell time: %x", dwell_time);
10050 
10051 	ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(dwell_time);
10052 	hdd_debug("usrcfg: %x", ant_div_usrcfg);
10053 
10054 	errno = wma_cli_set_command(link_info->vdev_id,
10055 				    wmi_pdev_param_ant_div_usrcfg,
10056 				    ant_div_usrcfg, PDEV_CMD);
10057 	if (errno)
10058 		hdd_err("Failed to set probe dwell time, %d", errno);
10059 
10060 	return errno;
10061 }
10062 
10063 static int hdd_config_ant_div_chain(struct wlan_hdd_link_info *link_info,
10064 				    const struct nlattr *attr)
10065 {
10066 	uint32_t antdiv_chain;
10067 	int errno;
10068 
10069 	antdiv_chain = nla_get_u32(attr);
10070 	hdd_debug("antdiv_chain: %d", antdiv_chain);
10071 
10072 	errno = wma_cli_set_command(link_info->vdev_id,
10073 				    wmi_pdev_param_force_chain_ant,
10074 				    antdiv_chain, PDEV_CMD);
10075 	if (errno)
10076 		hdd_err("Failed to set chain, %d", errno);
10077 
10078 	return errno;
10079 }
10080 
10081 static int hdd_config_ant_div_selftest(struct wlan_hdd_link_info *link_info,
10082 				       const struct nlattr *attr)
10083 {
10084 	uint32_t antdiv_selftest;
10085 	int errno;
10086 
10087 	antdiv_selftest = nla_get_u32(attr);
10088 	hdd_debug("antdiv_selftest: %d", antdiv_selftest);
10089 	errno = wma_cli_set_command(link_info->vdev_id,
10090 				    wmi_pdev_param_ant_div_selftest,
10091 				    antdiv_selftest, PDEV_CMD);
10092 	if (errno)
10093 		hdd_err("Failed to set selftest, %d", errno);
10094 
10095 	return errno;
10096 }
10097 
10098 static int
10099 hdd_config_ant_div_selftest_intvl(struct wlan_hdd_link_info *link_info,
10100 				  const struct nlattr *attr)
10101 {
10102 	uint32_t antdiv_selftest_intvl;
10103 	int errno;
10104 
10105 	antdiv_selftest_intvl = nla_get_u32(attr);
10106 	hdd_debug("antdiv_selftest_intvl: %d", antdiv_selftest_intvl);
10107 	errno = wma_cli_set_command(link_info->vdev_id,
10108 				    wmi_pdev_param_ant_div_selftest_intvl,
10109 				    antdiv_selftest_intvl, PDEV_CMD);
10110 	if (errno)
10111 		hdd_err("Failed to set selftest interval, %d", errno);
10112 
10113 	return errno;
10114 }
10115 
10116 static int
10117 hdd_config_ignore_assoc_disallowed(struct wlan_hdd_link_info *link_info,
10118 				   const struct nlattr *attr)
10119 {
10120 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
10121 	uint8_t ignore_assoc_disallowed;
10122 
10123 	ignore_assoc_disallowed = nla_get_u8(attr);
10124 	hdd_debug("%u", ignore_assoc_disallowed);
10125 	if ((ignore_assoc_disallowed < QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
10126 	    (ignore_assoc_disallowed > QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
10127 		return -EINVAL;
10128 
10129 	sme_set_check_assoc_disallowed(hdd_ctx->mac_handle,
10130 				       !ignore_assoc_disallowed);
10131 
10132 	return 0;
10133 }
10134 
10135 static int hdd_config_restrict_offchannel(struct wlan_hdd_link_info *link_info,
10136 					  const struct nlattr *attr)
10137 {
10138 	uint8_t restrict_offchan;
10139 
10140 	restrict_offchan = nla_get_u8(attr);
10141 	hdd_debug("%u", restrict_offchan);
10142 
10143 	if (restrict_offchan > 1) {
10144 		hdd_err("Invalid value %u", restrict_offchan);
10145 		return -EINVAL;
10146 	}
10147 
10148 	return wlan_hdd_handle_restrict_offchan_config(link_info->adapter,
10149 						       restrict_offchan);
10150 }
10151 
10152 static int
10153 hdd_config_total_beacon_miss_count(struct wlan_hdd_link_info *link_info,
10154 				   const struct nlattr *attr)
10155 {
10156 	struct hdd_adapter *adapter = link_info->adapter;
10157 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10158 	uint8_t first_miss_count;
10159 	uint8_t final_miss_count;
10160 	uint8_t total_miss_count;
10161 	QDF_STATUS status;
10162 
10163 	if (adapter->device_mode != QDF_STA_MODE) {
10164 		hdd_err("Only supported in sta mode");
10165 		return -EINVAL;
10166 	}
10167 
10168 	total_miss_count = nla_get_u8(attr);
10169 	ucfg_mlme_get_roam_bmiss_first_bcnt(hdd_ctx->psoc,
10170 					    &first_miss_count);
10171 	if (total_miss_count <= first_miss_count) {
10172 		hdd_err("Total %u needs to exceed first %u",
10173 			total_miss_count, first_miss_count);
10174 		return -EINVAL;
10175 	}
10176 
10177 	final_miss_count = total_miss_count - first_miss_count;
10178 
10179 	if (!ucfg_mlme_validate_roam_bmiss_final_bcnt(final_miss_count))
10180 		return -EINVAL;
10181 
10182 	hdd_debug("First count %u, final count %u",
10183 		  first_miss_count, final_miss_count);
10184 
10185 	status = sme_set_roam_bmiss_final_bcnt(hdd_ctx->mac_handle,
10186 					       link_info->vdev_id,
10187 					       final_miss_count);
10188 	if (QDF_IS_STATUS_ERROR(status)) {
10189 		hdd_err("Failed to set final count, status %u", status);
10190 		return qdf_status_to_os_return(status);
10191 	}
10192 
10193 	status = sme_set_bmiss_bcnt(link_info->vdev_id,
10194 				    first_miss_count,
10195 				    final_miss_count);
10196 	if (QDF_IS_STATUS_ERROR(status))
10197 		hdd_err("Failed to set count, status %u", status);
10198 
10199 	return qdf_status_to_os_return(status);
10200 }
10201 
10202 #ifdef WLAN_FEATURE_LL_MODE
10203 static inline
10204 void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level)
10205 {
10206 	if (latency_level ==
10207 		QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW)
10208 		wlan_hdd_set_pm_qos_request(hdd_ctx, true);
10209 	else
10210 		wlan_hdd_set_pm_qos_request(hdd_ctx, false);
10211 }
10212 #else
10213 static inline
10214 void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level)
10215 {
10216 }
10217 #endif
10218 
10219 /**
10220  * hdd_set_wlm_host_latency_level() - set latency flags based on latency flags
10221  * @hdd_ctx: hdd context
10222  * @adapter: adapter context
10223  * @latency_host_flags: host latency flags
10224  *
10225  * Return: none
10226  */
10227 static void hdd_set_wlm_host_latency_level(struct hdd_context *hdd_ctx,
10228 					   struct hdd_adapter *adapter,
10229 					   uint32_t latency_host_flags)
10230 {
10231 	ol_txrx_soc_handle soc_hdl = cds_get_context(QDF_MODULE_ID_SOC);
10232 	struct wlan_objmgr_vdev *vdev;
10233 
10234 	if (!soc_hdl)
10235 		return;
10236 
10237 	if (latency_host_flags & WLM_HOST_PM_QOS_FLAG) {
10238 		hdd_ctx->pm_qos_request_flags |=
10239 					(1 << adapter->deflink->vdev_id);
10240 	} else {
10241 		hdd_ctx->pm_qos_request_flags &=
10242 					~(1 << adapter->deflink->vdev_id);
10243 	}
10244 
10245 	if (hdd_ctx->pm_qos_request_flags)
10246 		wlan_hdd_set_pm_qos_request(hdd_ctx, true);
10247 	else
10248 		wlan_hdd_set_pm_qos_request(hdd_ctx, false);
10249 
10250 	if (latency_host_flags & WLM_HOST_HBB_FLAG)
10251 		ucfg_dp_set_high_bus_bw_request(hdd_ctx->psoc,
10252 						adapter->deflink->vdev_id,
10253 						true);
10254 	else
10255 		ucfg_dp_set_high_bus_bw_request(hdd_ctx->psoc,
10256 						adapter->deflink->vdev_id,
10257 						false);
10258 
10259 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
10260 	if (!vdev)
10261 		return;
10262 
10263 	if (latency_host_flags & WLM_HOST_RX_THREAD_FLAG)
10264 		ucfg_dp_runtime_disable_rx_thread(vdev, true);
10265 	else
10266 		ucfg_dp_runtime_disable_rx_thread(vdev, false);
10267 
10268 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
10269 }
10270 
10271 #ifdef MULTI_CLIENT_LL_SUPPORT
10272 void
10273 hdd_latency_level_event_handler_cb(const struct latency_level_data *event_data,
10274 				   uint8_t vdev_id)
10275 {
10276 	struct osif_request *request;
10277 	struct latency_level_data *data;
10278 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10279 	struct hdd_adapter *hdd_adapter;
10280 	uint32_t latency_host_flags = 0;
10281 	QDF_STATUS status;
10282 	struct wlan_hdd_link_info *link_info;
10283 
10284 	hdd_enter();
10285 
10286 	if (wlan_hdd_validate_context(hdd_ctx))
10287 		return;
10288 
10289 	if (!event_data) {
10290 		hdd_err("Invalid latency level event data");
10291 		return;
10292 	}
10293 
10294 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
10295 	if (!link_info) {
10296 		hdd_err("adapter is NULL vdev_id = %d", vdev_id);
10297 		return;
10298 	}
10299 
10300 	hdd_adapter = link_info->adapter;
10301 	if (hdd_adapter->multi_ll_resp_expected) {
10302 		request =
10303 			osif_request_get(hdd_adapter->multi_ll_response_cookie);
10304 		if (!request) {
10305 			hdd_err("Invalid request");
10306 			return;
10307 		}
10308 		data = osif_request_priv(request);
10309 		data->latency_level = event_data->latency_level;
10310 		data->vdev_id = event_data->vdev_id;
10311 		osif_request_complete(request);
10312 		osif_request_put(request);
10313 	} else {
10314 		hdd_adapter->latency_level = event_data->latency_level;
10315 		wlan_hdd_set_wlm_mode(hdd_ctx, hdd_adapter->latency_level);
10316 		hdd_debug("adapter->latency_level:%d",
10317 			  hdd_adapter->latency_level);
10318 		status = ucfg_mlme_get_latency_host_flags(hdd_ctx->psoc,
10319 						hdd_adapter->latency_level,
10320 						&latency_host_flags);
10321 		if (QDF_IS_STATUS_ERROR(status))
10322 			hdd_err("failed to get latency host flags");
10323 		else
10324 			hdd_set_wlm_host_latency_level(hdd_ctx, hdd_adapter,
10325 						       latency_host_flags);
10326 		}
10327 
10328 	hdd_exit();
10329 }
10330 
10331 uint8_t wlan_hdd_get_client_id_bitmap(struct hdd_adapter *adapter)
10332 {
10333 	uint8_t i, client_id_bitmap = 0;
10334 
10335 	for (i = 0; i < WLM_MAX_HOST_CLIENT; i++) {
10336 		if (!adapter->client_info[i].in_use)
10337 			continue;
10338 		client_id_bitmap |=
10339 			BIT(adapter->client_info[i].client_id);
10340 	}
10341 
10342 	return client_id_bitmap;
10343 }
10344 
10345 QDF_STATUS wlan_hdd_get_set_client_info_id(struct hdd_adapter *adapter,
10346 					   uint32_t port_id,
10347 					   uint32_t *client_id)
10348 {
10349 	uint8_t i;
10350 	QDF_STATUS status = QDF_STATUS_E_INVAL;
10351 
10352 	for (i = 0; i < WLM_MAX_HOST_CLIENT; i++) {
10353 		if (adapter->client_info[i].in_use) {
10354 			/* Receives set latency cmd for an existing port id */
10355 			if (port_id == adapter->client_info[i].port_id) {
10356 				*client_id = adapter->client_info[i].client_id;
10357 				status = QDF_STATUS_SUCCESS;
10358 				break;
10359 			}
10360 			continue;
10361 		} else {
10362 			/* Process set latency level from a new client */
10363 			adapter->client_info[i].in_use = true;
10364 			adapter->client_info[i].port_id = port_id;
10365 			*client_id = adapter->client_info[i].client_id;
10366 			status = QDF_STATUS_SUCCESS;
10367 			break;
10368 		}
10369 	}
10370 
10371 	if (i == WLM_MAX_HOST_CLIENT)
10372 		hdd_debug("Max client ID reached");
10373 
10374 	return status;
10375 }
10376 
10377 QDF_STATUS wlan_hdd_set_wlm_latency_level(struct hdd_adapter *adapter,
10378 					  uint16_t latency_level,
10379 					  uint32_t client_id_bitmap,
10380 					  bool force_reset)
10381 {
10382 	QDF_STATUS status;
10383 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10384 	int ret;
10385 	struct osif_request *request = NULL;
10386 	struct latency_level_data *priv;
10387 	static const struct osif_request_params params = {
10388 		.priv_size = sizeof(*priv),
10389 		.timeout_ms = WLAN_WAIT_WLM_LATENCY_LEVEL,
10390 		.dealloc = NULL,
10391 	};
10392 
10393 	/* ignore unless in STA mode */
10394 	if (adapter->device_mode != QDF_STA_MODE) {
10395 		hdd_debug_rl("WLM offload is supported in STA mode only");
10396 		return QDF_STATUS_E_FAILURE;
10397 	}
10398 
10399 	adapter->multi_ll_resp_expected = true;
10400 
10401 	request = osif_request_alloc(&params);
10402 	if (!request) {
10403 		hdd_err("Request allocation failure");
10404 		return QDF_STATUS_E_FAILURE;
10405 	}
10406 	adapter->multi_ll_response_cookie = osif_request_cookie(request);
10407 	adapter->multi_ll_req_in_progress = true;
10408 
10409 	status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
10410 					   adapter->deflink->vdev_id,
10411 					   latency_level, client_id_bitmap,
10412 					   force_reset);
10413 	if (QDF_IS_STATUS_ERROR(status)) {
10414 		hdd_err("Failure while sending command to fw");
10415 		goto err;
10416 	}
10417 
10418 	ret = osif_request_wait_for_response(request);
10419 	if (ret) {
10420 		hdd_err("SME timed out while retrieving latency level");
10421 		status = qdf_status_from_os_return(ret);
10422 		goto err;
10423 	}
10424 	priv = osif_request_priv(request);
10425 	if (!priv) {
10426 		hdd_err("invalid get latency level");
10427 		status = QDF_STATUS_E_FAILURE;
10428 		goto err;
10429 	}
10430 
10431 	hdd_debug("latency level received from FW:%d", priv->latency_level);
10432 	adapter->latency_level = priv->latency_level;
10433 err:
10434 	if (request)
10435 		osif_request_put(request);
10436 	adapter->multi_ll_req_in_progress = false;
10437 	adapter->multi_ll_resp_expected = false;
10438 	adapter->multi_ll_response_cookie = NULL;
10439 
10440 	return status;
10441 }
10442 
10443 bool hdd_get_multi_client_ll_support(struct hdd_adapter *adapter)
10444 {
10445 	return adapter->multi_client_ll_support;
10446 }
10447 
10448 /**
10449  * wlan_hdd_reset_client_info() - reset multi client info table
10450  * @adapter: adapter context
10451  * @client_id: client id
10452  *
10453  * Return: none
10454  */
10455 static void wlan_hdd_reset_client_info(struct hdd_adapter *adapter,
10456 				       uint32_t client_id)
10457 {
10458 	adapter->client_info[client_id].in_use = false;
10459 	adapter->client_info[client_id].port_id = 0;
10460 	adapter->client_info[client_id].client_id = client_id;
10461 }
10462 
10463 QDF_STATUS wlan_hdd_set_wlm_client_latency_level(struct hdd_adapter *adapter,
10464 						 uint32_t port_id,
10465 						 uint16_t latency_level)
10466 {
10467 	uint32_t client_id, client_id_bitmap;
10468 	QDF_STATUS status;
10469 
10470 	status = wlan_hdd_get_set_client_info_id(adapter, port_id,
10471 						 &client_id);
10472 	if (QDF_IS_STATUS_ERROR(status))
10473 		return status;
10474 
10475 	client_id_bitmap = BIT(client_id);
10476 	status = wlan_hdd_set_wlm_latency_level(adapter,
10477 						latency_level,
10478 						client_id_bitmap,
10479 						false);
10480 	if (QDF_IS_STATUS_ERROR(status)) {
10481 		hdd_debug("Fail to set latency level for client_id:%d",
10482 			  client_id);
10483 		wlan_hdd_reset_client_info(adapter, client_id);
10484 		return status;
10485 	}
10486 	return status;
10487 }
10488 
10489 /**
10490  * wlan_hdd_get_multi_ll_req_in_progress() - get multi_ll_req_in_progress flag
10491  * @adapter: adapter context
10492  *
10493  * Return: true if multi ll req in progress
10494  */
10495 static bool wlan_hdd_get_multi_ll_req_in_progress(struct hdd_adapter *adapter)
10496 {
10497 	return adapter->multi_ll_req_in_progress;
10498 }
10499 #else
10500 static inline bool
10501 wlan_hdd_get_multi_ll_req_in_progress(struct hdd_adapter *adapter)
10502 {
10503 	return false;
10504 }
10505 #endif
10506 
10507 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
10508 static QDF_STATUS hdd_get_netlink_sender_portid(struct hdd_context *hdd_ctx,
10509 						uint32_t *port_id)
10510 {
10511 	struct wiphy *wiphy = hdd_ctx->wiphy;
10512 
10513 	/* get netlink portid of sender */
10514 	*port_id =  cfg80211_vendor_cmd_get_sender(wiphy);
10515 
10516 	return QDF_STATUS_SUCCESS;
10517 }
10518 #else
10519 static inline QDF_STATUS
10520 hdd_get_netlink_sender_portid(struct hdd_context *hdd_ctx, uint32_t *port_id)
10521 {
10522 	return QDF_STATUS_E_NOSUPPORT;
10523 }
10524 #endif
10525 
10526 static int hdd_config_latency_level(struct wlan_hdd_link_info *link_info,
10527 				    const struct nlattr *attr)
10528 {
10529 	struct hdd_adapter *adapter = link_info->adapter;
10530 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10531 	uint32_t port_id;
10532 	uint16_t latency_level, host_latency_level;
10533 	QDF_STATUS status;
10534 	uint32_t latency_host_flags = 0;
10535 	int ret;
10536 
10537 	if (hdd_validate_adapter(adapter))
10538 		return -EINVAL;
10539 
10540 	if (!hdd_is_wlm_latency_manager_supported(hdd_ctx))
10541 		return -ENOTSUPP;
10542 
10543 	latency_level = nla_get_u16(attr);
10544 	switch (latency_level) {
10545 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
10546 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR:
10547 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
10548 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
10549 		/* valid values */
10550 		break;
10551 	default:
10552 		hdd_err("Invalid value %u", latency_level);
10553 		return -EINVAL;
10554 	}
10555 
10556 	host_latency_level = latency_level - 1;
10557 
10558 	if (hdd_get_multi_client_ll_support(adapter)) {
10559 		if (wlan_hdd_get_multi_ll_req_in_progress(adapter)) {
10560 			hdd_err_rl("multi ll request already in progress");
10561 			return -EBUSY;
10562 		}
10563 		/* get netlink portid of sender */
10564 		status = hdd_get_netlink_sender_portid(hdd_ctx, &port_id);
10565 		if (QDF_IS_STATUS_ERROR(status))
10566 			goto error;
10567 		status = wlan_hdd_set_wlm_client_latency_level(adapter, port_id,
10568 							host_latency_level);
10569 		if (QDF_IS_STATUS_ERROR(status)) {
10570 			hdd_debug("Fail to set latency level");
10571 			goto error;
10572 		}
10573 	} else {
10574 		status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
10575 						   link_info->vdev_id,
10576 						   host_latency_level, 0,
10577 						   false);
10578 		if (QDF_IS_STATUS_ERROR(status)) {
10579 			hdd_err("set latency level failed, %u", status);
10580 			goto error;
10581 		}
10582 		adapter->latency_level = host_latency_level;
10583 	}
10584 
10585 	wlan_hdd_set_wlm_mode(hdd_ctx, adapter->latency_level);
10586 	hdd_debug("adapter->latency_level:%d", adapter->latency_level);
10587 
10588 	status = ucfg_mlme_get_latency_host_flags(hdd_ctx->psoc,
10589 						  adapter->latency_level,
10590 						  &latency_host_flags);
10591 	if (QDF_IS_STATUS_ERROR(status))
10592 		hdd_err("failed to get latency host flags");
10593 	else
10594 		hdd_set_wlm_host_latency_level(hdd_ctx, adapter,
10595 					       latency_host_flags);
10596 error:
10597 	ret = qdf_status_to_os_return(status);
10598 
10599 	return ret;
10600 }
10601 
10602 static int hdd_config_disable_fils(struct wlan_hdd_link_info *link_info,
10603 				   const struct nlattr *attr)
10604 {
10605 	struct hdd_adapter *adapter = link_info->adapter;
10606 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10607 	uint8_t disable_fils;
10608 	bool enabled;
10609 	QDF_STATUS status;
10610 
10611 	/* ignore unless in STA mode */
10612 	if (adapter->device_mode != QDF_STA_MODE)
10613 		return 0;
10614 
10615 	disable_fils = nla_get_u8(attr);
10616 	hdd_debug("%u", disable_fils);
10617 
10618 	enabled = !disable_fils;
10619 	status = ucfg_mlme_set_fils_enabled_info(hdd_ctx->psoc, enabled);
10620 	if (QDF_IS_STATUS_ERROR(status))
10621 		hdd_err("could not set fils enabled info, %d", status);
10622 
10623 	status = ucfg_mlme_set_enable_bcast_probe_rsp(hdd_ctx->psoc, enabled);
10624 	if (QDF_IS_STATUS_ERROR(status))
10625 		hdd_err("could not set enable bcast probe resp info, %d",
10626 			status);
10627 
10628 	status = wma_cli_set_command(link_info->vdev_id,
10629 				     wmi_vdev_param_enable_bcast_probe_response,
10630 				     !disable_fils, VDEV_CMD);
10631 	if (QDF_IS_STATUS_ERROR(status))
10632 		hdd_err("failed to set enable bcast probe resp, %d",
10633 			status);
10634 
10635 	return qdf_status_to_os_return(status);
10636 }
10637 
10638 static int hdd_set_primary_interface(struct wlan_hdd_link_info *link_info,
10639 				     const struct nlattr *attr)
10640 {
10641 	struct hdd_adapter *adapter = link_info->adapter;
10642 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10643 	bool is_set_primary_iface;
10644 	QDF_STATUS status;
10645 	uint8_t vdev_id,  primary_vdev_id, dual_sta_policy;
10646 	int set_value;
10647 	uint32_t count;
10648 	bool enable_mcc_adaptive_sch = false;
10649 
10650 	/* ignore unless in STA mode */
10651 	if (adapter->device_mode != QDF_STA_MODE)
10652 		return 0;
10653 
10654 	is_set_primary_iface = nla_get_u8(attr);
10655 
10656 	vdev_id = link_info->vdev_id;
10657 	primary_vdev_id =
10658 		is_set_primary_iface ? vdev_id : WLAN_UMAC_VDEV_ID_MAX;
10659 
10660 	status = ucfg_mlme_set_primary_interface(hdd_ctx->psoc,
10661 						 primary_vdev_id);
10662 	if (QDF_IS_STATUS_ERROR(status)) {
10663 		hdd_err("could not set primary interface, %d", status);
10664 		return -EINVAL;
10665 	}
10666 
10667 	/* After SSR, the dual sta configuration is lost. As SSR is hidden from
10668 	 * userland, this command will not come from userspace after a SSR. To
10669 	 * restore this configuration, save this in hdd context and restore
10670 	 * after re-init.
10671 	 */
10672 	hdd_ctx->dual_sta_policy.primary_vdev_id = primary_vdev_id;
10673 
10674 	count = policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
10675 							  PM_STA_MODE, NULL);
10676 
10677 	if (count < 2) {
10678 		hdd_debug("STA + STA concurrency not present, count:%d", count);
10679 		return 0;
10680 	}
10681 
10682 	/* If dual sta roaming enabled and sta concurrency on different mac then
10683 	 * no need to enable roaming on primary as both STA's have roaming
10684 	 * enabled.
10685 	 * If dual sta roaming enabled and both sta in MCC or SCC then need
10686 	 * to enable roaming on primary vdev.
10687 	 * If dual sta roaming NOT enabled then need to enable roaming on
10688 	 * primary vdev for sta concurrency on different mac.
10689 	 */
10690 	if (wlan_mlme_is_primary_interface_configured(hdd_ctx->psoc))
10691 		if ((ucfg_mlme_get_dual_sta_roaming_enabled(hdd_ctx->psoc) &&
10692 		     !policy_mgr_concurrent_sta_on_different_mac(hdd_ctx->psoc)) ||
10693 		    !ucfg_mlme_get_dual_sta_roaming_enabled(hdd_ctx->psoc)) {
10694 			hdd_err("Enable roaming on requested interface: %d",
10695 				link_info->vdev_id);
10696 			hdd_debug("Enable roaming on requested interface: %d",
10697 				  link_info->vdev_id);
10698 			wlan_cm_roam_state_change(hdd_ctx->pdev,
10699 						  link_info->vdev_id,
10700 						  WLAN_ROAM_RSO_ENABLED,
10701 						  REASON_ROAM_SET_PRIMARY);
10702 	}
10703 
10704 	/*
10705 	 * send duty cycle percentage to FW only if STA + STA
10706 	 * concurrency is in MCC.
10707 	 */
10708 	if (!policy_mgr_current_concurrency_is_mcc(hdd_ctx->psoc)) {
10709 		hdd_debug("STA + STA concurrency not in MCC");
10710 		return 0;
10711 	}
10712 
10713 	status = ucfg_mlme_get_dual_sta_policy(hdd_ctx->psoc, &dual_sta_policy);
10714 	if (QDF_IS_STATUS_ERROR(status)) {
10715 		hdd_err("could not get dual sta policy, %d", status);
10716 		return -EINVAL;
10717 	}
10718 
10719 	hdd_debug("is_set_primary_iface: %d, primary vdev id: %d, dual_sta_policy:%d",
10720 		  is_set_primary_iface, primary_vdev_id, dual_sta_policy);
10721 
10722 	if (is_set_primary_iface && dual_sta_policy ==
10723 	    QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY) {
10724 		hdd_debug("Disable mcc_adaptive_scheduler");
10725 		ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc,
10726 						     &enable_mcc_adaptive_sch);
10727 		if (enable_mcc_adaptive_sch) {
10728 			ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch(
10729 							hdd_ctx->psoc, false);
10730 			if (QDF_IS_STATUS_ERROR(sme_set_mas(false))) {
10731 				hdd_err("Fail to disable mcc adaptive sched.");
10732 					return -EINVAL;
10733 			}
10734 		}
10735 		/* Configure mcc duty cycle percentage */
10736 		set_value =
10737 		   ucfg_mlme_get_mcc_duty_cycle_percentage(hdd_ctx->pdev);
10738 		if (set_value < 0) {
10739 			hdd_err("Invalid mcc duty cycle");
10740 			return -EINVAL;
10741 		}
10742 		wlan_hdd_send_mcc_vdev_quota(adapter, set_value);
10743 	} else {
10744 		hdd_debug("Enable mcc_adaptive_scheduler");
10745 		ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc,
10746 						     &enable_mcc_adaptive_sch);
10747 		if (enable_mcc_adaptive_sch) {
10748 			ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch(
10749 							hdd_ctx->psoc, true);
10750 			if (QDF_STATUS_SUCCESS != sme_set_mas(true)) {
10751 				hdd_err("Fail to enable mcc_adaptive_sched.");
10752 				return -EAGAIN;
10753 			}
10754 		}
10755 	}
10756 
10757 	return 0;
10758 }
10759 
10760 static int hdd_config_rsn_ie(struct wlan_hdd_link_info *link_info,
10761 			     const struct nlattr *attr)
10762 {
10763 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
10764 	uint8_t force_rsne_override;
10765 
10766 	force_rsne_override = nla_get_u8(attr);
10767 	if (force_rsne_override > 1) {
10768 		hdd_err("Invalid value %d", force_rsne_override);
10769 		return -EINVAL;
10770 	}
10771 
10772 	hdd_ctx->force_rsne_override = force_rsne_override;
10773 	hdd_debug("force_rsne_override - %d", force_rsne_override);
10774 
10775 	return 0;
10776 }
10777 
10778 static int hdd_config_gtx(struct wlan_hdd_link_info *link_info,
10779 			  const struct nlattr *attr)
10780 {
10781 	uint8_t config_gtx;
10782 	int errno;
10783 
10784 	config_gtx = nla_get_u8(attr);
10785 	if (config_gtx > 1) {
10786 		hdd_err_rl("Invalid config_gtx value %d", config_gtx);
10787 		return -EINVAL;
10788 	}
10789 
10790 	errno = sme_cli_set_command(link_info->vdev_id,
10791 				    wmi_vdev_param_gtx_enable,
10792 				    config_gtx, VDEV_CMD);
10793 	if (errno)
10794 		hdd_err("Failed to set GTX, %d", errno);
10795 
10796 	return errno;
10797 }
10798 
10799 /**
10800  * hdd_config_disconnect_ies() - Configure disconnect IEs
10801  * @link_info: Link info pointer in HDD adapter
10802  * @attr: array of pointer to struct nlattr
10803  *
10804  * Return: 0 on success; error number otherwise
10805  */
10806 static int hdd_config_disconnect_ies(struct wlan_hdd_link_info *link_info,
10807 				     const struct nlattr *attr)
10808 {
10809 	struct hdd_adapter *adapter = link_info->adapter;
10810 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10811 	QDF_STATUS status;
10812 
10813 	hdd_debug("IE len %u session %u device mode %u",
10814 		  nla_len(attr), link_info->vdev_id,
10815 		  adapter->device_mode);
10816 	if (!nla_len(attr) ||
10817 	    nla_len(attr) > SIR_MAC_MAX_ADD_IE_LENGTH + 2 ||
10818 	    !wlan_is_ie_valid(nla_data(attr), nla_len(attr))) {
10819 		hdd_err("Invalid disconnect IEs");
10820 		return -EINVAL;
10821 	}
10822 
10823 	status = sme_set_disconnect_ies(hdd_ctx->mac_handle,
10824 					link_info->vdev_id,
10825 					nla_data(attr),
10826 					nla_len(attr));
10827 	if (QDF_IS_STATUS_ERROR(status))
10828 		hdd_err("Failed to set disconnect_ies");
10829 
10830 	return qdf_status_to_os_return(status);
10831 }
10832 
10833 #ifdef WLAN_FEATURE_ELNA
10834 /**
10835  * hdd_set_elna_bypass() - Set eLNA bypass
10836  * @link_info: Link info pointer in HDD adapter
10837  * @attr: Pointer to struct nlattr
10838  *
10839  * Return: 0 on success; error number otherwise
10840  */
10841 static int hdd_set_elna_bypass(struct wlan_hdd_link_info *link_info,
10842 			       const struct nlattr *attr)
10843 {
10844 	int ret;
10845 	struct wlan_objmgr_vdev *vdev;
10846 
10847 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_FWOL_NB_ID);
10848 	if (!vdev)
10849 		return -EINVAL;
10850 
10851 	ret = os_if_fwol_set_elna_bypass(vdev, attr);
10852 
10853 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_FWOL_NB_ID);
10854 
10855 	return ret;
10856 }
10857 #endif
10858 
10859 /**
10860  * hdd_mac_chwidth_to_bonding_mode() - get bonding_mode from chan width
10861  * @chwidth: chan width
10862  *
10863  * Return: bonding mode
10864  */
10865 static uint32_t hdd_mac_chwidth_to_bonding_mode(
10866 			enum eSirMacHTChannelWidth chwidth)
10867 {
10868 	uint32_t bonding_mode;
10869 
10870 	switch (chwidth) {
10871 	case eHT_CHANNEL_WIDTH_20MHZ:
10872 		bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
10873 		break;
10874 	default:
10875 		bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
10876 	}
10877 
10878 	return bonding_mode;
10879 }
10880 
10881 int hdd_set_mac_chan_width(struct hdd_adapter *adapter,
10882 			   enum eSirMacHTChannelWidth chwidth,
10883 			   uint8_t link_id)
10884 {
10885 	uint32_t bonding_mode;
10886 
10887 	bonding_mode = hdd_mac_chwidth_to_bonding_mode(chwidth);
10888 
10889 	return hdd_update_channel_width(adapter, chwidth,
10890 					bonding_mode, link_id);
10891 }
10892 
10893 /**
10894  * hdd_set_channel_width() - set channel width
10895  * @link_info: Link info pointer in HDD adapter.
10896  * @tb: array of pointer to struct nlattr
10897  *
10898  * Return: 0 on success, negative errno on failure
10899  */
10900 static int hdd_set_channel_width(struct wlan_hdd_link_info *link_info,
10901 				 struct nlattr *tb[])
10902 {
10903 	int rem;
10904 	uint8_t nl80211_chwidth = 0xFF;
10905 	uint8_t link_id = 0xFF;
10906 	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
10907 	struct nlattr *curr_attr;
10908 	struct nlattr *chn_bd = NULL;
10909 	struct nlattr *mlo_link_id;
10910 
10911 	if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS])
10912 		goto skip_mlo;
10913 
10914 	nla_for_each_nested(curr_attr,
10915 			    tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS], rem) {
10916 		if (wlan_cfg80211_nla_parse_nested(tb2,
10917 						QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
10918 						   curr_attr,
10919 						   bandwidth_mlo_policy)){
10920 			hdd_err_rl("nla_parse failed");
10921 			return -EINVAL;
10922 		}
10923 
10924 		chn_bd = tb2[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH];
10925 		mlo_link_id = tb2[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID];
10926 
10927 		if (!chn_bd || !mlo_link_id)
10928 			return 0;
10929 
10930 		nl80211_chwidth = nla_get_u8(chn_bd);
10931 		if (nl80211_chwidth < eHT_CHANNEL_WIDTH_20MHZ ||
10932 		    nl80211_chwidth > eHT_MAX_CHANNEL_WIDTH) {
10933 			hdd_err("Invalid channel width:%u", nl80211_chwidth);
10934 			return -EINVAL;
10935 		}
10936 
10937 		link_id = nla_get_u8(mlo_link_id);
10938 		if (link_id > WLAN_MAX_LINK_ID) {
10939 			hdd_debug("invalid link_id:%u", link_id);
10940 			return -EINVAL;
10941 		}
10942 	}
10943 
10944 	if (link_id != 0xFF)
10945 		goto set_chan_width;
10946 
10947 skip_mlo:
10948 	chn_bd = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH];
10949 
10950 	if (!chn_bd)
10951 		return 0;
10952 
10953 	nl80211_chwidth = nla_get_u8(chn_bd);
10954 
10955 	if (nl80211_chwidth < eHT_CHANNEL_WIDTH_20MHZ ||
10956 	    nl80211_chwidth > eHT_MAX_CHANNEL_WIDTH) {
10957 		hdd_err("Invalid channel width");
10958 		return -EINVAL;
10959 	}
10960 
10961 set_chan_width:
10962 	return hdd_set_mac_chan_width(link_info->adapter,
10963 				      nl80211_chwidth, link_id);
10964 }
10965 
10966 /**
10967  * hdd_set_dynamic_bw() - enable / disable dynamic bandwidth
10968  * @link_info: Link info in adapter
10969  * @attr: nla attr sent by supplicant
10970  *
10971  * Return: 0 on success, negative errno on failure
10972  */
10973 static int hdd_set_dynamic_bw(struct wlan_hdd_link_info *link_info,
10974 			      const struct nlattr *attr)
10975 {
10976 	uint8_t enable;
10977 
10978 	enable = nla_get_u8(attr);
10979 	return wma_cli_set_command(link_info->vdev_id,
10980 				   wmi_pdev_param_dynamic_bw,
10981 				   enable, PDEV_CMD);
10982 }
10983 
10984 /**
10985  * hdd_set_nss() - set the number of spatial streams supported by the adapter
10986  * @link_info: Link info pointer in HDD adapter
10987  * @attr: pointer to nla attr
10988  *
10989  * Return: 0 on success, negative errno on failure
10990  */
10991 static int hdd_set_nss(struct wlan_hdd_link_info *link_info,
10992 		       const struct nlattr *attr)
10993 {
10994 	uint8_t nss;
10995 	int ret;
10996 	QDF_STATUS status;
10997 
10998 	nss = nla_get_u8(attr);
10999 	status = hdd_update_nss(link_info, nss, nss);
11000 	ret = qdf_status_to_os_return(status);
11001 
11002 	if (ret == 0 && link_info->adapter->device_mode == QDF_SAP_MODE)
11003 		ret = wma_cli_set_command(link_info->vdev_id,
11004 					  wmi_vdev_param_nss, nss, VDEV_CMD);
11005 
11006 	return ret;
11007 }
11008 
11009 #ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD
11010 #define DYNAMIC_ARP_NS_ENABLE    1
11011 #define DYNAMIC_ARP_NS_DISABLE   0
11012 
11013 /**
11014  * hdd_set_arp_ns_offload() - enable/disable arp/ns offload feature
11015  * @link_info: Link info pointer in HDD adapter
11016  * @attr: pointer to nla attr
11017  *
11018  * Return: 0 on success, negative errno on failure
11019  */
11020 static int hdd_set_arp_ns_offload(struct wlan_hdd_link_info *link_info,
11021 				  const struct nlattr *attr)
11022 {
11023 	uint8_t offload_state;
11024 	int errno;
11025 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
11026 	struct hdd_adapter *adapter = link_info->adapter;
11027 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11028 	struct wlan_objmgr_vdev *vdev;
11029 
11030 	errno = wlan_hdd_validate_context(hdd_ctx);
11031 	if (errno)
11032 		return errno;
11033 
11034 	if (!ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc) ||
11035 	    !ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
11036 		hdd_err_rl("ARP/NS Offload is disabled by ini");
11037 		return -EINVAL;
11038 	}
11039 
11040 	if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
11041 		hdd_err_rl("active mode offload is disabled by ini");
11042 		return -EINVAL;
11043 	}
11044 
11045 	if (adapter->device_mode != QDF_STA_MODE &&
11046 	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
11047 		hdd_err_rl("only support on sta/p2p-cli mode");
11048 		return -EINVAL;
11049 	}
11050 
11051 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
11052 	if (!vdev) {
11053 		hdd_err("vdev is NULL");
11054 		return -EINVAL;
11055 	}
11056 
11057 	offload_state = nla_get_u8(attr);
11058 
11059 	if (offload_state == DYNAMIC_ARP_NS_ENABLE)
11060 		qdf_status = ucfg_pmo_dynamic_arp_ns_offload_enable(vdev);
11061 	else if (offload_state == DYNAMIC_ARP_NS_DISABLE)
11062 		qdf_status = ucfg_pmo_dynamic_arp_ns_offload_disable(vdev);
11063 
11064 	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
11065 		if (offload_state == DYNAMIC_ARP_NS_ENABLE)
11066 			ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(vdev);
11067 		else
11068 			ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(vdev);
11069 	}
11070 
11071 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
11072 		if (qdf_status == QDF_STATUS_E_ALREADY) {
11073 			hdd_info_rl("already set arp/ns offload %d",
11074 				    offload_state);
11075 			errno = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
11076 		} else {
11077 			errno = qdf_status_to_os_return(qdf_status);
11078 		}
11079 
11080 		goto vdev_ref;
11081 	}
11082 
11083 	if (!hdd_is_vdev_in_conn_state(link_info)) {
11084 		hdd_info("set not in connect state, updated state %d",
11085 			 offload_state);
11086 		errno = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
11087 		goto vdev_ref;
11088 	}
11089 
11090 	if (offload_state == DYNAMIC_ARP_NS_ENABLE) {
11091 		hdd_enable_arp_offload(adapter, vdev,
11092 				       pmo_arp_ns_offload_dynamic_update);
11093 		hdd_enable_ns_offload(adapter, vdev,
11094 				      pmo_arp_ns_offload_dynamic_update);
11095 	} else if (offload_state == DYNAMIC_ARP_NS_DISABLE) {
11096 		hdd_disable_arp_offload(adapter, vdev,
11097 					pmo_arp_ns_offload_dynamic_update);
11098 		hdd_disable_ns_offload(adapter, vdev,
11099 				       pmo_arp_ns_offload_dynamic_update);
11100 	}
11101 
11102 vdev_ref:
11103 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11104 	return errno;
11105 }
11106 
11107 #undef DYNAMIC_ARP_NS_ENABLE
11108 #undef DYNAMIC_ARP_NS_DISABLE
11109 #endif
11110 
11111 #ifdef WLAN_FEATURE_DBAM_CONFIG
11112 
11113 static int
11114 hdd_convert_qca_dbam_config_mode(enum qca_dbam_config qca_dbam,
11115 				 enum coex_dbam_config_mode *coex_dbam)
11116 {
11117 	switch (qca_dbam) {
11118 	case QCA_DBAM_DISABLE:
11119 		*coex_dbam = COEX_DBAM_DISABLE;
11120 		break;
11121 	case QCA_DBAM_ENABLE:
11122 		*coex_dbam = COEX_DBAM_ENABLE;
11123 		break;
11124 	case QCA_DBAM_FORCE_ENABLE:
11125 		*coex_dbam = COEX_DBAM_FORCE_ENABLE;
11126 		break;
11127 	default:
11128 		hdd_err("Invalid dbam config mode %d", qca_dbam);
11129 		return -EINVAL;
11130 	}
11131 
11132 	return 0;
11133 }
11134 
11135 static int
11136 hdd_convert_dbam_comp_status(enum coex_dbam_comp_status dbam_resp)
11137 {
11138 	switch (dbam_resp) {
11139 	case COEX_DBAM_COMP_SUCCESS:
11140 		return 0;
11141 	case COEX_DBAM_COMP_NOT_SUPPORT:
11142 		return -ENOTSUPP;
11143 	case COEX_DBAM_COMP_FAIL:
11144 		return -EINVAL;
11145 	default:
11146 		hdd_err("Invalid dbam config resp received from FW");
11147 		break;
11148 	}
11149 
11150 	return -EINVAL;
11151 }
11152 
11153 /**
11154  * hdd_dbam_config_resp_cb() - DBAM config response callback
11155  * @context: request manager context
11156  * @resp: pointer to dbam config fw response
11157  *
11158  * Return: 0 on success, negative errno on failure
11159  */
11160 static void
11161 hdd_dbam_config_resp_cb(void *context,
11162 			enum coex_dbam_comp_status *resp)
11163 {
11164 	struct osif_request *request;
11165 	struct coex_dbam_config_resp *priv;
11166 
11167 	request = osif_request_get(context);
11168 	if (!request) {
11169 		osif_err("Obsolete request");
11170 		return;
11171 	}
11172 
11173 	priv = osif_request_priv(request);
11174 	priv->dbam_resp = *resp;
11175 
11176 	osif_request_complete(request);
11177 	osif_request_put(request);
11178 }
11179 
11180 int hdd_send_dbam_config(struct hdd_adapter *adapter,
11181 			 enum coex_dbam_config_mode dbam_mode)
11182 {
11183 	int errno;
11184 	QDF_STATUS status;
11185 	struct wlan_objmgr_vdev *vdev;
11186 	enum coex_dbam_comp_status dbam_resp;
11187 	struct coex_dbam_config_params dbam_params = {0};
11188 	void *cookie;
11189 	struct osif_request *request;
11190 	struct coex_dbam_config_resp *priv;
11191 	static const struct osif_request_params params = {
11192 		.priv_size = sizeof(*priv),
11193 		.timeout_ms = WLAN_SET_DBAM_CONFIG_TIMEOUT,
11194 	};
11195 
11196 	errno = hdd_validate_adapter(adapter);
11197 	if (errno)
11198 		return errno;
11199 
11200 	request = osif_request_alloc(&params);
11201 	if (!request) {
11202 		osif_err("Request allocation failure");
11203 		return -ENOMEM;
11204 	}
11205 	cookie = osif_request_cookie(request);
11206 
11207 	dbam_params.vdev_id = adapter->deflink->vdev_id;
11208 	dbam_params.dbam_mode = dbam_mode;
11209 
11210 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
11211 	if (!vdev) {
11212 		hdd_err("vdev is NULL");
11213 		errno = -EINVAL;
11214 		goto err;
11215 	}
11216 
11217 	status = ucfg_coex_send_dbam_config(vdev, &dbam_params,
11218 					    hdd_dbam_config_resp_cb, cookie);
11219 
11220 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11221 
11222 	if (!QDF_IS_STATUS_SUCCESS(status)) {
11223 		hdd_err("Unable to set dbam config to [%u]", dbam_mode);
11224 		errno = qdf_status_to_os_return(status);
11225 		goto err;
11226 	}
11227 
11228 	errno = osif_request_wait_for_response(request);
11229 	if (errno) {
11230 		osif_err("DBAM config operation timed out");
11231 		goto err;
11232 	}
11233 
11234 	priv = osif_request_priv(request);
11235 	dbam_resp = priv->dbam_resp;
11236 	errno = hdd_convert_dbam_comp_status(dbam_resp);
11237 err:
11238 	osif_request_put(request);
11239 	return errno;
11240 }
11241 
11242 /**
11243  * hdd_set_dbam_config() - set DBAM config
11244  * @link_info: Link info pointer in HDD adapter
11245  * @attr: pointer to nla attr
11246  *
11247  * Return: 0 on success, negative errno on failure
11248  */
11249 static int hdd_set_dbam_config(struct wlan_hdd_link_info *link_info,
11250 			       const struct nlattr *attr)
11251 {
11252 	struct hdd_adapter *adapter = link_info->adapter;
11253 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11254 	int errno;
11255 	enum qca_dbam_config dbam_config;
11256 	enum coex_dbam_config_mode dbam_mode;
11257 
11258 	errno = wlan_hdd_validate_context(hdd_ctx);
11259 	if (errno)
11260 		return -EINVAL;
11261 
11262 	if (hdd_ctx->num_rf_chains < 2) {
11263 		hdd_debug("Num of chains [%u] < 2, DBAM config is not allowed",
11264 			  hdd_ctx->num_rf_chains);
11265 		return -EINVAL;
11266 	}
11267 
11268 	dbam_config = nla_get_u8(attr);
11269 	errno = hdd_convert_qca_dbam_config_mode(dbam_config, &dbam_mode);
11270 	if (errno)
11271 		return errno;
11272 
11273 	/* Store dbam config in hdd_ctx, to restore in case of an SSR */
11274 	adapter->is_dbam_configured = true;
11275 	hdd_ctx->dbam_mode = dbam_mode;
11276 
11277 	return hdd_send_dbam_config(adapter, dbam_mode);
11278 }
11279 #endif
11280 
11281 /**
11282  * hdd_set_beamformer_periodic_sounding() - enable/disable Tx Beamforming
11283  * @link_info: Link info pointer in HDD adapter
11284  * @attr: pointer to nla attr
11285  *
11286  * Return: 0 on success, negative on failure
11287  */
11288 static int
11289 hdd_set_beamformer_periodic_sounding(struct wlan_hdd_link_info *link_info,
11290 				     const struct nlattr *attr)
11291 {
11292 	uint8_t cfg_val;
11293 	int set_val;
11294 
11295 	cfg_val = nla_get_u8(attr);
11296 
11297 	set_val = cfg_val ? TX_BFER_NDP_PERIODICITY : 0;
11298 	return wma_cli_set_command(link_info->vdev_id,
11299 				   WMI_PDEV_PARAM_TXBF_SOUND_PERIOD_CMDID,
11300 				   set_val, PDEV_CMD);
11301 }
11302 
11303 /**
11304  * hdd_set_wfc_state() - Set wfc state
11305  * @link_info: Link info pointer in HDD adapter
11306  * @attr: pointer to nla attr
11307  *
11308  * Return: 0 on success, negative on failure
11309  */
11310 static int hdd_set_wfc_state(struct wlan_hdd_link_info *link_info,
11311 			     const struct nlattr *attr)
11312 {
11313 	uint8_t cfg_val;
11314 	enum pld_wfc_mode set_val;
11315 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11316 	int errno;
11317 
11318 	errno = wlan_hdd_validate_context(hdd_ctx);
11319 	if (errno)
11320 		return errno;
11321 
11322 	cfg_val = nla_get_u8(attr);
11323 
11324 	hdd_debug_rl("set wfc state %d", cfg_val);
11325 	if (cfg_val == 0)
11326 		set_val = PLD_WFC_MODE_OFF;
11327 	else if (cfg_val == 1)
11328 		set_val = PLD_WFC_MODE_ON;
11329 	else
11330 		return -EINVAL;
11331 
11332 	return pld_set_wfc_mode(hdd_ctx->parent_dev, set_val);
11333 
11334 }
11335 
11336 /**
11337  * hdd_set_ul_mu_config() - Configure UL MU i.e suspend/enable
11338  * @link_info: Link info pointer in HDD adapter
11339  * @attr: pointer to nla attr
11340  *
11341  * Return: 0 on success, negative on failure
11342  */
11343 
11344 static int hdd_set_ul_mu_config(struct wlan_hdd_link_info *link_info,
11345 				const struct nlattr *attr)
11346 {
11347 	uint8_t ulmu;
11348 	uint8_t ulmu_disable;
11349 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11350 	int errno;
11351 	QDF_STATUS qdf_status;
11352 
11353 	errno = wlan_hdd_validate_context(hdd_ctx);
11354 	if (errno) {
11355 		hdd_err("Invalid HDD ctx, errno : %d", errno);
11356 		return errno;
11357 	}
11358 
11359 	ulmu = nla_get_u8(attr);
11360 	if (ulmu != QCA_UL_MU_SUSPEND && ulmu != QCA_UL_MU_ENABLE) {
11361 		hdd_err("Invalid ulmu value, ulmu : %d", ulmu);
11362 		return -EINVAL;
11363 	}
11364 
11365 	hdd_debug("UL MU value : %d", ulmu);
11366 
11367 	if (ulmu == QCA_UL_MU_SUSPEND)
11368 		ulmu_disable = 1;
11369 	else
11370 		ulmu_disable = 0;
11371 
11372 	qdf_status = ucfg_mlme_set_ul_mu_config(hdd_ctx->psoc,
11373 						link_info->vdev_id,
11374 						ulmu_disable);
11375 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
11376 		errno = -EINVAL;
11377 		hdd_err("Failed to set UL MU, errno : %d", errno);
11378 	}
11379 
11380 	return errno;
11381 }
11382 
11383 #ifdef WLAN_FEATURE_11BE_MLO
11384 static int hdd_test_config_emlsr_mode(struct hdd_context *hdd_ctx,
11385 				      bool cfg_val)
11386 
11387 {
11388 	hdd_debug("11be op mode setting %d", cfg_val);
11389 	if (cfg_val && policy_mgr_is_hw_emlsr_capable(hdd_ctx->psoc)) {
11390 		hdd_debug("HW supports EMLSR mode, set caps");
11391 		ucfg_mlme_set_emlsr_mode_enabled(hdd_ctx->psoc, cfg_val);
11392 	} else {
11393 		hdd_debug("Default mode: MLMR, no action required");
11394 	}
11395 
11396 	return 0;
11397 }
11398 
11399 static int
11400 hdd_test_config_emlsr_action_mode(struct hdd_adapter *adapter,
11401 				  enum wlan_emlsr_action_mode emlsr_mode)
11402 {
11403 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11404 	uint8_t i, num_links = 0;
11405 	uint16_t vdev_count = 0;
11406 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
11407 	struct qdf_mac_addr active_link_addr[2];
11408 
11409 	mlo_sta_get_vdev_list(adapter->deflink->vdev, &vdev_count,
11410 			      wlan_vdev_list);
11411 	for (i = 0; i < vdev_count; i++) {
11412 		if (!wlan_vdev_list[i])
11413 			continue;
11414 		qdf_mem_copy(&active_link_addr[i],
11415 			     wlan_vdev_mlme_get_macaddr(wlan_vdev_list[i]),
11416 			     QDF_MAC_ADDR_SIZE);
11417 		num_links++;
11418 		if (emlsr_mode == WLAN_EMLSR_MODE_EXIT)
11419 			break;
11420 	}
11421 
11422 	for (i = 0; i < vdev_count; i++)
11423 		mlo_release_vdev_ref(wlan_vdev_list[i]);
11424 
11425 	hdd_debug("number of links to force enable: %d", num_links);
11426 
11427 	if (num_links >= 1)
11428 		sme_activate_mlo_links(hdd_ctx->mac_handle,
11429 				       adapter->deflink->vdev_id,
11430 				       num_links, active_link_addr);
11431 
11432 	return 0;
11433 }
11434 
11435 /**
11436  * hdd_set_epcs_capability() - Set EPCS capability enable or not
11437  * @link_info: link info pointer
11438  * @attr: pointer to nla attr
11439  *
11440  * Return: 0 on success, negative on failure
11441  */
11442 static int hdd_set_epcs_capability(struct wlan_hdd_link_info *link_info,
11443 				   const struct nlattr *attr)
11444 {
11445 	uint8_t cfg_val;
11446 	struct wlan_objmgr_vdev *vdev;
11447 
11448 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
11449 	if (!vdev)
11450 		return -EINVAL;
11451 
11452 	cfg_val = nla_get_u8(attr);
11453 	hdd_debug("Configure EPCS capability %s(%d)",
11454 		  cfg_val ? "Enable" : "Disable", cfg_val);
11455 	if (cfg_val < WLAN_EPCS_CAP_DISABLED ||
11456 	    cfg_val > WLAN_EPCS_CAP_ENABLE) {
11457 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11458 		return -EINVAL;
11459 	}
11460 
11461 	ucfg_epcs_set_config(vdev, cfg_val);
11462 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11463 
11464 	return 0;
11465 }
11466 
11467 /**
11468  * hdd_trigger_epcs_function() - Trigger EPCS function to enable or disable
11469  * @link_info: link info pointer
11470  * @attr: pointer to nla attr
11471  *
11472  * Return: 0 on success, negative on failure
11473  */
11474 static int hdd_trigger_epcs_function(struct wlan_hdd_link_info *link_info,
11475 				     const struct nlattr *attr)
11476 {
11477 	uint8_t cfg_val;
11478 	struct wlan_objmgr_vdev *vdev;
11479 	enum wlan_epcs_evt event;
11480 	int status = -EINVAL;
11481 
11482 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
11483 	if (!vdev)
11484 		return status;
11485 
11486 	cfg_val = nla_get_u8(attr);
11487 	hdd_debug("Trigger EPCS %d", cfg_val);
11488 
11489 	switch (cfg_val) {
11490 	/* enable EPCS function to send request frame */
11491 	case WLAN_EPCS_FRAME_REQUEST:
11492 		event = WLAN_EPCS_EV_ACTION_FRAME_TX_REQ;
11493 		break;
11494 	/* disable EPCS function to send teardown frame */
11495 	case WLAN_EPCS_FRAME_TEARDOWN:
11496 		event = WLAN_EPCS_EV_ACTION_FRAME_TX_TEARDOWN;
11497 		break;
11498 	default:
11499 		goto rel_ref;
11500 	}
11501 
11502 	ucfg_epcs_deliver_cmd(vdev, event);
11503 	status = 0;
11504 
11505 rel_ref:
11506 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11507 	return status;
11508 }
11509 #else
11510 static inline int
11511 hdd_test_config_emlsr_mode(struct hdd_context *hdd_ctx, bool cfg_val)
11512 {
11513 	return 0;
11514 }
11515 
11516 static inline int
11517 hdd_test_config_emlsr_action_mode(struct hdd_adapter *adapter,
11518 				  enum wlan_emlsr_action_mode emlsr_mode)
11519 {
11520 	return 0;
11521 }
11522 #endif
11523 
11524 #ifdef WLAN_FEATURE_11BE
11525 /**
11526  * hdd_set_eht_max_simultaneous_links() - Set EHT maximum number of
11527  * simultaneous links
11528  * @link_info: Link info pointer in HDD adapter
11529  * @attr: pointer to nla attr
11530  *
11531  * Return: 0 on success, negative on failure
11532  */
11533 static int
11534 hdd_set_eht_max_simultaneous_links(struct wlan_hdd_link_info *link_info,
11535 				   const struct nlattr *attr)
11536 {
11537 	uint8_t cfg_val;
11538 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11539 
11540 	cfg_val = nla_get_u8(attr);
11541 	if (cfg_val > MAX_SIMULTANEOUS_STA_ML_LINKS)
11542 		return -EINVAL;
11543 
11544 	sme_set_mlo_max_simultaneous_links(hdd_ctx->mac_handle,
11545 					   link_info->vdev_id, cfg_val);
11546 
11547 	return 0;
11548 }
11549 
11550 /**
11551  * hdd_set_eht_max_num_links() - Set EHT maximum number of links
11552  * @link_info: Link info pointer in HDD adapter
11553  * @attr: pointer to nla attr
11554  *
11555  * Return: 0 on success, negative on failure
11556  */
11557 static int hdd_set_eht_max_num_links(struct wlan_hdd_link_info *link_info,
11558 				     const struct nlattr *attr)
11559 {
11560 	uint8_t cfg_val;
11561 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11562 
11563 	cfg_val = nla_get_u8(attr);
11564 	if (cfg_val > MAX_NUM_STA_ML_LINKS)
11565 		return -EINVAL;
11566 
11567 	sme_set_mlo_max_links(hdd_ctx->mac_handle,
11568 			      link_info->vdev_id, cfg_val);
11569 
11570 	return 0;
11571 }
11572 
11573 /**
11574  * hdd_get_cfg_eht_mode() - Convert qca wlan EHT mode enum to cfg wlan EHT mode
11575  * @qca_wlan_eht_mode: qca wlan eht mode
11576  *
11577  * Return: EHT mode on success, 0 on failure
11578  */
11579 static enum wlan_eht_mode
11580 hdd_get_cfg_eht_mode(enum qca_wlan_eht_mlo_mode qca_wlan_eht_mode)
11581 {
11582 	switch (qca_wlan_eht_mode) {
11583 	case QCA_WLAN_EHT_MLSR:
11584 		return WLAN_EHT_MODE_MLSR;
11585 	case QCA_WLAN_EHT_EMLSR:
11586 		return WLAN_EHT_MODE_EMLSR;
11587 	case QCA_WLAN_EHT_NON_STR_MLMR:
11588 	case QCA_WLAN_EHT_STR_MLMR:
11589 		return WLAN_EHT_MODE_MLMR;
11590 	default:
11591 		hdd_debug("Invalid EHT mode");
11592 		return WLAN_EHT_MODE_DISABLED;
11593 	}
11594 }
11595 
11596 /**
11597  * hdd_set_eht_mlo_mode() - Set EHT MLO mode of operation
11598  * @link_info: Link info pointer in HDD adapter
11599  * @attr: pointer to nla attr
11600  *
11601  * Return: 0 on success, negative on failure
11602  */
11603 static int hdd_set_eht_mlo_mode(struct wlan_hdd_link_info *link_info,
11604 				const struct nlattr *attr)
11605 {
11606 	uint8_t cfg_val;
11607 	struct hdd_adapter *adapter = link_info->adapter;
11608 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11609 	enum wlan_eht_mode eht_mode;
11610 
11611 	cfg_val = nla_get_u8(attr);
11612 	hdd_debug("Configure EHT mode of operation: %d", cfg_val);
11613 
11614 	eht_mode = hdd_get_cfg_eht_mode(cfg_val);
11615 
11616 	if (eht_mode == WLAN_EHT_MODE_EMLSR &&
11617 	    adapter->device_mode == QDF_STA_MODE) {
11618 		hdd_test_config_emlsr_mode(hdd_ctx, true);
11619 		ucfg_mlme_set_bss_color_collision_det_sta(hdd_ctx->psoc, false);
11620 	}
11621 
11622 	ucfg_mlme_set_eht_mode(hdd_ctx->psoc, eht_mode);
11623 
11624 	return 0;
11625 }
11626 #else
11627 static inline int
11628 hdd_set_eht_max_simultaneous_links(struct wlan_hdd_link_info *link_info,
11629 				   const struct nlattr *attr)
11630 {
11631 	return 0;
11632 }
11633 
11634 static inline int
11635 hdd_set_eht_max_num_links(struct wlan_hdd_link_info  *link_info,
11636 			  const struct nlattr *attr)
11637 {
11638 	return 0;
11639 }
11640 
11641 static inline int
11642 hdd_set_eht_mlo_mode(struct wlan_hdd_link_info *link_info,
11643 		     const struct nlattr *attr)
11644 {
11645 	return 0;
11646 }
11647 #endif
11648 
11649 #ifdef WLAN_FEATURE_11BE_MLO
11650 static int hdd_set_link_force_active(struct wlan_hdd_link_info *link_info,
11651 				     const struct nlattr *attr)
11652 {
11653 	struct hdd_context *hdd_ctx = NULL;
11654 	struct nlattr *curr_attr;
11655 	struct qdf_mac_addr active_link_addr[2];
11656 	struct qdf_mac_addr *mac_addr_ptr;
11657 	uint32_t num_links = 0;
11658 	int32_t len;
11659 	struct hdd_adapter *adapter = link_info->adapter;
11660 
11661 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11662 	if (!hdd_ctx)
11663 		return -EINVAL;
11664 
11665 	if (attr && adapter->device_mode == QDF_STA_MODE) {
11666 		nla_for_each_nested(curr_attr, &attr[0], len) {
11667 			mac_addr_ptr = &active_link_addr[num_links];
11668 			qdf_mem_copy(mac_addr_ptr, nla_data(curr_attr),
11669 				     ETH_ALEN);
11670 			hdd_debug(QDF_MAC_ADDR_FMT " is link[%d] mac address",
11671 				  QDF_MAC_ADDR_REF(mac_addr_ptr->bytes),
11672 				  num_links);
11673 			num_links++;
11674 		}
11675 		sme_activate_mlo_links(hdd_ctx->mac_handle,
11676 				       link_info->vdev_id, num_links,
11677 				       active_link_addr);
11678 	}
11679 	hdd_debug("number of links to force active: %d", num_links);
11680 
11681 	return 0;
11682 }
11683 
11684 /**
11685  * hdd_get_cfg_emlsr_mode() - Convert qca wlan EMLSR mode enum to cfg wlan
11686  * EMLSR action mode
11687  * @qca_wlan_emlsr_mode: qca wlan EMLSR mode
11688  *
11689  * Return: EMLSR mode on success, 0 on failure
11690  */
11691 static enum wlan_emlsr_action_mode
11692 hdd_get_cfg_emlsr_mode(enum qca_wlan_eht_mlo_mode qca_wlan_emlsr_mode)
11693 {
11694 	switch (qca_wlan_emlsr_mode) {
11695 	case QCA_WLAN_EMLSR_MODE_ENTER:
11696 		return WLAN_EMLSR_MODE_ENTER;
11697 	case QCA_WLAN_EMLSR_MODE_EXIT:
11698 		return WLAN_EMLSR_MODE_EXIT;
11699 	default:
11700 		hdd_debug("Invalid EMLSR action mode");
11701 		return WLAN_EMLSR_MODE_DISABLED;
11702 	}
11703 }
11704 
11705 static int hdd_set_emlsr_mode(struct wlan_hdd_link_info *link_info,
11706 			      const struct nlattr *attr)
11707 {
11708 	uint8_t cfg_val;
11709 	enum wlan_emlsr_action_mode emlsr_action_mode;
11710 
11711 	if (!attr)
11712 		return -EINVAL;
11713 
11714 	cfg_val = nla_get_u8(attr);
11715 
11716 	emlsr_action_mode = hdd_get_cfg_emlsr_mode(cfg_val);
11717 
11718 	hdd_debug("EMLSR mode: %s", emlsr_action_mode == WLAN_EMLSR_MODE_ENTER ?
11719 		  "Enter" : "Exit");
11720 
11721 	hdd_test_config_emlsr_action_mode(link_info->adapter,
11722 					  emlsr_action_mode);
11723 
11724 	return 0;
11725 }
11726 #else
11727 static inline int
11728 hdd_set_link_force_active(struct wlan_hdd_link_info *link_info,
11729 			  const struct nlattr *attr)
11730 {
11731 	return 0;
11732 }
11733 
11734 static inline
11735 int hdd_set_emlsr_mode(struct wlan_hdd_link_info *link_info,
11736 		       const struct nlattr *attr)
11737 {
11738 	return 0;
11739 }
11740 
11741 static inline int
11742 hdd_set_epcs_capability(struct wlan_hdd_link_info *link_info,
11743 			const struct nlattr *attr)
11744 {
11745 	return 0;
11746 }
11747 
11748 static inline int
11749 hdd_trigger_epcs_function(struct wlan_hdd_link_info *link_info,
11750 			  const struct nlattr *attr)
11751 {
11752 	return 0;
11753 }
11754 #endif
11755 
11756 /**
11757  * hdd_set_master_channel_list() - set master channel list from set wifi
11758  * attribute
11759  * @link_info: hdd link info
11760  * @attr: Pointer to struct nlattr
11761  *
11762  * Return: 0 on success, else error number
11763  */
11764 static int
11765 hdd_set_master_channel_list(struct wlan_hdd_link_info *link_info,
11766 			    const struct nlattr *attr)
11767 {
11768 	struct sap_config *sap_config;
11769 	qdf_freq_t freq;
11770 	uint16_t count = 0;
11771 	qdf_freq_t *freq_list;
11772 	struct nlattr *nested_attr;
11773 	int tmp, ret = 0;
11774 
11775 	if (link_info->adapter->device_mode != QDF_SAP_MODE) {
11776 		hdd_debug("command not received for sap");
11777 		return -EINVAL;
11778 	}
11779 	freq_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(qdf_freq_t));
11780 	if (!freq_list)
11781 		return -ENOMEM;
11782 
11783 	sap_config = &link_info->adapter->deflink->session.ap.sap_config;
11784 
11785 	nla_for_each_nested(nested_attr, attr, tmp) {
11786 		freq = nla_get_u32(nested_attr);
11787 		if (!freq) {
11788 			hdd_err("invalid freq");
11789 			ret = -EINVAL;
11790 			goto out;
11791 		}
11792 		freq_list[count] = freq;
11793 		count++;
11794 		if (count >= NUM_CHANNELS)
11795 			break;
11796 	}
11797 	if (!count) {
11798 		hdd_err("no valid freq found");
11799 		ret = -EINVAL;
11800 		goto out;
11801 	}
11802 	ret = wlansap_update_sap_chan_list(sap_config, freq_list, count);
11803 	if (ret)
11804 		hdd_err("sap chan list update failure");
11805 out:
11806 	qdf_mem_free(freq_list);
11807 
11808 	return ret;
11809 }
11810 
11811 /**
11812  * typedef independent_setter_fn - independent attribute handler
11813  * @link_info: Link info pointer in HDD adapter
11814  * @attr: The nl80211 attribute being applied
11815  *
11816  * Defines the signature of functions in the independent attribute vtable
11817  *
11818  * Return: 0 if the attribute was handled successfully, otherwise an errno
11819  */
11820 typedef int (*independent_setter_fn)(struct wlan_hdd_link_info *link_info,
11821 				     const struct nlattr *attr);
11822 
11823 /**
11824  * struct independent_setters
11825  * @id: vendor attribute which this entry handles
11826  * @cb: callback function to invoke to process the attribute when present
11827  */
11828 struct independent_setters {
11829 	uint32_t id;
11830 	independent_setter_fn cb;
11831 };
11832 
11833 /* vtable for independent setters */
11834 static const struct independent_setters independent_setters[] = {
11835 	{QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
11836 	 hdd_config_scan_default_ies},
11837 	{QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT,
11838 	 hdd_config_fine_time_measurement},
11839 	{QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM,
11840 	 hdd_config_modulated_dtim},
11841 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
11842 	 hdd_config_listen_interval},
11843 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LRO,
11844 	 hdd_config_lro},
11845 	{QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE,
11846 	 hdd_config_scan_enable},
11847 	{QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR,
11848 	 hdd_config_stats_avg_factor},
11849 	{QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME,
11850 	 hdd_config_guard_time},
11851 	{QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY,
11852 	 hdd_config_non_agg_retry},
11853 	{QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY,
11854 	 hdd_config_agg_retry},
11855 	{QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY,
11856 	 hdd_config_mgmt_retry},
11857 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY,
11858 	 hdd_config_ctrl_retry},
11859 	{QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY,
11860 	 hdd_config_propagation_delay},
11861 	{QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY,
11862 	 hdd_config_propagation_abs_delay},
11863 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT,
11864 	 hdd_config_tx_fail_count},
11865 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND,
11866 	 hdd_config_channel_avoidance_ind},
11867 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA,
11868 	 hdd_config_ant_div_ena},
11869 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF,
11870 	 hdd_config_ant_div_snr_diff},
11871 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME,
11872 	 hdd_config_ant_div_probe_dwell_time},
11873 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN,
11874 	 hdd_config_ant_div_chain},
11875 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST,
11876 	 hdd_config_ant_div_selftest},
11877 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL,
11878 	 hdd_config_ant_div_selftest_intvl},
11879 	{QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED,
11880 	 hdd_config_ignore_assoc_disallowed},
11881 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL,
11882 	 hdd_config_restrict_offchannel},
11883 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT,
11884 	 hdd_config_total_beacon_miss_count},
11885 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL,
11886 	 hdd_config_latency_level},
11887 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS,
11888 	 hdd_config_disable_fils},
11889 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE,
11890 	 hdd_config_rsn_ie},
11891 	{QCA_WLAN_VENDOR_ATTR_CONFIG_GTX,
11892 	 hdd_config_gtx},
11893 	{QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES,
11894 	 hdd_config_disconnect_ies},
11895 #ifdef WLAN_FEATURE_ELNA
11896 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
11897 	 hdd_set_elna_bypass},
11898 #endif
11899 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
11900 	 hdd_set_roam_reason_vsie_status},
11901 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC,
11902 	 hdd_config_ldpc},
11903 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC,
11904 	 hdd_config_tx_stbc},
11905 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
11906 	 hdd_config_rx_stbc},
11907 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
11908 	 hdd_set_dynamic_bw},
11909 	{QCA_WLAN_VENDOR_ATTR_CONFIG_NSS,
11910 	 hdd_set_nss},
11911 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE,
11912 	 hdd_config_udp_qos_upgrade_threshold},
11913 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY,
11914 	 hdd_set_primary_interface},
11915 	{QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS,
11916 	 hdd_set_ft_over_ds},
11917 #ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD
11918 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD,
11919 	 hdd_set_arp_ns_offload},
11920 #endif
11921 #ifdef WLAN_FEATURE_DBAM_CONFIG
11922 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DBAM,
11923 	 hdd_set_dbam_config},
11924 #endif
11925 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE_FOR_BE_BK,
11926 	 hdd_config_udp_qos_upgrade_be_bk},
11927 	{QCA_WLAN_VENDOR_ATTR_CONFIG_BEAMFORMER_PERIODIC_SOUNDING,
11928 	 hdd_set_beamformer_periodic_sounding},
11929 
11930 	{QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE,
11931 	 hdd_set_wfc_state},
11932 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_SIMULTANEOUS_LINKS,
11933 	 hdd_set_eht_max_simultaneous_links},
11934 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_CAPABILITY,
11935 	 hdd_set_epcs_capability},
11936 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_FUNCTION,
11937 	 hdd_trigger_epcs_function},
11938 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_NUM_LINKS,
11939 	 hdd_set_eht_max_num_links},
11940 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MODE,
11941 	 hdd_set_eht_mlo_mode},
11942 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_ACTIVE_LINKS,
11943 	 hdd_set_link_force_active},
11944 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EMLSR_MODE_SWITCH,
11945 	 hdd_set_emlsr_mode},
11946 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UL_MU_CONFIG,
11947 	 hdd_set_ul_mu_config},
11948 	{QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST,
11949 	 hdd_set_master_channel_list},
11950 };
11951 
11952 #ifdef WLAN_FEATURE_ELNA
11953 /**
11954  * hdd_get_elna_bypass() - Get eLNA bypass
11955  * @link_info: Link info pointer in HDD adapter
11956  * @skb: sk buffer to hold nl80211 attributes
11957  * @attr: Pointer to struct nlattr
11958  *
11959  * Return: 0 on success; error number otherwise
11960  */
11961 static int hdd_get_elna_bypass(struct wlan_hdd_link_info *link_info,
11962 			       struct sk_buff *skb,
11963 			       const struct nlattr *attr)
11964 {
11965 	int ret;
11966 	struct wlan_objmgr_vdev *vdev;
11967 
11968 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_FWOL_NB_ID);
11969 	if (!vdev)
11970 		return -EINVAL;
11971 
11972 	ret = os_if_fwol_get_elna_bypass(vdev, skb, attr);
11973 
11974 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_FWOL_NB_ID);
11975 
11976 	return ret;
11977 }
11978 #endif
11979 
11980 /**
11981  * hdd_get_roam_reason_vsie_status() - Get roam_reason_vsie
11982  * @link_info: Link info pointer in HDD adapter
11983  * @skb: sk buffer to hold nl80211 attributes
11984  * @attr: Pointer to struct nlattr
11985  *
11986  * Return: 0 on success; error number otherwise
11987  */
11988 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
11989 static int hdd_get_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
11990 					   struct sk_buff *skb,
11991 					   const struct nlattr *attr)
11992 {
11993 	uint8_t roam_reason_vsie_enabled;
11994 	struct hdd_context *hdd_ctx = NULL;
11995 	QDF_STATUS status;
11996 
11997 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11998 
11999 	status = ucfg_mlme_get_roam_reason_vsie_status
12000 			       (hdd_ctx->psoc,
12001 				&roam_reason_vsie_enabled);
12002 	if (QDF_IS_STATUS_ERROR(status)) {
12003 		hdd_err("get roam reason vsie failed");
12004 		return -EINVAL;
12005 	}
12006 	hdd_debug("is roam_reason_vsie_enabled %d", roam_reason_vsie_enabled);
12007 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
12008 		       roam_reason_vsie_enabled)) {
12009 		hdd_err("nla_put failure");
12010 		return -EINVAL;
12011 	}
12012 
12013 	return 0;
12014 }
12015 #else
12016 static inline int
12017 hdd_get_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
12018 				struct sk_buff *skb, const struct nlattr *attr)
12019 {
12020 	return -EINVAL;
12021 }
12022 #endif
12023 
12024 static int hdd_vendor_attr_ldpc_get(struct wlan_hdd_link_info *link_info,
12025 				    struct sk_buff *skb,
12026 				    const struct nlattr *attr)
12027 {
12028 	int ldpc, ret;
12029 
12030 	ret = hdd_get_ldpc(link_info->adapter, &ldpc);
12031 	if (ret) {
12032 		hdd_err("get ldpc failed");
12033 		return -EINVAL;
12034 	}
12035 
12036 	hdd_debug("ldpc %u", ldpc);
12037 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC,
12038 		       (uint8_t)ldpc)) {
12039 		hdd_err("nla_put failure");
12040 		return -EINVAL;
12041 	}
12042 
12043 	return 0;
12044 }
12045 
12046 static int hdd_vendor_attr_tx_stbc_get(struct wlan_hdd_link_info *link_info,
12047 				       struct sk_buff *skb,
12048 				       const struct nlattr *attr)
12049 {
12050 	int tx_stbc;
12051 	int ret;
12052 
12053 	ret = hdd_get_tx_stbc(link_info->adapter, &tx_stbc);
12054 	if (ret) {
12055 		hdd_err("get tx_stbc failed");
12056 		return -EINVAL;
12057 	}
12058 
12059 	hdd_debug("tx_stbc %u", tx_stbc);
12060 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC,
12061 		       (uint8_t)tx_stbc)) {
12062 		hdd_err("nla_put failure");
12063 		return -EINVAL;
12064 	}
12065 
12066 	return 0;
12067 }
12068 
12069 static int hdd_vendor_attr_rx_stbc_get(struct wlan_hdd_link_info *link_info,
12070 				       struct sk_buff *skb,
12071 				       const struct nlattr *attr)
12072 {
12073 	int rx_stbc;
12074 	int ret;
12075 
12076 	ret = hdd_get_rx_stbc(link_info->adapter, &rx_stbc);
12077 	if (ret) {
12078 		hdd_err("get rx_stbc failed");
12079 		return -EINVAL;
12080 	}
12081 
12082 	hdd_debug("rx_stbc %u", rx_stbc);
12083 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
12084 		       (uint8_t)rx_stbc)) {
12085 		hdd_err("nla_put failure");
12086 		return -EINVAL;
12087 	}
12088 
12089 	return 0;
12090 }
12091 
12092 /**
12093  * hdd_get_tx_ampdu() - Get TX AMPDU
12094  * @link_info: Link info in HDD adapter
12095  * @skb: sk buffer to hold nl80211 attributes
12096  * @attr: Pointer to struct nlattr
12097  *
12098  * Return: 0 on success; error number otherwise
12099  */
12100 static int hdd_get_tx_ampdu(struct wlan_hdd_link_info *link_info,
12101 			    struct sk_buff *skb, const struct nlattr *attr)
12102 {
12103 	int value;
12104 
12105 	value = wma_cli_get_command(link_info->vdev_id,
12106 				    GEN_VDEV_PARAM_TX_AMPDU, GEN_CMD);
12107 	if (value < 0) {
12108 		hdd_err("Failed to get tx_ampdu");
12109 		return -EINVAL;
12110 	}
12111 
12112 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION,
12113 		       (uint8_t)value)) {
12114 		hdd_err("nla_put failure");
12115 		return -EINVAL;
12116 	}
12117 
12118 	return 0;
12119 }
12120 
12121 /**
12122  * hdd_get_rx_ampdu() - Get RX AMPDU
12123  * @link_info: Link info in HDD adapter
12124  * @skb: sk buffer to hold nl80211 attributes
12125  * @attr: Pointer to struct nlattr
12126  *
12127  * Return: 0 on success; error number otherwise
12128  */
12129 static int hdd_get_rx_ampdu(struct wlan_hdd_link_info *link_info,
12130 			    struct sk_buff *skb, const struct nlattr *attr)
12131 {
12132 	int value;
12133 
12134 	value = wma_cli_get_command(link_info->vdev_id,
12135 				    GEN_VDEV_PARAM_RX_AMPDU, GEN_CMD);
12136 	if (value < 0) {
12137 		hdd_err("Failed to get rx_ampdu");
12138 		return -EINVAL;
12139 	}
12140 
12141 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION,
12142 		       (uint8_t)value)) {
12143 		hdd_err("nla_put failure");
12144 		return -EINVAL;
12145 	}
12146 
12147 	return 0;
12148 }
12149 
12150 /**
12151  * hdd_get_tx_amsdu() - Get TX AMSDU
12152  * @link_info: Link info pointer in HDD adapter
12153  * @skb: sk buffer to hold nl80211 attributes
12154  * @attr: Pointer to struct nlattr
12155  *
12156  * Return: 0 on success; error number otherwise
12157  */
12158 static int hdd_get_tx_amsdu(struct wlan_hdd_link_info *link_info,
12159 			    struct sk_buff *skb, const struct nlattr *attr)
12160 {
12161 	int value;
12162 
12163 	value = wma_cli_get_command(link_info->vdev_id,
12164 				    GEN_VDEV_PARAM_TX_AMSDU, GEN_CMD);
12165 	if (value < 0) {
12166 		hdd_err("Failed to get tx_amsdu");
12167 		return -EINVAL;
12168 	}
12169 
12170 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION,
12171 		       (uint8_t)value)) {
12172 		hdd_err("nla_put failure");
12173 		return -EINVAL;
12174 	}
12175 
12176 	return 0;
12177 }
12178 
12179 /**
12180  * hdd_get_rx_amsdu() - Get RX AMSDU
12181  * @link_info: Link info pointer in HDD adapter
12182  * @skb: sk buffer to hold nl80211 attributes
12183  * @attr: Pointer to struct nlattr
12184  *
12185  * Return: 0 on success; error number otherwise
12186  */
12187 static int hdd_get_rx_amsdu(struct wlan_hdd_link_info *link_info,
12188 			    struct sk_buff *skb, const struct nlattr *attr)
12189 {
12190 	int value;
12191 
12192 	value = wma_cli_get_command(link_info->vdev_id,
12193 				    GEN_VDEV_PARAM_RX_AMSDU, GEN_CMD);
12194 	if (value < 0) {
12195 		hdd_err("Failed to get rx_amsdu");
12196 		return -EINVAL;
12197 	}
12198 
12199 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION,
12200 		       (uint8_t)value)) {
12201 		hdd_err("nla_put failure");
12202 		return -EINVAL;
12203 	}
12204 
12205 	return 0;
12206 }
12207 
12208 /**
12209  * hdd_get_channel_width() - Get channel width
12210  * @link_info: Link info pointer in HDD adapter
12211  * @skb: sk buffer to hold nl80211 attributes
12212  * @attr: Pointer to struct nlattr
12213  *
12214  * Return: 0 on success; error number otherwise
12215  */
12216 static int hdd_get_channel_width(struct wlan_hdd_link_info *link_info,
12217 				 struct sk_buff *skb, const struct nlattr *attr)
12218 {
12219 	enum eSirMacHTChannelWidth chwidth;
12220 	uint8_t nl80211_chwidth;
12221 
12222 	chwidth = wma_cli_get_command(link_info->vdev_id,
12223 				      wmi_vdev_param_chwidth, VDEV_CMD);
12224 	if (chwidth < 0) {
12225 		hdd_err("Failed to get chwidth");
12226 		return -EINVAL;
12227 	}
12228 
12229 	nl80211_chwidth = hdd_chwidth_to_nl80211_chwidth(chwidth);
12230 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH,
12231 		       nl80211_chwidth)) {
12232 		hdd_err("nla_put failure");
12233 		return -EINVAL;
12234 	}
12235 
12236 	return 0;
12237 }
12238 
12239 /**
12240  * hdd_get_mlo_max_band_info() - Get channel width
12241  * @link_info: Link info pointer in HDD adapter
12242  * @skb: sk buffer to hold nl80211 attributes
12243  * @attr: Pointer to struct nlattr
12244  *
12245  * Return: 0 on success; error number otherwise
12246  */
12247 static int hdd_get_mlo_max_band_info(struct wlan_hdd_link_info *link_info,
12248 				     struct sk_buff *skb,
12249 				     const struct nlattr *attr)
12250 {
12251 	enum eSirMacHTChannelWidth chwidth;
12252 	struct nlattr *mlo_bd = NULL;
12253 	struct nlattr *mlo_bd_info = NULL;
12254 	uint32_t i = 0;
12255 	uint32_t link_id = 0;
12256 	struct wlan_objmgr_vdev *vdev, *link_vdev;
12257 	struct wlan_channel *bss_chan;
12258 
12259 	chwidth = wma_cli_get_command(link_info->vdev_id,
12260 				      wmi_vdev_param_chwidth, VDEV_CMD);
12261 	if (chwidth < 0) {
12262 		hdd_err("Failed to get chwidth %u", chwidth);
12263 		return -EINVAL;
12264 	}
12265 
12266 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
12267 	if (!vdev)
12268 		return -EINVAL;
12269 
12270 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
12271 		bss_chan = wlan_vdev_mlme_get_bss_chan(vdev);
12272 
12273 		if (nla_put_u8(skb, CONFIG_CHANNEL_WIDTH,
12274 			       (uint8_t)bss_chan->ch_width)) {
12275 			hdd_err("nla_put chn width failure");
12276 		}
12277 	} else {
12278 		mlo_bd_info = nla_nest_start(skb, CONFIG_MLO_LINKS);
12279 		for (link_id = 0; link_id < WLAN_MAX_LINK_ID; link_id++) {
12280 			link_vdev = mlo_get_vdev_by_link_id(vdev, link_id);
12281 			if (!link_vdev)
12282 				continue;
12283 
12284 			mlo_bd = nla_nest_start(skb, i);
12285 			if (!mlo_bd) {
12286 				hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12287 				mlo_release_vdev_ref(link_vdev);
12288 				hdd_err("nla_nest_start fail");
12289 				return -EINVAL;
12290 			}
12291 			bss_chan = wlan_vdev_mlme_get_bss_chan(link_vdev);
12292 			if (!bss_chan) {
12293 				hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12294 				mlo_release_vdev_ref(link_vdev);
12295 				hdd_err("fail to get bss_chan info");
12296 				return QDF_STATUS_E_FAILURE;
12297 			}
12298 			if (nla_put_u8(skb, CONFIG_MLO_LINK_ID, link_id)) {
12299 				hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12300 				mlo_release_vdev_ref(link_vdev);
12301 				hdd_err("nla_put failure");
12302 				return -EINVAL;
12303 			}
12304 
12305 			if (nla_put_u8(skb, CONFIG_CHANNEL_WIDTH,
12306 				       (uint8_t)bss_chan->ch_width)) {
12307 				hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12308 				mlo_release_vdev_ref(link_vdev);
12309 				hdd_err("nla_put failure");
12310 				return -EINVAL;
12311 			}
12312 			nla_nest_end(skb, mlo_bd);
12313 			i++;
12314 			mlo_release_vdev_ref(link_vdev);
12315 		}
12316 		nla_nest_end(skb, mlo_bd_info);
12317 	}
12318 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12319 	return 0;
12320 }
12321 
12322 /**
12323  * hdd_get_dynamic_bw() - Get dynamic bandwidth disabled / enabled
12324  * @link_info: Link info pointer in HDD adapter
12325  * @skb: sk buffer to hold nl80211 attributes
12326  * @attr: Pointer to struct nlattr
12327  *
12328  * Return: 0 on success; error number otherwise
12329  */
12330 static int hdd_get_dynamic_bw(struct wlan_hdd_link_info *link_info,
12331 			      struct sk_buff *skb, const struct nlattr *attr)
12332 {
12333 	int enable;
12334 
12335 	enable = wma_cli_get_command(link_info->vdev_id,
12336 				     wmi_pdev_param_dynamic_bw, PDEV_CMD);
12337 	if (enable < 0) {
12338 		hdd_err("Failed to get dynamic_bw");
12339 		return -EINVAL;
12340 	}
12341 
12342 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
12343 		       (uint8_t)enable)) {
12344 		hdd_err("nla_put failure");
12345 		return -EINVAL;
12346 	}
12347 
12348 	return 0;
12349 }
12350 
12351 /**
12352  * hdd_get_nss_config() - Get the number of spatial streams supported by
12353  * the adapter
12354  * @link_info: Link info pointer in HDD adapter
12355  * @skb: sk buffer to hold nl80211 attributes
12356  * @attr: Pointer to struct nlattr
12357  *
12358  * Return: 0 on success; error number otherwise
12359  */
12360 static int hdd_get_nss_config(struct wlan_hdd_link_info *link_info,
12361 			      struct sk_buff *skb, const struct nlattr *attr)
12362 {
12363 	uint8_t nss;
12364 	struct hdd_adapter *adapter = link_info->adapter;
12365 
12366 	if (adapter->device_mode == QDF_SAP_MODE) {
12367 		int value;
12368 
12369 		value = wma_cli_get_command(link_info->vdev_id,
12370 					    wmi_vdev_param_nss, VDEV_CMD);
12371 		if (value < 0) {
12372 			hdd_err("Failed to get nss");
12373 			return -EINVAL;
12374 		}
12375 		nss = (uint8_t)value;
12376 	} else {
12377 		QDF_STATUS status;
12378 
12379 		status = hdd_get_nss(adapter, &nss);
12380 		if (!QDF_IS_STATUS_SUCCESS(status)) {
12381 			hdd_err("Failed to get nss");
12382 			return -EINVAL;
12383 		}
12384 	}
12385 
12386 	hdd_debug("nss %d", nss);
12387 
12388 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_NSS, nss)) {
12389 		hdd_err("nla_put failure");
12390 		return -EINVAL;
12391 	}
12392 
12393 	return 0;
12394 }
12395 
12396 /**
12397  * hdd_get_num_tx_chains_config() - Get the number of tx chains supported by
12398  * the adapter
12399  * @link_info: Link info pointer in HDD adapter
12400  * @skb: sk buffer to hold nl80211 attributes
12401  * @attr: Pointer to struct nlattr
12402  *
12403  * Return: 0 on success; error number otherwise
12404  */
12405 static int hdd_get_num_tx_chains_config(struct wlan_hdd_link_info *link_info,
12406 					struct sk_buff *skb,
12407 					const struct nlattr *attr)
12408 {
12409 	uint8_t tx_chains;
12410 	QDF_STATUS status;
12411 
12412 	if (!hdd_is_vdev_in_conn_state(link_info)) {
12413 		hdd_err("Not in connected state");
12414 		return -EINVAL;
12415 	}
12416 
12417 	status = hdd_get_num_tx_chains(link_info, &tx_chains);
12418 	if (!QDF_IS_STATUS_SUCCESS(status)) {
12419 		hdd_err("Failed to get num tx chains");
12420 		return -EINVAL;
12421 	}
12422 
12423 	hdd_debug("num_tx_chains %d", tx_chains);
12424 	if (nla_put_u8(skb,
12425 		       QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS, tx_chains)) {
12426 		hdd_err("nla_put failure");
12427 		return -EINVAL;
12428 	}
12429 
12430 	return 0;
12431 }
12432 
12433 /**
12434  * hdd_get_tx_nss_config() - Get the number of tx spatial streams supported by
12435  * the adapter
12436  * @link_info: Link info pointer in HDD adapter
12437  * @skb: sk buffer to hold nl80211 attributes
12438  * @attr: Pointer to struct nlattr
12439  *
12440  * Return: 0 on success; error number otherwise
12441  */
12442 static int hdd_get_tx_nss_config(struct wlan_hdd_link_info *link_info,
12443 				 struct sk_buff *skb, const struct nlattr *attr)
12444 {
12445 	uint8_t tx_nss;
12446 	QDF_STATUS status;
12447 
12448 	if (!hdd_is_vdev_in_conn_state(link_info)) {
12449 		hdd_err("Not in connected state");
12450 		return -EINVAL;
12451 	}
12452 
12453 	status = hdd_get_tx_nss(link_info, &tx_nss);
12454 	if (!QDF_IS_STATUS_SUCCESS(status)) {
12455 		hdd_err("Failed to get nss");
12456 		return -EINVAL;
12457 	}
12458 
12459 	hdd_debug("tx_nss %d", tx_nss);
12460 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS, tx_nss)) {
12461 		hdd_err("nla_put failure");
12462 		return -EINVAL;
12463 	}
12464 
12465 	return 0;
12466 }
12467 
12468 /**
12469  * hdd_get_num_rx_chains_config() - Get the number of rx chains supported by
12470  * the adapter
12471  * @link_info: Link info pointer in HDD adapter
12472  * @skb: sk buffer to hold nl80211 attributes
12473  * @attr: Pointer to struct nlattr
12474  *
12475  * Return: 0 on success; error number otherwise
12476  */
12477 static int hdd_get_num_rx_chains_config(struct wlan_hdd_link_info *link_info,
12478 					struct sk_buff *skb,
12479 					const struct nlattr *attr)
12480 {
12481 	uint8_t rx_chains;
12482 	QDF_STATUS status;
12483 
12484 	if (!hdd_is_vdev_in_conn_state(link_info)) {
12485 		hdd_err("Not in connected state");
12486 		return -EINVAL;
12487 	}
12488 
12489 	status = hdd_get_num_rx_chains(link_info, &rx_chains);
12490 	if (!QDF_IS_STATUS_SUCCESS(status)) {
12491 		hdd_err("Failed to get num rx chains");
12492 		return -EINVAL;
12493 	}
12494 
12495 	hdd_debug("num_rx_chains %d", rx_chains);
12496 	if (nla_put_u8(skb,
12497 		       QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS, rx_chains)) {
12498 		hdd_err("nla_put failure");
12499 		return -EINVAL;
12500 	}
12501 
12502 	return 0;
12503 }
12504 
12505 /**
12506  * hdd_get_rx_nss_config() - Get the number of rx spatial streams supported by
12507  * the adapter
12508  * @link_info: Link info pointer in HDD adapter
12509  * @skb: sk buffer to hold nl80211 attributes
12510  * @attr: Pointer to struct nlattr
12511  *
12512  * Return: 0 on success; error number otherwise
12513  */
12514 static int hdd_get_rx_nss_config(struct wlan_hdd_link_info *link_info,
12515 				 struct sk_buff *skb, const struct nlattr *attr)
12516 {
12517 	uint8_t rx_nss;
12518 	QDF_STATUS status;
12519 
12520 	if (!hdd_is_vdev_in_conn_state(link_info)) {
12521 		hdd_err("Not in connected state");
12522 		return -EINVAL;
12523 	}
12524 
12525 	status = hdd_get_rx_nss(link_info, &rx_nss);
12526 	if (!QDF_IS_STATUS_SUCCESS(status)) {
12527 		hdd_err("Failed to get nss");
12528 		return -EINVAL;
12529 	}
12530 
12531 	hdd_debug("rx_nss %d", rx_nss);
12532 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS, rx_nss)) {
12533 		hdd_err("nla_put failure");
12534 		return -EINVAL;
12535 	}
12536 
12537 	return 0;
12538 }
12539 
12540 /**
12541  * hdd_get_listen_interval_config() - Get listen interval from driver
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_listen_interval_config(struct wlan_hdd_link_info *link_info,
12549 					  struct sk_buff *skb,
12550 					  const struct nlattr *attr)
12551 {
12552 	uint32_t listen_interval = 0;
12553 	QDF_STATUS status;
12554 	struct hdd_adapter *adapter = link_info->adapter;
12555 	struct wlan_objmgr_vdev *vdev;
12556 
12557 	if (adapter->device_mode != QDF_STA_MODE &&
12558 	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
12559 		hdd_err("Device not in STA / P2P-CLI mode");
12560 		return -EINVAL;
12561 	}
12562 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
12563 	if (!vdev) {
12564 		hdd_err("Failed to get vdev");
12565 		return -EINVAL;
12566 	}
12567 
12568 	status = ucfg_pmo_get_listen_interval(vdev, &listen_interval);
12569 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12570 	if (status != QDF_STATUS_SUCCESS) {
12571 		hdd_err("vdev/vdev ctx NULL for getting listen interval");
12572 		return -EINVAL;
12573 	}
12574 
12575 	hdd_debug("listen interval %d", listen_interval);
12576 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
12577 			listen_interval)) {
12578 		hdd_err("nla_put failure");
12579 		return -EINVAL;
12580 	}
12581 
12582 	return 0;
12583 }
12584 
12585 /**
12586  * hdd_get_optimized_power_config() - Get the number of spatial streams
12587  * supported by the adapter
12588  * @link_info: Link info pointer in HDD adapter
12589  * @skb: sk buffer to hold nl80211 attributes
12590  * @attr: Pointer to struct nlattr
12591  *
12592  * Return: 0 on success; error number otherwise
12593  */
12594 static int hdd_get_optimized_power_config(struct wlan_hdd_link_info *link_info,
12595 					  struct sk_buff *skb,
12596 					  const struct nlattr *attr)
12597 {
12598 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12599 	uint8_t optimized_power_cfg;
12600 	int errno;
12601 
12602 	errno = wlan_hdd_validate_context(hdd_ctx);
12603 	if (errno)
12604 		return errno;
12605 
12606 	optimized_power_cfg  = ucfg_pmo_get_power_save_mode(hdd_ctx->psoc);
12607 
12608 	if (nla_put_u8(skb,
12609 		       QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT,
12610 		       optimized_power_cfg)) {
12611 		hdd_err_rl("nla_put failure");
12612 		return -EINVAL;
12613 	}
12614 
12615 	return 0;
12616 }
12617 
12618 /**
12619  * typedef config_getter_fn - get configuration handler
12620  * @link_info: Link info pointer in HDD adapter
12621  * @skb: sk buffer to hold nl80211 attributes
12622  * @attr: The nl80211 attribute being applied
12623  *
12624  * Defines the signature of functions in the attribute vtable
12625  *
12626  * Return: 0 if the attribute was handled successfully, otherwise an errno
12627  */
12628 typedef int (*config_getter_fn)(struct wlan_hdd_link_info *link_info,
12629 				struct sk_buff *skb,
12630 				const struct nlattr *attr);
12631 
12632 /**
12633  * struct config_getters
12634  * @id: vendor attribute which this entry handles
12635  * @max_attr_len: Maximum length of the attribute
12636  * @cb: callback function to invoke to process the attribute when present
12637  */
12638 struct config_getters {
12639 	uint32_t id;
12640 	size_t max_attr_len;
12641 	config_getter_fn cb;
12642 };
12643 
12644 /* vtable for config getters */
12645 static const struct config_getters config_getters[] = {
12646 #ifdef WLAN_FEATURE_ELNA
12647 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
12648 	 sizeof(uint8_t),
12649 	 hdd_get_elna_bypass},
12650 #endif
12651 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
12652 	 sizeof(uint8_t),
12653 	 hdd_get_roam_reason_vsie_status},
12654 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION,
12655 	 sizeof(uint8_t),
12656 	 hdd_get_tx_ampdu},
12657 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION,
12658 	 sizeof(uint8_t),
12659 	 hdd_get_rx_ampdu},
12660 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION,
12661 	 sizeof(uint8_t),
12662 	 hdd_get_tx_amsdu},
12663 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION,
12664 	 sizeof(uint8_t),
12665 	 hdd_get_rx_amsdu},
12666 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC,
12667 	 sizeof(uint8_t),
12668 	 hdd_vendor_attr_ldpc_get},
12669 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC,
12670 	 sizeof(uint8_t),
12671 	 hdd_vendor_attr_tx_stbc_get},
12672 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
12673 	 sizeof(uint8_t),
12674 	 hdd_vendor_attr_rx_stbc_get},
12675 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH,
12676 	 sizeof(uint8_t),
12677 	 hdd_get_channel_width},
12678 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
12679 	 sizeof(uint8_t),
12680 	 hdd_get_dynamic_bw},
12681 	{QCA_WLAN_VENDOR_ATTR_CONFIG_NSS,
12682 	 sizeof(uint8_t),
12683 	 hdd_get_nss_config},
12684 	{QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT,
12685 	 sizeof(uint8_t),
12686 	 hdd_get_optimized_power_config},
12687 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS,
12688 	 sizeof(uint8_t),
12689 	 hdd_get_tx_nss_config},
12690 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS,
12691 	 sizeof(uint8_t),
12692 	 hdd_get_rx_nss_config},
12693 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
12694 	 sizeof(uint32_t),
12695 	 hdd_get_listen_interval_config},
12696 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS,
12697 	 sizeof(uint8_t),
12698 	 hdd_get_num_tx_chains_config},
12699 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS,
12700 	 sizeof(uint8_t),
12701 	 hdd_get_num_rx_chains_config},
12702 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS,
12703 	 WLAN_MAX_ML_BSS_LINKS * sizeof(uint8_t) * 2,
12704 	 hdd_get_mlo_max_band_info},
12705 };
12706 
12707 /**
12708  * hdd_get_configuration() - Handle get configuration
12709  * @link_info: Link info pointer in HDD adapter
12710  * @tb: parsed attribute array
12711  *
12712  * This is a table-driven function which dispatches attributes
12713  * in a QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION
12714  * vendor command.
12715  *
12716  * Return: 0 if there were no issues, otherwise errno of the last issue
12717  */
12718 static int hdd_get_configuration(struct wlan_hdd_link_info *link_info,
12719 				 struct nlattr **tb)
12720 {
12721 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12722 	uint32_t i, id;
12723 	unsigned long nl_buf_len = NLMSG_HDRLEN;
12724 	struct sk_buff *skb;
12725 	struct nlattr *attr;
12726 	config_getter_fn cb;
12727 	int errno = 0;
12728 
12729 	for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
12730 		id = config_getters[i].id;
12731 		attr = tb[id];
12732 		if (!attr)
12733 			continue;
12734 
12735 		nl_buf_len += NLA_HDRLEN +
12736 			      NLA_ALIGN(config_getters[i].max_attr_len);
12737 	}
12738 
12739 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
12740 						       nl_buf_len);
12741 	if (!skb) {
12742 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
12743 		return -ENOMEM;
12744 	}
12745 
12746 	for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
12747 		id = config_getters[i].id;
12748 		attr = tb[id];
12749 		if (!attr)
12750 			continue;
12751 
12752 		hdd_debug("Get wifi configuration %d", id);
12753 
12754 		cb = config_getters[i].cb;
12755 		errno = cb(link_info, skb, attr);
12756 		if (errno)
12757 			break;
12758 	}
12759 
12760 	if (errno) {
12761 		hdd_err("Failed to get wifi configuration, errno = %d", errno);
12762 		wlan_cfg80211_vendor_free_skb(skb);
12763 		return -EINVAL;
12764 	}
12765 
12766 	wlan_cfg80211_vendor_cmd_reply(skb);
12767 
12768 	return errno;
12769 }
12770 
12771 /**
12772  * hdd_set_independent_configuration() - Handle independent attributes
12773  * @link_info: Link info pointer in HDD adapter
12774  * @tb: parsed attribute array
12775  *
12776  * This is a table-driven function which dispatches independent
12777  * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
12778  * vendor command. An attribute is considered independent if it
12779  * doesn't depend upon any other attributes
12780  *
12781  * Return: 0 if there were no issues, otherwise errno of the last issue
12782  */
12783 static int
12784 hdd_set_independent_configuration(struct wlan_hdd_link_info *link_info,
12785 				  struct nlattr **tb)
12786 {
12787 	uint32_t i;
12788 	uint32_t id;
12789 	struct nlattr *attr;
12790 	independent_setter_fn cb;
12791 	int errno = 0;
12792 	int ret;
12793 
12794 	for (i = 0; i < QDF_ARRAY_SIZE(independent_setters); i++) {
12795 		id = independent_setters[i].id;
12796 		attr = tb[id];
12797 		if (!attr)
12798 			continue;
12799 
12800 		hdd_debug("Set wifi configuration %d", id);
12801 
12802 		cb = independent_setters[i].cb;
12803 		ret = cb(link_info, attr);
12804 		if (ret)
12805 			errno = ret;
12806 	}
12807 
12808 	return errno;
12809 }
12810 
12811 /**
12812  * typedef interdependent_setter_fn - interdependent attribute handler
12813  * @link_info: Link info pointer in HDD adapter
12814  * @tb: The parsed nl80211 attributes being applied
12815  *
12816  * Defines the signature of functions in the interdependent attribute vtable
12817  *
12818  * Return: 0 if attributes were handled successfully, otherwise an errno
12819  */
12820 typedef int (*interdependent_setter_fn)(struct wlan_hdd_link_info *link_info,
12821 					struct nlattr **tb);
12822 
12823 /* vtable for interdependent setters */
12824 static const interdependent_setter_fn interdependent_setters[] = {
12825 	hdd_config_access_policy,
12826 	hdd_config_mpdu_aggregation,
12827 	hdd_config_ant_div_period,
12828 	hdd_config_ant_div_snr_weight,
12829 	wlan_hdd_cfg80211_wifi_set_reorder_timeout,
12830 	wlan_hdd_cfg80211_wifi_set_rx_blocksize,
12831 	hdd_config_msdu_aggregation,
12832 	hdd_config_vdev_chains,
12833 	hdd_config_ani,
12834 	hdd_config_tx_rx_nss,
12835 	hdd_process_generic_set_cmd,
12836 	hdd_config_phy_mode,
12837 	hdd_config_power,
12838 	hdd_set_channel_width,
12839 };
12840 
12841 /**
12842  * hdd_set_interdependent_configuration() - Handle interdependent attributes
12843  * @link_info: Link info pointer in hdd adapter
12844  * @tb: parsed attribute array
12845  *
12846  * This is a table-driven function which handles interdependent
12847  * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
12848  * vendor command. A set of attributes is considered interdependent if
12849  * they depend upon each other. In the typical case if one of the
12850  * attributes is present in the the attribute array, then all of the
12851  * attributes must be present.
12852  *
12853  * Return: 0 if there were no issues, otherwise errno of the last issue
12854  */
12855 static int
12856 hdd_set_interdependent_configuration(struct wlan_hdd_link_info *link_info,
12857 				     struct nlattr **tb)
12858 {
12859 	uint32_t i;
12860 	interdependent_setter_fn cb;
12861 	int errno = 0;
12862 	int ret;
12863 
12864 	for (i = 0; i < QDF_ARRAY_SIZE(interdependent_setters); i++) {
12865 		cb = interdependent_setters[i];
12866 		ret = cb(link_info, tb);
12867 		if (ret)
12868 			errno = ret;
12869 	}
12870 
12871 	return errno;
12872 }
12873 
12874 /**
12875  * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
12876  * vendor command
12877  *
12878  * @wiphy: wiphy device pointer
12879  * @wdev: wireless device pointer
12880  * @data: Vendor command data buffer
12881  * @data_len: Buffer length
12882  *
12883  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
12884  *
12885  * Return: Error code.
12886  */
12887 static int
12888 __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
12889 					   struct wireless_dev *wdev,
12890 					   const void *data,
12891 					   int data_len)
12892 {
12893 	struct net_device *dev = wdev->netdev;
12894 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
12895 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
12896 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
12897 	int errno, ret;
12898 
12899 	hdd_enter_dev(dev);
12900 
12901 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12902 		hdd_err("Command not allowed in FTM mode");
12903 		return -EPERM;
12904 	}
12905 
12906 	errno = wlan_hdd_validate_context(hdd_ctx);
12907 	if (errno)
12908 		return errno;
12909 
12910 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
12911 				    data_len, wlan_hdd_wifi_config_policy)) {
12912 		hdd_err("invalid attr");
12913 		return -EINVAL;
12914 	}
12915 
12916 	ret = hdd_set_independent_configuration(adapter->deflink, tb);
12917 	if (ret)
12918 		errno = ret;
12919 
12920 	ret = hdd_set_interdependent_configuration(adapter->deflink, tb);
12921 	if (ret)
12922 		errno = ret;
12923 
12924 	return errno;
12925 }
12926 
12927 /**
12928  * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
12929  * vendor command
12930  *
12931  * @wiphy: wiphy device pointer
12932  * @wdev: wireless device pointer
12933  * @data: Vendor command data buffer
12934  * @data_len: Buffer length
12935  *
12936  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
12937  *
12938  * Return: EOK or other error codes.
12939  */
12940 static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
12941 						    struct wireless_dev *wdev,
12942 						    const void *data,
12943 						    int data_len)
12944 {
12945 	int errno;
12946 	struct osif_vdev_sync *vdev_sync;
12947 
12948 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
12949 	if (errno)
12950 		return errno;
12951 
12952 	errno = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
12953 							   data, data_len);
12954 
12955 	osif_vdev_sync_op_stop(vdev_sync);
12956 
12957 	return errno;
12958 }
12959 
12960 /**
12961  * __wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
12962  * vendor command
12963  * @wiphy: wiphy device pointer
12964  * @wdev: wireless device pointer
12965  * @data: Vendor command data buffer
12966  * @data_len: Buffer length
12967  *
12968  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
12969  *
12970  * Return: Error code.
12971  */
12972 static int
12973 __wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
12974 					   struct wireless_dev *wdev,
12975 					   const void *data,
12976 					   int data_len)
12977 {
12978 	struct net_device *dev = wdev->netdev;
12979 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
12980 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
12981 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
12982 	int errno, ret;
12983 
12984 	hdd_enter_dev(dev);
12985 
12986 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12987 		hdd_err("Command not allowed in FTM mode");
12988 		return -EPERM;
12989 	}
12990 
12991 	errno = wlan_hdd_validate_context(hdd_ctx);
12992 	if (errno)
12993 		return errno;
12994 
12995 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
12996 				    data_len, wlan_hdd_wifi_config_policy)) {
12997 		hdd_err("invalid attr");
12998 		return -EINVAL;
12999 	}
13000 
13001 	/* Generic command is used by EasyMesh,
13002 	 * route the command to SON module if it is Generic
13003 	 *
13004 	 * GENERIC_COMMAND to get configs can not be done as part of dispatch
13005 	 * table because, for each command sent as part of GENERIC command,
13006 	 * return value is different and is handled in SON module as well.
13007 	 * Hence having return type with dispatch table is not possible as
13008 	 * we will not be able to generalize the return for each of get sub
13009 	 * command sent as part of GENERIC command.
13010 	 */
13011 	if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND])
13012 		return hdd_son_send_get_wifi_generic_command(wiphy, wdev, tb);
13013 
13014 	ret = hdd_get_configuration(adapter->deflink, tb);
13015 	if (ret)
13016 		errno = ret;
13017 
13018 	return errno;
13019 }
13020 
13021 /**
13022  * wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
13023  * vendor command
13024  *
13025  * @wiphy: wiphy device pointer
13026  * @wdev: wireless device pointer
13027  * @data: Vendor command data buffer
13028  * @data_len: Buffer length
13029  *
13030  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
13031  *
13032  * Return: EOK or other error codes.
13033  */
13034 static int wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
13035 						    struct wireless_dev *wdev,
13036 						    const void *data,
13037 						    int data_len)
13038 {
13039 	int errno;
13040 	struct osif_vdev_sync *vdev_sync;
13041 
13042 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13043 	if (errno)
13044 		return errno;
13045 
13046 	errno = __wlan_hdd_cfg80211_wifi_configuration_get(wiphy, wdev,
13047 							   data, data_len);
13048 
13049 	osif_vdev_sync_op_stop(vdev_sync);
13050 
13051 	return errno;
13052 }
13053 
13054 static void hdd_disable_runtime_pm_for_user(struct hdd_context *hdd_ctx)
13055 {
13056 	struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
13057 
13058 	if (!ctx)
13059 		return;
13060 
13061 	if (ctx->is_user_wakelock_acquired)
13062 		return;
13063 
13064 	ctx->is_user_wakelock_acquired = true;
13065 	qdf_runtime_pm_prevent_suspend(&ctx->user);
13066 }
13067 
13068 static int hdd_test_config_6ghz_security_test_mode(struct hdd_context *hdd_ctx,
13069 						   struct nlattr *attr)
13070 
13071 {
13072 	uint8_t cfg_val;
13073 	bool rf_test_mode = false;
13074 	QDF_STATUS status;
13075 
13076 	status = ucfg_mlme_is_rf_test_mode_enabled(hdd_ctx->psoc,
13077 						   &rf_test_mode);
13078 	if (!QDF_IS_STATUS_SUCCESS(status)) {
13079 		hdd_err("Get rf test mode failed");
13080 		return -EINVAL;
13081 	}
13082 	if (rf_test_mode) {
13083 		hdd_err("rf test mode is enabled, ignore setting");
13084 		return 0;
13085 	}
13086 
13087 	cfg_val = nla_get_u8(attr);
13088 	hdd_debug("safe mode setting %d", cfg_val);
13089 	wlan_mlme_set_safe_mode_enable(hdd_ctx->psoc, cfg_val);
13090 	if (cfg_val) {
13091 		wlan_cm_set_check_6ghz_security(hdd_ctx->psoc, false);
13092 		wlan_cm_set_6ghz_key_mgmt_mask(hdd_ctx->psoc,
13093 					       DEFAULT_KEYMGMT_6G_MASK);
13094 	} else {
13095 		wlan_cm_set_check_6ghz_security(hdd_ctx->psoc, true);
13096 		wlan_cm_set_6ghz_key_mgmt_mask(hdd_ctx->psoc,
13097 					       ALLOWED_KEYMGMT_6G_MASK);
13098 	}
13099 
13100 	return 0;
13101 }
13102 
13103 /**
13104  * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
13105  * vendor command
13106  *
13107  * @wiphy: wiphy device pointer
13108  * @wdev: wireless device pointer
13109  * @data: Vendor command data buffer
13110  * @data_len: Buffer length
13111  *
13112  * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
13113  *
13114  * Return: Error code.
13115  */
13116 static int
13117 __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
13118 		struct wireless_dev *wdev, const void *data, int data_len)
13119 {
13120 	struct net_device *dev = wdev->netdev;
13121 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13122 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
13123 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
13124 	int ret_val = 0;
13125 	uint8_t cfg_val = 0;
13126 	uint8_t ini_val = 0;
13127 	uint8_t set_val = 0;
13128 	struct sme_config_params *sme_config;
13129 	bool update_sme_cfg = false;
13130 	uint8_t tid = 0, ac;
13131 	uint16_t buff_size = 0;
13132 	mac_handle_t mac_handle;
13133 	QDF_STATUS status;
13134 	bool bval = false;
13135 	uint8_t value = 0;
13136 	uint8_t wmm_mode = 0;
13137 	uint32_t bss_max_idle_period = 0;
13138 	uint32_t cmd_id;
13139 	uint8_t link_id = 0xFF;
13140 	struct keep_alive_req keep_alive_req = {0};
13141 	struct set_wfatest_params wfa_param = {0};
13142 	struct wlan_hdd_link_info *link_info = adapter->link_info;
13143 	struct hdd_station_ctx *hdd_sta_ctx =
13144 			WLAN_HDD_GET_STATION_CTX_PTR(link_info);
13145 	uint8_t op_mode;
13146 
13147 	hdd_enter_dev(dev);
13148 
13149 	sme_config = qdf_mem_malloc(sizeof(*sme_config));
13150 	if (!sme_config)
13151 		return -ENOMEM;
13152 
13153 	mac_handle = hdd_ctx->mac_handle;
13154 	sme_get_config_param(mac_handle, sme_config);
13155 
13156 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13157 		hdd_err("Command not allowed in FTM mode");
13158 		ret_val = -EPERM;
13159 		goto send_err;
13160 	}
13161 
13162 	ret_val = wlan_hdd_validate_context(hdd_ctx);
13163 	if (ret_val)
13164 		goto send_err;
13165 
13166 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
13167 		hdd_err("Driver Modules are closed, can not start logger");
13168 		ret_val = -EINVAL;
13169 		goto send_err;
13170 	}
13171 
13172 	if (wlan_cfg80211_nla_parse(tb,
13173 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
13174 			data, data_len, wlan_hdd_wifi_test_config_policy)) {
13175 		hdd_err("invalid attr");
13176 		ret_val = -EINVAL;
13177 		goto send_err;
13178 	}
13179 
13180 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
13181 		cfg_val = nla_get_u8(tb[
13182 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
13183 			);
13184 		hdd_debug("set addba accept req from peer value %d", cfg_val);
13185 		ret_val = sme_set_addba_accept(mac_handle,
13186 					       link_info->vdev_id,
13187 					       cfg_val);
13188 		if (ret_val)
13189 			goto send_err;
13190 	}
13191 
13192 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
13193 		cfg_val = nla_get_u8(tb[
13194 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
13195 		hdd_debug("set HE MCS value 0x%0X", cfg_val);
13196 		ret_val = sme_update_he_mcs(mac_handle,
13197 					    link_info->vdev_id, cfg_val);
13198 		if (ret_val)
13199 			goto send_err;
13200 	}
13201 
13202 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
13203 		cfg_val = nla_get_u8(tb[
13204 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
13205 		if (!cfg_val) {
13206 			sme_config->csr_config.WMMSupportMode =
13207 				hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
13208 			hdd_debug("wmm is disabled");
13209 		} else {
13210 			status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc,
13211 							&wmm_mode);
13212 			if (!QDF_IS_STATUS_SUCCESS(status)) {
13213 				hdd_err("Get wmm_mode failed");
13214 				ret_val = -EINVAL;
13215 				goto send_err;
13216 			}
13217 			sme_config->csr_config.WMMSupportMode =
13218 				hdd_to_csr_wmm_mode(wmm_mode);
13219 			hdd_debug("using wmm default value");
13220 		}
13221 		update_sme_cfg = true;
13222 	}
13223 
13224 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
13225 		cfg_val = nla_get_u8(tb[
13226 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
13227 		if (cfg_val) {
13228 			/*Auto BA mode*/
13229 			set_val = 0;
13230 			hdd_debug("BA operating mode is set to auto");
13231 		} else {
13232 			/*Manual BA mode*/
13233 			set_val = 1;
13234 			hdd_debug("BA operating mode is set to Manual");
13235 		}
13236 
13237 		op_mode = wlan_get_opmode_from_vdev_id(
13238 						hdd_ctx->pdev,
13239 						link_info->vdev_id);
13240 		if (op_mode == QDF_STA_MODE)
13241 			sme_set_ba_opmode(mac_handle,
13242 					  link_info->vdev_id,
13243 					  set_val);
13244 
13245 		if (!cfg_val) {
13246 			ret_val = wma_cli_set_command(
13247 				link_info->vdev_id,
13248 				wmi_vdev_param_amsdu_aggregation_size_optimization,
13249 				0, VDEV_CMD);
13250 		}
13251 	}
13252 
13253 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
13254 		cfg_val = nla_get_u8(tb[
13255 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
13256 			);
13257 		if (cfg_val > HE_FRAG_LEVEL1)
13258 			set_val = HE_FRAG_LEVEL1;
13259 		else
13260 			set_val = cfg_val;
13261 
13262 		hdd_debug("set HE fragmention to %d", set_val);
13263 		ret_val = sme_update_he_frag_supp(mac_handle,
13264 						  link_info->vdev_id,
13265 						  set_val);
13266 	}
13267 
13268 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
13269 		cfg_val = nla_get_u8(tb[
13270 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
13271 		sme_config->csr_config.wep_tkip_in_he = cfg_val;
13272 		hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
13273 
13274 		update_sme_cfg = true;
13275 	}
13276 
13277 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
13278 		if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
13279 			tid = nla_get_u8(tb[
13280 				QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
13281 		} else {
13282 			hdd_err("TID is not set for ADD/DEL BA cfg");
13283 			ret_val = -EINVAL;
13284 			goto send_err;
13285 		}
13286 		cfg_val = nla_get_u8(tb[
13287 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
13288 		if (cfg_val == QCA_WLAN_ADD_BA) {
13289 			if (tb[
13290 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
13291 				buff_size = nla_get_u16(tb[
13292 				QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
13293 			ret_val = sme_send_addba_req(mac_handle,
13294 						     link_info->vdev_id,
13295 						     tid, buff_size);
13296 		} else if (cfg_val == QCA_WLAN_DELETE_BA) {
13297 		} else {
13298 			hdd_err("Invalid BA session cfg");
13299 			ret_val = -EINVAL;
13300 			goto send_err;
13301 		}
13302 	} else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
13303 		buff_size = nla_get_u16(tb[
13304 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
13305 		hdd_debug("set buff size to %d for all tids", buff_size);
13306 		ret_val = sme_set_ba_buff_size(mac_handle,
13307 					       link_info->vdev_id,
13308 					       buff_size);
13309 		if (ret_val)
13310 			goto send_err;
13311 
13312 		if (buff_size > 512)
13313 			/* Configure ADDBA req buffer size to 1024 */
13314 			set_val = HDD_BA_MODE_1024;
13315 		else if (buff_size > 256)
13316 			/* Configure ADDBA req buffer size to 512 */
13317 			set_val = HDD_BA_MODE_512;
13318 		else if (buff_size > 64)
13319 			/* Configure ADDBA req buffer size to 256 */
13320 			set_val = HDD_BA_MODE_256;
13321 		else
13322 			/* Configure ADDBA req buffer size to 64 */
13323 			set_val = HDD_BA_MODE_64;
13324 
13325 		sme_set_ba_opmode(mac_handle, link_info->vdev_id,
13326 				  set_val);
13327 
13328 		ret_val = wma_cli_set_command(link_info->vdev_id,
13329 					      wmi_vdev_param_set_ba_mode,
13330 					      set_val, VDEV_CMD);
13331 		if (ret_val)
13332 			hdd_err("Failed to set BA operating mode %d", set_val);
13333 		ret_val = wma_cli_set_command(link_info->vdev_id,
13334 					      GEN_VDEV_PARAM_AMPDU,
13335 					      buff_size, GEN_CMD);
13336 	}
13337 
13338 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
13339 		int he_mcs_val;
13340 
13341 		if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
13342 			ac = nla_get_u8(tb[
13343 			     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
13344 		} else {
13345 			hdd_err("AC is not set for NO ACK policy config");
13346 			ret_val = -EINVAL;
13347 			goto send_err;
13348 		}
13349 		cfg_val = nla_get_u8(tb[
13350 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
13351 		hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
13352 		ret_val = sme_set_no_ack_policy(mac_handle,
13353 						link_info->vdev_id,
13354 						cfg_val, ac);
13355 		if (cfg_val) {
13356 			status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc,
13357 							     &bval);
13358 			if (!QDF_IS_STATUS_SUCCESS(status))
13359 				hdd_err("unable to get vht_enable2x2");
13360 			if (bval)
13361 				/*2x2 MCS 5 value*/
13362 				he_mcs_val = 0x45;
13363 			else
13364 				/*1x1 MCS 5 value*/
13365 				he_mcs_val = 0x25;
13366 
13367 			if (hdd_set_11ax_rate(adapter, he_mcs_val, NULL))
13368 				hdd_err("HE MCS set failed, MCS val %0x",
13369 						he_mcs_val);
13370 		} else {
13371 			if (hdd_set_11ax_rate(adapter, 0xFF, NULL))
13372 				hdd_err("disable fixed rate failed");
13373 		}
13374 	}
13375 
13376 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE;
13377 	if (tb[cmd_id]) {
13378 		cfg_val = nla_get_u8(tb[cmd_id]);
13379 		hdd_debug("Keep alive data type %d", cfg_val);
13380 		if (cfg_val == QCA_WLAN_KEEP_ALIVE_DATA) {
13381 			ret_val = hdd_set_grat_arp_keepalive(adapter);
13382 			if (ret_val) {
13383 				hdd_err("Keep alive data type set failed");
13384 				goto send_err;
13385 			}
13386 		} else {
13387 			if (cfg_val == QCA_WLAN_KEEP_ALIVE_MGMT)
13388 				keep_alive_req.packetType =
13389 						SIR_KEEP_ALIVE_MGMT_FRAME;
13390 			else
13391 				keep_alive_req.packetType =
13392 						SIR_KEEP_ALIVE_NULL_PKT;
13393 			ucfg_mlme_get_sta_keep_alive_period(
13394 						hdd_ctx->psoc,
13395 						&keep_alive_req.timePeriod);
13396 			keep_alive_req.sessionId = link_info->vdev_id;
13397 			status = sme_set_keep_alive(hdd_ctx->mac_handle,
13398 						    link_info->vdev_id,
13399 						    &keep_alive_req);
13400 			if (QDF_IS_STATUS_ERROR(status)) {
13401 				hdd_err("Failed to set keepalive");
13402 				ret_val = qdf_status_to_os_return(status);
13403 				goto send_err;
13404 			}
13405 		}
13406 	}
13407 
13408 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]) {
13409 		cfg_val = nla_get_u8(tb[
13410 				QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]);
13411 		hdd_debug("Set HE LTF to %d", cfg_val);
13412 		ret_val = sme_set_auto_rate_he_ltf(mac_handle,
13413 						   link_info->vdev_id,
13414 						   cfg_val);
13415 		if (ret_val)
13416 			sme_err("Failed to set auto rate HE LTF");
13417 
13418 		ret_val = wma_cli_set_command(link_info->vdev_id,
13419 					      wmi_vdev_param_set_he_ltf,
13420 					      cfg_val, VDEV_CMD);
13421 		if (ret_val)
13422 			goto send_err;
13423 	}
13424 
13425 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE;
13426 	if (tb[cmd_id]) {
13427 		cfg_val = nla_get_u8(tb[
13428 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]);
13429 		hdd_debug("Set Tx beamformee to %d", cfg_val);
13430 		ret_val = sme_update_tx_bfee_supp(mac_handle,
13431 						  link_info->vdev_id,
13432 						  cfg_val);
13433 		if (ret_val)
13434 			sme_err("Failed to update Tx beamformee support");
13435 
13436 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
13437 					      cfg_val, EHT_TX_BFEE_ENABLE,
13438 					      adapter->device_mode);
13439 		if (ret_val)
13440 			sme_err("Failed to set Tx beamformee cap");
13441 
13442 	}
13443 
13444 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS;
13445 	if (tb[cmd_id]) {
13446 		cfg_val = nla_get_u8(tb[cmd_id]);
13447 		ret_val = sme_update_he_capabilities(mac_handle,
13448 						     link_info->vdev_id,
13449 						     cfg_val, cmd_id);
13450 		if (ret_val)
13451 			sme_err("Failed to update HE cap");
13452 	}
13453 
13454 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT;
13455 	if (tb[cmd_id]) {
13456 		cfg_val = nla_get_u8(tb[cmd_id]);
13457 		ret_val = sme_update_he_capabilities(mac_handle,
13458 						     link_info->vdev_id,
13459 						     cfg_val, cmd_id);
13460 		if (ret_val)
13461 			sme_err("Failed to update HE cap");
13462 	}
13463 
13464 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]) {
13465 		cfg_val = nla_get_u8(tb[
13466 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]);
13467 		status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
13468 								&value);
13469 		if (!QDF_IS_STATUS_SUCCESS(status))
13470 			hdd_err("unable to get tx_bfee_ant_supp");
13471 
13472 		if (!cfg_in_range(CFG_VHT_BEAMFORMEE_ANT_SUPP, cfg_val)) {
13473 			hdd_err("NSTS %d not supported, supp_val %d", cfg_val,
13474 				value);
13475 			ret_val = -ENOTSUPP;
13476 			goto send_err;
13477 		}
13478 		hdd_debug("Set Tx beamformee NSTS to %d", cfg_val);
13479 		ret_val = sme_update_tx_bfee_nsts(hdd_ctx->mac_handle,
13480 						  link_info->vdev_id,
13481 						  cfg_val,
13482 						  value);
13483 		if (ret_val)
13484 			sme_err("Failed to set Tx beamformee cap");
13485 
13486 	}
13487 
13488 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]) {
13489 		cfg_val = nla_get_u8(tb[
13490 				     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]);
13491 		if (cfg_val) {
13492 			hdd_debug("Set HE mac padding dur to %d", cfg_val);
13493 			ret_val = sme_cli_set_command(
13494 					link_info->vdev_id,
13495 					wmi_vdev_param_mu_edca_fw_update_en,
13496 					0, VDEV_CMD);
13497 			if (ret_val)
13498 				hdd_err("MU_EDCA update disable failed");
13499 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
13500 			sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
13501 			if (sme_update_mu_edca_params(
13502 						hdd_ctx->mac_handle,
13503 						link_info->vdev_id))
13504 				hdd_err("Failed to send mu edca params");
13505 		} else {
13506 			ret_val = sme_cli_set_command(
13507 					link_info->vdev_id,
13508 					wmi_vdev_param_mu_edca_fw_update_en,
13509 					1, VDEV_CMD);
13510 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
13511 		}
13512 		ret_val = sme_update_he_trigger_frm_mac_pad(
13513 						    hdd_ctx->mac_handle,
13514 						    link_info->vdev_id,
13515 						    cfg_val);
13516 		if (ret_val)
13517 			hdd_err("Failed to set Trig frame mac padding cap");
13518 	}
13519 
13520 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]) {
13521 		cfg_val = nla_get_u8(tb[
13522 				     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]);
13523 		if (cfg_val) {
13524 			ret_val = sme_cli_set_command(
13525 					link_info->vdev_id,
13526 					wmi_vdev_param_mu_edca_fw_update_en,
13527 					0, VDEV_CMD);
13528 			if (ret_val)
13529 				hdd_err("MU_EDCA update disable failed");
13530 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
13531 			sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
13532 			if (sme_update_mu_edca_params(
13533 						hdd_ctx->mac_handle,
13534 						link_info->vdev_id))
13535 				hdd_err("Failed to send mu edca params");
13536 		} else {
13537 			ret_val = sme_cli_set_command(
13538 					link_info->vdev_id,
13539 					wmi_vdev_param_mu_edca_fw_update_en,
13540 					1, VDEV_CMD);
13541 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
13542 		}
13543 	}
13544 
13545 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]) {
13546 		cfg_val = nla_get_u8(tb[
13547 				     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]);
13548 		ret_val = sme_update_he_om_ctrl_supp(hdd_ctx->mac_handle,
13549 						     link_info->vdev_id,
13550 						     cfg_val);
13551 	}
13552 
13553 	cmd_id =
13554 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA;
13555 	if (tb[cmd_id]) {
13556 		cfg_val = nla_get_u8(tb[cmd_id]);
13557 		if (cfg_val)
13558 			status = ucfg_mlme_set_scan_probe_unicast_ra(
13559 							hdd_ctx->psoc, true);
13560 		else
13561 			status = ucfg_mlme_set_scan_probe_unicast_ra(
13562 							hdd_ctx->psoc, false);
13563 		if (!QDF_IS_STATUS_SUCCESS(status))
13564 			hdd_err("unable to set unicat probe ra cfg");
13565 	}
13566 
13567 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OMI_TX;
13568 	if (tb[cmd_id]) {
13569 		struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_OMI_MAX + 1];
13570 		struct nlattr *curr_attr;
13571 		int tmp, rc;
13572 		struct omi_ctrl_tx omi_data = {0};
13573 
13574 		nla_for_each_nested(curr_attr, tb[cmd_id], tmp) {
13575 			rc = wlan_cfg80211_nla_parse(
13576 					tb2, QCA_WLAN_VENDOR_ATTR_OMI_MAX,
13577 					nla_data(curr_attr),
13578 					nla_len(curr_attr),
13579 					qca_wlan_vendor_attr_omi_tx_policy);
13580 			if (rc) {
13581 				hdd_err("Invalid ATTR");
13582 				goto send_err;
13583 			}
13584 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW;
13585 			if (tb2[cmd_id]) {
13586 				cfg_val = nla_get_u8(tb2[cmd_id]);
13587 				ret_val = sme_set_he_om_ctrl_param(
13588 						    hdd_ctx->mac_handle,
13589 						    link_info->vdev_id,
13590 						    cmd_id, cfg_val);
13591 			}
13592 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS;
13593 			if (tb2[cmd_id]) {
13594 				cfg_val = nla_get_u8(tb2[cmd_id]);
13595 				ret_val = sme_set_he_om_ctrl_param(
13596 						    hdd_ctx->mac_handle,
13597 						    link_info->vdev_id,
13598 						    cmd_id, cfg_val);
13599 			}
13600 
13601 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE;
13602 			if (tb2[cmd_id]) {
13603 				cfg_val = nla_get_u8(tb2[cmd_id]);
13604 				ret_val = sme_set_he_om_ctrl_param(
13605 						    hdd_ctx->mac_handle,
13606 						    link_info->vdev_id,
13607 						    cmd_id, cfg_val);
13608 			}
13609 
13610 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS;
13611 			if (tb2[cmd_id]) {
13612 				cfg_val = nla_get_u8(tb2[cmd_id]);
13613 				ret_val = sme_set_he_om_ctrl_param(
13614 						    hdd_ctx->mac_handle,
13615 						    link_info->vdev_id,
13616 						    cmd_id, cfg_val);
13617 			}
13618 
13619 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE;
13620 			if (tb2[cmd_id]) {
13621 				cfg_val = nla_get_u8(tb2[cmd_id]);
13622 				ret_val = sme_set_he_om_ctrl_param(
13623 						    hdd_ctx->mac_handle,
13624 						    link_info->vdev_id,
13625 						    cmd_id, cfg_val);
13626 			}
13627 
13628 			cmd_id = QCA_WLAN_VENDOR_ATTR_EHT_OMI_RX_NSS_EXTN;
13629 			if (tb2[cmd_id]) {
13630 				cfg_val = nla_get_u8(tb2[cmd_id]);
13631 				hdd_debug("EHT OM ctrl Rx Nss %d", cfg_val);
13632 				omi_data.eht_rx_nss_ext = cfg_val;
13633 			}
13634 
13635 			cmd_id = QCA_WLAN_VENDOR_ATTR_EHT_OMI_CH_BW_EXTN;
13636 			if (tb2[cmd_id]) {
13637 				cfg_val = nla_get_u8(tb2[cmd_id]);
13638 				hdd_debug("Set EHT OM ctrl BW to %d", cfg_val);
13639 				omi_data.eht_ch_bw_ext = cfg_val;
13640 			}
13641 
13642 			cmd_id = QCA_WLAN_VENDOR_ATTR_EHT_OMI_TX_NSS_EXTN;
13643 			if (tb2[cmd_id]) {
13644 				cfg_val = nla_get_u8(tb2[cmd_id]);
13645 				hdd_debug("EHT OM ctrl Tx Nss %d", cfg_val);
13646 				omi_data.eht_tx_nss_ext = cfg_val;
13647 			}
13648 		}
13649 
13650 		if (ret_val) {
13651 			sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
13652 			goto send_err;
13653 		}
13654 		ret_val = sme_send_he_om_ctrl_update(hdd_ctx->mac_handle,
13655 						     link_info->vdev_id,
13656 						     &omi_data);
13657 	}
13658 
13659 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG])
13660 		sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
13661 
13662 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU;
13663 	if (tb[cmd_id]) {
13664 		int i;
13665 		enum wlan_eht_mode eht_mode;
13666 		uint8_t op_mode;
13667 
13668 		cfg_val = nla_get_u8(tb[cmd_id]);
13669 		ucfg_mlme_get_eht_mode(hdd_ctx->psoc, &eht_mode);
13670 		if (eht_mode == WLAN_EHT_MODE_MLMR ||
13671 		    eht_mode == WLAN_EHT_MODE_MLSR ||
13672 		    eht_mode == WLAN_EHT_MODE_EMLSR) {
13673 			for (i = 0; i < WLAN_MAX_VDEVS; i++) {
13674 				op_mode = wlan_get_opmode_from_vdev_id(
13675 						hdd_ctx->pdev, i);
13676 				if (op_mode != QDF_STA_MODE) {
13677 					hdd_debug("vdev_id %d is not STA", i);
13678 					continue;
13679 				}
13680 				hdd_debug("Tx SU PPDU enable %d, vdev_id %d",
13681 					  cfg_val, i);
13682 				if (cfg_val)
13683 					sme_config_su_ppdu_queue(i, true);
13684 				else
13685 					sme_config_su_ppdu_queue(i, false);
13686 			}
13687 		} else {
13688 			if (cfg_val)
13689 				sme_config_su_ppdu_queue(link_info->vdev_id,
13690 							 true);
13691 			else
13692 				sme_config_su_ppdu_queue(link_info->vdev_id,
13693 							 false);
13694 		}
13695 	}
13696 
13697 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT;
13698 	if (tb[cmd_id]) {
13699 		cfg_val = nla_get_u8(tb[cmd_id]);
13700 		hdd_debug("Configure 2G VHT support %d", cfg_val);
13701 		ucfg_mlme_set_vht_for_24ghz(hdd_ctx->psoc,
13702 					    (cfg_val ? true : false));
13703 	}
13704 
13705 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP;
13706 	if (tb[cmd_id]) {
13707 		cfg_val = nla_get_u8(tb[cmd_id]);
13708 		hdd_debug("Configure +HTC_HE support %d", cfg_val);
13709 		sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
13710 					  link_info->vdev_id,
13711 					  (cfg_val ? true : false));
13712 	}
13713 
13714 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX;
13715 	if (tb[cmd_id]) {
13716 		cfg_val = nla_get_u8(tb[cmd_id]);
13717 		hdd_debug("Configure Punctured preamble Rx %d", cfg_val);
13718 		ret_val = sme_update_he_capabilities(mac_handle,
13719 						     link_info->vdev_id,
13720 						     cfg_val, cmd_id);
13721 		if (ret_val)
13722 			sme_err("Failed to update HE cap");
13723 	}
13724 
13725 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS;
13726 	if (tb[cmd_id]) {
13727 		hdd_disable_runtime_pm_for_user(hdd_ctx);
13728 		cfg_val = nla_get_u8(tb[cmd_id]);
13729 		hdd_debug("Configure HE testbed defaults %d", cfg_val);
13730 		if (!cfg_val)
13731 			sme_reset_he_caps(hdd_ctx->mac_handle,
13732 					  link_info->vdev_id);
13733 		else
13734 			sme_set_he_testbed_def(hdd_ctx->mac_handle,
13735 					       link_info->vdev_id);
13736 	}
13737 
13738 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU;
13739 	if (tb[cmd_id]) {
13740 		cfg_val = nla_get_u8(tb[cmd_id]);
13741 		hdd_debug("Configure Action frame Tx in TB PPDU %d", cfg_val);
13742 		sme_config_action_tx_in_tb_ppdu(hdd_ctx->mac_handle,
13743 						link_info->vdev_id,
13744 						cfg_val);
13745 	}
13746 
13747 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP]) {
13748 		ret_val = hdd_test_config_twt_setup_session(adapter, tb);
13749 		if (ret_val)
13750 			goto send_err;
13751 	}
13752 
13753 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE]) {
13754 		ret_val = hdd_test_config_twt_terminate_session(adapter, tb);
13755 		if (ret_val)
13756 			goto send_err;
13757 	}
13758 
13759 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT;
13760 	if (tb[cmd_id]) {
13761 		cfg_val = nla_get_u8(tb[cmd_id]);
13762 		hdd_debug("twt_request: val %d", cfg_val);
13763 		ret_val = sme_update_he_twt_req_support(
13764 						hdd_ctx->mac_handle,
13765 						link_info->vdev_id,
13766 						cfg_val);
13767 	}
13768 
13769 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO;
13770 	if (tb[cmd_id]) {
13771 		cfg_val = nla_get_u8(tb[cmd_id]);
13772 		ini_val = cfg_get(hdd_ctx->psoc, CFG_HE_UL_MUMIMO);
13773 		hdd_debug("fullbw_ulmumimo: cfg %d, ini %d", cfg_val, ini_val);
13774 		if (cfg_val) {
13775 			switch (ini_val) {
13776 			case CFG_NO_SUPPORT_UL_MUMIMO:
13777 			case CFG_FULL_BW_SUPPORT_UL_MUMIMO:
13778 				cfg_val = CFG_FULL_BW_SUPPORT_UL_MUMIMO;
13779 				break;
13780 			case CFG_PARTIAL_BW_SUPPORT_UL_MUMIMO:
13781 			case CFG_FULL_PARTIAL_BW_SUPPORT_UL_MUMIMO:
13782 				cfg_val = CFG_FULL_PARTIAL_BW_SUPPORT_UL_MUMIMO;
13783 				break;
13784 			}
13785 		} else {
13786 			switch (ini_val) {
13787 			case CFG_NO_SUPPORT_UL_MUMIMO:
13788 			case CFG_FULL_BW_SUPPORT_UL_MUMIMO:
13789 				cfg_val = CFG_NO_SUPPORT_UL_MUMIMO;
13790 				break;
13791 			case CFG_PARTIAL_BW_SUPPORT_UL_MUMIMO:
13792 			case CFG_FULL_PARTIAL_BW_SUPPORT_UL_MUMIMO:
13793 				cfg_val = CFG_PARTIAL_BW_SUPPORT_UL_MUMIMO;
13794 				break;
13795 			}
13796 		}
13797 		ret_val = sme_update_he_full_ul_mumimo(
13798 						hdd_ctx->mac_handle,
13799 						link_info->vdev_id,
13800 						cfg_val);
13801 	}
13802 
13803 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX;
13804 	if (tb[cmd_id]) {
13805 		cfg_val = nla_get_u8(tb[cmd_id]);
13806 		hdd_debug("disable Tx cfg: val %d", cfg_val);
13807 		sme_set_cfg_disable_tx(hdd_ctx->mac_handle,
13808 				       link_info->vdev_id, cfg_val);
13809 	}
13810 
13811 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION;
13812 	if (tb[cmd_id]) {
13813 		cfg_val = nla_get_u8(tb[cmd_id]);
13814 		hdd_debug("pmf cfg: val %d", cfg_val);
13815 		sme_set_pmf_wep_cfg(hdd_ctx->mac_handle, cfg_val);
13816 	}
13817 
13818 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD;
13819 	if (tb[cmd_id]) {
13820 		cfg_val = nla_get_u16(tb[cmd_id]);
13821 		hdd_debug("bss max idle period %d", cfg_val);
13822 		sme_set_bss_max_idle_period(hdd_ctx->mac_handle, cfg_val);
13823 	}
13824 
13825 	cmd_id =
13826 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE;
13827 	if (tb[cmd_id]) {
13828 		cfg_val = nla_get_u8(tb[cmd_id]);
13829 		if (cfg_val)
13830 			ucfg_mlme_get_sta_keep_alive_period(
13831 							hdd_ctx->psoc,
13832 							&bss_max_idle_period);
13833 		hdd_debug("bss max idle period %d", bss_max_idle_period);
13834 		sme_set_bss_max_idle_period(hdd_ctx->mac_handle,
13835 					    bss_max_idle_period);
13836 	}
13837 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX;
13838 	if (tb[cmd_id]) {
13839 		hdd_info("Send disassoc mgmt frame");
13840 		sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
13841 					    link_info->vdev_id,
13842 					    hdd_sta_ctx->conn_info.bssid.bytes,
13843 					    1, false);
13844 	}
13845 
13846 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX;
13847 	if (tb[cmd_id]) {
13848 		cfg_val = nla_get_u8(tb[cmd_id]);
13849 		hdd_info("RU 242 tone Tx enable: %d", cfg_val);
13850 		sme_set_ru_242_tone_tx_cfg(hdd_ctx->mac_handle, cfg_val);
13851 		if (cfg_val)
13852 			hdd_update_channel_width(
13853 					adapter, eHT_CHANNEL_WIDTH_20MHZ,
13854 					WNI_CFG_CHANNEL_BONDING_MODE_DISABLE,
13855 					link_id);
13856 	}
13857 
13858 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE;
13859 	if (tb[cmd_id]) {
13860 		cfg_val = nla_get_u8(tb[cmd_id]);
13861 		hdd_debug("EU SU PPDU type Tx enable: %d", cfg_val);
13862 		if (cfg_val) {
13863 			hdd_update_channel_width(
13864 					adapter, eHT_CHANNEL_WIDTH_20MHZ,
13865 					WNI_CFG_CHANNEL_BONDING_MODE_DISABLE,
13866 					link_id);
13867 			hdd_set_tx_stbc(link_info, 0);
13868 			hdd_set_11ax_rate(adapter, 0x400, NULL);
13869 			status = wma_cli_set_command(
13870 					link_info->vdev_id,
13871 					wmi_vdev_param_he_range_ext,
13872 					1, VDEV_CMD);
13873 			if (QDF_IS_STATUS_ERROR(status))
13874 				hdd_err("failed to set HE_RANGE_EXT, %d",
13875 					status);
13876 			status = wma_cli_set_command(
13877 					link_info->vdev_id,
13878 					wmi_vdev_param_non_data_he_range_ext,
13879 					1, VDEV_CMD);
13880 			if (QDF_IS_STATUS_ERROR(status))
13881 				hdd_err("fail to set NON_DATA_HE_RANGE_EXT %d",
13882 					status);
13883 		} else {
13884 			hdd_update_channel_width(
13885 					adapter, eHT_CHANNEL_WIDTH_160MHZ,
13886 					link_id,
13887 					WNI_CFG_CHANNEL_BONDING_MODE_ENABLE);
13888 			hdd_set_tx_stbc(link_info, 1);
13889 			hdd_set_11ax_rate(adapter, 0xFFFF, NULL);
13890 			status = wma_cli_set_command(
13891 					link_info->vdev_id,
13892 					wmi_vdev_param_he_range_ext,
13893 					0, VDEV_CMD);
13894 			if (QDF_IS_STATUS_ERROR(status))
13895 				hdd_err("failed to set HE_RANGE_EXT, %d",
13896 					status);
13897 			status = wma_cli_set_command(
13898 					link_info->vdev_id,
13899 					wmi_vdev_param_non_data_he_range_ext,
13900 					0, VDEV_CMD);
13901 			if (QDF_IS_STATUS_ERROR(status))
13902 				hdd_err("fail to set NON_DATA_HE_RANGE_EXT %d",
13903 					status);
13904 		}
13905 
13906 	}
13907 
13908 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED;
13909 	if (tb[cmd_id]) {
13910 		wfa_param.vdev_id = link_info->vdev_id;
13911 		wfa_param.value = nla_get_u8(tb[cmd_id]);
13912 
13913 		if (wfa_param.value < RSNXE_DEFAULT ||
13914 		    wfa_param.value > RSNXE_OVERRIDE_2) {
13915 			hdd_debug("Invalid RSNXE override %d", wfa_param.value);
13916 			goto send_err;
13917 		}
13918 		wfa_param.cmd = WFA_CONFIG_RXNE;
13919 		hdd_info("send wfa test config RXNE used %d", wfa_param.value);
13920 
13921 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
13922 						&wfa_param);
13923 	}
13924 
13925 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA;
13926 	if (tb[cmd_id]) {
13927 		wfa_param.vdev_id = link_info->vdev_id;
13928 		wfa_param.value = nla_get_u8(tb[cmd_id]);
13929 
13930 		if (wfa_param.value != CSA_DEFAULT &&
13931 		    wfa_param.value != CSA_IGNORE) {
13932 			hdd_debug("Invalid CSA config %d", wfa_param.value);
13933 			goto send_err;
13934 		}
13935 		wfa_param.cmd = WFA_CONFIG_CSA;
13936 		hdd_info("send wfa test config CSA used %d", wfa_param.value);
13937 
13938 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
13939 						&wfa_param);
13940 	}
13941 
13942 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE;
13943 	if (tb[cmd_id]) {
13944 		ret_val = hdd_test_config_6ghz_security_test_mode(hdd_ctx,
13945 								  tb[cmd_id]);
13946 		if (ret_val)
13947 			goto send_err;
13948 	}
13949 
13950 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE;
13951 	if (tb[cmd_id]) {
13952 		struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX + 1];
13953 
13954 		wfa_param.vdev_id = link_info->vdev_id;
13955 		wfa_param.cmd = WFA_CONFIG_OCV;
13956 		if (wlan_cfg80211_nla_parse_nested(
13957 				tb2, QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX,
13958 				tb[cmd_id], wlan_oci_override_policy)) {
13959 			hdd_debug("Failed to parse OCI override");
13960 			goto send_err;
13961 		}
13962 
13963 		if (!(tb2[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE] &&
13964 		      tb2[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY])) {
13965 			hdd_debug("Invalid ATTR FRAME_TYPE/FREQUENCY");
13966 			goto send_err;
13967 		}
13968 
13969 		wfa_param.ocv_param = qdf_mem_malloc(
13970 				sizeof(struct ocv_wfatest_params));
13971 		if (!wfa_param.ocv_param) {
13972 			hdd_err("Failed to alloc memory for ocv param");
13973 			goto send_err;
13974 		}
13975 
13976 		cmd_id = QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE;
13977 		switch (nla_get_u8(tb2[cmd_id])) {
13978 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ:
13979 			wfa_param.ocv_param->frame_type =
13980 				WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_SAQUERY_REQ;
13981 			break;
13982 
13983 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP:
13984 			wfa_param.ocv_param->frame_type =
13985 				WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_SAQUERY_RSP;
13986 			break;
13987 
13988 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ:
13989 			wfa_param.ocv_param->frame_type =
13990 				WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_FT_REASSOC_REQ;
13991 			break;
13992 
13993 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FILS_REASSOC_REQ:
13994 			wfa_param.ocv_param->frame_type =
13995 			WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_FILS_REASSOC_REQ;
13996 			break;
13997 
13998 		default:
13999 			hdd_debug("Invalid frame type for ocv test config %d",
14000 				  nla_get_u8(tb2[cmd_id]));
14001 			qdf_mem_free(wfa_param.ocv_param);
14002 				goto send_err;
14003 		}
14004 
14005 		cmd_id = QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY;
14006 		wfa_param.ocv_param->freq = nla_get_u32(tb2[cmd_id]);
14007 
14008 		if (!WLAN_REG_IS_24GHZ_CH_FREQ(wfa_param.ocv_param->freq) &&
14009 		    !WLAN_REG_IS_5GHZ_CH_FREQ(wfa_param.ocv_param->freq) &&
14010 		    !WLAN_REG_IS_6GHZ_CHAN_FREQ(wfa_param.ocv_param->freq)) {
14011 			hdd_debug("Invalid Freq %d", wfa_param.ocv_param->freq);
14012 			qdf_mem_free(wfa_param.ocv_param);
14013 			goto send_err;
14014 		}
14015 
14016 		hdd_info("send wfa test config OCV frame type %d freq %d",
14017 			 wfa_param.ocv_param->frame_type,
14018 			 wfa_param.ocv_param->freq);
14019 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14020 						&wfa_param);
14021 		qdf_mem_free(wfa_param.ocv_param);
14022 	}
14023 
14024 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT;
14025 	if (tb[cmd_id]) {
14026 		wfa_param.vdev_id = link_info->vdev_id;
14027 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14028 
14029 		if (wfa_param.value != SA_QUERY_TIMEOUT_DEFAULT &&
14030 		    wfa_param.value != SA_QUERY_TIMEOUT_IGNORE) {
14031 			hdd_debug("Invalid SA query timeout config %d",
14032 				  wfa_param.value);
14033 			goto send_err;
14034 		}
14035 		wfa_param.cmd = WFA_CONFIG_SA_QUERY;
14036 		hdd_info("send wfa test config SAquery %d", wfa_param.value);
14037 
14038 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14039 						&wfa_param);
14040 	}
14041 
14042 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX;
14043 	if (tb[cmd_id] && adapter->device_mode == QDF_SAP_MODE) {
14044 		wfa_param.vdev_id = link_info->vdev_id;
14045 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14046 
14047 		if (!(wfa_param.value == FILS_DISCV_FRAMES_DISABLE ||
14048 		      wfa_param.value == FILS_DISCV_FRAMES_ENABLE)) {
14049 			hdd_debug("Invalid FILS_DISCV_FRAMES config %d",
14050 				  wfa_param.value);
14051 			goto send_err;
14052 		}
14053 		wfa_param.cmd = WFA_FILS_DISCV_FRAMES;
14054 		hdd_info("send wfa FILS_DISCV_FRAMES TX config %d",
14055 			 wfa_param.value);
14056 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14057 						&wfa_param);
14058 	}
14059 
14060 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE;
14061 	if (tb[cmd_id]) {
14062 		wfa_param.vdev_id = link_info->vdev_id;
14063 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14064 
14065 		if (!(wfa_param.value == H2E_RSNXE_DEFAULT ||
14066 		      wfa_param.value == H2E_RSNXE_IGNORE)) {
14067 			hdd_debug("Invalid RSNXE_IGNORE config %d",
14068 				  wfa_param.value);
14069 			goto send_err;
14070 		}
14071 		wfa_param.cmd = WFA_IGNORE_H2E_RSNXE;
14072 		hdd_info("send wfa WFA_IGNORE_H2E_RSNXE config %d",
14073 			 wfa_param.value);
14074 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14075 						&wfa_param);
14076 	}
14077 
14078 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_11BE_EMLSR_MODE;
14079 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14080 		cfg_val = nla_get_u8(tb[cmd_id]);
14081 
14082 		ret_val = hdd_test_config_emlsr_mode(hdd_ctx, cfg_val);
14083 	}
14084 
14085 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BEAMFORMER_PERIODIC_SOUNDING;
14086 	if (tb[cmd_id]) {
14087 		cfg_val = nla_get_u8(tb[cmd_id]);
14088 
14089 		set_val = cfg_val ? TX_BFER_NDP_PERIODICITY : 0;
14090 
14091 		ret_val = wma_cli_set_command(
14092 					link_info->vdev_id,
14093 					WMI_PDEV_PARAM_TXBF_SOUND_PERIOD_CMDID,
14094 					set_val, PDEV_CMD);
14095 	}
14096 
14097 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_80MHZ;
14098 	if (tb[cmd_id]) {
14099 		cfg_val = nla_get_u8(tb[cmd_id]);
14100 		hdd_debug("Configure Tx BF < 80 MHz: %d", cfg_val);
14101 
14102 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14103 					      cfg_val, EHT_TX_BFEE_SS_80MHZ,
14104 					      adapter->device_mode);
14105 		if (ret_val)
14106 			sme_err("Failed to update EHT Tx BFEE cap");
14107 	}
14108 
14109 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_160MHZ;
14110 	if (tb[cmd_id]) {
14111 		cfg_val = nla_get_u8(tb[cmd_id]);
14112 		hdd_debug("Configure Tx BF for 160 MHz: %d", cfg_val);
14113 
14114 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14115 					      cfg_val, EHT_TX_BFEE_SS_160MHZ,
14116 					      adapter->device_mode);
14117 		if (ret_val)
14118 			sme_err("Failed to update EHT Tx BFEE cap");
14119 	}
14120 
14121 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_320MHZ;
14122 	if (tb[cmd_id]) {
14123 		cfg_val = nla_get_u8(tb[cmd_id]);
14124 		hdd_debug("Configure Tx BF for 320 MHz: %d", cfg_val);
14125 
14126 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14127 					      cfg_val, EHT_TX_BFEE_SS_320MHZ,
14128 					      adapter->device_mode);
14129 		if (ret_val)
14130 			sme_err("Failed to update EHT Tx BFEE cap");
14131 	}
14132 
14133 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EXCLUDE_STA_PROF_IN_PROBE_REQ;
14134 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14135 		cfg_val = nla_get_u8(tb[cmd_id]);
14136 
14137 		if (cfg_val) {
14138 			wlan_vdev_obj_lock(link_info->vdev);
14139 			wlan_vdev_mlme_cap_set(
14140 					link_info->vdev,
14141 					WLAN_VDEV_C_EXCL_STA_PROF_PRB_REQ);
14142 			wlan_vdev_obj_unlock(link_info->vdev);
14143 		} else {
14144 			wlan_vdev_obj_lock(link_info->vdev);
14145 			wlan_vdev_mlme_cap_clear(
14146 					link_info->vdev,
14147 					WLAN_VDEV_C_EXCL_STA_PROF_PRB_REQ);
14148 			wlan_vdev_obj_unlock(link_info->vdev);
14149 		}
14150 		hdd_debug("Sta profile in Probe req frame: %d", cfg_val);
14151 	}
14152 
14153 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_EHT_TESTBED_DEFAULTS;
14154 	if (tb[cmd_id]) {
14155 		cfg_val = nla_get_u8(tb[cmd_id]);
14156 		hdd_debug("Configure EHT testbed defaults %d", cfg_val);
14157 		if (!cfg_val)
14158 			sme_reset_eht_caps(hdd_ctx->mac_handle,
14159 					   link_info->vdev_id);
14160 		else
14161 			sme_set_eht_testbed_def(hdd_ctx->mac_handle,
14162 						link_info->vdev_id);
14163 
14164 		sme_set_vdev_ies_per_band(hdd_ctx->mac_handle,
14165 					  link_info->vdev_id,
14166 					  adapter->device_mode);
14167 	}
14168 
14169 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MCS;
14170 	if (tb[cmd_id]) {
14171 		cfg_val = nla_get_u8(tb[cmd_id]);
14172 		sme_update_eht_cap_mcs(hdd_ctx->mac_handle, link_info->vdev_id,
14173 				       cfg_val);
14174 		sme_set_vdev_ies_per_band(hdd_ctx->mac_handle,
14175 					  link_info->vdev_id,
14176 					  adapter->device_mode);
14177 	}
14178 
14179 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_TB_SOUNDING_FB_RL;
14180 	if (tb[cmd_id]) {
14181 		cfg_val = nla_get_u8(tb[cmd_id]);
14182 		hdd_debug("Configure TB sounding feedback rate limit: %d",
14183 			  cfg_val);
14184 
14185 		ret_val = sme_update_eht_caps(
14186 					mac_handle, link_info->vdev_id,
14187 					cfg_val,
14188 					EHT_TX_BFEE_SOUNDING_FEEDBACK_RATELIMIT,
14189 					adapter->device_mode);
14190 		if (ret_val)
14191 			sme_err("Failed to update EHT Tx BFEE cap");
14192 	}
14193 
14194 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_OM_CTRL_SUPPORT;
14195 	if (tb[cmd_id]) {
14196 		cfg_val = nla_get_u8(tb[cmd_id]);
14197 		hdd_debug("EHT OM control support: %d", cfg_val);
14198 
14199 		ret_val = sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
14200 						    link_info->vdev_id,
14201 						    true);
14202 		if (ret_val)
14203 			hdd_err("Could not set htc_he");
14204 
14205 		ret_val = sme_update_eht_om_ctrl_supp(hdd_ctx->mac_handle,
14206 						      link_info->vdev_id,
14207 						      cfg_val);
14208 		if (ret_val)
14209 			hdd_err("Could not update EHT OM control fields");
14210 	}
14211 
14212 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EMLSR_PADDING_DELAY;
14213 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14214 		cfg_val = nla_get_u8(tb[cmd_id]);
14215 		hdd_debug("Configure EMLSR padding delay subfield to %d",
14216 			  cfg_val);
14217 		if (cfg_val)
14218 			wlan_mlme_cfg_set_emlsr_pad_delay(hdd_ctx->psoc,
14219 							  cfg_val);
14220 	}
14221 
14222 	cmd_id =  QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FORCE_MLO_POWER_SAVE_BCN_PERIOD;
14223 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14224 		uint32_t bitmap = 0;
14225 		uint32_t vdev_id, idx;
14226 
14227 		cfg_val = nla_get_u8(tb[cmd_id]);
14228 		hdd_debug("Send vdev pause on ML sta vdev for %d beacon periods",
14229 			  cfg_val);
14230 		bitmap = policy_mgr_get_active_vdev_bitmap(hdd_ctx->psoc);
14231 		for (idx = 0; idx < 32; idx++) {
14232 			if (bitmap & (1 << idx)) {
14233 				vdev_id = idx;
14234 				ret_val = sme_send_vdev_pause_for_bcn_period(
14235 							mac_handle,
14236 							vdev_id, cfg_val);
14237 				if (ret_val)
14238 					sme_err("Failed to send vdev pause");
14239 			}
14240 		}
14241 	}
14242 
14243 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_STR_TX;
14244 	if (tb[cmd_id]) {
14245 		uint32_t arg[2];
14246 
14247 		hdd_debug("Send EHT MLO STR TX indication to FW");
14248 		arg[0] = 676;
14249 		arg[1] = 1;
14250 
14251 		ret_val = sme_send_unit_test_cmd(link_info->vdev_id,
14252 						 0x48, 2, arg);
14253 
14254 		if (ret_val)
14255 			sme_err("Failed to send STR TX indication");
14256 	}
14257 
14258 	if (update_sme_cfg)
14259 		sme_update_config(mac_handle, sme_config);
14260 
14261 send_err:
14262 	qdf_mem_free(sme_config);
14263 
14264 	return ret_val;
14265 }
14266 
14267 /**
14268  * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
14269  * vendor command
14270  *
14271  * @wiphy: wiphy device pointer
14272  * @wdev: wireless device pointer
14273  * @data: Vendor command data buffer
14274  * @data_len: Buffer length
14275  *
14276  * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
14277  *
14278  * Return: EOK or other error codes.
14279  */
14280 static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
14281 		struct wireless_dev *wdev, const void *data, int data_len)
14282 {
14283 	int errno;
14284 	struct osif_vdev_sync *vdev_sync;
14285 
14286 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
14287 	if (errno)
14288 		return errno;
14289 
14290 	errno = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
14291 							 data, data_len);
14292 
14293 	osif_vdev_sync_op_stop(vdev_sync);
14294 
14295 	return errno;
14296 }
14297 
14298 const struct nla_policy qca_wlan_vendor_wifi_logger_start_policy[
14299 		QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
14300 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
14301 		= {.type = NLA_U32 },
14302 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
14303 		= {.type = NLA_U32 },
14304 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
14305 		= {.type = NLA_U32 },
14306 };
14307 
14308 /**
14309  * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
14310  * or disable the collection of packet statistics from the firmware
14311  * @wiphy:    WIPHY structure pointer
14312  * @wdev:     Wireless device structure pointer
14313  * @data:     Pointer to the data received
14314  * @data_len: Length of the data received
14315  *
14316  * This function enables or disables the collection of packet statistics from
14317  * the firmware
14318  *
14319  * Return: 0 on success and errno on failure
14320  */
14321 static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
14322 		struct wireless_dev *wdev,
14323 		const void *data,
14324 		int data_len)
14325 {
14326 	QDF_STATUS status;
14327 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
14328 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
14329 	struct sir_wifi_start_log start_log = { 0 };
14330 	mac_handle_t mac_handle;
14331 
14332 	hdd_enter_dev(wdev->netdev);
14333 
14334 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
14335 		hdd_err("Command not allowed in FTM mode");
14336 		return -EPERM;
14337 	}
14338 
14339 	status = wlan_hdd_validate_context(hdd_ctx);
14340 	if (status)
14341 		return status;
14342 
14343 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
14344 		hdd_err("Driver Modules are closed, can not start logger");
14345 		return -EINVAL;
14346 	}
14347 
14348 	if (wlan_cfg80211_nla_parse(tb,
14349 				    QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
14350 				    data, data_len,
14351 				    qca_wlan_vendor_wifi_logger_start_policy)) {
14352 		hdd_err("Invalid attribute");
14353 		return -EINVAL;
14354 	}
14355 
14356 	/* Parse and fetch ring id */
14357 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
14358 		hdd_err("attr ATTR failed");
14359 		return -EINVAL;
14360 	}
14361 	start_log.ring_id = nla_get_u32(
14362 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
14363 	hdd_debug("Ring ID=%d", start_log.ring_id);
14364 
14365 	/* Parse and fetch verbose level */
14366 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
14367 		hdd_err("attr verbose_level failed");
14368 		return -EINVAL;
14369 	}
14370 	start_log.verbose_level = nla_get_u32(
14371 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
14372 	hdd_debug("verbose_level=%d", start_log.verbose_level);
14373 
14374 	/* Parse and fetch flag */
14375 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
14376 		hdd_err("attr flag failed");
14377 		return -EINVAL;
14378 	}
14379 	start_log.is_iwpriv_command = nla_get_u32(
14380 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
14381 
14382 	start_log.user_triggered = 1;
14383 
14384 	/* size is buff size which can be set using iwpriv command*/
14385 	start_log.size = 0;
14386 	start_log.is_pktlog_buff_clear = false;
14387 
14388 	cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
14389 
14390 	if (start_log.ring_id == RING_ID_WAKELOCK) {
14391 		/* Start/stop wakelock events */
14392 		if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
14393 			cds_set_wakelock_logging(true);
14394 		else
14395 			cds_set_wakelock_logging(false);
14396 		return 0;
14397 	}
14398 
14399 	if (start_log.ring_id == RING_ID_PER_PACKET_STATS) {
14400 		if (hdd_ctx->is_pktlog_enabled &&
14401 		    (start_log.verbose_level == WLAN_LOG_LEVEL_ACTIVE))
14402 			return 0;
14403 
14404 		if ((!hdd_ctx->is_pktlog_enabled) &&
14405 		    (start_log.verbose_level != WLAN_LOG_LEVEL_ACTIVE))
14406 			return 0;
14407 	}
14408 
14409 	mac_handle = hdd_ctx->mac_handle;
14410 	status = sme_wifi_start_logger(mac_handle, start_log);
14411 	if (!QDF_IS_STATUS_SUCCESS(status)) {
14412 		hdd_err("sme_wifi_start_logger failed(err=%d)",
14413 				status);
14414 		return -EINVAL;
14415 	}
14416 
14417 	if (start_log.ring_id == RING_ID_PER_PACKET_STATS) {
14418 		if (start_log.verbose_level == WLAN_LOG_LEVEL_ACTIVE)
14419 			hdd_ctx->is_pktlog_enabled = true;
14420 		else
14421 			hdd_ctx->is_pktlog_enabled = false;
14422 	}
14423 
14424 	return 0;
14425 }
14426 
14427 /**
14428  * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
14429  * or disable the collection of packet statistics from the firmware
14430  * @wiphy:    WIPHY structure pointer
14431  * @wdev:     Wireless device structure pointer
14432  * @data:     Pointer to the data received
14433  * @data_len: Length of the data received
14434  *
14435  * This function is used to enable or disable the collection of packet
14436  * statistics from the firmware
14437  *
14438  * Return: 0 on success and errno on failure
14439  */
14440 static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
14441 		struct wireless_dev *wdev,
14442 		const void *data,
14443 		int data_len)
14444 {
14445 	struct osif_psoc_sync *psoc_sync;
14446 	int errno;
14447 
14448 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
14449 	if (errno)
14450 		return errno;
14451 
14452 	errno = __wlan_hdd_cfg80211_wifi_logger_start(wiphy, wdev,
14453 						      data, data_len);
14454 
14455 	osif_psoc_sync_op_stop(psoc_sync);
14456 
14457 	return errno;
14458 }
14459 
14460 const struct nla_policy qca_wlan_vendor_wifi_logger_get_ring_data_policy[
14461 		QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
14462 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
14463 		= {.type = NLA_U32 },
14464 };
14465 
14466 /**
14467  * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
14468  * @wiphy:    WIPHY structure pointer
14469  * @wdev:     Wireless device structure pointer
14470  * @data:     Pointer to the data received
14471  * @data_len: Length of the data received
14472  *
14473  * This function is used to flush or retrieve the per packet statistics from
14474  * the driver
14475  *
14476  * Return: 0 on success and errno on failure
14477  */
14478 static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
14479 		struct wireless_dev *wdev,
14480 		const void *data,
14481 		int data_len)
14482 {
14483 	QDF_STATUS status;
14484 	uint32_t ring_id;
14485 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
14486 	struct nlattr *tb
14487 		[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
14488 
14489 	hdd_enter();
14490 
14491 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
14492 		hdd_err("Command not allowed in FTM mode");
14493 		return -EPERM;
14494 	}
14495 
14496 	status = wlan_hdd_validate_context(hdd_ctx);
14497 	if (status)
14498 		return status;
14499 
14500 	if (wlan_cfg80211_nla_parse(tb,
14501 			    QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
14502 			    data, data_len,
14503 			    qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
14504 		hdd_err("Invalid attribute");
14505 		return -EINVAL;
14506 	}
14507 
14508 	/* Parse and fetch ring id */
14509 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
14510 		hdd_err("attr ATTR failed");
14511 		return -EINVAL;
14512 	}
14513 
14514 	ring_id = nla_get_u32(
14515 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
14516 
14517 	if (ring_id == RING_ID_PER_PACKET_STATS) {
14518 		wlan_logging_set_per_pkt_stats();
14519 		hdd_debug("Flushing/Retrieving packet stats");
14520 	} else if (ring_id == RING_ID_DRIVER_DEBUG) {
14521 		/*
14522 		 * As part of DRIVER ring ID, flush both driver and fw logs.
14523 		 * For other Ring ID's driver doesn't have any rings to flush
14524 		 */
14525 		hdd_debug("Bug report triggered by framework");
14526 
14527 		status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
14528 				WLAN_LOG_INDICATOR_FRAMEWORK,
14529 				WLAN_LOG_REASON_CODE_UNUSED,
14530 				false, false);
14531 		if (QDF_STATUS_SUCCESS != status) {
14532 			hdd_err("Failed to trigger bug report");
14533 			return -EINVAL;
14534 		}
14535 		status = wlan_logging_wait_for_flush_log_completion();
14536 		if (!QDF_IS_STATUS_SUCCESS(status)) {
14537 			hdd_err("wait for flush log timed out");
14538 			return qdf_status_to_os_return(status);
14539 		}
14540 	} else {
14541 		wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
14542 					   WLAN_LOG_INDICATOR_FRAMEWORK,
14543 					   WLAN_LOG_REASON_CODE_UNUSED,
14544 					   ring_id);
14545 	}
14546 	return 0;
14547 }
14548 
14549 /**
14550  * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
14551  * @wiphy:    WIPHY structure pointer
14552  * @wdev:     Wireless device structure pointer
14553  * @data:     Pointer to the data received
14554  * @data_len: Length of the data received
14555  *
14556  * This function is used to flush or retrieve the per packet statistics from
14557  * the driver
14558  *
14559  * Return: 0 on success and errno on failure
14560  */
14561 static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
14562 		struct wireless_dev *wdev,
14563 		const void *data,
14564 		int data_len)
14565 {
14566 	struct osif_psoc_sync *psoc_sync;
14567 	int errno;
14568 
14569 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
14570 	if (errno)
14571 		return errno;
14572 
14573 	errno = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy, wdev,
14574 							      data, data_len);
14575 
14576 	osif_psoc_sync_op_stop(psoc_sync);
14577 
14578 	return errno;
14579 }
14580 
14581 #ifdef WLAN_FEATURE_OFFLOAD_PACKETS
14582 /**
14583  * hdd_map_req_id_to_pattern_id() - map request id to pattern id
14584  * @hdd_ctx: HDD context
14585  * @request_id: [input] request id
14586  * @pattern_id: [output] pattern id
14587  *
14588  * This function loops through request id to pattern id array
14589  * if the slot is available, store the request id and return pattern id
14590  * if entry exists, return the pattern id
14591  *
14592  * Return: 0 on success and errno on failure
14593  */
14594 static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
14595 					  uint32_t request_id,
14596 					  uint8_t *pattern_id)
14597 {
14598 	uint32_t i;
14599 
14600 	mutex_lock(&hdd_ctx->op_ctx.op_lock);
14601 	for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
14602 		if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
14603 			hdd_ctx->op_ctx.op_table[i].request_id = request_id;
14604 			*pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
14605 			mutex_unlock(&hdd_ctx->op_ctx.op_lock);
14606 			return 0;
14607 		} else if (hdd_ctx->op_ctx.op_table[i].request_id ==
14608 					request_id) {
14609 			*pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
14610 			mutex_unlock(&hdd_ctx->op_ctx.op_lock);
14611 			return 0;
14612 		}
14613 	}
14614 	mutex_unlock(&hdd_ctx->op_ctx.op_lock);
14615 	return -ENOBUFS;
14616 }
14617 
14618 /**
14619  * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
14620  * @hdd_ctx: HDD context
14621  * @request_id: [input] request id
14622  * @pattern_id: [output] pattern id
14623  *
14624  * This function loops through request id to pattern id array
14625  * reset request id to 0 (slot available again) and
14626  * return pattern id
14627  *
14628  * Return: 0 on success and errno on failure
14629  */
14630 static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
14631 					  uint32_t request_id,
14632 					  uint8_t *pattern_id)
14633 {
14634 	uint32_t i;
14635 
14636 	mutex_lock(&hdd_ctx->op_ctx.op_lock);
14637 	for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
14638 		if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
14639 			hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
14640 			*pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
14641 			mutex_unlock(&hdd_ctx->op_ctx.op_lock);
14642 			return 0;
14643 		}
14644 	}
14645 	mutex_unlock(&hdd_ctx->op_ctx.op_lock);
14646 	return -EINVAL;
14647 }
14648 
14649 
14650 /*
14651  * define short names for the global vendor params
14652  * used by __wlan_hdd_cfg80211_offloaded_packets()
14653  */
14654 #define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
14655 #define PARAM_REQUEST_ID \
14656 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
14657 #define PARAM_CONTROL \
14658 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
14659 #define PARAM_IP_PACKET \
14660 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
14661 #define PARAM_SRC_MAC_ADDR \
14662 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
14663 #define PARAM_DST_MAC_ADDR \
14664 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
14665 #define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
14666 #define PARAM_PROTO_TYPE \
14667 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE
14668 
14669 const struct nla_policy offloaded_packet_policy[
14670 			QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX + 1] = {
14671 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL] = {
14672 			.type = NLA_U32},
14673 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID] = {.type = NLA_U32},
14674 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA] = {
14675 			.type = NLA_BINARY},
14676 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR] = {
14677 			.type = NLA_BINARY,
14678 			.len = QDF_MAC_ADDR_SIZE },
14679 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR] = {
14680 			.type = NLA_BINARY,
14681 			.len = QDF_MAC_ADDR_SIZE },
14682 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD] = {
14683 			.type = NLA_U32},
14684 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE] = {
14685 			.type = NLA_U16},
14686 };
14687 
14688 /**
14689  * wlan_hdd_add_tx_ptrn() - add tx pattern
14690  * @adapter: adapter pointer
14691  * @hdd_ctx: hdd context
14692  * @tb: nl attributes
14693  *
14694  * This function reads the NL attributes and forms a AddTxPtrn message
14695  * posts it to SME.
14696  *
14697  */
14698 static int
14699 wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
14700 			struct nlattr **tb)
14701 {
14702 	struct sSirAddPeriodicTxPtrn *add_req;
14703 	QDF_STATUS status;
14704 	uint32_t request_id, len;
14705 	int32_t ret;
14706 	uint8_t pattern_id = 0;
14707 	struct qdf_mac_addr dst_addr;
14708 	uint16_t eth_type = htons(ETH_P_IP);
14709 	mac_handle_t mac_handle;
14710 
14711 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
14712 		hdd_err("Not in Connected state!");
14713 		return -ENOTSUPP;
14714 	}
14715 
14716 	add_req = qdf_mem_malloc(sizeof(*add_req));
14717 	if (!add_req)
14718 		return -ENOMEM;
14719 
14720 	/* Parse and fetch request Id */
14721 	if (!tb[PARAM_REQUEST_ID]) {
14722 		hdd_err("attr request id failed");
14723 		ret = -EINVAL;
14724 		goto fail;
14725 	}
14726 
14727 	request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
14728 	if (request_id == MAX_REQUEST_ID) {
14729 		hdd_err("request_id cannot be MAX");
14730 		ret = -EINVAL;
14731 		goto fail;
14732 	}
14733 	hdd_debug("Request Id: %u", request_id);
14734 
14735 	if (!tb[PARAM_PERIOD]) {
14736 		hdd_err("attr period failed");
14737 		ret = -EINVAL;
14738 		goto fail;
14739 	}
14740 
14741 	add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
14742 	hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
14743 	if (add_req->usPtrnIntervalMs == 0) {
14744 		hdd_err("Invalid interval zero, return failure");
14745 		ret = -EINVAL;
14746 		goto fail;
14747 	}
14748 
14749 	if (!tb[PARAM_SRC_MAC_ADDR]) {
14750 		hdd_err("attr source mac address failed");
14751 		ret = -EINVAL;
14752 		goto fail;
14753 	}
14754 	nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
14755 			QDF_MAC_ADDR_SIZE);
14756 	hdd_debug("input src mac address: "QDF_MAC_ADDR_FMT,
14757 			QDF_MAC_ADDR_REF(add_req->mac_address.bytes));
14758 
14759 	if (!qdf_is_macaddr_equal(&add_req->mac_address,
14760 				  &adapter->mac_addr)) {
14761 		hdd_err("input src mac address and connected ap bssid are different");
14762 		ret = -EINVAL;
14763 		goto fail;
14764 	}
14765 
14766 	if (!tb[PARAM_DST_MAC_ADDR]) {
14767 		hdd_err("attr dst mac address failed");
14768 		ret = -EINVAL;
14769 		goto fail;
14770 	}
14771 	nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
14772 	hdd_debug("input dst mac address: "QDF_MAC_ADDR_FMT,
14773 			QDF_MAC_ADDR_REF(dst_addr.bytes));
14774 
14775 	if (!tb[PARAM_IP_PACKET]) {
14776 		hdd_err("attr ip packet failed");
14777 		ret = -EINVAL;
14778 		goto fail;
14779 	}
14780 	add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
14781 	hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
14782 
14783 	if (add_req->ucPtrnSize < 0 ||
14784 		add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
14785 					ETH_HLEN)) {
14786 		hdd_err("Invalid IP packet len: %d",
14787 				add_req->ucPtrnSize);
14788 		ret = -EINVAL;
14789 		goto fail;
14790 	}
14791 
14792 	if (!tb[PARAM_PROTO_TYPE])
14793 		eth_type = htons(ETH_P_IP);
14794 	else
14795 		eth_type = htons(nla_get_u16(tb[PARAM_PROTO_TYPE]));
14796 
14797 	hdd_debug("packet proto type: %u", eth_type);
14798 
14799 	len = 0;
14800 	qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
14801 	len += QDF_MAC_ADDR_SIZE;
14802 	qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
14803 			QDF_MAC_ADDR_SIZE);
14804 	len += QDF_MAC_ADDR_SIZE;
14805 	qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
14806 	len += 2;
14807 
14808 	/*
14809 	 * This is the IP packet, add 14 bytes Ethernet (802.3) header
14810 	 * ------------------------------------------------------------
14811 	 * | 14 bytes Ethernet (802.3) header | IP header and payload |
14812 	 * ------------------------------------------------------------
14813 	 */
14814 	qdf_mem_copy(&add_req->ucPattern[len],
14815 			nla_data(tb[PARAM_IP_PACKET]),
14816 			add_req->ucPtrnSize);
14817 	add_req->ucPtrnSize += len;
14818 
14819 	ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
14820 	if (ret) {
14821 		hdd_err("req id to pattern id failed (ret=%d)", ret);
14822 		goto fail;
14823 	}
14824 	add_req->ucPtrnId = pattern_id;
14825 	hdd_debug("pattern id: %d", add_req->ucPtrnId);
14826 
14827 	mac_handle = hdd_ctx->mac_handle;
14828 	status = sme_add_periodic_tx_ptrn(mac_handle, add_req);
14829 	if (!QDF_IS_STATUS_SUCCESS(status)) {
14830 		hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
14831 		ret = qdf_status_to_os_return(status);
14832 		goto fail;
14833 	}
14834 
14835 	hdd_exit();
14836 
14837 fail:
14838 	qdf_mem_free(add_req);
14839 	return ret;
14840 }
14841 
14842 /**
14843  * wlan_hdd_del_tx_ptrn() - delete tx pattern
14844  * @adapter: adapter pointer
14845  * @hdd_ctx: hdd context
14846  * @tb: nl attributes
14847  *
14848  * This function reads the NL attributes and forms a DelTxPtrn message
14849  * posts it to SME.
14850  *
14851  */
14852 static int
14853 wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
14854 			struct nlattr **tb)
14855 {
14856 	struct sSirDelPeriodicTxPtrn *del_req;
14857 	QDF_STATUS status;
14858 	uint32_t request_id, ret;
14859 	uint8_t pattern_id = 0;
14860 	mac_handle_t mac_handle;
14861 
14862 	/* Parse and fetch request Id */
14863 	if (!tb[PARAM_REQUEST_ID]) {
14864 		hdd_err("attr request id failed");
14865 		return -EINVAL;
14866 	}
14867 	request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
14868 	if (request_id == MAX_REQUEST_ID) {
14869 		hdd_err("request_id cannot be MAX");
14870 		return -EINVAL;
14871 	}
14872 
14873 	ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
14874 	if (ret) {
14875 		hdd_err("req id to pattern id failed (ret=%d)", ret);
14876 		return -EINVAL;
14877 	}
14878 
14879 	del_req = qdf_mem_malloc(sizeof(*del_req));
14880 	if (!del_req)
14881 		return -ENOMEM;
14882 
14883 	qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
14884 	hdd_debug(QDF_MAC_ADDR_FMT,
14885 		  QDF_MAC_ADDR_REF(del_req->mac_address.bytes));
14886 	del_req->ucPtrnId = pattern_id;
14887 	hdd_debug("Request Id: %u Pattern id: %d",
14888 			 request_id, del_req->ucPtrnId);
14889 
14890 	mac_handle = hdd_ctx->mac_handle;
14891 	status = sme_del_periodic_tx_ptrn(mac_handle, del_req);
14892 	if (!QDF_IS_STATUS_SUCCESS(status)) {
14893 		hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
14894 		goto fail;
14895 	}
14896 
14897 	hdd_exit();
14898 	qdf_mem_free(del_req);
14899 	return 0;
14900 
14901 fail:
14902 	qdf_mem_free(del_req);
14903 	return -EINVAL;
14904 }
14905 
14906 
14907 /**
14908  * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
14909  * @wiphy: Pointer to wireless phy
14910  * @wdev: Pointer to wireless device
14911  * @data: Pointer to data
14912  * @data_len: Data length
14913  *
14914  * Return: 0 on success, negative errno on failure
14915  */
14916 static int
14917 __wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
14918 				     struct wireless_dev *wdev,
14919 				     const void *data,
14920 				     int data_len)
14921 {
14922 	struct net_device *dev = wdev->netdev;
14923 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14924 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
14925 	struct nlattr *tb[PARAM_MAX + 1];
14926 	uint8_t control;
14927 	int ret;
14928 
14929 	hdd_enter_dev(dev);
14930 
14931 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
14932 		hdd_err("Command not allowed in FTM mode");
14933 		return -EPERM;
14934 	}
14935 
14936 	ret = wlan_hdd_validate_context(hdd_ctx);
14937 	if (ret)
14938 		return ret;
14939 
14940 	if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
14941 		hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
14942 		return -ENOTSUPP;
14943 	}
14944 
14945 	if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len,
14946 				    offloaded_packet_policy)) {
14947 		hdd_err("Invalid ATTR");
14948 		return -EINVAL;
14949 	}
14950 
14951 	if (!tb[PARAM_CONTROL]) {
14952 		hdd_err("attr control failed");
14953 		return -EINVAL;
14954 	}
14955 	control = nla_get_u32(tb[PARAM_CONTROL]);
14956 	hdd_debug("Control: %d", control);
14957 
14958 	if (control == WLAN_START_OFFLOADED_PACKETS)
14959 		return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
14960 	if (control == WLAN_STOP_OFFLOADED_PACKETS)
14961 		return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
14962 
14963 	hdd_err("Invalid control: %d", control);
14964 	return -EINVAL;
14965 }
14966 
14967 /*
14968  * done with short names for the global vendor params
14969  * used by __wlan_hdd_cfg80211_offloaded_packets()
14970  */
14971 #undef PARAM_MAX
14972 #undef PARAM_REQUEST_ID
14973 #undef PARAM_CONTROL
14974 #undef PARAM_IP_PACKET
14975 #undef PARAM_SRC_MAC_ADDR
14976 #undef PARAM_DST_MAC_ADDR
14977 #undef PARAM_PERIOD
14978 #undef PARAM_PROTO_TYPE
14979 
14980 /**
14981  * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
14982  * @wiphy:    wiphy structure pointer
14983  * @wdev:     Wireless device structure pointer
14984  * @data:     Pointer to the data received
14985  * @data_len: Length of @data
14986  *
14987  * Return: 0 on success; errno on failure
14988  */
14989 static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
14990 						struct wireless_dev *wdev,
14991 						const void *data,
14992 						int data_len)
14993 {
14994 	int errno;
14995 	struct osif_vdev_sync *vdev_sync;
14996 
14997 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
14998 	if (errno)
14999 		return errno;
15000 
15001 	errno = __wlan_hdd_cfg80211_offloaded_packets(wiphy, wdev,
15002 						      data, data_len);
15003 
15004 	osif_vdev_sync_op_stop(vdev_sync);
15005 
15006 	return errno;
15007 }
15008 #endif
15009 
15010 #ifdef WLAN_NS_OFFLOAD
15011 const struct nla_policy ns_offload_set_policy[
15012 			QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
15013 	[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
15014 };
15015 
15016 /**
15017  * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
15018  * @wiphy: Pointer to wireless phy
15019  * @wdev: Pointer to wireless device
15020  * @data: Pointer to data
15021  * @data_len: Length of @data
15022  *
15023  * Return: 0 on success, negative errno on failure
15024  */
15025 static int
15026 __wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
15027 			struct wireless_dev *wdev,
15028 			const void *data, int data_len)
15029 {
15030 	int status;
15031 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
15032 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15033 	struct net_device *dev = wdev->netdev;
15034 	struct hdd_adapter *adapter =  WLAN_HDD_GET_PRIV_PTR(dev);
15035 	struct wlan_objmgr_vdev *vdev;
15036 
15037 	hdd_enter_dev(wdev->netdev);
15038 
15039 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15040 		hdd_err("Command not allowed in FTM mode");
15041 		return -EPERM;
15042 	}
15043 
15044 	status = wlan_hdd_validate_context(hdd_ctx);
15045 	if (0 != status)
15046 		return status;
15047 
15048 	if (!ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
15049 		hdd_err("ND Offload not supported");
15050 		return -EINVAL;
15051 	}
15052 
15053 	if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
15054 		hdd_warn("Active mode offload is disabled");
15055 		return -EINVAL;
15056 	}
15057 
15058 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
15059 				    (struct nlattr *)data, data_len,
15060 				    ns_offload_set_policy)) {
15061 		hdd_err("nla_parse failed");
15062 		return -EINVAL;
15063 	}
15064 
15065 	if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
15066 		hdd_err("ND Offload flag attribute not present");
15067 		return -EINVAL;
15068 	}
15069 
15070 	hdd_ctx->ns_offload_enable =
15071 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
15072 
15073 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
15074 	if (!vdev)
15075 		return -EINVAL;
15076 
15077 	/* update ns offload in case it is already enabled/disabled */
15078 	if (hdd_ctx->ns_offload_enable)
15079 		hdd_enable_ns_offload(adapter, vdev,
15080 				      pmo_ns_offload_dynamic_update);
15081 	else
15082 		hdd_disable_ns_offload(adapter, vdev,
15083 				       pmo_ns_offload_dynamic_update);
15084 
15085 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
15086 	return 0;
15087 }
15088 
15089 /**
15090  * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
15091  * @wiphy:   pointer to wireless wiphy structure.
15092  * @wdev:    pointer to wireless_dev structure.
15093  * @data:    Pointer to the data to be passed via vendor interface
15094  * @data_len:Length of the data to be passed
15095  *
15096  * Return:   Return the Success or Failure code.
15097  */
15098 static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
15099 					struct wireless_dev *wdev,
15100 					const void *data, int data_len)
15101 {
15102 	int errno;
15103 	struct osif_vdev_sync *vdev_sync;
15104 
15105 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
15106 	if (errno)
15107 		return errno;
15108 
15109 	errno = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
15110 
15111 	osif_vdev_sync_op_stop(vdev_sync);
15112 
15113 	return errno;
15114 }
15115 #endif /* WLAN_NS_OFFLOAD */
15116 
15117 /**
15118  * struct weighed_pcl: Preferred channel info
15119  * @freq: Channel frequency
15120  * @weight: Weightage of the channel
15121  * @flag: Validity of the channel in p2p negotiation
15122  */
15123 struct weighed_pcl {
15124 		u32 freq;
15125 		u32 weight;
15126 		u32 flag;
15127 };
15128 
15129 const struct nla_policy get_preferred_freq_list_policy[
15130 		QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
15131 	[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
15132 		.type = NLA_U32},
15133 };
15134 
15135 static uint32_t wlan_hdd_populate_weigh_pcl(
15136 				struct wlan_objmgr_psoc *psoc,
15137 				struct policy_mgr_pcl_chan_weights *
15138 				chan_weights,
15139 				struct weighed_pcl *w_pcl,
15140 				enum policy_mgr_con_mode intf_mode)
15141 {
15142 	u32 i, j, valid_weight;
15143 	u32 chan_idx = 0;
15144 	u32 pcl_len = chan_weights->pcl_len;
15145 	u32 conn_count = policy_mgr_get_connection_count(psoc);
15146 
15147 	/* convert channel number to frequency */
15148 	for (i = 0; i < chan_weights->pcl_len; i++) {
15149 		w_pcl[i].freq = chan_weights->pcl_list[i];
15150 		w_pcl[i].weight = chan_weights->weight_list[i];
15151 
15152 		if (policy_mgr_is_beaconing_mode(intf_mode))
15153 			w_pcl[i].flag = PCL_CHANNEL_SUPPORT_GO;
15154 		else
15155 			w_pcl[i].flag = PCL_CHANNEL_SUPPORT_CLI;
15156 	}
15157 	chan_idx = pcl_len;
15158 	if (!conn_count || policy_mgr_is_hw_dbs_capable(psoc) ||
15159 	    policy_mgr_is_interband_mcc_supported(psoc)) {
15160 		if (pcl_len && chan_weights->weight_list[pcl_len - 1] >
15161 		    PCL_GROUPS_WEIGHT_DIFFERENCE)
15162 		/*
15163 		 * Set non-pcl channels weight 20 point less than the
15164 		 * last PCL entry
15165 		 */
15166 			valid_weight = chan_weights->weight_list[pcl_len - 1] -
15167 					PCL_GROUPS_WEIGHT_DIFFERENCE;
15168 		else
15169 			valid_weight = 1;
15170 
15171 		/* Include rest of the valid channels */
15172 		for (i = 0; i < chan_weights->saved_num_chan; i++) {
15173 			for (j = 0; j < chan_weights->pcl_len; j++) {
15174 				if (chan_weights->saved_chan_list[i] ==
15175 					chan_weights->pcl_list[j])
15176 					break;
15177 			}
15178 			if (j == chan_weights->pcl_len) {
15179 				w_pcl[chan_idx].freq =
15180 					chan_weights->saved_chan_list[i];
15181 
15182 				if (!chan_weights->weighed_valid_list[i]) {
15183 					w_pcl[chan_idx].flag =
15184 						PCL_CHANNEL_EXCLUDE_IN_GO_NEG;
15185 					w_pcl[chan_idx].weight = 0;
15186 				} else {
15187 					if (policy_mgr_is_beaconing_mode(
15188 								intf_mode))
15189 						w_pcl[chan_idx].flag =
15190 						      PCL_CHANNEL_SUPPORT_GO;
15191 					else
15192 						w_pcl[chan_idx].flag =
15193 						      PCL_CHANNEL_SUPPORT_CLI;
15194 					w_pcl[chan_idx].weight = valid_weight;
15195 				}
15196 				chan_idx++;
15197 			}
15198 		}
15199 	}
15200 	return chan_idx;
15201 }
15202 
15203 /** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
15204  * @wiphy: Pointer to wireless phy
15205  * @wdev: Pointer to wireless device
15206  * @data: Pointer to data
15207  * @data_len: Data length
15208  *
15209  * This function return the preferred frequency list generated by the policy
15210  * manager.
15211  *
15212  * Return: success or failure code
15213  */
15214 static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
15215 						 struct wireless_dev
15216 						 *wdev, const void *data,
15217 						 int data_len)
15218 {
15219 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15220 	int i, ret = 0;
15221 	QDF_STATUS status;
15222 	uint32_t pcl_len = 0;
15223 	uint32_t pcl_len_legacy = 0;
15224 	uint32_t freq_list[NUM_CHANNELS];
15225 	uint32_t freq_list_legacy[NUM_CHANNELS];
15226 	enum policy_mgr_con_mode intf_mode;
15227 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
15228 	struct sk_buff *reply_skb;
15229 	struct weighed_pcl *w_pcl;
15230 	struct nlattr *nla_attr, *channel;
15231 	struct policy_mgr_pcl_chan_weights *chan_weights;
15232 	struct net_device *ndev = wdev->netdev;
15233 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
15234 
15235 	hdd_enter_dev(wdev->netdev);
15236 
15237 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15238 		hdd_err("Command not allowed in FTM mode");
15239 		return -EPERM;
15240 	}
15241 
15242 	ret = wlan_hdd_validate_context(hdd_ctx);
15243 	if (ret)
15244 		return -EINVAL;
15245 
15246 	if (wlan_cfg80211_nla_parse(tb,
15247 			       QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
15248 			       data, data_len,
15249 			       get_preferred_freq_list_policy)) {
15250 		hdd_err("Invalid ATTR");
15251 		return -EINVAL;
15252 	}
15253 
15254 	if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
15255 		hdd_err("attr interface type failed");
15256 		return -EINVAL;
15257 	}
15258 
15259 	intf_mode = nla_get_u32(tb
15260 		    [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
15261 
15262 	if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
15263 		hdd_err("Invalid interface type");
15264 		return -EINVAL;
15265 	}
15266 
15267 	hdd_debug("Userspace requested pref freq list");
15268 
15269 	chan_weights =
15270 		qdf_mem_malloc(sizeof(struct policy_mgr_pcl_chan_weights));
15271 	if (!chan_weights)
15272 		return -ENOMEM;
15273 
15274 	status = policy_mgr_get_pcl(
15275 			hdd_ctx->psoc, intf_mode, chan_weights->pcl_list,
15276 			&chan_weights->pcl_len, chan_weights->weight_list,
15277 			QDF_ARRAY_SIZE(chan_weights->weight_list),
15278 			adapter->deflink->vdev_id);
15279 	if (status != QDF_STATUS_SUCCESS) {
15280 		hdd_err("Get pcl failed");
15281 		qdf_mem_free(chan_weights);
15282 		return -EINVAL;
15283 	}
15284 	/*
15285 	 * save the pcl in freq_list_legacy to be sent up with
15286 	 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST.
15287 	 * freq_list will carry the extended pcl in
15288 	 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL.
15289 	 */
15290 	pcl_len_legacy = chan_weights->pcl_len;
15291 	for (i = 0; i < pcl_len_legacy; i++)
15292 		freq_list_legacy[i] = chan_weights->pcl_list[i];
15293 	chan_weights->saved_num_chan = NUM_CHANNELS;
15294 	ucfg_mlme_get_valid_channels(hdd_ctx->psoc,
15295 				     chan_weights->saved_chan_list,
15296 				     &chan_weights->saved_num_chan);
15297 	policy_mgr_get_valid_chan_weights(hdd_ctx->psoc, chan_weights,
15298 					  intf_mode,
15299 					  adapter->deflink->vdev);
15300 	w_pcl = qdf_mem_malloc(sizeof(struct weighed_pcl) * NUM_CHANNELS);
15301 	if (!w_pcl) {
15302 		qdf_mem_free(chan_weights);
15303 		return -ENOMEM;
15304 	}
15305 	pcl_len = wlan_hdd_populate_weigh_pcl(hdd_ctx->psoc, chan_weights,
15306 					      w_pcl, intf_mode);
15307 	qdf_mem_free(chan_weights);
15308 
15309 	for (i = 0; i < pcl_len; i++)
15310 		freq_list[i] = w_pcl[i].freq;
15311 
15312 	/* send the freq_list back to supplicant */
15313 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(
15314 			wiphy,
15315 			(sizeof(u32) + NLA_HDRLEN) +
15316 			(sizeof(u32) * pcl_len_legacy + NLA_HDRLEN) +
15317 			NLA_HDRLEN +
15318 			(NLA_HDRLEN * 4 + sizeof(u32) * 3) * pcl_len +
15319 			NLMSG_HDRLEN);
15320 
15321 	if (!reply_skb) {
15322 		hdd_err("Allocate reply_skb failed");
15323 		qdf_mem_free(w_pcl);
15324 		return -EINVAL;
15325 	}
15326 
15327 	if (nla_put_u32(reply_skb,
15328 		QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
15329 			intf_mode) ||
15330 	    nla_put(reply_skb,
15331 		    QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
15332 		    sizeof(uint32_t) * pcl_len_legacy,
15333 		    freq_list_legacy)) {
15334 		hdd_err("nla put fail");
15335 		wlan_cfg80211_vendor_free_skb(reply_skb);
15336 		qdf_mem_free(w_pcl);
15337 		return -EINVAL;
15338 	}
15339 
15340 	i = QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL;
15341 	nla_attr = nla_nest_start(reply_skb, i);
15342 
15343 	if (!nla_attr) {
15344 		hdd_err("nla nest start fail");
15345 		wlan_cfg80211_vendor_free_skb(reply_skb);
15346 		qdf_mem_free(w_pcl);
15347 		return -EINVAL;
15348 	}
15349 
15350 	for (i = 0; i < pcl_len; i++) {
15351 		channel = nla_nest_start(reply_skb, i);
15352 		if (!channel) {
15353 			hdd_err("updating pcl list failed");
15354 			wlan_cfg80211_vendor_free_skb(reply_skb);
15355 			qdf_mem_free(w_pcl);
15356 			return -EINVAL;
15357 		}
15358 		if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
15359 				w_pcl[i].freq) ||
15360 		    nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
15361 				w_pcl[i].weight) ||
15362 		    nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FLAG,
15363 				w_pcl[i].flag)) {
15364 			hdd_err("nla put fail");
15365 			wlan_cfg80211_vendor_free_skb(reply_skb);
15366 			qdf_mem_free(w_pcl);
15367 			return -EINVAL;
15368 		}
15369 		nla_nest_end(reply_skb, channel);
15370 	}
15371 	nla_nest_end(reply_skb, nla_attr);
15372 	qdf_mem_free(w_pcl);
15373 
15374 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
15375 }
15376 
15377 /** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
15378  * @wiphy: Pointer to wireless phy
15379  * @wdev: Pointer to wireless device
15380  * @data: Pointer to data
15381  * @data_len: Data length
15382  *
15383  * This function return the preferred frequency list generated by the policy
15384  * manager.
15385  *
15386  * Return: success or failure code
15387  */
15388 static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
15389 						 struct wireless_dev
15390 						 *wdev, const void *data,
15391 						 int data_len)
15392 {
15393 	struct osif_psoc_sync *psoc_sync;
15394 	int errno;
15395 
15396 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
15397 	if (errno)
15398 		return errno;
15399 
15400 	errno = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
15401 							    data, data_len);
15402 
15403 	osif_psoc_sync_op_stop(psoc_sync);
15404 
15405 	return errno;
15406 }
15407 
15408 const struct nla_policy set_probable_oper_channel_policy[
15409 		QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
15410 	[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
15411 		.type = NLA_U32},
15412 	[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
15413 		.type = NLA_U32},
15414 };
15415 
15416 /**
15417  * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
15418  * @wiphy: Pointer to wireless phy
15419  * @wdev: Pointer to wireless device
15420  * @data: Pointer to data
15421  * @data_len: Data length
15422  *
15423  * Return: 0 on success, negative errno on failure
15424  */
15425 static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
15426 						struct wireless_dev *wdev,
15427 						const void *data,
15428 						int data_len)
15429 {
15430 	struct net_device *ndev = wdev->netdev;
15431 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
15432 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15433 	int ret = 0;
15434 	enum policy_mgr_con_mode intf_mode;
15435 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
15436 	uint32_t ch_freq, conc_ext_flags;
15437 
15438 	hdd_enter_dev(ndev);
15439 
15440 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15441 		hdd_err("Command not allowed in FTM mode");
15442 		return -EPERM;
15443 	}
15444 
15445 	ret = wlan_hdd_validate_context(hdd_ctx);
15446 	if (ret)
15447 		return ret;
15448 
15449 	if (wlan_cfg80211_nla_parse(tb,
15450 				 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
15451 				 data, data_len,
15452 				 set_probable_oper_channel_policy)) {
15453 		hdd_err("Invalid ATTR");
15454 		return -EINVAL;
15455 	}
15456 
15457 	if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
15458 		hdd_err("attr interface type failed");
15459 		return -EINVAL;
15460 	}
15461 
15462 	intf_mode = nla_get_u32(tb
15463 		    [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
15464 
15465 	if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
15466 		hdd_err("Invalid interface type");
15467 		return -EINVAL;
15468 	}
15469 
15470 	if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
15471 		hdd_err("attr probable freq failed");
15472 		return -EINVAL;
15473 	}
15474 
15475 	ch_freq = nla_get_u32(tb[
15476 			      QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]);
15477 	conc_ext_flags = policy_mgr_get_conc_ext_flags(adapter->deflink->vdev,
15478 						       false);
15479 
15480 	/* check pcl table */
15481 	if (!policy_mgr_allow_concurrency(hdd_ctx->psoc, intf_mode,
15482 					  ch_freq, HW_MODE_20_MHZ,
15483 					  conc_ext_flags,
15484 					  adapter->deflink->vdev_id)) {
15485 		hdd_err("Set channel hint failed due to concurrency check");
15486 		return -EINVAL;
15487 	}
15488 
15489 	if (QDF_P2P_GO_MODE != adapter->device_mode)
15490 		wlan_hdd_cleanup_remain_on_channel_ctx(adapter->deflink);
15491 
15492 	if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, ch_freq,
15493 				POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
15494 		hdd_err("Failed to change hw mode");
15495 		return -EINVAL;
15496 	}
15497 
15498 	return 0;
15499 }
15500 
15501 /**
15502  * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
15503  * @wiphy: Pointer to wireless phy
15504  * @wdev: Pointer to wireless device
15505  * @data: Pointer to data
15506  * @data_len: Data length
15507  *
15508  * Return: 0 on success, negative errno on failure
15509  */
15510 static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
15511 						struct wireless_dev *wdev,
15512 						const void *data,
15513 						int data_len)
15514 {
15515 	int errno;
15516 	struct osif_vdev_sync *vdev_sync;
15517 
15518 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
15519 	if (errno)
15520 		return errno;
15521 
15522 	errno = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
15523 							      data, data_len);
15524 
15525 	osif_vdev_sync_op_stop(vdev_sync);
15526 
15527 	return errno;
15528 }
15529 
15530 static const struct
15531 nla_policy
15532 wlan_hdd_get_link_properties_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
15533 	[QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
15534 		.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
15535 };
15536 
15537 /**
15538  * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
15539  * @wiphy: WIPHY structure pointer
15540  * @wdev: Wireless device structure pointer
15541  * @data: Pointer to the data received
15542  * @data_len: Length of the data received
15543  *
15544  * This function is used to get link properties like nss, rate flags and
15545  * operating frequency for the active connection with the given peer.
15546  *
15547  * Return: 0 on success and errno on failure
15548  */
15549 static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
15550 						   struct wireless_dev *wdev,
15551 						   const void *data,
15552 						   int data_len)
15553 {
15554 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15555 	struct net_device *dev = wdev->netdev;
15556 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15557 	struct hdd_station_ctx *hdd_sta_ctx;
15558 	struct hdd_ap_ctx *ap_ctx;
15559 	struct hdd_station_info *sta_info;
15560 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
15561 	uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
15562 	struct sk_buff *reply_skb;
15563 	uint32_t rate_flags = 0;
15564 	uint8_t nss;
15565 	uint8_t final_rate_flags = 0;
15566 	uint32_t freq;
15567 
15568 	hdd_enter_dev(dev);
15569 
15570 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15571 		hdd_err("Command not allowed in FTM mode");
15572 		return -EPERM;
15573 	}
15574 
15575 	if (0 != wlan_hdd_validate_context(hdd_ctx))
15576 		return -EINVAL;
15577 
15578 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
15579 				    data_len,
15580 				    wlan_hdd_get_link_properties_policy)) {
15581 		hdd_err("Invalid attribute");
15582 		return -EINVAL;
15583 	}
15584 
15585 	if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
15586 		hdd_err("Attribute peerMac not provided for mode=%d",
15587 		       adapter->device_mode);
15588 		return -EINVAL;
15589 	}
15590 
15591 	if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
15592 		hdd_err("Attribute peerMac is invalid for mode=%d",
15593 			adapter->device_mode);
15594 		return -EINVAL;
15595 	}
15596 
15597 	qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
15598 		     QDF_MAC_ADDR_SIZE);
15599 	hdd_debug("peerMac="QDF_MAC_ADDR_FMT" for device_mode:%d",
15600 		  QDF_MAC_ADDR_REF(peer_mac), adapter->device_mode);
15601 
15602 	if (adapter->device_mode == QDF_STA_MODE ||
15603 	    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
15604 		hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
15605 		if (!hdd_cm_is_vdev_associated(adapter->deflink) ||
15606 		    qdf_mem_cmp(hdd_sta_ctx->conn_info.bssid.bytes,
15607 			peer_mac, QDF_MAC_ADDR_SIZE)) {
15608 			hdd_err("Not Associated to mac "QDF_MAC_ADDR_FMT,
15609 			       QDF_MAC_ADDR_REF(peer_mac));
15610 			return -EINVAL;
15611 		}
15612 
15613 		nss  = hdd_sta_ctx->conn_info.nss;
15614 		freq = hdd_sta_ctx->conn_info.chan_freq;
15615 		rate_flags = hdd_sta_ctx->conn_info.rate_flags;
15616 	} else if (adapter->device_mode == QDF_P2P_GO_MODE ||
15617 		   adapter->device_mode == QDF_SAP_MODE) {
15618 
15619 		if (QDF_IS_ADDR_BROADCAST(peer_mac)) {
15620 			hdd_err("Ignore bcast/self sta");
15621 			return -EINVAL;
15622 		}
15623 
15624 		sta_info = hdd_get_sta_info_by_mac(
15625 					&adapter->sta_info_list, peer_mac,
15626 					STA_INFO_CFG80211_GET_LINK_PROPERTIES);
15627 
15628 		if (!sta_info) {
15629 			hdd_err("No active peer with mac = " QDF_MAC_ADDR_FMT,
15630 				QDF_MAC_ADDR_REF(peer_mac));
15631 			return -EINVAL;
15632 		}
15633 
15634 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
15635 		nss = sta_info->nss;
15636 		freq = ap_ctx->operating_chan_freq;
15637 		rate_flags = sta_info->rate_flags;
15638 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
15639 				     STA_INFO_CFG80211_GET_LINK_PROPERTIES);
15640 	} else {
15641 		hdd_err("Not Associated! with mac "QDF_MAC_ADDR_FMT,
15642 		       QDF_MAC_ADDR_REF(peer_mac));
15643 		return -EINVAL;
15644 	}
15645 
15646 	if (!(rate_flags & TX_RATE_LEGACY)) {
15647 		if (rate_flags & TX_RATE_VHT80) {
15648 			final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
15649 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
15650 			final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
15651 #endif
15652 		} else if (rate_flags & TX_RATE_VHT40) {
15653 			final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
15654 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
15655 			final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
15656 #endif
15657 		} else if (rate_flags & TX_RATE_VHT20) {
15658 			final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
15659 		} else if (rate_flags &
15660 				(TX_RATE_HT20 | TX_RATE_HT40)) {
15661 			final_rate_flags |= RATE_INFO_FLAGS_MCS;
15662 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
15663 			if (rate_flags & TX_RATE_HT40)
15664 				final_rate_flags |=
15665 					RATE_INFO_FLAGS_40_MHZ_WIDTH;
15666 #endif
15667 		}
15668 
15669 		if (rate_flags & TX_RATE_SGI) {
15670 			if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
15671 				final_rate_flags |= RATE_INFO_FLAGS_MCS;
15672 			final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
15673 		}
15674 	}
15675 
15676 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
15677 							     sizeof(u8) +
15678 							     sizeof(u8) +
15679 							     sizeof(u32) +
15680 							     NLMSG_HDRLEN);
15681 	if (!reply_skb) {
15682 		hdd_err("getLinkProperties: skb alloc failed");
15683 		return -EINVAL;
15684 	}
15685 
15686 	if (nla_put_u8(reply_skb,
15687 		QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
15688 		nss) ||
15689 	    nla_put_u8(reply_skb,
15690 		QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
15691 		final_rate_flags) ||
15692 	    nla_put_u32(reply_skb,
15693 		QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
15694 		freq)) {
15695 		hdd_err("nla_put failed");
15696 		wlan_cfg80211_vendor_free_skb(reply_skb);
15697 		return -EINVAL;
15698 	}
15699 
15700 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
15701 }
15702 
15703 /**
15704  * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
15705  * properties.
15706  * @wiphy: WIPHY structure pointer
15707  * @wdev: Wireless device structure pointer
15708  * @data: Pointer to the data received
15709  * @data_len: Length of the data received
15710  *
15711  * This function is used to get link properties like nss, rate flags and
15712  * operating frequency for the active connection with the given peer.
15713  *
15714  * Return: 0 on success and errno on failure
15715  */
15716 static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
15717 						 struct wireless_dev *wdev,
15718 						 const void *data,
15719 						 int data_len)
15720 {
15721 	int errno;
15722 	struct osif_vdev_sync *vdev_sync;
15723 
15724 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
15725 	if (errno)
15726 		return errno;
15727 
15728 	errno = __wlan_hdd_cfg80211_get_link_properties(wiphy, wdev,
15729 							data, data_len);
15730 
15731 	osif_vdev_sync_op_stop(vdev_sync);
15732 
15733 	return errno;
15734 }
15735 
15736 const struct nla_policy
15737 wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
15738 	[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8},
15739 	[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY] = {.type = NLA_U32},
15740 	[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
15741 							.type = NLA_BINARY},
15742 };
15743 
15744 const struct nla_policy
15745 wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
15746 	[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8},
15747 	[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8},
15748 	[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT] = {.type = NLA_U32},
15749 };
15750 
15751 /**
15752  * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
15753  * @wiphy: Pointer to wireless phy
15754  * @wdev: Pointer to wireless device
15755  * @data: Pointer to data
15756  * @data_len: Length of @data
15757  *
15758  * This function parses the incoming NL vendor command data attributes and
15759  * updates the SAP context about channel_hint and DFS mode.
15760  * If channel_hint is set, SAP will choose that channel
15761  * as operating channel.
15762  *
15763  * If DFS mode is enabled, driver will include DFS channels
15764  * in ACS else driver will skip DFS channels.
15765  *
15766  * Return: 0 on success, negative errno on failure
15767  */
15768 static int
15769 __wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
15770 		struct wireless_dev *wdev,
15771 		const void *data, int data_len)
15772 {
15773 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15774 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
15775 	int ret;
15776 	struct acs_dfs_policy *acs_policy;
15777 	int mode = DFS_MODE_NONE;
15778 	uint32_t freq_hint = 0;
15779 
15780 	hdd_enter_dev(wdev->netdev);
15781 
15782 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15783 		hdd_err("Command not allowed in FTM mode");
15784 		return -EINVAL;
15785 	}
15786 
15787 	ret = wlan_hdd_validate_context(hdd_ctx);
15788 	if (0 != ret)
15789 		return ret;
15790 
15791 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
15792 				    data, data_len,
15793 				    wlan_hdd_set_acs_dfs_config_policy)) {
15794 		hdd_err("invalid attr");
15795 		return -EINVAL;
15796 	}
15797 
15798 	acs_policy = &hdd_ctx->acs_policy;
15799 	/*
15800 	 * SCM sends this attribute to restrict SAP from choosing
15801 	 * DFS channels from ACS.
15802 	 */
15803 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
15804 		mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
15805 
15806 	if (!IS_DFS_MODE_VALID(mode)) {
15807 		hdd_err("attr acs dfs mode is not valid");
15808 		return -EINVAL;
15809 	}
15810 	acs_policy->acs_dfs_mode = mode;
15811 
15812 	/*
15813 	 * SCM sends this attribute to provide an active channel,
15814 	 * to skip redundant ACS between drivers, and save driver start up time
15815 	 */
15816 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]) {
15817 		freq_hint = nla_get_u32(
15818 				tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]);
15819 	} else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]) {
15820 		uint32_t channel_hint = nla_get_u8(
15821 				tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
15822 
15823 		freq_hint = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
15824 							 channel_hint);
15825 	}
15826 
15827 	if (freq_hint && !WLAN_REG_IS_24GHZ_CH_FREQ(freq_hint) &&
15828 	    !WLAN_REG_IS_5GHZ_CH_FREQ(freq_hint) &&
15829 	    !WLAN_REG_IS_6GHZ_CHAN_FREQ(freq_hint)) {
15830 		hdd_err("acs channel frequency is not valid");
15831 		return -EINVAL;
15832 	}
15833 
15834 	acs_policy->acs_chan_freq = freq_hint;
15835 
15836 	return 0;
15837 }
15838 
15839 /**
15840  * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
15841  * @wiphy:    wiphy structure pointer
15842  * @wdev:     Wireless device structure pointer
15843  * @data:     Pointer to the data received
15844  * @data_len: Length of @data
15845  *
15846  * This function parses the incoming NL vendor command data attributes and
15847  * updates the SAP context about channel_hint and DFS mode.
15848  *
15849  * Return: 0 on success; errno on failure
15850  */
15851 static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
15852 		struct wireless_dev *wdev,
15853 		const void *data, int data_len)
15854 {
15855 	struct osif_psoc_sync *psoc_sync;
15856 	int errno;
15857 
15858 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
15859 	if (errno)
15860 		return errno;
15861 
15862 	errno = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
15863 
15864 	osif_psoc_sync_op_stop(psoc_sync);
15865 
15866 	return errno;
15867 }
15868 
15869 /**
15870  * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
15871  * @mode : cfg80211 dfs mode
15872  *
15873  * Return: return csr sta roam dfs mode else return NONE
15874  */
15875 static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
15876 		enum dfs_mode mode)
15877 {
15878 	switch (mode) {
15879 	case DFS_MODE_ENABLE:
15880 		return STA_ROAM_POLICY_DFS_ENABLED;
15881 	case DFS_MODE_DISABLE:
15882 		return STA_ROAM_POLICY_DFS_DISABLED;
15883 	case DFS_MODE_DEPRIORITIZE:
15884 		return STA_ROAM_POLICY_DFS_DEPRIORITIZE;
15885 	default:
15886 		hdd_err("STA Roam policy dfs mode is NONE");
15887 		return  STA_ROAM_POLICY_NONE;
15888 	}
15889 }
15890 
15891 uint8_t
15892 hdd_get_sap_operating_band_by_link_info(struct wlan_hdd_link_info *link_info)
15893 {
15894 	uint32_t operating_chan_freq;
15895 	uint8_t sap_operating_band = 0;
15896 	struct hdd_ap_ctx *ap_ctx;
15897 	enum QDF_OPMODE opmode = link_info->adapter->device_mode;
15898 
15899 	if (opmode != QDF_SAP_MODE && opmode != QDF_P2P_GO_MODE)
15900 		return BAND_UNKNOWN;
15901 
15902 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
15903 	operating_chan_freq = ap_ctx->operating_chan_freq;
15904 
15905 	if (WLAN_REG_IS_24GHZ_CH_FREQ(operating_chan_freq))
15906 		sap_operating_band = BAND_2G;
15907 	else if (WLAN_REG_IS_5GHZ_CH_FREQ(operating_chan_freq) ||
15908 		 WLAN_REG_IS_6GHZ_CHAN_FREQ(operating_chan_freq))
15909 		sap_operating_band = BAND_5G;
15910 	else
15911 		sap_operating_band = BAND_UNKNOWN;
15912 
15913 	return sap_operating_band;
15914 }
15915 
15916 /*
15917  * hdd_get_sap_operating_band:  Get current operating channel
15918  * for sap.
15919  * @hdd_ctx: hdd context
15920  *
15921  * Return : Corresponding band for SAP operating channel
15922  */
15923 uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
15924 {
15925 	struct hdd_adapter *adapter, *next_adapter = NULL;
15926 	uint8_t operating_band = 0;
15927 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_SAP_OPERATING_BAND;
15928 	struct wlan_hdd_link_info *link_info;
15929 
15930 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
15931 					   dbgid) {
15932 		if (adapter->device_mode != QDF_SAP_MODE) {
15933 			hdd_adapter_dev_put_debug(adapter, dbgid);
15934 			continue;
15935 		}
15936 
15937 		link_info = adapter->deflink;
15938 		operating_band =
15939 			hdd_get_sap_operating_band_by_link_info(link_info);
15940 
15941 		hdd_adapter_dev_put_debug(adapter, dbgid);
15942 	}
15943 
15944 	return operating_band;
15945 }
15946 
15947 static inline QDF_STATUS
15948 wlan_hdd_config_dp_direct_link_profile(struct hdd_adapter *adapter,
15949 				       enum host_concurrent_ap_policy ap_policy)
15950 {
15951 	struct wlan_objmgr_vdev *vdev = adapter->deflink->vdev;
15952 	enum host_concurrent_ap_policy prev_ap_policy;
15953 
15954 	prev_ap_policy = ucfg_mlme_get_ap_policy(vdev);
15955 
15956 	hdd_debug("Current AP policy %d prev AP policy %d", ap_policy,
15957 		  prev_ap_policy);
15958 
15959 	switch (prev_ap_policy) {
15960 	case HOST_CONCURRENT_AP_POLICY_UNSPECIFIED:
15961 		switch (ap_policy) {
15962 		case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
15963 			return ucfg_dp_config_direct_link(adapter->dev, true,
15964 							  false);
15965 		case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
15966 			return ucfg_dp_config_direct_link(adapter->dev, true,
15967 							  true);
15968 		default:
15969 			break;
15970 		}
15971 		break;
15972 	case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
15973 		switch (ap_policy) {
15974 		case HOST_CONCURRENT_AP_POLICY_UNSPECIFIED:
15975 		case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
15976 			return ucfg_dp_config_direct_link(adapter->dev, true,
15977 							  false);
15978 		default:
15979 			break;
15980 		}
15981 		break;
15982 	case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
15983 		switch (ap_policy) {
15984 		case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
15985 			return ucfg_dp_config_direct_link(adapter->dev, true,
15986 							  true);
15987 		default:
15988 			break;
15989 		}
15990 		break;
15991 	default:
15992 		break;
15993 	}
15994 
15995 	return QDF_STATUS_SUCCESS;
15996 }
15997 
15998 const struct nla_policy
15999 wlan_hdd_set_sta_roam_config_policy[
16000 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
16001 	[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
16002 	[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
16003 };
16004 
16005 /**
16006  * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
16007  * for station connection or roaming.
16008  * @wiphy: Pointer to wireless phy
16009  * @wdev: Pointer to wireless device
16010  * @data: Pointer to data
16011  * @data_len: Length of @data
16012  *
16013  * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
16014  * channels needs to be skipped in scanning or not.
16015  * If dfs_mode is disabled, driver will not scan DFS channels.
16016  * If skip_unsafe_channels is set, driver will skip unsafe channels
16017  * in Scanning.
16018  *
16019  * Return: 0 on success, negative errno on failure
16020  */
16021 static int
16022 __wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
16023 				    struct wireless_dev *wdev,
16024 				    const void *data, int data_len)
16025 {
16026 	struct net_device *dev = wdev->netdev;
16027 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16028 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16029 	struct nlattr *tb[
16030 		QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
16031 	int ret;
16032 	enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
16033 	enum dfs_mode mode = DFS_MODE_NONE;
16034 	bool skip_unsafe_channels = false;
16035 	QDF_STATUS status;
16036 	uint8_t sap_operating_band;
16037 	mac_handle_t mac_handle;
16038 
16039 	hdd_enter_dev(dev);
16040 
16041 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16042 		hdd_err("Command not allowed in FTM mode");
16043 		return -EINVAL;
16044 	}
16045 
16046 	ret = wlan_hdd_validate_context(hdd_ctx);
16047 	if (0 != ret)
16048 		return ret;
16049 	if (wlan_cfg80211_nla_parse(tb,
16050 			       QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
16051 			       data, data_len,
16052 			       wlan_hdd_set_sta_roam_config_policy)) {
16053 		hdd_err("invalid attr");
16054 		return -EINVAL;
16055 	}
16056 	if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
16057 		mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
16058 	if (!IS_DFS_MODE_VALID(mode)) {
16059 		hdd_err("attr sta roam dfs mode policy is not valid");
16060 		return -EINVAL;
16061 	}
16062 
16063 	sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
16064 
16065 	if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
16066 		skip_unsafe_channels = nla_get_u8(
16067 			tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
16068 	sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
16069 	mac_handle = hdd_ctx->mac_handle;
16070 	status = sme_update_sta_roam_policy(mac_handle, sta_roam_dfs_mode,
16071 					    skip_unsafe_channels,
16072 					    adapter->deflink->vdev_id,
16073 					    sap_operating_band);
16074 
16075 	if (!QDF_IS_STATUS_SUCCESS(status)) {
16076 		hdd_err("sme_update_sta_roam_policy (err=%d)", status);
16077 		return -EINVAL;
16078 	}
16079 	return 0;
16080 }
16081 
16082 /**
16083  * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
16084  * connection and roaming for station.
16085  * @wiphy:    wiphy structure pointer
16086  * @wdev:     Wireless device structure pointer
16087  * @data:     Pointer to the data received
16088  * @data_len: Length of @data
16089  *
16090  * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
16091  * channels needs to be skipped in scanning or not.
16092  * If dfs_mode is disabled, driver will not scan DFS channels.
16093  * If skip_unsafe_channels is set, driver will skip unsafe channels
16094  * in Scanning.
16095  * Return: 0 on success; errno on failure
16096  */
16097 static int
16098 wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
16099 				  struct wireless_dev *wdev, const void *data,
16100 				  int data_len)
16101 {
16102 	int errno;
16103 	struct osif_vdev_sync *vdev_sync;
16104 
16105 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16106 	if (errno)
16107 		return errno;
16108 
16109 	errno = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev,
16110 						    data, data_len);
16111 
16112 	osif_vdev_sync_op_stop(vdev_sync);
16113 
16114 	return errno;
16115 }
16116 
16117 const struct nla_policy
16118 wlan_hdd_set_concurrent_session_policy[
16119 QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX + 1] = {
16120 	[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG] = {.type = NLA_U8 },
16121 	[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG] = {.type = NLA_U8 },
16122 };
16123 
16124 /**
16125  * __wlan_hdd_cfg80211_dual_sta_policy() - Wrapper to configure the concurrent
16126  * session policies
16127  * @hdd_ctx: Pointer to HDD context
16128  * @tb: parsed attribute array
16129  *
16130  * Configure the concurrent session policies when multiple STA ifaces are
16131  * (getting) active.
16132  * Return: 0 on success; errno on failure
16133  */
16134 static int __wlan_hdd_cfg80211_dual_sta_policy(struct hdd_context *hdd_ctx,
16135 					       struct nlattr **tb)
16136 {
16137 	QDF_STATUS status;
16138 	uint8_t dual_sta_config =
16139 		QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED;
16140 
16141 	dual_sta_config = nla_get_u8(
16142 			tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG]);
16143 	hdd_debug("Concurrent STA policy : %d", dual_sta_config);
16144 
16145 	if (dual_sta_config > QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED)
16146 		return -EINVAL;
16147 
16148 	status = ucfg_mlme_set_dual_sta_policy(hdd_ctx->psoc, dual_sta_config);
16149 	if (QDF_IS_STATUS_ERROR(status)) {
16150 		hdd_err("failed to set MLME dual sta config");
16151 		return -EINVAL;
16152 	}
16153 
16154 	/* After SSR, the dual sta configuration is lost. As SSR is hidden from
16155 	 * userland, this command will not come from userspace after a SSR. To
16156 	 * restore this configuration, save this in hdd context and restore
16157 	 * after re-init.
16158 	 */
16159 	hdd_ctx->dual_sta_policy.dual_sta_policy = dual_sta_config;
16160 
16161 	return 0;
16162 }
16163 
16164 /**
16165  * __wlan_hdd_cfg80211_ap_policy() - Wrapper to configure the concurrent
16166  * session policies
16167  * @adapter: HDD adapter
16168  * @tb: parsed attribute array
16169  *
16170  * Configure the concurrent session policies when multiple STA ifaces are
16171  * (getting) active.
16172  * Return: 0 on success; errno on failure
16173  */
16174 static int __wlan_hdd_cfg80211_ap_policy(struct hdd_adapter *adapter,
16175 					 struct nlattr **tb)
16176 {
16177 	QDF_STATUS status;
16178 	uint8_t vdev_id;
16179 	int ret;
16180 	uint8_t ap_cfg_policy;
16181 	uint32_t profile = 0;
16182 	enum QDF_OPMODE device_mode;
16183 	uint8_t ap_config =
16184 		QCA_WLAN_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING;
16185 
16186 	vdev_id = wlan_vdev_get_id(adapter->deflink->vdev);
16187 	device_mode = hdd_get_device_mode(vdev_id);
16188 	if (device_mode != QDF_SAP_MODE) {
16189 		hdd_err_rl("command not allowed in %d mode, vdev_id: %d",
16190 			   device_mode, vdev_id);
16191 		return -EINVAL;
16192 	}
16193 
16194 	ap_config = nla_get_u8(
16195 		tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG]);
16196 	hdd_debug("AP policy : %d", ap_config);
16197 
16198 	if (ap_config > QCA_WLAN_CONCURRENT_AP_POLICY_XR) {
16199 		hdd_err_rl("Invalid concurrent policy ap config %d", ap_config);
16200 		return -EINVAL;
16201 	}
16202 
16203 	ap_cfg_policy = wlan_mlme_convert_ap_policy_config(ap_config);
16204 	if (ap_cfg_policy == HOST_CONCURRENT_AP_POLICY_XR)
16205 		profile = AP_PROFILE_XR_ENABLE;
16206 	else if (ap_cfg_policy == HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO ||
16207 		 ap_cfg_policy ==
16208 		 HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING)
16209 		profile = AP_PROFILE_XPAN_ENABLE;
16210 	ret = wma_cli_set_command(vdev_id, wmi_vdev_param_set_profile,
16211 				  profile, VDEV_CMD);
16212 	if (ret) {
16213 		hdd_err("Failed to set profile %d", profile);
16214 		return -EINVAL;
16215 	}
16216 	status = wlan_hdd_config_dp_direct_link_profile(adapter, ap_cfg_policy);
16217 	if (QDF_IS_STATUS_ERROR(status)) {
16218 		hdd_err("failed to set DP ap config");
16219 		return -EINVAL;
16220 	}
16221 	status = ucfg_mlme_set_ap_policy(adapter->deflink->vdev, ap_cfg_policy);
16222 	if (QDF_IS_STATUS_ERROR(status)) {
16223 		hdd_err("failed to set MLME ap config");
16224 		return -EINVAL;
16225 	}
16226 
16227 	wlan_mlme_ll_lt_sap_send_oce_flags_fw(adapter->deflink->vdev);
16228 	wlan_vdev_mlme_feat_ext_cap_clear(adapter->deflink->vdev,
16229 					  WLAN_VDEV_FEXT_FILS_DISC_6G_SAP);
16230 	return 0;
16231 }
16232 
16233 /**
16234  * __wlan_hdd_cfg80211_concurrent_session_policy() - Wrapper to configure the
16235  * concurrent session policies
16236  * @wiphy:    wiphy structure pointer
16237  * @wdev:     Wireless device structure pointer
16238  * @data:     Pointer to the data received
16239  * @data_len: Length of @data
16240  *
16241  * Configure the concurrent session policies when low latency SAP or multiple
16242  * STA ifaces are (getting) active.
16243  * Return: 0 on success; errno on failure
16244  */
16245 static int __wlan_hdd_cfg80211_concurrent_session_policy(
16246 						struct wiphy *wiphy,
16247 						struct wireless_dev *wdev,
16248 						const void *data, int data_len)
16249 {
16250 	struct net_device *ndev = wdev->netdev;
16251 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
16252 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX + 1];
16253 
16254 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16255 		hdd_err_rl("Command not allowed in FTM mode");
16256 		return -EPERM;
16257 	}
16258 
16259 	if (hdd_validate_adapter(adapter)) {
16260 		hdd_err_rl("Invalid adapter");
16261 		return -EINVAL;
16262 	}
16263 
16264 	if (wlan_hdd_validate_context(adapter->hdd_ctx)) {
16265 		hdd_err_rl("Invalid hdd context");
16266 		return -EINVAL;
16267 	}
16268 
16269 	if (wlan_cfg80211_nla_parse(
16270 				tb,
16271 				QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX,
16272 				data, data_len,
16273 				wlan_hdd_set_concurrent_session_policy)) {
16274 		hdd_err_rl("nla_parse failed");
16275 		return -EINVAL;
16276 	}
16277 
16278 	if (!tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG] &&
16279 	    !tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG]) {
16280 		hdd_err_rl("concurrent session policy attr not present");
16281 		return -EINVAL;
16282 	}
16283 
16284 	if (tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG])
16285 		__wlan_hdd_cfg80211_dual_sta_policy(adapter->hdd_ctx, tb);
16286 
16287 	if (tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG])
16288 		__wlan_hdd_cfg80211_ap_policy(adapter, tb);
16289 
16290 	return 0;
16291 }
16292 
16293 /**
16294  * wlan_hdd_cfg80211_concurrent_session_policy() -  Wrapper to configure the
16295  * concurrent session policies
16296  * @wiphy:    wiphy structure pointer
16297  * @wdev:     Wireless device structure pointer
16298  * @data:     Pointer to the data received
16299  * @data_len: Length of @data
16300  *
16301  * Configure the concurrent session policies when multiple STA ifaces are
16302  * (getting) active.
16303  * Return: 0 on success; errno on failure
16304  */
16305 static int wlan_hdd_cfg80211_concurrent_session_policy(
16306 						struct wiphy *wiphy,
16307 						struct wireless_dev *wdev,
16308 						const void *data,
16309 						int data_len)
16310 {
16311 	int errno;
16312 	struct osif_vdev_sync *vdev_sync;
16313 
16314 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16315 	if (errno)
16316 		return errno;
16317 
16318 	errno = __wlan_hdd_cfg80211_concurrent_session_policy(
16319 						wiphy, wdev, data,
16320 						data_len);
16321 
16322 
16323 	osif_vdev_sync_op_stop(vdev_sync);
16324 
16325 	return errno;
16326 }
16327 
16328 #ifdef FEATURE_WLAN_CH_AVOID
16329 /**
16330  * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
16331  * is on unsafe channel.
16332  * @wiphy:    wiphy structure pointer
16333  * @wdev:     Wireless device structure pointer
16334  * @data:     Pointer to the data received
16335  * @data_len: Length of @data
16336  *
16337  * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
16338  * on any of unsafe channels.
16339  * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
16340  * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
16341  *
16342  * Return: 0 on success; errno on failure
16343  */
16344 static int
16345 __wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
16346 		struct wireless_dev *wdev,
16347 		const void *data, int data_len)
16348 {
16349 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16350 	int ret;
16351 	qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
16352 	struct ch_avoid_ind_type *channel_list;
16353 	struct ch_avoid_ind_type avoid_freq_list;
16354 	enum QDF_GLOBAL_MODE curr_mode;
16355 	uint8_t num_args = 0;
16356 
16357 	hdd_enter_dev(wdev->netdev);
16358 
16359 	if (!qdf_ctx)
16360 		return -EINVAL;
16361 
16362 	curr_mode = hdd_get_conparam();
16363 	if (QDF_GLOBAL_FTM_MODE == curr_mode ||
16364 	    QDF_GLOBAL_MONITOR_MODE == curr_mode) {
16365 		hdd_err("Command not allowed in FTM/MONITOR mode");
16366 		return -EINVAL;
16367 	}
16368 
16369 	ret = wlan_hdd_validate_context(hdd_ctx);
16370 	if (0 != ret)
16371 		return ret;
16372 	qdf_mem_zero(&avoid_freq_list, sizeof(struct ch_avoid_ind_type));
16373 
16374 	if (!data && data_len == 0) {
16375 		hdd_debug("Clear avoid frequency list");
16376 		goto process_unsafe_channel;
16377 	}
16378 	if (!data || data_len < (sizeof(channel_list->ch_avoid_range_cnt) +
16379 				 sizeof(struct ch_avoid_freq_type))) {
16380 		hdd_err("Avoid frequency channel list empty");
16381 		return -EINVAL;
16382 	}
16383 	num_args = (data_len - sizeof(channel_list->ch_avoid_range_cnt)) /
16384 		   sizeof(channel_list->avoid_freq_range[0].start_freq);
16385 
16386 
16387 	if (num_args < 2 || num_args > CH_AVOID_MAX_RANGE * 2 ||
16388 	    num_args % 2 != 0) {
16389 		hdd_err("Invalid avoid frequency channel list");
16390 		return -EINVAL;
16391 	}
16392 
16393 	channel_list = (struct ch_avoid_ind_type *)data;
16394 	if (channel_list->ch_avoid_range_cnt == 0 ||
16395 	    channel_list->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE ||
16396 	    2 * channel_list->ch_avoid_range_cnt != num_args) {
16397 		hdd_err("Invalid frequency range count %d",
16398 			channel_list->ch_avoid_range_cnt);
16399 		return -EINVAL;
16400 	}
16401 
16402 	qdf_mem_copy(&avoid_freq_list, channel_list, data_len);
16403 
16404 process_unsafe_channel:
16405 	ucfg_reg_ch_avoid(hdd_ctx->psoc, &avoid_freq_list);
16406 
16407 	return 0;
16408 }
16409 
16410 /**
16411  * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
16412  * is on unsafe channel.
16413  * @wiphy:    wiphy structure pointer
16414  * @wdev:     Wireless device structure pointer
16415  * @data:     Pointer to the data received
16416  * @data_len: Length of @data
16417  *
16418  * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
16419  * on any of unsafe channels.
16420  * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
16421  * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
16422  *
16423  * Return: 0 on success; errno on failure
16424  */
16425 static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
16426 		struct wireless_dev *wdev,
16427 		const void *data, int data_len)
16428 {
16429 	struct osif_psoc_sync *psoc_sync;
16430 	int errno;
16431 
16432 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
16433 	if (errno)
16434 		return errno;
16435 
16436 	errno = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
16437 
16438 	osif_psoc_sync_op_stop(psoc_sync);
16439 
16440 	return errno;
16441 }
16442 
16443 #endif
16444 /**
16445  * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
16446  * SAP is on unsafe channel.
16447  * @wiphy:    wiphy structure pointer
16448  * @wdev:     Wireless device structure pointer
16449  * @data:     Pointer to the data received
16450  * @data_len: Length of @data
16451  *
16452  * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
16453  * driver.
16454  * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
16455  * will initiate restart of sap.
16456  *
16457  * Return: 0 on success; errno on failure
16458  */
16459 static int
16460 __wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
16461 		struct wireless_dev *wdev,
16462 		const void *data, int data_len)
16463 {
16464 	struct net_device *ndev = wdev->netdev;
16465 	struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
16466 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16467 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
16468 	struct hdd_ap_ctx *ap_ctx;
16469 	int ret;
16470 	uint32_t chan_freq = 0;
16471 	bool chan_freq_present = false;
16472 	QDF_STATUS status;
16473 	struct wlan_hdd_link_info *link_info;
16474 
16475 	hdd_enter();
16476 
16477 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16478 		hdd_err("Command not allowed in FTM mode");
16479 		return -EINVAL;
16480 	}
16481 
16482 	ret = wlan_hdd_validate_context(hdd_ctx);
16483 	if (0 != ret)
16484 		return -EINVAL;
16485 
16486 	link_info = hostapd_adapter->deflink;
16487 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
16488 				    data, data_len,
16489 				    wlan_hdd_sap_config_policy)) {
16490 		hdd_err("invalid attr");
16491 		return -EINVAL;
16492 	}
16493 
16494 	if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]) {
16495 		chan_freq = nla_get_u32(
16496 				tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]);
16497 		chan_freq_present = true;
16498 	} else if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
16499 		uint32_t config_channel =
16500 			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
16501 
16502 		chan_freq = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
16503 							 config_channel);
16504 		chan_freq_present = true;
16505 	}
16506 
16507 	if (chan_freq_present) {
16508 		if (!test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
16509 			hdd_err("SAP is not started yet. Restart sap will be invalid");
16510 			return -EINVAL;
16511 		}
16512 
16513 		if (!WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq) &&
16514 		    !WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq) &&
16515 		    !WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq)) {
16516 			hdd_err("Channel frequency %u is invalid to restart SAP",
16517 				chan_freq);
16518 			return -ENOTSUPP;
16519 		}
16520 
16521 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
16522 		ap_ctx->sap_config.chan_freq = chan_freq;
16523 		ap_ctx->sap_config.ch_params.ch_width =
16524 					ap_ctx->sap_config.ch_width_orig;
16525 		ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
16526 
16527 		if (sap_phymode_is_eht(ap_ctx->sap_config.SapHw_mode))
16528 			wlan_reg_set_create_punc_bitmap(
16529 				&ap_ctx->sap_config.ch_params, true);
16530 		wlan_reg_set_channel_params_for_pwrmode(
16531 				hdd_ctx->pdev, chan_freq,
16532 				ap_ctx->sap_config.sec_ch_freq,
16533 				&ap_ctx->sap_config.ch_params,
16534 				REG_CURRENT_PWR_MODE);
16535 
16536 		hdd_restart_sap(link_info);
16537 	}
16538 
16539 	if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
16540 		uint32_t freq_len, i;
16541 		uint32_t *freq;
16542 
16543 		hdd_debug("setting mandatory freq/chan list");
16544 
16545 		freq_len = nla_len(
16546 		    tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
16547 		    sizeof(uint32_t);
16548 
16549 		if (freq_len > NUM_CHANNELS) {
16550 			hdd_err("insufficient space to hold channels");
16551 			return -ENOMEM;
16552 		}
16553 
16554 		freq = nla_data(
16555 		    tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
16556 
16557 		hdd_debug("freq_len=%d", freq_len);
16558 
16559 		for (i = 0; i < freq_len; i++) {
16560 			hdd_debug("freq[%d]=%d", i, freq[i]);
16561 		}
16562 
16563 		status = policy_mgr_set_sap_mandatory_channels(
16564 			hdd_ctx->psoc, freq, freq_len);
16565 		if (QDF_IS_STATUS_ERROR(status))
16566 			return -EINVAL;
16567 	}
16568 
16569 	return 0;
16570 }
16571 
16572 /**
16573  * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
16574  * @wiphy:    wiphy structure pointer
16575  * @wdev:     Wireless device structure pointer
16576  * @data:     Pointer to the data received
16577  * @data_len: Length of @data
16578  *
16579  * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
16580  * driver.
16581  * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
16582  * will initiate restart of sap.
16583  *
16584  * Return: 0 on success; errno on failure
16585  */
16586 static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
16587 		struct wireless_dev *wdev,
16588 		const void *data, int data_len)
16589 {
16590 	int errno;
16591 	struct osif_vdev_sync *vdev_sync;
16592 
16593 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16594 	if (errno)
16595 		return errno;
16596 
16597 	errno = __wlan_hdd_cfg80211_sap_configuration_set(wiphy, wdev,
16598 							  data, data_len);
16599 
16600 	osif_vdev_sync_op_stop(vdev_sync);
16601 
16602 	return errno;
16603 }
16604 
16605 /**
16606  * wlan_hdd_process_wake_lock_stats() - wrapper function to absract cp_stats
16607  * or legacy get_wake_lock_stats API.
16608  * @hdd_ctx: pointer to hdd_ctx
16609  *
16610  * Return: 0 on success; error number otherwise.
16611  */
16612 static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
16613 {
16614 	return wlan_cfg80211_mc_cp_stats_get_wakelock_stats(hdd_ctx->psoc,
16615 							    hdd_ctx->wiphy);
16616 }
16617 
16618 /**
16619  * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
16620  * @wiphy: wiphy pointer
16621  * @wdev: pointer to struct wireless_dev
16622  * @data: pointer to incoming NL vendor data
16623  * @data_len: length of @data
16624  *
16625  * This function parses the incoming NL vendor command data attributes and
16626  * invokes the SME Api and blocks on a completion variable.
16627  * WMA copies required data and invokes callback
16628  * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
16629  *
16630  * Return: 0 on success; error number otherwise.
16631  */
16632 static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
16633 					struct wireless_dev *wdev,
16634 					const void *data,
16635 					int data_len)
16636 {
16637 	int ret;
16638 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16639 
16640 	hdd_enter();
16641 
16642 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16643 		hdd_err("Command not allowed in FTM mode");
16644 		return -EINVAL;
16645 	}
16646 
16647 	ret = wlan_hdd_validate_context(hdd_ctx);
16648 	if (0 != ret)
16649 		return -EINVAL;
16650 
16651 	ret = wlan_hdd_process_wake_lock_stats(hdd_ctx);
16652 	hdd_exit();
16653 	return ret;
16654 }
16655 
16656 /**
16657  * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
16658  * @wiphy: wiphy pointer
16659  * @wdev: pointer to struct wireless_dev
16660  * @data: pointer to incoming NL vendor data
16661  * @data_len: length of @data
16662  *
16663  * This function parses the incoming NL vendor command data attributes and
16664  * invokes the SME Api and blocks on a completion variable.
16665  * WMA copies required data and invokes callback
16666  * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
16667  *
16668  * Return: 0 on success; error number otherwise.
16669  */
16670 static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
16671 						struct wireless_dev *wdev,
16672 						const void *data, int data_len)
16673 {
16674 	struct osif_psoc_sync *psoc_sync;
16675 	int errno;
16676 
16677 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
16678 	if (errno)
16679 		return errno;
16680 
16681 	errno = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev,
16682 						       data, data_len);
16683 
16684 	osif_psoc_sync_op_stop(psoc_sync);
16685 
16686 	return errno;
16687 }
16688 
16689 /**
16690  * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
16691  * @wiphy:    wiphy structure pointer
16692  * @wdev:     Wireless device structure pointer
16693  * @data:     Pointer to the data received
16694  * @data_len: Length of @data
16695  *
16696  * This function reads wmi max bus size and fill in the skb with
16697  * NL attributes and send up the NL event.
16698  * Return: 0 on success; errno on failure
16699  */
16700 static int
16701 __wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
16702 				 struct wireless_dev *wdev,
16703 				 const void *data, int data_len)
16704 {
16705 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16706 	int ret_val;
16707 	struct sk_buff *skb;
16708 	uint32_t nl_buf_len;
16709 
16710 	hdd_enter();
16711 
16712 	ret_val = wlan_hdd_validate_context(hdd_ctx);
16713 	if (ret_val)
16714 		return ret_val;
16715 
16716 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16717 		hdd_err("Command not allowed in FTM mode");
16718 		return -EINVAL;
16719 	}
16720 
16721 	hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
16722 
16723 	nl_buf_len = NLMSG_HDRLEN;
16724 	nl_buf_len +=  (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
16725 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
16726 						       nl_buf_len);
16727 	if (!skb) {
16728 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
16729 		return -ENOMEM;
16730 	}
16731 
16732 	if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
16733 			hdd_ctx->wmi_max_len)) {
16734 		hdd_err("nla put failure");
16735 		goto nla_put_failure;
16736 	}
16737 
16738 	wlan_cfg80211_vendor_cmd_reply(skb);
16739 
16740 	hdd_exit();
16741 
16742 	return 0;
16743 
16744 nla_put_failure:
16745 	wlan_cfg80211_vendor_free_skb(skb);
16746 	return -EINVAL;
16747 }
16748 
16749 /**
16750  * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
16751  * @wiphy:    wiphy structure pointer
16752  * @wdev:     Wireless device structure pointer
16753  * @data:     Pointer to the data received
16754  * @data_len: Length of @data
16755  *
16756  * Return: 0 on success; errno on failure
16757  */
16758 static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
16759 					  struct wireless_dev *wdev,
16760 					  const void *data, int data_len)
16761 {
16762 	struct osif_psoc_sync *psoc_sync;
16763 	int errno;
16764 
16765 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
16766 	if (errno)
16767 		return errno;
16768 
16769 	errno = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
16770 
16771 	osif_psoc_sync_op_stop(psoc_sync);
16772 
16773 	return errno;
16774 }
16775 
16776 /**
16777  * __wlan_hdd_cfg80211_get_radio_combination_matrix() - get radio matrix info
16778  * @wiphy:   pointer to wireless wiphy structure.
16779  * @wdev:    pointer to wireless_dev structure.
16780  * @data:    Pointer to the data to be passed via vendor interface
16781  * @data_len:Length of the data to be passed
16782  *
16783  * Return:   Return the Success or Failure code.
16784  */
16785 static int
16786 __wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy *wiphy,
16787 						 struct wireless_dev *wdev,
16788 						 const void *data,
16789 						 int data_len)
16790 {
16791 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16792 	struct sk_buff *reply_skb;
16793 	int ret;
16794 	int skb_len;
16795 	struct nlattr *combination, *combination_cfg, *radio, *radio_comb;
16796 	uint32_t comb_num = 0;
16797 	struct radio_combination comb[MAX_RADIO_COMBINATION];
16798 	int comb_idx, radio_idx;
16799 	enum qca_set_band qca_band;
16800 
16801 	hdd_enter();
16802 
16803 	ret = wlan_hdd_validate_context(hdd_ctx);
16804 	if (ret)
16805 		return ret;
16806 
16807 	ucfg_policy_mgr_get_radio_combinations(hdd_ctx->psoc, comb,
16808 					       QDF_ARRAY_SIZE(comb),
16809 					       &comb_num);
16810 	if (!comb_num) {
16811 		hdd_err("invalid combination 0");
16812 		return -EINVAL;
16813 	}
16814 
16815 	/* band and antenna */
16816 	skb_len = nla_total_size(sizeof(uint32_t)) +
16817 		  nla_total_size(sizeof(uint8_t));
16818 	/* radio nested for max 2 MACs*/
16819 	skb_len = nla_total_size(skb_len) * MAX_MAC;
16820 	/* one radio combination */
16821 	skb_len = nla_total_size(nla_total_size(skb_len));
16822 	/* total combinations */
16823 	skb_len = nla_total_size(comb_num * nla_total_size(skb_len));
16824 	skb_len = NLMSG_HDRLEN + skb_len;
16825 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
16826 	if (!reply_skb) {
16827 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed, len %d",
16828 			skb_len);
16829 		return -EINVAL;
16830 	}
16831 
16832 	combination_cfg = nla_nest_start(reply_skb,
16833 			QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_SUPPORTED_CFGS);
16834 	if (!combination_cfg) {
16835 		ret = -ENOMEM;
16836 		goto err;
16837 	}
16838 	for (comb_idx = 0; comb_idx < comb_num; comb_idx++) {
16839 		combination = nla_nest_start(reply_skb, comb_idx);
16840 		if (!combination) {
16841 			ret = -ENOMEM;
16842 			goto err;
16843 		}
16844 		radio_comb = nla_nest_start(reply_skb,
16845 				QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_CFGS);
16846 		if (!radio_comb) {
16847 			ret = -ENOMEM;
16848 			goto err;
16849 		}
16850 		for (radio_idx = 0; radio_idx < MAX_MAC; radio_idx++) {
16851 			if (!comb[comb_idx].band_mask[radio_idx])
16852 				break;
16853 			radio = nla_nest_start(reply_skb, radio_idx);
16854 			if (!radio) {
16855 				ret = -ENOMEM;
16856 				goto err;
16857 			}
16858 			if (comb[comb_idx].band_mask[radio_idx] ==
16859 							BIT(REG_BAND_5G)) {
16860 				qca_band = QCA_SETBAND_5G;
16861 			} else if (comb[comb_idx].band_mask[radio_idx] ==
16862 							BIT(REG_BAND_6G)) {
16863 				qca_band = QCA_SETBAND_6G;
16864 			} else if (comb[comb_idx].band_mask[radio_idx] ==
16865 							BIT(REG_BAND_2G)) {
16866 				qca_band = QCA_SETBAND_2G;
16867 			} else {
16868 				hdd_err("invalid band mask 0 for comb %d radio %d",
16869 					comb_idx, radio_idx);
16870 				ret = -EINVAL;
16871 				goto err;
16872 			}
16873 
16874 			if (nla_put_u32(reply_skb,
16875 				       QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_BAND,
16876 				       qca_band)) {
16877 				ret = -ENOMEM;
16878 				goto err;
16879 			}
16880 			if (nla_put_u8(reply_skb,
16881 				       QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_ANTENNA,
16882 				       comb[comb_idx].antenna[radio_idx])) {
16883 				ret = -ENOMEM;
16884 				goto err;
16885 			}
16886 			hdd_debug("comb[%d]:cfg[%d]: band %d, antenna %d",
16887 				  comb_idx, radio_idx, qca_band,
16888 				  comb[comb_idx].antenna[radio_idx]);
16889 			nla_nest_end(reply_skb, radio);
16890 		}
16891 		nla_nest_end(reply_skb, radio_comb);
16892 		nla_nest_end(reply_skb, combination);
16893 	}
16894 	nla_nest_end(reply_skb, combination_cfg);
16895 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
16896 
16897 err:
16898 	wlan_cfg80211_vendor_free_skb(reply_skb);
16899 	return ret;
16900 }
16901 
16902 /**
16903  * wlan_hdd_cfg80211_get_radio_combination_matrix() - get radio matrix info
16904  * @wiphy:   pointer to wireless wiphy structure.
16905  * @wdev:    pointer to wireless_dev structure.
16906  * @data:    Pointer to the data to be passed via vendor interface
16907  * @data_len:Length of the data to be passed
16908  *
16909  * Return:   Return the Success or Failure code.
16910  */
16911 static int
16912 wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy *wiphy,
16913 					       struct wireless_dev *wdev,
16914 					       const void *data, int data_len)
16915 {
16916 	struct osif_psoc_sync *psoc_sync;
16917 	int errno;
16918 
16919 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
16920 	if (errno)
16921 		return errno;
16922 
16923 	errno = __wlan_hdd_cfg80211_get_radio_combination_matrix(wiphy, wdev,
16924 								 data,
16925 								 data_len);
16926 
16927 	osif_psoc_sync_op_stop(psoc_sync);
16928 
16929 	return errno;
16930 }
16931 
16932 const struct nla_policy setband_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
16933 	[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = {.type = NLA_U32},
16934 	[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK] = {.type = NLA_U32},
16935 };
16936 
16937 /**
16938  *__wlan_hdd_cfg80211_setband() - set band
16939  * @wiphy: Pointer to wireless phy
16940  * @wdev: Pointer to wireless device
16941  * @data: Pointer to data
16942  * @data_len: Length of @data
16943  *
16944  * Return: 0 on success, negative errno on failure
16945  */
16946 static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
16947 				       struct wireless_dev *wdev,
16948 				       const void *data, int data_len)
16949 {
16950 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16951 	struct net_device *dev = wdev->netdev;
16952 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
16953 	int ret;
16954 	uint32_t reg_wifi_band_bitmap = 0, band_val, band_mask;
16955 
16956 	hdd_enter();
16957 
16958 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16959 		hdd_err("Command not allowed in FTM mode");
16960 		return -EPERM;
16961 	}
16962 
16963 	ret = wlan_hdd_validate_context(hdd_ctx);
16964 	if (ret)
16965 		return ret;
16966 
16967 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
16968 				    data, data_len, setband_policy)) {
16969 		hdd_err("Invalid ATTR");
16970 		return -EINVAL;
16971 	}
16972 
16973 	if (tb[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK]) {
16974 		band_mask = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK]);
16975 		reg_wifi_band_bitmap =
16976 			wlan_vendor_bitmap_to_reg_wifi_band_bitmap(hdd_ctx->psoc,
16977 								   band_mask);
16978 		hdd_debug("[SET BAND] set band mask:%d", reg_wifi_band_bitmap);
16979 	} else if (tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
16980 		band_val = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]);
16981 		reg_wifi_band_bitmap =
16982 			hdd_reg_legacy_setband_to_reg_wifi_band_bitmap(
16983 								      band_val);
16984 	}
16985 
16986 	if (!reg_wifi_band_bitmap) {
16987 		hdd_err("attr SETBAND_VALUE failed");
16988 		return -EINVAL;
16989 	}
16990 
16991 	ret = hdd_reg_set_band(dev, reg_wifi_band_bitmap);
16992 
16993 	hdd_exit();
16994 	return ret;
16995 }
16996 
16997 /**
16998  * wlan_hdd_validate_acs_channel() - validate channel frequency provided by ACS
16999  * @link_info: Pointer to link_info in adapter
17000  * @chan_freq: channel frequency in MHz
17001  * @chan_bw: channel bandiodth in MHz
17002  *
17003  * return: QDF status based on success or failure
17004  */
17005 static QDF_STATUS
17006 wlan_hdd_validate_acs_channel(struct wlan_hdd_link_info *link_info,
17007 			      uint32_t chan_freq, int chan_bw)
17008 {
17009 	struct hdd_context *hdd_ctx;
17010 	struct sap_context *sap_context;
17011 
17012 	hdd_ctx = link_info->adapter->hdd_ctx;
17013 	if (QDF_STATUS_SUCCESS !=
17014 	    wlan_hdd_validate_operation_channel(hdd_ctx, chan_freq))
17015 		return QDF_STATUS_E_FAILURE;
17016 
17017 	sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
17018 	if ((wlansap_is_channel_in_nol_list(sap_context, chan_freq,
17019 					    PHY_SINGLE_CHANNEL_CENTERED))) {
17020 		hdd_info("channel %d is in nol", chan_freq);
17021 		return -EINVAL;
17022 	}
17023 
17024 	if ((wlansap_is_channel_leaking_in_nol(sap_context,
17025 					       chan_freq, chan_bw))) {
17026 		hdd_info("channel freq %d is leaking in nol", chan_freq);
17027 		return -EINVAL;
17028 	}
17029 
17030 	return 0;
17031 
17032 }
17033 
17034 static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
17035 				     struct sap_config *sap_config,
17036 				     struct hdd_vendor_chan_info *channel_list)
17037 {
17038 	uint8_t ch_width;
17039 	QDF_STATUS status;
17040 	uint32_t channel_bonding_mode;
17041 
17042 	sap_config->chan_freq = channel_list->pri_chan_freq;
17043 
17044 	sap_config->ch_params.center_freq_seg0 =
17045 		wlan_reg_freq_to_chan(hdd_ctx->pdev,
17046 				      channel_list->vht_seg0_center_chan_freq);
17047 	sap_config->ch_params.center_freq_seg1 =
17048 		wlan_reg_freq_to_chan(hdd_ctx->pdev,
17049 				      channel_list->vht_seg1_center_chan_freq);
17050 
17051 	sap_config->ch_params.sec_ch_offset =
17052 		wlan_reg_freq_to_chan(hdd_ctx->pdev,
17053 				      channel_list->ht_sec_chan_freq);
17054 
17055 	sap_config->ch_params.ch_width =
17056 				hdd_map_nl_chan_width(channel_list->chan_width);
17057 	if (!WLAN_REG_IS_24GHZ_CH_FREQ(sap_config->chan_freq)) {
17058 		status =
17059 			ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
17060 							&ch_width);
17061 		if (!QDF_IS_STATUS_SUCCESS(status))
17062 			hdd_err("Failed to set channel_width");
17063 		sap_config->ch_width_orig = ch_width;
17064 	} else {
17065 		ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
17066 						    &channel_bonding_mode);
17067 		sap_config->ch_width_orig = channel_bonding_mode ?
17068 			CH_WIDTH_40MHZ : CH_WIDTH_20MHZ;
17069 	}
17070 	sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
17071 	sap_config->acs_cfg.ch_width =
17072 				hdd_map_nl_chan_width(channel_list->chan_width);
17073 	sap_config->acs_cfg.vht_seg0_center_ch_freq =
17074 			channel_list->vht_seg0_center_chan_freq;
17075 	sap_config->acs_cfg.vht_seg1_center_ch_freq =
17076 			channel_list->vht_seg1_center_chan_freq;
17077 	sap_config->acs_cfg.ht_sec_ch_freq =
17078 			channel_list->ht_sec_chan_freq;
17079 }
17080 
17081 static int hdd_update_acs_channel(struct wlan_hdd_link_info *link_info,
17082 				  uint8_t reason, uint8_t channel_cnt,
17083 				  struct hdd_vendor_chan_info *channel_list)
17084 {
17085 	struct sap_config *sap_config;
17086 	struct hdd_ap_ctx *hdd_ap_ctx;
17087 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
17088 	QDF_STATUS status = QDF_STATUS_SUCCESS;
17089 	mac_handle_t mac_handle;
17090 	uint32_t ch;
17091 
17092 	if (!channel_list) {
17093 		hdd_err("channel_list is NULL");
17094 		return -EINVAL;
17095 	}
17096 
17097 	hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
17098 	sap_config = &link_info->session.ap.sap_config;
17099 
17100 	if (QDF_TIMER_STATE_RUNNING ==
17101 	    qdf_mc_timer_get_current_state(&hdd_ap_ctx->vendor_acs_timer)) {
17102 		qdf_mc_timer_stop(&hdd_ap_ctx->vendor_acs_timer);
17103 	}
17104 
17105 	if (channel_list->pri_chan_freq == 0) {
17106 		/* Check mode, set default channel */
17107 		channel_list->pri_chan_freq = 2437;
17108 		/*
17109 		 * sap_select_default_oper_chan(mac_handle,
17110 		 *      sap_config->acs_cfg.hw_mode);
17111 		 */
17112 	}
17113 
17114 	mac_handle = hdd_ctx->mac_handle;
17115 	switch (reason) {
17116 	/* SAP init case */
17117 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
17118 		hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
17119 		/* Update Hostapd */
17120 		wlan_hdd_cfg80211_acs_ch_select_evt(link_info, true);
17121 		break;
17122 
17123 	/* DFS detected on current channel */
17124 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
17125 		ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
17126 					   channel_list->pri_chan_freq);
17127 
17128 		wlan_sap_update_next_channel(
17129 			WLAN_HDD_GET_SAP_CTX_PTR(link_info), (uint8_t)ch,
17130 			hdd_map_nl_chan_width(channel_list->chan_width));
17131 		status = sme_update_new_channel_event(
17132 					mac_handle, link_info->vdev_id);
17133 		break;
17134 
17135 	/* LTE coex event on current channel */
17136 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
17137 		ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
17138 					   channel_list->pri_chan_freq);
17139 		sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
17140 		sap_config->acs_cfg.ch_width =
17141 				hdd_map_nl_chan_width(channel_list->chan_width);
17142 		hdd_ap_ctx->sap_config.ch_width_orig =
17143 				sap_config->acs_cfg.ch_width;
17144 		wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc,
17145 					    link_info->vdev_id,
17146 					    CSA_REASON_LTE_COEX);
17147 		hdd_switch_sap_channel(link_info, (uint8_t)ch, true);
17148 		break;
17149 
17150 	default:
17151 		hdd_info("invalid reason for timer invoke");
17152 	}
17153 	hdd_exit();
17154 	return qdf_status_to_os_return(status);
17155 }
17156 
17157 /*
17158  * Define short name for vendor channel set config
17159  */
17160 #define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
17161 #define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
17162 #define SET_CHAN_PRIMARY_CHANNEL \
17163 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
17164 #define SET_CHAN_SECONDARY_CHANNEL \
17165 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
17166 #define SET_CHAN_SEG0_CENTER_CHANNEL \
17167 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
17168 #define	SET_CHAN_SEG1_CENTER_CHANNEL \
17169 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
17170 #define	SET_CHAN_CHANNEL_WIDTH \
17171 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
17172 
17173 #define SET_CHAN_FREQ_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST
17174 #define SET_CHAN_FREQUENCY_PRIMARY \
17175 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY
17176 #define SET_CHAN_FREQUENCY_SECONDARY \
17177 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY
17178 #define SET_CHAN_SEG0_CENTER_FREQUENCY \
17179 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0
17180 #define SET_CHAN_SEG1_CENTER_FREQUENCY \
17181 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1
17182 
17183 #define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
17184 #define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
17185 
17186 static const struct nla_policy acs_chan_config_policy[SET_CHAN_MAX + 1] = {
17187 	[SET_CHAN_REASON] = {.type = NLA_U8},
17188 	[SET_CHAN_CHAN_LIST] = {.type = NLA_NESTED},
17189 	[SET_CHAN_FREQ_LIST] = {.type = NLA_NESTED},
17190 };
17191 
17192 static const struct nla_policy acs_chan_list_policy[SET_CHAN_MAX + 1] = {
17193 	[SET_CHAN_PRIMARY_CHANNEL] = {.type = NLA_U8},
17194 	[SET_CHAN_SECONDARY_CHANNEL] = {.type = NLA_U8},
17195 	[SET_CHAN_SEG0_CENTER_CHANNEL] = {.type = NLA_U8},
17196 	[SET_CHAN_SEG1_CENTER_CHANNEL] = {.type = NLA_U8},
17197 	[SET_CHAN_CHANNEL_WIDTH] = {.type = NLA_U8},
17198 	[SET_EXT_ACS_BAND] = {.type = NLA_U8},
17199 
17200 	[SET_CHAN_FREQUENCY_PRIMARY] = {.type = NLA_U32},
17201 	[SET_CHAN_FREQUENCY_SECONDARY] = {.type = NLA_U32},
17202 	[SET_CHAN_SEG0_CENTER_FREQUENCY] = {.type = NLA_U32},
17203 	[SET_CHAN_SEG1_CENTER_FREQUENCY] = {.type = NLA_U32},
17204 };
17205 
17206 /**
17207  * hdd_extract_external_acs_frequencies() - API to parse and extract vendor acs
17208  * channel frequency (in MHz) configuration.
17209  * @hdd_ctx: pointer to hdd context
17210  * @list_ptr: pointer to hdd_vendor_chan_info
17211  * @channel_cnt: channel count
17212  * @data: data
17213  * @data_len: data len
17214  *
17215  * Return: 0 on success, negative errno on failure
17216  */
17217 static int
17218 hdd_extract_external_acs_frequencies(struct hdd_context *hdd_ctx,
17219 				     struct hdd_vendor_chan_info **list_ptr,
17220 				     uint8_t *channel_cnt,
17221 				     const void *data, int data_len)
17222 {
17223 	int rem;
17224 	uint32_t i = 0;
17225 	struct nlattr *tb[SET_CHAN_MAX + 1];
17226 	struct nlattr *tb2[SET_CHAN_MAX + 1];
17227 	struct nlattr *curr_attr;
17228 	struct hdd_vendor_chan_info *channel_list;
17229 
17230 	if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
17231 				    acs_chan_config_policy)) {
17232 		hdd_err("Invalid ATTR");
17233 		return -EINVAL;
17234 	}
17235 
17236 	nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem)
17237 		i++;
17238 
17239 	if (!i) {
17240 		hdd_err_rl("Error: channel count is zero");
17241 		return -EINVAL;
17242 	}
17243 
17244 	if (i > NUM_CHANNELS) {
17245 		hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
17246 		return -ENOMEM;
17247 	}
17248 
17249 	channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
17250 	if (!channel_list)
17251 		return -ENOMEM;
17252 
17253 	*channel_cnt = (uint8_t)i;
17254 	i = 0;
17255 	nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem) {
17256 		if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
17257 						   curr_attr,
17258 						   acs_chan_list_policy)) {
17259 			hdd_err_rl("nla_parse failed");
17260 			qdf_mem_free(channel_list);
17261 			*channel_cnt = 0;
17262 			return -EINVAL;
17263 		}
17264 
17265 		if (tb2[SET_EXT_ACS_BAND])
17266 			channel_list[i].band =
17267 				nla_get_u8(tb2[SET_EXT_ACS_BAND]);
17268 
17269 		if (tb2[SET_CHAN_FREQUENCY_PRIMARY])
17270 			channel_list[i].pri_chan_freq =
17271 				nla_get_u32(tb2[SET_CHAN_FREQUENCY_PRIMARY]);
17272 
17273 		if (tb2[SET_CHAN_FREQUENCY_SECONDARY])
17274 			channel_list[i].ht_sec_chan_freq =
17275 				nla_get_u32(tb2[SET_CHAN_FREQUENCY_SECONDARY]);
17276 
17277 		if (tb2[SET_CHAN_SEG0_CENTER_FREQUENCY])
17278 			channel_list[i].vht_seg0_center_chan_freq =
17279 			 nla_get_u32(tb2[SET_CHAN_SEG0_CENTER_FREQUENCY]);
17280 
17281 		if (tb2[SET_CHAN_SEG1_CENTER_FREQUENCY])
17282 			channel_list[i].vht_seg1_center_chan_freq =
17283 			 nla_get_u32(tb2[SET_CHAN_SEG1_CENTER_FREQUENCY]);
17284 
17285 		if (tb2[SET_CHAN_CHANNEL_WIDTH])
17286 			channel_list[i].chan_width =
17287 				nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
17288 
17289 		hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
17290 			  i, channel_list[i].pri_chan_freq,
17291 			  channel_list[i].ht_sec_chan_freq,
17292 			  channel_list[i].vht_seg0_center_chan_freq,
17293 			  channel_list[i].vht_seg1_center_chan_freq,
17294 			  channel_list[i].chan_width);
17295 		i++;
17296 	}
17297 	*list_ptr = channel_list;
17298 
17299 	return 0;
17300 }
17301 
17302 /**
17303  * hdd_extract_external_acs_channels() - API to parse and extract vendor acs
17304  * channel configuration.
17305  * @hdd_ctx: pointer to hdd context
17306  * @list_ptr: pointer to hdd_vendor_chan_info
17307  * @channel_cnt: channel count
17308  * @data: data
17309  * @data_len: data len
17310  *
17311  * Return: 0 on success, negative errno on failure
17312  */
17313 static int
17314 hdd_extract_external_acs_channels(struct hdd_context *hdd_ctx,
17315 				  struct hdd_vendor_chan_info **list_ptr,
17316 				  uint8_t *channel_cnt,
17317 				  const void *data, int data_len)
17318 {
17319 	int rem;
17320 	uint32_t i = 0;
17321 	struct nlattr *tb[SET_CHAN_MAX + 1];
17322 	struct nlattr *tb2[SET_CHAN_MAX + 1];
17323 	struct nlattr *curr_attr;
17324 	struct hdd_vendor_chan_info *channel_list;
17325 
17326 	if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
17327 				    acs_chan_config_policy)) {
17328 		hdd_err("Invalid ATTR");
17329 		return -EINVAL;
17330 	}
17331 
17332 	nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
17333 		i++;
17334 
17335 	if (!i) {
17336 		hdd_err_rl("Error: channel count is zero");
17337 		return -EINVAL;
17338 	}
17339 
17340 	if (i > NUM_CHANNELS) {
17341 		hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
17342 		return -ENOMEM;
17343 	}
17344 
17345 	channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
17346 	if (!channel_list)
17347 		return -ENOMEM;
17348 
17349 	*channel_cnt = (uint8_t)i;
17350 	i = 0;
17351 	nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
17352 		if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
17353 						   curr_attr,
17354 						   acs_chan_list_policy)) {
17355 			hdd_err("nla_parse failed");
17356 			qdf_mem_free(channel_list);
17357 			*channel_cnt = 0;
17358 			return -EINVAL;
17359 		}
17360 
17361 		if (tb2[SET_EXT_ACS_BAND]) {
17362 			channel_list[i].band =
17363 				nla_get_u8(tb2[SET_EXT_ACS_BAND]);
17364 		}
17365 
17366 		if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
17367 			uint32_t ch =
17368 				nla_get_u8(tb2[SET_CHAN_PRIMARY_CHANNEL]);
17369 
17370 			channel_list[i].pri_chan_freq =
17371 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
17372 		}
17373 
17374 		if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
17375 			uint32_t ch =
17376 				nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
17377 
17378 			channel_list[i].ht_sec_chan_freq =
17379 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
17380 		}
17381 
17382 		if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
17383 			uint32_t ch =
17384 				nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
17385 
17386 			channel_list[i].vht_seg0_center_chan_freq =
17387 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
17388 		}
17389 
17390 		if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
17391 			uint32_t ch =
17392 				nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
17393 
17394 			channel_list[i].vht_seg1_center_chan_freq =
17395 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
17396 		}
17397 
17398 		if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
17399 			channel_list[i].chan_width =
17400 				nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
17401 		}
17402 		hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
17403 			  i, channel_list[i].pri_chan_freq,
17404 			  channel_list[i].ht_sec_chan_freq,
17405 			  channel_list[i].vht_seg0_center_chan_freq,
17406 			  channel_list[i].vht_seg1_center_chan_freq,
17407 			  channel_list[i].chan_width);
17408 		i++;
17409 	}
17410 	*list_ptr = channel_list;
17411 
17412 	return 0;
17413 }
17414 
17415 /**
17416  * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
17417  * @hdd_ctx: pointer to hdd context
17418  * @chan_list_ptr: pointer to hdd_vendor_chan_info
17419  * @reason: channel change reason
17420  * @channel_cnt: channel count
17421  * @data: data
17422  * @data_len: data len
17423  *
17424  * Return: 0 on success, negative errno on failure
17425  */
17426 static int
17427 hdd_parse_vendor_acs_chan_config(struct hdd_context *hdd_ctx,
17428 				 struct hdd_vendor_chan_info **chan_list_ptr,
17429 				 uint8_t *reason, uint8_t *channel_cnt,
17430 				 const void *data, int data_len)
17431 {
17432 	struct nlattr *tb[SET_CHAN_MAX + 1];
17433 	int ret;
17434 
17435 	if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
17436 				    acs_chan_config_policy)) {
17437 		hdd_err("Invalid ATTR");
17438 		return -EINVAL;
17439 	}
17440 
17441 	if (tb[SET_CHAN_REASON])
17442 		*reason = nla_get_u8(tb[SET_CHAN_REASON]);
17443 
17444 	if (!tb[SET_CHAN_FREQ_LIST] && !tb[SET_CHAN_CHAN_LIST]) {
17445 		hdd_err("Both channel list and frequency list are empty");
17446 		return -EINVAL;
17447 	}
17448 
17449 	if (tb[SET_CHAN_FREQ_LIST]) {
17450 		ret = hdd_extract_external_acs_frequencies(hdd_ctx,
17451 							   chan_list_ptr,
17452 							   channel_cnt,
17453 							   data, data_len);
17454 		if (ret) {
17455 			hdd_err("Failed to extract frequencies");
17456 			return ret;
17457 		}
17458 
17459 		return 0;
17460 	}
17461 
17462 	ret = hdd_extract_external_acs_channels(hdd_ctx, chan_list_ptr,
17463 						channel_cnt, data, data_len);
17464 	if (ret)
17465 		hdd_err("Failed to extract channels");
17466 
17467 	return ret;
17468 }
17469 
17470 /*
17471  * Undef short names for vendor set channel configuration
17472  */
17473 #undef SET_CHAN_REASON
17474 #undef SET_CHAN_CHAN_LIST
17475 #undef SET_CHAN_PRIMARY_CHANNEL
17476 #undef SET_CHAN_SECONDARY_CHANNEL
17477 #undef SET_CHAN_SEG0_CENTER_CHANNEL
17478 #undef SET_CHAN_SEG1_CENTER_CHANNEL
17479 
17480 #undef SET_CHAN_FREQ_LIST
17481 #undef SET_CHAN_FREQUENCY_PRIMARY
17482 #undef SET_CHAN_FREQUENCY_SECONDARY
17483 #undef SET_CHAN_SEG0_CENTER_FREQUENCY
17484 #undef SET_CHAN_SEG1_CENTER_FREQUENCY
17485 
17486 #undef SET_CHAN_CHANNEL_WIDTH
17487 #undef SET_CHAN_MAX
17488 
17489 /**
17490  * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
17491  * @wiphy: Pointer to wireless phy
17492  * @wdev: Pointer to wireless device
17493  * @data: Pointer to data
17494  * @data_len: Length of @data
17495  *
17496  * Return: 0 on success, negative errno on failure
17497  */
17498 static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
17499 						     struct wireless_dev *wdev,
17500 						     const void *data,
17501 						     int data_len)
17502 {
17503 	int ret_val;
17504 	QDF_STATUS status;
17505 	enum phy_ch_width phy_ch_width;
17506 	uint8_t channel_cnt = 0, reason = -1;
17507 	struct hdd_vendor_chan_info *chan_list = NULL;
17508 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
17509 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17510 	struct hdd_vendor_chan_info *chan_list_ptr;
17511 	struct wlan_hdd_link_info *link_info = adapter->deflink;
17512 
17513 	hdd_enter();
17514 
17515 	ret_val = wlan_hdd_validate_context(hdd_ctx);
17516 	if (ret_val)
17517 		return ret_val;
17518 
17519 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
17520 		hdd_err("Command not allowed in FTM mode");
17521 		return -EINVAL;
17522 	}
17523 
17524 	if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &link_info->link_flags)) {
17525 		clear_bit(VENDOR_ACS_RESPONSE_PENDING, &link_info->link_flags);
17526 	} else {
17527 		hdd_err("already timeout happened for acs");
17528 		return -EINVAL;
17529 	}
17530 
17531 	ret_val = hdd_parse_vendor_acs_chan_config(hdd_ctx, &chan_list,
17532 						   &reason, &channel_cnt, data,
17533 						   data_len);
17534 	chan_list_ptr = chan_list;
17535 	if (ret_val)
17536 		return ret_val;
17537 
17538 	/* Validate channel to be set */
17539 	while (channel_cnt && chan_list) {
17540 		phy_ch_width = hdd_map_nl_chan_width(chan_list->chan_width);
17541 		status = wlan_hdd_validate_acs_channel(link_info,
17542 						       chan_list->pri_chan_freq,
17543 						       phy_ch_width);
17544 		if (status == QDF_STATUS_SUCCESS)
17545 			break;
17546 		else if (channel_cnt == 1) {
17547 			hdd_err("invalid channel frequ %u received from app",
17548 				chan_list->pri_chan_freq);
17549 			chan_list->pri_chan_freq = 0;
17550 			break;
17551 		}
17552 
17553 		channel_cnt--;
17554 		chan_list++;
17555 	}
17556 
17557 	if ((channel_cnt <= 0) || !chan_list) {
17558 		hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
17559 			chan_list);
17560 		qdf_mem_free(chan_list_ptr);
17561 		return -EINVAL;
17562 	}
17563 
17564 	hdd_debug("received primary channel freq as %d",
17565 		  chan_list->pri_chan_freq);
17566 
17567 	ret_val = hdd_update_acs_channel(link_info, reason,
17568 					 channel_cnt, chan_list);
17569 	qdf_mem_free(chan_list_ptr);
17570 	return ret_val;
17571 }
17572 
17573 /**
17574  * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
17575  * @wiphy: Pointer to wireless phy
17576  * @wdev: Pointer to wireless device
17577  * @data: Pointer to data
17578  * @data_len: Length of @data
17579  *
17580  * Return: 0 on success, negative errno on failure
17581  */
17582 static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
17583 						struct wireless_dev *wdev,
17584 						const void *data, int data_len)
17585 {
17586 	int errno;
17587 	struct osif_vdev_sync *vdev_sync;
17588 
17589 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
17590 	if (errno)
17591 		return errno;
17592 
17593 	errno = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev,
17594 							  data, data_len);
17595 
17596 	osif_vdev_sync_op_stop(vdev_sync);
17597 
17598 	return errno;
17599 }
17600 
17601 /**
17602  * wlan_hdd_cfg80211_setband() - Wrapper to setband
17603  * @wiphy:    wiphy structure pointer
17604  * @wdev:     Wireless device structure pointer
17605  * @data:     Pointer to the data received
17606  * @data_len: Length of @data
17607  *
17608  * Return: 0 on success; errno on failure
17609  */
17610 static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
17611 				    struct wireless_dev *wdev,
17612 				    const void *data, int data_len)
17613 {
17614 	int errno;
17615 	struct osif_vdev_sync *vdev_sync;
17616 
17617 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
17618 	if (errno)
17619 		return errno;
17620 
17621 	errno = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
17622 
17623 	osif_vdev_sync_op_stop(vdev_sync);
17624 
17625 	return errno;
17626 }
17627 
17628 /**
17629  *__wlan_hdd_cfg80211_getband() - get band
17630  * @wiphy: Pointer to wireless phy
17631  * @wdev: Pointer to wireless device
17632  * @data: Pointer to data
17633  * @data_len: Length of @data
17634  *
17635  * Return: 0 on success, negative errno on failure
17636  */
17637 static int __wlan_hdd_cfg80211_getband(struct wiphy *wiphy,
17638 				       struct wireless_dev *wdev,
17639 				       const void *data, int data_len)
17640 {
17641 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17642 	struct sk_buff *skb;
17643 	QDF_STATUS status = QDF_STATUS_SUCCESS;
17644 	int ret;
17645 	uint32_t reg_wifi_band_bitmap, vendor_band_mask;
17646 
17647 	hdd_enter();
17648 
17649 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17650 		hdd_err("Command not allowed in FTM mode");
17651 		return -EPERM;
17652 	}
17653 
17654 	ret = wlan_hdd_validate_context(hdd_ctx);
17655 	if (ret)
17656 		return ret;
17657 
17658 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
17659 						       sizeof(uint32_t) +
17660 						       NLA_HDRLEN);
17661 
17662 	if (!skb) {
17663 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
17664 		return -ENOMEM;
17665 	}
17666 
17667 	status = ucfg_reg_get_band(hdd_ctx->pdev, &reg_wifi_band_bitmap);
17668 	if (!QDF_IS_STATUS_SUCCESS(status)) {
17669 		hdd_err("failed to get band");
17670 		goto failure;
17671 	}
17672 
17673 	vendor_band_mask = wlan_reg_wifi_band_bitmap_to_vendor_bitmap(
17674 							reg_wifi_band_bitmap);
17675 
17676 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SETBAND_MASK,
17677 			vendor_band_mask)) {
17678 		hdd_err("nla put failure");
17679 		goto failure;
17680 	}
17681 
17682 	wlan_cfg80211_vendor_cmd_reply(skb);
17683 
17684 	hdd_exit();
17685 
17686 	return 0;
17687 
17688 failure:
17689 	wlan_cfg80211_vendor_free_skb(skb);
17690 	return -EINVAL;
17691 }
17692 
17693 /**
17694  * wlan_hdd_cfg80211_getband() - Wrapper to getband
17695  * @wiphy:    wiphy structure pointer
17696  * @wdev:     Wireless device structure pointer
17697  * @data:     Pointer to the data received
17698  * @data_len: Length of @data
17699  *
17700  * Return: 0 on success; errno on failure
17701  */
17702 static int wlan_hdd_cfg80211_getband(struct wiphy *wiphy,
17703 				     struct wireless_dev *wdev,
17704 				     const void *data, int data_len)
17705 {
17706 	int errno;
17707 	struct osif_vdev_sync *vdev_sync;
17708 
17709 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
17710 	if (errno)
17711 		return errno;
17712 
17713 	errno = __wlan_hdd_cfg80211_getband(wiphy, wdev, data, data_len);
17714 
17715 	osif_vdev_sync_op_stop(vdev_sync);
17716 
17717 	return errno;
17718 }
17719 
17720 static const struct
17721 nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
17722 	[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
17723 	[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]       = {.type = NLA_BINARY,
17724 						 .len = QDF_MAC_ADDR_SIZE},
17725 };
17726 
17727 void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
17728 				struct rso_cmd_status *rso_status)
17729 {
17730 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
17731 	struct wlan_hdd_link_info *link_info;
17732 
17733 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, rso_status->vdev_id);
17734 	if (!link_info) {
17735 		hdd_err("Invalid vdev");
17736 		return;
17737 	}
17738 
17739 	link_info->adapter->lfr_fw_status.is_disabled = rso_status->status;
17740 	complete(&link_info->adapter->lfr_fw_status.disable_lfr_event);
17741 }
17742 
17743 /**
17744  * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
17745  * @wiphy: Pointer to wireless phy
17746  * @wdev: Pointer to wireless device
17747  * @data: Pointer to data
17748  * @data_len: Length of @data
17749  *
17750  * This function is used to enable/disable roaming using vendor commands
17751  *
17752  * Return: 0 on success, negative errno on failure
17753  */
17754 static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
17755 						struct wireless_dev *wdev,
17756 						const void *data, int data_len)
17757 {
17758 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17759 	struct net_device *dev = wdev->netdev;
17760 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
17761 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
17762 	uint32_t is_fast_roam_enabled;
17763 	int ret;
17764 	QDF_STATUS qdf_status;
17765 	unsigned long rc;
17766 	bool roaming_enabled;
17767 
17768 	hdd_enter_dev(dev);
17769 
17770 	ret = wlan_hdd_validate_context(hdd_ctx);
17771 	if (0 != ret)
17772 		return ret;
17773 
17774 	if (adapter->device_mode != QDF_STA_MODE) {
17775 		hdd_err_rl("command not allowed in %d mode, vdev_id: %d",
17776 			   adapter->device_mode, adapter->deflink->vdev_id);
17777 		return -EINVAL;
17778 	}
17779 
17780 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17781 		hdd_err("Command not allowed in FTM mode");
17782 		return -EINVAL;
17783 	}
17784 
17785 	ret = wlan_cfg80211_nla_parse(tb,
17786 				      QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
17787 				      qca_wlan_vendor_attr);
17788 	if (ret) {
17789 		hdd_err("Invalid ATTR");
17790 		return -EINVAL;
17791 	}
17792 
17793 	/* Parse and fetch Enable flag */
17794 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
17795 		hdd_err("attr enable failed");
17796 		return -EINVAL;
17797 	}
17798 
17799 	is_fast_roam_enabled = nla_get_u32(
17800 				tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
17801 	hdd_debug("ROAM_CONFIG: isFastRoamEnabled %d", is_fast_roam_enabled);
17802 
17803 	if (sme_roaming_in_progress(hdd_ctx->mac_handle,
17804 				    adapter->deflink->vdev_id)) {
17805 		hdd_err_rl("Roaming in progress for vdev %d",
17806 			   adapter->deflink->vdev_id);
17807 		return -EAGAIN;
17808 	}
17809 
17810 	/*
17811 	 * Get current roaming state and decide whether to wait for RSO_STOP
17812 	 * response or not.
17813 	 */
17814 	roaming_enabled = ucfg_is_rso_enabled(hdd_ctx->pdev,
17815 					      adapter->deflink->vdev_id);
17816 
17817 	/* Update roaming */
17818 	qdf_status = ucfg_user_space_enable_disable_rso(
17819 						hdd_ctx->pdev,
17820 						adapter->deflink->vdev_id,
17821 						is_fast_roam_enabled);
17822 	if (QDF_IS_STATUS_ERROR(qdf_status))
17823 		hdd_err("ROAM_CONFIG: sme_config_fast_roaming failed with status=%d",
17824 			qdf_status);
17825 
17826 	ret = qdf_status_to_os_return(qdf_status);
17827 
17828 	if (hdd_cm_is_vdev_associated(adapter->deflink) &&
17829 	    roaming_enabled &&
17830 	    QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
17831 		INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
17832 		/*
17833 		 * wait only for LFR disable in fw as LFR enable
17834 		 * is always success
17835 		 */
17836 		rc = wait_for_completion_timeout(
17837 				&adapter->lfr_fw_status.disable_lfr_event,
17838 				msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
17839 		if (!rc) {
17840 			hdd_err("Timed out waiting for RSO CMD status");
17841 			return -ETIMEDOUT;
17842 		}
17843 
17844 		if (!adapter->lfr_fw_status.is_disabled) {
17845 			hdd_err("Roam disable attempt in FW fails");
17846 			return -EBUSY;
17847 		}
17848 	}
17849 
17850 	hdd_exit();
17851 	return ret;
17852 }
17853 
17854 /**
17855  * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
17856  * @wiphy: Pointer to wireless phy
17857  * @wdev: Pointer to wireless device
17858  * @data: Pointer to data
17859  * @data_len: Length of @data
17860  *
17861  * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
17862  *
17863  * Return: 0 on success, negative errno on failure
17864  */
17865 static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
17866 					  struct wireless_dev *wdev,
17867 					  const void *data, int data_len)
17868 {
17869 	int errno;
17870 	struct osif_vdev_sync *vdev_sync;
17871 
17872 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
17873 	if (errno)
17874 		return errno;
17875 
17876 	errno = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev,
17877 						     data, data_len);
17878 
17879 	osif_vdev_sync_op_stop(vdev_sync);
17880 
17881 	return errno;
17882 }
17883 
17884 /*
17885  * define short names for the global vendor params
17886  * used by wlan_hdd_cfg80211_setarp_stats_cmd()
17887  */
17888 #define STATS_SET_INVALID \
17889 	QCA_ATTR_NUD_STATS_SET_INVALID
17890 #define STATS_SET_START \
17891 	QCA_ATTR_NUD_STATS_SET_START
17892 #define STATS_GW_IPV4 \
17893 	QCA_ATTR_NUD_STATS_GW_IPV4
17894 #define STATS_SET_DATA_PKT_INFO \
17895 		QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
17896 #define STATS_SET_MAX \
17897 	QCA_ATTR_NUD_STATS_SET_MAX
17898 
17899 const struct nla_policy
17900 qca_wlan_vendor_set_nud_stats_policy[STATS_SET_MAX + 1] = {
17901 	[STATS_SET_START] = {.type = NLA_FLAG },
17902 	[STATS_GW_IPV4] = {.type = NLA_U32 },
17903 	[STATS_SET_DATA_PKT_INFO] = {.type = NLA_NESTED },
17904 };
17905 
17906 /* define short names for the global vendor params */
17907 #define CONNECTIVITY_STATS_SET_INVALID \
17908 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
17909 #define STATS_PKT_INFO_TYPE \
17910 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
17911 #define STATS_DNS_DOMAIN_NAME \
17912 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
17913 #define STATS_SRC_PORT \
17914 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
17915 #define STATS_DEST_PORT \
17916 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
17917 #define STATS_DEST_IPV4 \
17918 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
17919 #define STATS_DEST_IPV6 \
17920 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
17921 #define CONNECTIVITY_STATS_SET_MAX \
17922 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
17923 
17924 const struct nla_policy
17925 qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
17926 	[STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
17927 	[STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
17928 					.len = DNS_DOMAIN_NAME_MAX_LEN },
17929 	[STATS_SRC_PORT] = {.type = NLA_U32 },
17930 	[STATS_DEST_PORT] = {.type = NLA_U32 },
17931 	[STATS_DEST_IPV4] = {.type = NLA_U32 },
17932 	[STATS_DEST_IPV6] = {.type = NLA_BINARY,
17933 					.len = ICMPv6_ADDR_LEN },
17934 };
17935 
17936 const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
17937 		QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
17938 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] =
17939 	VENDOR_NLA_POLICY_NESTED(qca_wlan_vendor_set_trace_level_policy),
17940 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
17941 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
17942 };
17943 
17944 /**
17945  * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
17946  * @wiphy: Pointer to wireless phy
17947  * @wdev: Pointer to wireless device
17948  * @data: Pointer to data
17949  * @data_len: Length of @data
17950  *
17951  * Return: 0 on success, negative errno on failure
17952  */
17953 static int
17954 __wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
17955 					struct wireless_dev *wdev,
17956 					const void *data,
17957 					int data_len)
17958 {
17959 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17960 	struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
17961 	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
17962 	struct nlattr *apth;
17963 	int rem;
17964 	int ret = 1;
17965 	int print_idx = -1;
17966 	int module_id = -1;
17967 	int bit_mask = -1;
17968 	int status;
17969 
17970 	hdd_enter();
17971 
17972 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
17973 		hdd_err("Command not allowed in FTM mode");
17974 		return -EINVAL;
17975 	}
17976 
17977 	ret = wlan_hdd_validate_context(hdd_ctx);
17978 	if (ret != 0)
17979 		return -EINVAL;
17980 
17981 	print_idx = qdf_get_pidx();
17982 	if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
17983 		hdd_err("Invalid print control object index");
17984 		return -EINVAL;
17985 	}
17986 
17987 	if (wlan_cfg80211_nla_parse(tb1,
17988 				    QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
17989 				    data, data_len,
17990 				    qca_wlan_vendor_set_trace_level_policy)) {
17991 		hdd_err("Invalid attr");
17992 		return -EINVAL;
17993 	}
17994 
17995 	if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
17996 		hdd_err("attr trace level param failed");
17997 		return -EINVAL;
17998 	}
17999 
18000 	nla_for_each_nested(apth,
18001 			tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
18002 		if (wlan_cfg80211_nla_parse(tb2,
18003 				     QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
18004 				     nla_data(apth), nla_len(apth),
18005 				     qca_wlan_vendor_set_trace_level_policy)) {
18006 			hdd_err("Invalid attr");
18007 			return -EINVAL;
18008 		}
18009 
18010 		if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
18011 			hdd_err("attr Module ID failed");
18012 			return -EINVAL;
18013 		}
18014 		module_id = nla_get_u32
18015 			(tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
18016 
18017 		if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
18018 			hdd_err("attr Verbose mask failed");
18019 			return -EINVAL;
18020 		}
18021 		bit_mask = nla_get_u32
18022 		      (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
18023 
18024 		status = hdd_qdf_trace_enable(module_id, bit_mask);
18025 
18026 		if (status != 0)
18027 			hdd_err("can not set verbose mask %d for the category %d",
18028 				bit_mask, module_id);
18029 	}
18030 
18031 	hdd_exit();
18032 	return ret;
18033 }
18034 
18035 /**
18036  * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
18037  * @wiphy: Pointer to wireless phy
18038  * @wdev: Pointer to wireless device
18039  * @data: Pointer to data
18040  * @data_len: Length of @data
18041  *
18042  * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
18043  *
18044  * Return: 0 on success, negative errno on failure
18045  */
18046 
18047 static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
18048 						struct wireless_dev *wdev,
18049 						const void *data,
18050 						int data_len)
18051 {
18052 	struct osif_psoc_sync *psoc_sync;
18053 	int errno;
18054 
18055 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
18056 	if (errno)
18057 		return errno;
18058 
18059 	errno = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev,
18060 						    data, data_len);
18061 
18062 	osif_psoc_sync_op_stop(psoc_sync);
18063 
18064 	return errno;
18065 }
18066 
18067 /**
18068  * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
18069  * @wiphy: pointer to wireless wiphy structure.
18070  * @wdev: pointer to wireless_dev structure.
18071  * @data: pointer to apfind configuration data.
18072  * @data_len: the length in byte of apfind data.
18073  *
18074  * This is called when wlan driver needs to send arp stats to
18075  * firmware.
18076  *
18077  * Return: An error code or 0 on success.
18078  */
18079 static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
18080 					     struct wireless_dev *wdev,
18081 					     const void *data, int data_len)
18082 {
18083 	struct net_device   *dev = wdev->netdev;
18084 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18085 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18086 	struct wlan_objmgr_vdev *vdev;
18087 	int err = 0;
18088 
18089 	hdd_enter();
18090 
18091 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18092 		hdd_err("Command not allowed in FTM mode");
18093 		return -EINVAL;
18094 	}
18095 
18096 	err = wlan_hdd_validate_context(hdd_ctx);
18097 	if (0 != err)
18098 		return err;
18099 
18100 	if (adapter->deflink->vdev_id == WLAN_UMAC_VDEV_ID_MAX) {
18101 		hdd_err("Invalid vdev id");
18102 		return -EINVAL;
18103 	}
18104 
18105 	if (adapter->device_mode != QDF_STA_MODE) {
18106 		hdd_err("STATS supported in only STA mode!");
18107 		return -EINVAL;
18108 	}
18109 
18110 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
18111 		hdd_debug("Not Associated");
18112 		return 0;
18113 	}
18114 
18115 	if (hdd_is_roaming_in_progress(hdd_ctx))
18116 		return -EINVAL;
18117 
18118 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
18119 	if (!vdev)
18120 		return -EINVAL;
18121 
18122 	err = osif_dp_set_nud_stats(wiphy, vdev, data, data_len);
18123 
18124 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
18125 
18126 	hdd_exit();
18127 
18128 	return err;
18129 }
18130 
18131 /**
18132  * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
18133  * @wiphy: pointer to wireless wiphy structure.
18134  * @wdev: pointer to wireless_dev structure.
18135  * @data: pointer to apfind configuration data.
18136  * @data_len: the length in byte of apfind data.
18137  *
18138  * This is called when wlan driver needs to send arp stats to
18139  * firmware.
18140  *
18141  * Return: An error code or 0 on success.
18142  */
18143 static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
18144 					   struct wireless_dev *wdev,
18145 					   const void *data, int data_len)
18146 {
18147 	int errno;
18148 	struct osif_vdev_sync *vdev_sync;
18149 
18150 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18151 	if (errno)
18152 		return errno;
18153 
18154 	errno = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
18155 
18156 	osif_vdev_sync_op_stop(vdev_sync);
18157 
18158 	return errno;
18159 }
18160 
18161 #undef STATS_SET_INVALID
18162 #undef STATS_SET_START
18163 #undef STATS_GW_IPV4
18164 #undef STATS_SET_MAX
18165 
18166 /*
18167  * define short names for the global vendor params
18168  * used by wlan_hdd_cfg80211_setarp_stats_cmd()
18169  */
18170 #define STATS_GET_INVALID \
18171 	QCA_ATTR_NUD_STATS_SET_INVALID
18172 #define COUNT_FROM_NETDEV \
18173 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
18174 #define COUNT_TO_LOWER_MAC \
18175 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
18176 #define RX_COUNT_BY_LOWER_MAC \
18177 	QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
18178 #define COUNT_TX_SUCCESS \
18179 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
18180 #define RSP_RX_COUNT_BY_LOWER_MAC \
18181 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
18182 #define RSP_RX_COUNT_BY_UPPER_MAC \
18183 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
18184 #define RSP_COUNT_TO_NETDEV \
18185 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
18186 #define RSP_COUNT_OUT_OF_ORDER_DROP \
18187 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
18188 #define AP_LINK_ACTIVE \
18189 	QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
18190 #define AP_LINK_DAD \
18191 	QCA_ATTR_NUD_STATS_IS_DAD
18192 #define DATA_PKT_STATS \
18193 	QCA_ATTR_NUD_STATS_DATA_PKT_STATS
18194 #define STATS_GET_MAX \
18195 	QCA_ATTR_NUD_STATS_GET_MAX
18196 
18197 #define CHECK_STATS_INVALID \
18198 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
18199 #define CHECK_STATS_PKT_TYPE \
18200 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
18201 #define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
18202 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
18203 #define CHECK_STATS_PKT_SRC_PORT \
18204 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
18205 #define CHECK_STATS_PKT_DEST_PORT \
18206 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
18207 #define CHECK_STATS_PKT_DEST_IPV4 \
18208 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
18209 #define CHECK_STATS_PKT_DEST_IPV6 \
18210 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
18211 #define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
18212 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
18213 #define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
18214 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
18215 #define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
18216 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
18217 #define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
18218 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
18219 #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
18220 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
18221 #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
18222 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
18223 #define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
18224 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
18225 #define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
18226 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
18227 #define CHECK_DATA_STATS_MAX \
18228 	QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
18229 
18230 
18231 const struct nla_policy
18232 qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
18233 	[COUNT_FROM_NETDEV] = {.type = NLA_U16 },
18234 	[COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
18235 	[RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
18236 	[COUNT_TX_SUCCESS] = {.type = NLA_U16 },
18237 	[RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
18238 	[RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
18239 	[RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
18240 	[RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
18241 	[AP_LINK_ACTIVE] = {.type = NLA_FLAG },
18242 	[AP_LINK_DAD] = {.type = NLA_FLAG },
18243 	[DATA_PKT_STATS] = {.type = NLA_U16 },
18244 };
18245 
18246 /**
18247  * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
18248  * @wiphy: pointer to wireless wiphy structure.
18249  * @wdev: pointer to wireless_dev structure.
18250  * @data: pointer to apfind configuration data.
18251  * @data_len: the length in byte of apfind data.
18252  *
18253  * This is called when wlan driver needs to get arp stats to
18254  * firmware.
18255  *
18256  * Return: An error code or 0 on success.
18257  */
18258 static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
18259 					     struct wireless_dev *wdev,
18260 					     const void *data, int data_len)
18261 {
18262 	int err = 0;
18263 	struct net_device *dev = wdev->netdev;
18264 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18265 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18266 	struct wlan_objmgr_vdev *vdev;
18267 
18268 	hdd_enter();
18269 
18270 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18271 		hdd_err("Command not allowed in FTM mode");
18272 		return -EINVAL;
18273 	}
18274 
18275 	err = wlan_hdd_validate_context(hdd_ctx);
18276 	if (0 != err)
18277 		return err;
18278 
18279 	err = hdd_validate_adapter(adapter);
18280 	if (err)
18281 		return err;
18282 
18283 	if (adapter->device_mode != QDF_STA_MODE) {
18284 		hdd_err("STATS supported in only STA mode!");
18285 		return -EINVAL;
18286 	}
18287 
18288 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
18289 	if (!vdev)
18290 		return -EINVAL;
18291 
18292 	err = osif_dp_get_nud_stats(wiphy, vdev, data, data_len);
18293 
18294 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
18295 
18296 	return err;
18297 }
18298 
18299 /**
18300  * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
18301  * @wiphy: pointer to wireless wiphy structure.
18302  * @wdev: pointer to wireless_dev structure.
18303  * @data: pointer to apfind configuration data.
18304  * @data_len: the length in byte of apfind data.
18305  *
18306  * This is called when wlan driver needs to get arp stats to
18307  * firmware.
18308  *
18309  * Return: An error code or 0 on success.
18310  */
18311 static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
18312 					   struct wireless_dev *wdev,
18313 					   const void *data, int data_len)
18314 {
18315 	int errno;
18316 	struct osif_vdev_sync *vdev_sync;
18317 
18318 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18319 	if (errno)
18320 		return errno;
18321 
18322 	errno = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
18323 
18324 	osif_vdev_sync_op_stop(vdev_sync);
18325 
18326 	return errno;
18327 }
18328 
18329 #undef QCA_ATTR_NUD_STATS_SET_INVALID
18330 #undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
18331 #undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
18332 #undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
18333 #undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
18334 #undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
18335 #undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
18336 #undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
18337 #undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
18338 #undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
18339 #undef QCA_ATTR_NUD_STATS_GET_MAX
18340 
18341 void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity)
18342 {
18343 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
18344 	int status;
18345 
18346 	status = wlan_hdd_validate_context(hdd_ctx);
18347 	if (0 != status)
18348 		return;
18349 
18350 	if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
18351 		hdd_ctx->bt_a2dp_active = 1;
18352 	else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
18353 		hdd_ctx->bt_a2dp_active = 0;
18354 	else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
18355 		hdd_ctx->bt_vo_active = 1;
18356 	else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
18357 		hdd_ctx->bt_vo_active = 0;
18358 	else if (bt_activity == WLAN_COEX_EVENT_BT_PROFILE_CONNECTED)
18359 		hdd_ctx->bt_profile_con = 1;
18360 	else if (bt_activity == WLAN_COEX_EVENT_BT_PROFILE_DISCONNECTED)
18361 		hdd_ctx->bt_profile_con = 0;
18362 	else
18363 		return;
18364 
18365 	ucfg_scan_set_bt_activity(hdd_ctx->psoc, hdd_ctx->bt_a2dp_active);
18366 	hdd_debug("a2dp_active: %d vo_active: %d connected:%d",
18367 		  hdd_ctx->bt_a2dp_active,
18368 		  hdd_ctx->bt_vo_active, hdd_ctx->bt_profile_con);
18369 }
18370 
18371 /**
18372  * hdd_post_chain_rssi_rsp - send rsp to user space
18373  * @adapter: Pointer to adapter
18374  * @result: chain rssi result
18375  * @update_chain_rssi: update rssi, if this flag is set
18376  * @update_chain_evm: update evm, if this flag is set
18377  * @update_ant_id: update antenna id, if this flag is set
18378  *
18379  * Return: 0 for success, non-zero for failure
18380  */
18381 static int hdd_post_chain_rssi_rsp(struct hdd_adapter *adapter,
18382 				   struct chain_rssi_result *result,
18383 				   bool update_chain_rssi,
18384 				   bool update_chain_evm,
18385 				   bool update_ant_id)
18386 {
18387 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18388 	struct sk_buff *skb;
18389 	int len = NLMSG_HDRLEN;
18390 
18391 	len += update_chain_rssi ?
18392 		nla_total_size(sizeof(result->chain_rssi)) : 0;
18393 	len += update_chain_evm ?
18394 		nla_total_size(sizeof(result->chain_evm)) : 0;
18395 	len += update_ant_id ?
18396 		nla_total_size(sizeof(result->ant_id)) : 0;
18397 
18398 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, len);
18399 	if (!skb) {
18400 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
18401 		return -ENOMEM;
18402 	}
18403 
18404 	if (update_chain_rssi &&
18405 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI,
18406 		    sizeof(result->chain_rssi),
18407 		    result->chain_rssi)) {
18408 		goto nla_put_failure;
18409 	}
18410 
18411 	if (update_chain_evm &&
18412 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_EVM,
18413 		    sizeof(result->chain_evm),
18414 		    result->chain_evm)) {
18415 		goto nla_put_failure;
18416 	}
18417 
18418 	if (update_ant_id &&
18419 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO,
18420 		    sizeof(result->ant_id),
18421 		    result->ant_id)) {
18422 		goto nla_put_failure;
18423 	}
18424 
18425 	wlan_cfg80211_vendor_cmd_reply(skb);
18426 	return 0;
18427 
18428 nla_put_failure:
18429 	hdd_err("nla put fail");
18430 	wlan_cfg80211_vendor_free_skb(skb);
18431 	return -EINVAL;
18432 }
18433 
18434 #ifdef QCA_SUPPORT_CP_STATS
18435 /**
18436  * hdd_process_peer_chain_rssi_req() - fetch per chain rssi of a connected peer
18437  * @adapter: Pointer to adapter
18438  * @peer_macaddr: mac address of desired peer or AP
18439  *
18440  * Return: 0 for success, non-zero for failure
18441  */
18442 static int hdd_process_peer_chain_rssi_req(struct hdd_adapter *adapter,
18443 					   struct qdf_mac_addr *peer_macaddr)
18444 {
18445 	struct stats_event *stats;
18446 	struct wlan_objmgr_vdev *vdev;
18447 	struct chain_rssi_result chain_rssi;
18448 	int retval, index;
18449 
18450 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
18451 	if (!vdev)
18452 		return -EINVAL;
18453 
18454 	stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(vdev,
18455 							 peer_macaddr->bytes,
18456 							 &retval);
18457 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
18458 
18459 	if (retval || !stats) {
18460 		if (stats)
18461 			wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
18462 		hdd_err("Unable to get chain rssi from fw");
18463 		return retval;
18464 	}
18465 
18466 	for (index = 0; index < WMI_MAX_CHAINS; index++)
18467 		chain_rssi.chain_rssi[index] =
18468 		stats->peer_stats_info_ext->peer_rssi_per_chain[index];
18469 
18470 	wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
18471 
18472 	retval = hdd_post_chain_rssi_rsp(adapter, &chain_rssi,
18473 					 true, false, false);
18474 	if (retval)
18475 		hdd_err("Failed to post chain rssi");
18476 
18477 	return retval;
18478 }
18479 #else
18480 struct chain_rssi_priv {
18481 	struct chain_rssi_result chain_rssi;
18482 };
18483 
18484 /**
18485  * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
18486  * @context: opaque context originally passed to SME. HDD always passes
18487  * a cookie for the request context
18488  * @data: struct for get chain rssi
18489  *
18490  * This function receives the response/data from the lower layer and
18491  * checks to see if the thread is still waiting then post the results to
18492  * upper layer, if the request has timed out then ignore.
18493  *
18494  * Return: None
18495  */
18496 static void hdd_get_chain_rssi_cb(void *context,
18497 				  struct chain_rssi_result *data)
18498 {
18499 	struct osif_request *request;
18500 	struct chain_rssi_priv *priv;
18501 
18502 	hdd_enter();
18503 
18504 	request = osif_request_get(context);
18505 	if (!request) {
18506 		hdd_err("Obsolete request");
18507 		return;
18508 	}
18509 
18510 	priv = osif_request_priv(request);
18511 	priv->chain_rssi = *data;
18512 	osif_request_complete(request);
18513 	osif_request_put(request);
18514 }
18515 
18516 static int hdd_process_peer_chain_rssi_req(struct hdd_adapter *adapter,
18517 					   struct qdf_mac_addr *peer_macaddr)
18518 {
18519 	mac_handle_t mac_handle;
18520 	struct osif_request *request;
18521 	struct chain_rssi_priv *priv;
18522 	struct get_chain_rssi_req_params req_msg;
18523 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18524 	QDF_STATUS status;
18525 	int retval;
18526 	void *cookie;
18527 	static const struct osif_request_params params = {
18528 		.priv_size = sizeof(*priv),
18529 		.timeout_ms = WLAN_WAIT_TIME_STATS,
18530 	};
18531 
18532 	memcpy(&req_msg.peer_macaddr, peer_macaddr->bytes, QDF_MAC_ADDR_SIZE);
18533 	req_msg.session_id = adapter->deflink->vdev_id;
18534 
18535 	request = osif_request_alloc(&params);
18536 	if (!request) {
18537 		hdd_err("Request allocation failure");
18538 		return -ENOMEM;
18539 	}
18540 
18541 	cookie = osif_request_cookie(request);
18542 	mac_handle = hdd_ctx->mac_handle;
18543 	status = sme_get_chain_rssi(mac_handle,
18544 				    &req_msg,
18545 				    hdd_get_chain_rssi_cb,
18546 				    cookie);
18547 
18548 	if (status != QDF_STATUS_SUCCESS) {
18549 		hdd_err("Unable to get chain rssi");
18550 		retval = qdf_status_to_os_return(status);
18551 	} else {
18552 		retval = osif_request_wait_for_response(request);
18553 		if (retval) {
18554 			hdd_err("Target response timed out");
18555 		} else {
18556 			priv = osif_request_priv(request);
18557 			retval = hdd_post_chain_rssi_rsp(adapter,
18558 							 &priv->chain_rssi,
18559 							 true, true, true);
18560 			if (retval)
18561 				hdd_err("Failed to post chain rssi");
18562 		}
18563 	}
18564 	osif_request_put(request);
18565 	return retval;
18566 }
18567 #endif
18568 
18569 static const struct
18570 nla_policy get_chain_rssi_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
18571 	[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]       = {.type = NLA_BINARY,
18572 		.len = QDF_MAC_ADDR_SIZE},
18573 };
18574 
18575 static const struct nla_policy
18576 get_chan_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX + 1] = {
18577 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID] = {.type = NLA_U32},
18578 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ] = {.type = NLA_U32},
18579 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ] = {.type = NLA_U32},
18580 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ] = {.type = NLA_U32},
18581 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH] = {.type = NLA_U32},
18582 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK] = {.type = NLA_U32},
18583 };
18584 
18585 static const struct nla_policy
18586 get_usable_channel_policy[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1] = {
18587 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID] = {
18588 		.type = NLA_U32
18589 	},
18590 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK] = {
18591 		.type = NLA_U32
18592 	},
18593 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK] = {
18594 		.type = NLA_U32
18595 	},
18596 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK] = {
18597 		.type = NLA_U32
18598 	},
18599 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO] = {
18600 		.type = NLA_NESTED
18601 	},
18602 };
18603 
18604 #ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
18605 static enum nl80211_chan_width
18606 hdd_convert_phy_bw_to_nl_bw(enum phy_ch_width bw)
18607 {
18608 	switch (bw) {
18609 	case CH_WIDTH_20MHZ:
18610 		return NL80211_CHAN_WIDTH_20;
18611 	case CH_WIDTH_40MHZ:
18612 		return NL80211_CHAN_WIDTH_40;
18613 	case CH_WIDTH_160MHZ:
18614 		return NL80211_CHAN_WIDTH_160;
18615 	case CH_WIDTH_80MHZ:
18616 		return NL80211_CHAN_WIDTH_80;
18617 	case CH_WIDTH_80P80MHZ:
18618 		return NL80211_CHAN_WIDTH_80P80;
18619 	case CH_WIDTH_5MHZ:
18620 		return NL80211_CHAN_WIDTH_5;
18621 	case CH_WIDTH_10MHZ:
18622 		return NL80211_CHAN_WIDTH_10;
18623 #if defined(CFG80211_11BE_BASIC)
18624 	case CH_WIDTH_320MHZ:
18625 		return NL80211_CHAN_WIDTH_320;
18626 #else
18627 	case CH_WIDTH_320MHZ:
18628 		return NL80211_CHAN_WIDTH_20;
18629 #endif
18630 	case CH_WIDTH_INVALID:
18631 	case CH_WIDTH_MAX:
18632 		return NL80211_CHAN_WIDTH_20;
18633 	}
18634 
18635 	return NL80211_CHAN_WIDTH_20;
18636 }
18637 
18638 /**
18639  * hdd_fill_usable_channels_data() - Fill the data requested by userspace
18640  * @skb: SK buffer
18641  * @tb: List of attributes
18642  * @res_msg: structure of usable channel info
18643  * @count: no of usable channels
18644  *
18645  * Get the data corresponding to the attribute list specified in tb and
18646  * update the same to skb by populating the same attributes.
18647  *
18648  * Return: 0 on success; error number on failure
18649  */
18650 static int
18651 hdd_fill_usable_channels_data(struct sk_buff *skb, struct nlattr **tb,
18652 			      struct get_usable_chan_res_params *res_msg,
18653 			      int count)
18654 {
18655 	struct nlattr *config, *chan_params;
18656 	uint8_t i, bw, j = 0;
18657 
18658 	config = nla_nest_start(skb,
18659 				QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO);
18660 	if (!config) {
18661 		hdd_err("nla nest start failure");
18662 		return -EINVAL;
18663 	}
18664 	for (i = 0; i < count ; i++) {
18665 		if (!res_msg[i].freq)
18666 			continue;
18667 		chan_params = nla_nest_start(skb, j);
18668 		if (!chan_params)
18669 			return -EINVAL;
18670 		j++;
18671 		bw = hdd_convert_phy_bw_to_nl_bw(res_msg[i].bw);
18672 		if (nla_put_u32(skb,
18673 				QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ,
18674 				res_msg[i].freq) ||
18675 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ,
18676 				res_msg[i].seg0_freq) ||
18677 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ,
18678 				res_msg[i].seg1_freq) ||
18679 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH,
18680 				bw) ||
18681 		    nla_put_u32(skb,
18682 				QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK,
18683 				res_msg[i].iface_mode_mask)) {
18684 			hdd_err("nla put failure");
18685 			return -EINVAL;
18686 		}
18687 
18688 		nla_nest_end(skb, chan_params);
18689 	}
18690 	nla_nest_end(skb, config);
18691 	return 0;
18692 }
18693 
18694 /**
18695  * hdd_get_usable_channel_len() - calculate the length required by skb
18696  * @count: number of usable channels
18697  *
18698  * Find the required length to send usable channel data to upper layer
18699  *
18700  * Return: required len
18701  */
18702 static uint32_t
18703 hdd_get_usable_channel_len(uint32_t count)
18704 {
18705 	uint32_t len = 0;
18706 	struct get_usable_chan_res_params res_msg;
18707 
18708 	len = nla_total_size(sizeof(res_msg.freq)) +
18709 		nla_total_size(sizeof(res_msg.seg0_freq)) +
18710 		nla_total_size(sizeof(res_msg.seg1_freq)) +
18711 		nla_total_size(sizeof(res_msg.bw)) +
18712 		nla_total_size(sizeof(res_msg.iface_mode_mask));
18713 
18714 	return len * count;
18715 }
18716 
18717 /**
18718  * hdd_send_usable_channel() - Send usable channels as vendor cmd reply
18719  * @hdd_ctx: Pointer to hdd context
18720  * @res_msg: pointer to usable channel information
18721  * @count: number of channels
18722  * @tb: List of attributes
18723  *
18724  * Parse the attributes list tb and  get the data corresponding to the
18725  * attributes specified in tb. Send them as a vendor response.
18726  *
18727  * Return: 0 on success; error number on failure
18728  */
18729 static int
18730 hdd_send_usable_channel(struct hdd_context *hdd_ctx,
18731 			struct get_usable_chan_res_params *res_msg,
18732 			uint32_t count,
18733 			struct nlattr **tb)
18734 {
18735 	struct sk_buff *skb;
18736 	uint32_t skb_len;
18737 	int status;
18738 
18739 	skb_len = hdd_get_usable_channel_len(count);
18740 	if (!skb_len) {
18741 		hdd_err("No data requested");
18742 		return -EINVAL;
18743 	}
18744 
18745 	skb_len += NLMSG_HDRLEN;
18746 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
18747 	if (!skb) {
18748 		hdd_info("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
18749 		return -ENOMEM;
18750 	}
18751 
18752 	status = hdd_fill_usable_channels_data(skb, tb, res_msg, count);
18753 	if (status)
18754 		goto fail;
18755 
18756 	return wlan_cfg80211_vendor_cmd_reply(skb);
18757 
18758 fail:
18759 	hdd_err("nla put fail");
18760 	wlan_cfg80211_vendor_free_skb(skb);
18761 	return status;
18762 }
18763 
18764 /**
18765  * hdd_get_all_band_mask() - get supported nl80211 bands
18766  *
18767  * Return: supported band mask
18768  */
18769 static uint32_t
18770 hdd_get_all_band_mask(void)
18771 {
18772 	uint32_t band_mask = 0;
18773 
18774 	band_mask =
18775 		(1 << REG_BAND_2G) | (1 << REG_BAND_5G) | (1 << REG_BAND_6G);
18776 
18777 	return band_mask;
18778 }
18779 
18780 /**
18781  * hdd_get_all_iface_mode_mask() - get supported nl80211 iface mode
18782  *
18783  * Return: supported iface mode mask
18784  */
18785 static uint32_t
18786 hdd_get_all_iface_mode_mask(void)
18787 {
18788 	uint32_t mode_mask = 0;
18789 
18790 	mode_mask = (1 << NL80211_IFTYPE_STATION) |
18791 			(1 << NL80211_IFTYPE_AP) |
18792 			(1 << NL80211_IFTYPE_P2P_GO) |
18793 			(1 << NL80211_IFTYPE_P2P_CLIENT) |
18794 			(1 << NL80211_IFTYPE_P2P_DEVICE) |
18795 			(1 << NL80211_IFTYPE_NAN);
18796 
18797 	return mode_mask;
18798 }
18799 
18800 /**
18801  * hdd_convert_nl80211_to_reg_band_mask() - convert n80211 band to reg band
18802  * @band: nl80211 band
18803  *
18804  * Return: reg band value
18805  */
18806 
18807 static uint32_t
18808 hdd_convert_nl80211_to_reg_band_mask(enum nl80211_band band)
18809 {
18810 	uint32_t reg_band = 0;
18811 
18812 	if (band & 1 << NL80211_BAND_2GHZ)
18813 		reg_band |= 1 << REG_BAND_2G;
18814 	if (band & 1 << NL80211_BAND_5GHZ)
18815 		reg_band |= 1 << REG_BAND_5G;
18816 	if (band & 1 << NL80211_BAND_6GHZ)
18817 		reg_band |= 1 << REG_BAND_6G;
18818 	if (band & 1 << NL80211_BAND_60GHZ)
18819 		hdd_err("band: %d not supported", NL80211_BAND_60GHZ);
18820 
18821 	return reg_band;
18822 }
18823 
18824 /**
18825  * __wlan_hdd_cfg80211_get_usable_channel() - get chain rssi
18826  * @wiphy: wiphy pointer
18827  * @wdev: pointer to struct wireless_dev
18828  * @data: pointer to incoming NL vendor data
18829  * @data_len: length of @data
18830  *
18831  * Return: 0 on success; error number otherwise.
18832  */
18833 static int __wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
18834 						  struct wireless_dev *wdev,
18835 						  const void *data,
18836 						  int data_len)
18837 {
18838 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18839 	struct get_usable_chan_req_params req_msg = {0};
18840 	struct get_usable_chan_res_params *res_msg;
18841 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1];
18842 	int ret = 0;
18843 	uint32_t count = 0;
18844 	QDF_STATUS status;
18845 
18846 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18847 		hdd_err("Command not allowed in FTM mode");
18848 		return -EPERM;
18849 	}
18850 
18851 	ret = wlan_hdd_validate_context(hdd_ctx);
18852 	if (0 != ret)
18853 		return ret;
18854 
18855 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
18856 		hdd_err("Driver Modules are closed");
18857 		return -EINVAL;
18858 	}
18859 
18860 	res_msg = qdf_mem_malloc(NUM_CHANNELS *
18861 				 sizeof(*res_msg));
18862 
18863 	if (!res_msg) {
18864 		hdd_err("res_msg invalid");
18865 		return -EINVAL;
18866 	}
18867 
18868 	if (wlan_cfg80211_nla_parse(
18869 				tb, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX,
18870 				data, data_len, get_usable_channel_policy)) {
18871 		hdd_err("Invalid ATTR");
18872 		ret = -EINVAL;
18873 		goto err;
18874 	}
18875 
18876 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]) {
18877 		hdd_err("band mask not present");
18878 		req_msg.band_mask = hdd_get_all_band_mask();
18879 	} else {
18880 		req_msg.band_mask =
18881 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]);
18882 		if (!req_msg.band_mask)
18883 			req_msg.band_mask = hdd_get_all_band_mask();
18884 		else
18885 			req_msg.band_mask =
18886 			hdd_convert_nl80211_to_reg_band_mask(req_msg.band_mask);
18887 	}
18888 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]) {
18889 		hdd_err("iface mode mask not present");
18890 		req_msg.iface_mode_mask = hdd_get_all_iface_mode_mask();
18891 	} else {
18892 		req_msg.iface_mode_mask = nla_get_u32(
18893 		tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]);
18894 		if (!req_msg.iface_mode_mask)
18895 			req_msg.iface_mode_mask = hdd_get_all_iface_mode_mask();
18896 	}
18897 
18898 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]) {
18899 		hdd_err("usable channels filter mask not present");
18900 		req_msg.filter_mask = 0;
18901 	} else {
18902 		req_msg.filter_mask =
18903 			nla_get_u32(
18904 			tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]);
18905 	}
18906 
18907 	hdd_debug("get usable channel list for band %d mode %d filter %d",
18908 		  req_msg.band_mask, req_msg.iface_mode_mask,
18909 		  req_msg.filter_mask);
18910 
18911 	status = wlan_reg_get_usable_channel(hdd_ctx->pdev, req_msg,
18912 					     res_msg, &count,
18913 					     REG_CURRENT_PWR_MODE);
18914 	if (QDF_STATUS_SUCCESS != status) {
18915 		hdd_err("get usable channel failed %d", status);
18916 		ret = -EINVAL;
18917 		goto err;
18918 	}
18919 	hdd_debug("usable channel count : %d", count);
18920 
18921 	ret = hdd_send_usable_channel(hdd_ctx, res_msg, count, tb);
18922 	if (ret) {
18923 		hdd_err("failed to send usable_channels");
18924 		ret = -EINVAL;
18925 		goto err;
18926 	}
18927 
18928 err:
18929 	qdf_mem_free(res_msg);
18930 	if (ret)
18931 		return ret;
18932 	return qdf_status_to_os_return(status);
18933 }
18934 #endif
18935 
18936 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
18937 /**
18938  * enum roam_stats_set_params - Different types of params to set the roam stats
18939  * @ROAM_RT_STATS_DISABLED:                Roam stats feature disabled
18940  * @ROAM_RT_STATS_ENABLED:                 Roam stats feature enabled
18941  * @ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE: Roam stats enabled in suspend mode
18942  */
18943 enum roam_stats_set_params {
18944 	ROAM_RT_STATS_DISABLED = 0,
18945 	ROAM_RT_STATS_ENABLED = 1,
18946 	ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE = 2,
18947 };
18948 
18949 #define EVENTS_CONFIGURE QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE
18950 #define SUSPEND_STATE    QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE
18951 
18952 static const struct nla_policy
18953 set_roam_events_policy[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX + 1] = {
18954 	[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE] = {.type = NLA_U8},
18955 	[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE] = {.type = NLA_FLAG},
18956 };
18957 
18958 /**
18959  * __wlan_hdd_cfg80211_set_roam_events() - set roam stats
18960  * @wiphy: wiphy pointer
18961  * @wdev: pointer to struct wireless_dev
18962  * @data: pointer to incoming NL vendor data
18963  * @data_len: length of @data
18964  *
18965  * Return: 0 on success; error number otherwise.
18966  */
18967 static int __wlan_hdd_cfg80211_set_roam_events(struct wiphy *wiphy,
18968 					       struct wireless_dev *wdev,
18969 					       const void *data,
18970 					       int data_len)
18971 {
18972 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18973 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
18974 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX + 1];
18975 	QDF_STATUS status;
18976 	int ret;
18977 	uint8_t config, state, param = 0;
18978 
18979 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18980 		hdd_err("Command not allowed in FTM mode");
18981 		return -EPERM;
18982 	}
18983 
18984 	ret = wlan_hdd_validate_context(hdd_ctx);
18985 	if (ret != 0) {
18986 		hdd_err("Invalid hdd_ctx");
18987 		return ret;
18988 	}
18989 
18990 	ret = hdd_validate_adapter(adapter);
18991 	if (ret != 0) {
18992 		hdd_err("Invalid adapter");
18993 		return ret;
18994 	}
18995 
18996 	if (adapter->device_mode != QDF_STA_MODE) {
18997 		hdd_err("STATS supported in only STA mode!");
18998 		return -EINVAL;
18999 	}
19000 
19001 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX,
19002 				    data, data_len, set_roam_events_policy)) {
19003 		hdd_err("Invalid ATTR");
19004 		return -EINVAL;
19005 	}
19006 
19007 	if (!tb[EVENTS_CONFIGURE]) {
19008 		hdd_err("roam events configure not present");
19009 		return -EINVAL;
19010 	}
19011 
19012 	config = nla_get_u8(tb[EVENTS_CONFIGURE]);
19013 	hdd_debug("roam stats configured: %d", config);
19014 
19015 	if (!tb[SUSPEND_STATE]) {
19016 		hdd_debug("suspend state not present");
19017 		param = config ? ROAM_RT_STATS_ENABLED : ROAM_RT_STATS_DISABLED;
19018 	} else if (config == ROAM_RT_STATS_ENABLED) {
19019 		state = nla_get_flag(tb[SUSPEND_STATE]);
19020 		hdd_debug("Suspend state configured: %d", state);
19021 		param = ROAM_RT_STATS_ENABLED |
19022 			ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE;
19023 	}
19024 
19025 	hdd_debug("roam events param: %d", param);
19026 	ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc,
19027 				     param, ROAM_RT_STATS_ENABLE);
19028 
19029 	if (param == (ROAM_RT_STATS_ENABLED |
19030 		      ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE)) {
19031 		ucfg_pmo_enable_wakeup_event(hdd_ctx->psoc,
19032 					     adapter->deflink->vdev_id,
19033 					     WOW_ROAM_STATS_EVENT);
19034 		ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc,
19035 					     ROAM_RT_STATS_ENABLED,
19036 					     ROAM_RT_STATS_SUSPEND_MODE_ENABLE);
19037 	} else if (ucfg_cm_get_roam_rt_stats(hdd_ctx->psoc,
19038 					  ROAM_RT_STATS_SUSPEND_MODE_ENABLE)) {
19039 		ucfg_pmo_disable_wakeup_event(hdd_ctx->psoc,
19040 					      adapter->deflink->vdev_id,
19041 					      WOW_ROAM_STATS_EVENT);
19042 		ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc,
19043 					     ROAM_RT_STATS_DISABLED,
19044 					     ROAM_RT_STATS_SUSPEND_MODE_ENABLE);
19045 	}
19046 
19047 	status = ucfg_cm_roam_send_rt_stats_config(hdd_ctx->pdev,
19048 						   adapter->deflink->vdev_id,
19049 						   param);
19050 
19051 	return qdf_status_to_os_return(status);
19052 }
19053 
19054 #undef EVENTS_CONFIGURE
19055 #undef SUSPEND_STATE
19056 
19057 /**
19058  * wlan_hdd_cfg80211_set_roam_events() - set roam stats
19059  * @wiphy: wiphy pointer
19060  * @wdev: pointer to struct wireless_dev
19061  * @data: pointer to incoming NL vendor data
19062  * @data_len: length of @data
19063  *
19064  * Return: 0 on success; error number otherwise.
19065  */
19066 static int wlan_hdd_cfg80211_set_roam_events(struct wiphy *wiphy,
19067 					     struct wireless_dev *wdev,
19068 					     const void *data,
19069 					     int data_len)
19070 {
19071 	int errno;
19072 	struct osif_vdev_sync *vdev_sync;
19073 
19074 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19075 	if (errno)
19076 		return errno;
19077 
19078 	errno = __wlan_hdd_cfg80211_set_roam_events(wiphy, wdev,
19079 						    data, data_len);
19080 
19081 	osif_vdev_sync_op_stop(vdev_sync);
19082 
19083 	return errno;
19084 }
19085 #endif
19086 
19087 /**
19088  * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
19089  * @wiphy: wiphy pointer
19090  * @wdev: pointer to struct wireless_dev
19091  * @data: pointer to incoming NL vendor data
19092  * @data_len: length of @data
19093  *
19094  * Return: 0 on success; error number otherwise.
19095  */
19096 static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
19097 					      struct wireless_dev *wdev,
19098 					      const void *data,
19099 					      int data_len)
19100 {
19101 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
19102 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19103 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
19104 	struct qdf_mac_addr peer_macaddr;
19105 	int retval;
19106 
19107 	hdd_enter();
19108 
19109 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19110 		hdd_err("Command not allowed in FTM mode");
19111 		return -EPERM;
19112 	}
19113 
19114 	retval = wlan_hdd_validate_context(hdd_ctx);
19115 	if (0 != retval)
19116 		return retval;
19117 
19118 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
19119 				    data, data_len, get_chain_rssi_policy)) {
19120 		hdd_err("Invalid ATTR");
19121 		return -EINVAL;
19122 	}
19123 
19124 	if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
19125 		hdd_err("attr mac addr failed");
19126 		return -EINVAL;
19127 	}
19128 	if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) != QDF_MAC_ADDR_SIZE) {
19129 		hdd_err("incorrect mac size");
19130 		return -EINVAL;
19131 	}
19132 
19133 	qdf_copy_macaddr(&peer_macaddr,
19134 			 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]));
19135 
19136 	retval = hdd_process_peer_chain_rssi_req(adapter, &peer_macaddr);
19137 	hdd_exit();
19138 	return retval;
19139 }
19140 
19141 #ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
19142 /**
19143  * wlan_hdd_cfg80211_get_usable_channel() - get chain rssi
19144  * @wiphy: wiphy pointer
19145  * @wdev: pointer to struct wireless_dev
19146  * @data: pointer to incoming NL vendor data
19147  * @data_len: length of @data
19148  *
19149  * Return: 0 on success; error number otherwise.
19150  */
19151 static int wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
19152 						struct wireless_dev *wdev,
19153 						const void *data,
19154 						int data_len)
19155 {
19156 	int errno;
19157 	struct osif_vdev_sync *vdev_sync;
19158 
19159 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19160 	if (errno)
19161 		return errno;
19162 
19163 	errno = __wlan_hdd_cfg80211_get_usable_channel(wiphy, wdev,
19164 						       data, data_len);
19165 
19166 	osif_vdev_sync_op_stop(vdev_sync);
19167 
19168 	return errno;
19169 }
19170 #else
19171 static int wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
19172 						struct wireless_dev *wdev,
19173 						const void *data,
19174 						int data_len)
19175 {
19176 	hdd_debug("get usable channel feature not supported");
19177 	return -EPERM;
19178 }
19179 #endif
19180 
19181 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
19182 /**
19183  * os_if_monitor_mode_configure() - Wifi monitor mode configuration
19184  * vendor command
19185  * @adapter: hdd adapter
19186  * @data: Vendor command data buffer
19187  * @data_len: Buffer length
19188  *
19189  * Return: QDF_STATUS
19190  */
19191 static
19192 QDF_STATUS os_if_monitor_mode_configure(struct hdd_adapter *adapter,
19193 					const void *data, int data_len)
19194 {
19195 	struct wlan_objmgr_vdev *vdev;
19196 	QDF_STATUS status;
19197 
19198 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
19199 	if (!vdev)
19200 		return QDF_STATUS_E_INVAL;
19201 
19202 	status = os_if_dp_set_lpc_configure(vdev, data, data_len);
19203 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
19204 	return status;
19205 }
19206 
19207 #endif /* WLAN_FEATURE_LOCAL_PKT_CAPTURE */
19208 
19209 #if defined(WLAN_FEATURE_PKT_CAPTURE) || defined(WLAN_FEATURE_LOCAL_PKT_CAPTURE)
19210 
19211 /**
19212  * __wlan_hdd_cfg80211_set_monitor_mode() - Wifi monitor mode configuration
19213  * vendor command
19214  * @wiphy: wiphy device pointer
19215  * @wdev: wireless device pointer
19216  * @data: Vendor command data buffer
19217  * @data_len: Buffer length
19218  *
19219  * Handles .
19220  *
19221  * Return: 0 for Success and negative value for failure
19222  */
19223 static int
19224 __wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy,
19225 				     struct wireless_dev *wdev,
19226 				     const void *data, int data_len)
19227 {
19228 	struct net_device *dev = wdev->netdev;
19229 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19230 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
19231 	int errno;
19232 	QDF_STATUS status;
19233 
19234 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
19235 		hdd_err("Command not allowed in FTM mode");
19236 		return -EPERM;
19237 	}
19238 
19239 	errno = wlan_hdd_validate_context(hdd_ctx);
19240 	if (errno)
19241 		return errno;
19242 
19243 	errno = hdd_validate_adapter(adapter);
19244 	if (errno)
19245 		return errno;
19246 
19247 	if (!(ucfg_pkt_capture_get_mode(hdd_ctx->psoc) ||
19248 	      hdd_is_pkt_capture_mon_enable(adapter) ||
19249 	      ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc)))
19250 		return -EPERM;
19251 
19252 	status = os_if_monitor_mode_configure(adapter, data, data_len);
19253 
19254 	return qdf_status_to_os_return(status);
19255 }
19256 
19257 /**
19258  * wlan_hdd_cfg80211_set_monitor_mode() - set monitor mode
19259  * @wiphy: wiphy pointer
19260  * @wdev: pointer to struct wireless_dev
19261  * @data: pointer to incoming NL vendor data
19262  * @data_len: length of @data
19263  *
19264  * Return: 0 on success; error number otherwise.
19265  */
19266 static int wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy,
19267 					      struct wireless_dev *wdev,
19268 					      const void *data, int data_len)
19269 {
19270 	int errno;
19271 	struct osif_vdev_sync *vdev_sync;
19272 
19273 	hdd_enter_dev(wdev->netdev);
19274 
19275 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19276 	if (errno)
19277 		return errno;
19278 
19279 	errno = __wlan_hdd_cfg80211_set_monitor_mode(wiphy, wdev,
19280 						     data, data_len);
19281 
19282 	osif_vdev_sync_op_stop(vdev_sync);
19283 
19284 	hdd_exit();
19285 
19286 	return errno;
19287 }
19288 #endif
19289 
19290 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
19291 
19292 /**
19293  * __wlan_hdd_cfg80211_get_monitor_mode() - Get wifi monitor mode configuration
19294  * vendor command
19295  * @wiphy: wiphy device pointer
19296  * @wdev: wireless device pointer
19297  * @data: Vendor command data buffer
19298  * @data_len: Buffer length
19299  *
19300  * Return: 0 for Success and negative value for failure
19301  */
19302 static int
19303 __wlan_hdd_cfg80211_get_monitor_mode(struct wiphy *wiphy,
19304 				     struct wireless_dev *wdev,
19305 				     const void *data, int data_len)
19306 {
19307 	struct net_device *dev = wdev->netdev;
19308 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19309 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
19310 	struct wlan_objmgr_vdev *vdev;
19311 	int errno;
19312 	QDF_STATUS status;
19313 
19314 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
19315 		hdd_err("Command not allowed in FTM mode");
19316 		return -EPERM;
19317 	}
19318 
19319 	errno = wlan_hdd_validate_context(hdd_ctx);
19320 	if (errno)
19321 		return errno;
19322 
19323 	errno = hdd_validate_adapter(adapter);
19324 	if (errno)
19325 		return errno;
19326 
19327 	if (!ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc))
19328 		return -EPERM;
19329 
19330 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
19331 	if (!vdev)
19332 		return -EINVAL;
19333 
19334 	status = os_if_dp_get_lpc_state(vdev, data, data_len);
19335 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
19336 
19337 	return qdf_status_to_os_return(status);
19338 }
19339 
19340 /**
19341  * wlan_hdd_cfg80211_get_monitor_mode() - get monitor mode
19342  * @wiphy: wiphy pointer
19343  * @wdev: pointer to struct wireless_dev
19344  * @data: pointer to incoming NL vendor data
19345  * @data_len: length of @data
19346  *
19347  * Return: 0 on success; error number otherwise.
19348  */
19349 static int wlan_hdd_cfg80211_get_monitor_mode(struct wiphy *wiphy,
19350 					      struct wireless_dev *wdev,
19351 					      const void *data, int data_len)
19352 {
19353 	int errno;
19354 	struct osif_vdev_sync *vdev_sync;
19355 
19356 	hdd_enter_dev(wdev->netdev);
19357 
19358 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19359 	if (errno)
19360 		return errno;
19361 
19362 	errno = __wlan_hdd_cfg80211_get_monitor_mode(wiphy, wdev,
19363 						     data, data_len);
19364 
19365 	osif_vdev_sync_op_stop(vdev_sync);
19366 
19367 	hdd_exit();
19368 
19369 	return errno;
19370 }
19371 #endif
19372 
19373 /**
19374  * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
19375  * @wiphy: wiphy pointer
19376  * @wdev: pointer to struct wireless_dev
19377  * @data: pointer to incoming NL vendor data
19378  * @data_len: length of @data
19379  *
19380  * Return: 0 on success; error number otherwise.
19381  */
19382 static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
19383 					    struct wireless_dev *wdev,
19384 					    const void *data,
19385 					    int data_len)
19386 {
19387 	int errno;
19388 	struct osif_vdev_sync *vdev_sync;
19389 
19390 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19391 	if (errno)
19392 		return errno;
19393 
19394 	errno = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
19395 
19396 	osif_vdev_sync_op_stop(vdev_sync);
19397 
19398 	return errno;
19399 }
19400 
19401 /**
19402  * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
19403  * @skb: Pointer to skb
19404  * @info: mac mode info
19405  * @index: attribute type index for nla_nest_start()
19406  *
19407  * Return : 0 on success and errno on failure
19408  */
19409 static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
19410 				   struct connection_info *info, int index)
19411 {
19412 	struct nlattr *attr;
19413 	uint32_t freq;
19414 	struct hdd_context *hdd_ctx;
19415 	struct wlan_hdd_link_info *link_info;
19416 
19417 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
19418 	if (!hdd_ctx)
19419 		goto error;
19420 
19421 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, info->vdev_id);
19422 	if (!link_info)
19423 		goto error;
19424 
19425 	attr = nla_nest_start(skb, index);
19426 	if (!attr)
19427 		goto error;
19428 
19429 	freq = sme_chn_to_freq(info->channel);
19430 
19431 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
19432 	    link_info->adapter->dev->ifindex) ||
19433 	    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
19434 		goto error;
19435 
19436 	nla_nest_end(skb, attr);
19437 
19438 	return 0;
19439 error:
19440 	hdd_err("Fill buffer with interface info failed");
19441 	return -EINVAL;
19442 }
19443 
19444 /**
19445  * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
19446  * @skb: Pointer to skb
19447  * @info: mac mode info
19448  * @mac_id: MAC id
19449  * @conn_count: number of current connections
19450  *
19451  * Return : 0 on success and errno on failure
19452  */
19453 static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
19454 				  struct connection_info *info, uint32_t mac_id,
19455 				  uint32_t conn_count)
19456 {
19457 	struct nlattr *attr, *intf_attr;
19458 	uint32_t band = 0, i = 0, j = 0;
19459 	bool present = false;
19460 
19461 	while (i < conn_count) {
19462 		if (info[i].mac_id == mac_id) {
19463 			present = true;
19464 			if (info[i].channel <= SIR_11B_CHANNEL_END)
19465 				band |= 1 << NL80211_BAND_2GHZ;
19466 			else if (info[i].channel <= SIR_11A_CHANNEL_END)
19467 				band |= 1 << NL80211_BAND_5GHZ;
19468 		}
19469 		i++;
19470 	}
19471 
19472 	if (!present)
19473 		return 0;
19474 
19475 	i = 0;
19476 	attr = nla_nest_start(skb, mac_id);
19477 	if (!attr)
19478 		goto error;
19479 
19480 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
19481 	    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
19482 		goto error;
19483 
19484 	intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
19485 	if (!intf_attr)
19486 		goto error;
19487 
19488 	while (i < conn_count) {
19489 		if (info[i].mac_id == mac_id) {
19490 			if (wlan_hdd_fill_intf_info(skb, &info[i], j))
19491 				return -EINVAL;
19492 			j++;
19493 		}
19494 		i++;
19495 	}
19496 
19497 	nla_nest_end(skb, intf_attr);
19498 
19499 	nla_nest_end(skb, attr);
19500 
19501 	return 0;
19502 error:
19503 	hdd_err("Fill buffer with mac info failed");
19504 	return -EINVAL;
19505 }
19506 
19507 
19508 int wlan_hdd_send_mode_change_event(void)
19509 {
19510 	int err;
19511 	struct hdd_context *hdd_ctx;
19512 	struct sk_buff *skb;
19513 	struct nlattr *attr;
19514 	struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
19515 	uint32_t conn_count, mac_id;
19516 	enum qca_nl80211_vendor_subcmds_index index =
19517 		QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX;
19518 
19519 	hdd_enter();
19520 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
19521 	if (!hdd_ctx)
19522 		return -EINVAL;
19523 
19524 	err = wlan_hdd_validate_context(hdd_ctx);
19525 	if (0 != err)
19526 		return err;
19527 
19528 	conn_count = policy_mgr_get_connection_info(hdd_ctx->psoc, info);
19529 	if (!conn_count)
19530 		return -EINVAL;
19531 
19532 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
19533 					       (sizeof(uint32_t) * 4) *
19534 					       MAX_NUMBER_OF_CONC_CONNECTIONS +
19535 					       NLMSG_HDRLEN,
19536 					       index, GFP_KERNEL);
19537 	if (!skb) {
19538 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
19539 		return -ENOMEM;
19540 	}
19541 
19542 	attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
19543 	if (!attr) {
19544 		hdd_err("nla_nest_start failed");
19545 		wlan_cfg80211_vendor_free_skb(skb);
19546 		return -EINVAL;
19547 	}
19548 
19549 	for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
19550 		if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count)) {
19551 			wlan_cfg80211_vendor_free_skb(skb);
19552 			return -EINVAL;
19553 		}
19554 	}
19555 
19556 	nla_nest_end(skb, attr);
19557 
19558 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
19559 	hdd_exit();
19560 
19561 	return err;
19562 }
19563 
19564 
19565 /* Short name for QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS command */
19566 
19567 #define EXTSCAN_CONFIG_MAX \
19568 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
19569 #define EXTSCAN_CONFIG_REQUEST_ID \
19570 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
19571 #define EXTSCAN_CONFIG_WIFI_BAND \
19572 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND
19573 #define EXTSCAN_CONFIG_MAX_CHANNELS \
19574 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS
19575 #define EXTSCAN_RESULTS_NUM_CHANNELS \
19576 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS
19577 #define EXTSCAN_RESULTS_CHANNELS \
19578 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS
19579 
19580 static const struct nla_policy
19581 wlan_hdd_extscan_get_valid_channels_policy[EXTSCAN_CONFIG_MAX + 1] = {
19582 	[EXTSCAN_CONFIG_REQUEST_ID] = {.type = NLA_U32},
19583 	[EXTSCAN_CONFIG_WIFI_BAND] = {.type = NLA_U32},
19584 	[EXTSCAN_CONFIG_MAX_CHANNELS] = {.type = NLA_U32},
19585 };
19586 
19587 /**
19588  * hdd_remove_passive_channels () - remove passive channels
19589  * @wiphy: Pointer to wireless phy
19590  * @chan_list: channel list
19591  * @num_channels: number of channels
19592  *
19593  * Return: none
19594  */
19595 static void hdd_remove_passive_channels(struct wiphy *wiphy,
19596 					uint32_t *chan_list,
19597 					uint8_t *num_channels)
19598 {
19599 	uint8_t num_chan_temp = 0;
19600 	int i, j, k;
19601 
19602 	for (i = 0; i < *num_channels; i++)
19603 		for (j = 0; j < HDD_NUM_NL80211_BANDS; j++) {
19604 			if (!wiphy->bands[j])
19605 				continue;
19606 			for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
19607 				if ((chan_list[i] ==
19608 				     wiphy->bands[j]->channels[k].center_freq)
19609 				    && (!(wiphy->bands[j]->channels[k].flags &
19610 				       IEEE80211_CHAN_PASSIVE_SCAN))
19611 				) {
19612 					chan_list[num_chan_temp] = chan_list[i];
19613 					num_chan_temp++;
19614 				}
19615 			}
19616 		}
19617 
19618 	*num_channels = num_chan_temp;
19619 }
19620 
19621 /**
19622  * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
19623  * @wiphy: Pointer to wireless phy
19624  * @wdev: Pointer to wireless device
19625  * @data: Pointer to data
19626  * @data_len: Data length
19627  *
19628  * Return: none
19629  */
19630 static int
19631 __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
19632 					       struct wireless_dev
19633 					       *wdev, const void *data,
19634 					       int data_len)
19635 {
19636 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19637 	struct net_device *dev = wdev->netdev;
19638 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19639 	uint32_t chan_list[CFG_VALID_CHANNEL_LIST_LEN] = {0};
19640 	uint8_t num_channels  = 0, i, buf[256] = {0};
19641 	struct nlattr *tb[EXTSCAN_CONFIG_MAX + 1];
19642 	uint32_t request_id, max_channels;
19643 	tWifiBand wifi_band;
19644 	QDF_STATUS status;
19645 	struct sk_buff *reply_skb;
19646 	int ret, len = 0;
19647 
19648 	/* ENTER_DEV() intentionally not used in a frequently invoked API */
19649 
19650 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19651 		hdd_err("Command not allowed in FTM mode");
19652 		return -EPERM;
19653 	}
19654 
19655 	ret = wlan_hdd_validate_context(hdd_ctx);
19656 	if (0 != ret)
19657 		return -EINVAL;
19658 
19659 	if (wlan_cfg80211_nla_parse(tb, EXTSCAN_CONFIG_MAX, data, data_len,
19660 				  wlan_hdd_extscan_get_valid_channels_policy)) {
19661 		hdd_err("Invalid ATTR");
19662 		return -EINVAL;
19663 	}
19664 
19665 	/* Parse and fetch request Id */
19666 	if (!tb[EXTSCAN_CONFIG_REQUEST_ID]) {
19667 		hdd_err("attr request id failed");
19668 		return -EINVAL;
19669 	}
19670 	request_id = nla_get_u32(tb[EXTSCAN_CONFIG_REQUEST_ID]);
19671 
19672 	/* Parse and fetch wifi band */
19673 	if (!tb[EXTSCAN_CONFIG_WIFI_BAND]) {
19674 		hdd_err("attr wifi band failed");
19675 		return -EINVAL;
19676 	}
19677 	wifi_band = nla_get_u32(tb[EXTSCAN_CONFIG_WIFI_BAND]);
19678 	if (!tb[EXTSCAN_CONFIG_MAX_CHANNELS]) {
19679 		hdd_err("attr max channels failed");
19680 		return -EINVAL;
19681 	}
19682 	max_channels = nla_get_u32(tb[EXTSCAN_CONFIG_MAX_CHANNELS]);
19683 
19684 	if (max_channels > CFG_VALID_CHANNEL_LIST_LEN) {
19685 		hdd_err("Max channels %d exceeded Valid channel list len %d",
19686 			max_channels, CFG_VALID_CHANNEL_LIST_LEN);
19687 		return -EINVAL;
19688 	}
19689 
19690 	hdd_err("Req Id: %u Wifi band: %d Max channels: %d", request_id,
19691 		wifi_band, max_channels);
19692 	status = sme_get_valid_channels_by_band(hdd_ctx->mac_handle,
19693 						wifi_band, chan_list,
19694 						&num_channels);
19695 	if (QDF_STATUS_SUCCESS != status) {
19696 		hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
19697 		        status);
19698 		return -EINVAL;
19699 	}
19700 
19701 	num_channels = QDF_MIN(num_channels, max_channels);
19702 
19703 	if ((QDF_SAP_MODE == adapter->device_mode) ||
19704 	    !strncmp(hdd_get_fwpath(), "ap", 2))
19705 		hdd_remove_passive_channels(wiphy, chan_list,
19706 					    &num_channels);
19707 
19708 	hdd_debug("Number of channels: %d", num_channels);
19709 	for (i = 0; i < num_channels; i++)
19710 		len += scnprintf(buf + len, sizeof(buf) - len,
19711 				 "%u ", chan_list[i]);
19712 
19713 	hdd_debug("Channels: %s", buf);
19714 
19715 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
19716 							     sizeof(u32) +
19717 							     sizeof(u32) *
19718 							     num_channels +
19719 							     NLMSG_HDRLEN);
19720 
19721 	if (reply_skb) {
19722 		if (nla_put_u32(
19723 			reply_skb,
19724 			EXTSCAN_RESULTS_NUM_CHANNELS,
19725 			num_channels) ||
19726 		    nla_put(
19727 			reply_skb,
19728 			EXTSCAN_RESULTS_CHANNELS,
19729 			sizeof(u32) * num_channels, chan_list)) {
19730 			hdd_err("nla put fail");
19731 			wlan_cfg80211_vendor_free_skb(reply_skb);
19732 			return -EINVAL;
19733 		}
19734 		ret = wlan_cfg80211_vendor_cmd_reply(reply_skb);
19735 		return ret;
19736 	}
19737 
19738 	hdd_err("valid channels: buffer alloc fail");
19739 	return -EINVAL;
19740 }
19741 
19742 #undef EXTSCAN_CONFIG_MAX
19743 #undef EXTSCAN_CONFIG_REQUEST_ID
19744 #undef EXTSCAN_CONFIG_WIFI_BAND
19745 #undef ETCAN_CONFIG_MAX_CHANNELS
19746 #undef EXTSCAN_RESULTS_NUM_CHANNELS
19747 #undef EXTSCAN_RESULTS_CHANNELS
19748 
19749 /**
19750  * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
19751  * @wiphy: Pointer to wireless phy
19752  * @wdev: Pointer to wireless device
19753  * @data: Pointer to data
19754  * @data_len: Data length
19755  *
19756  * Return: 0 on success, negative errno on failure
19757  */
19758 static int wlan_hdd_cfg80211_extscan_get_valid_channels(
19759 					struct wiphy *wiphy,
19760 					struct wireless_dev *wdev,
19761 					const void *data, int data_len)
19762 {
19763 	struct osif_psoc_sync *psoc_sync;
19764 	int errno;
19765 
19766 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
19767 	if (errno)
19768 		return errno;
19769 
19770 	errno = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev,
19771 							       data, data_len);
19772 
19773 	osif_psoc_sync_op_stop(psoc_sync);
19774 
19775 	return errno;
19776 }
19777 
19778 #ifdef FEATURE_RADAR_HISTORY
19779 static uint32_t get_radar_history_evt_len(uint32_t count)
19780 {
19781 	uint32_t data_len = NLMSG_HDRLEN;
19782 
19783 	data_len +=
19784 	/* nested attribute hdr QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES */
19785 		nla_total_size(count *
19786 			       (nla_total_size(
19787 				     /* channel frequency */
19788 				     nla_total_size(sizeof(uint32_t)) +
19789 				     /* timestamp */
19790 				     nla_total_size(sizeof(uint64_t)) +
19791 				     /* radar detected flag */
19792 				     nla_total_size(0))));
19793 
19794 	return data_len;
19795 }
19796 
19797 /**
19798  * __wlan_hdd_cfg80211_get_radar_history () - Get radar history
19799  * @wiphy: Pointer to wireless phy
19800  * @wdev: Pointer to wireless device
19801  * @data: Pointer to data
19802  * @data_len: Data length
19803  *
19804  * Return: 0 on success, negative errno on failure
19805  */
19806 static int
19807 __wlan_hdd_cfg80211_get_radar_history(struct wiphy *wiphy,
19808 				      struct wireless_dev
19809 				      *wdev, const void *data,
19810 				      int data_len)
19811 {
19812 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19813 	QDF_STATUS status;
19814 	struct sk_buff *reply_skb = NULL;
19815 	int ret, len;
19816 	struct dfs_radar_history *radar_history = NULL;
19817 	uint32_t hist_count = 0;
19818 	int idx;
19819 	struct nlattr *ch_array, *ch_element;
19820 
19821 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
19822 		hdd_err("Command not allowed in FTM mode");
19823 		return -EPERM;
19824 	}
19825 
19826 	ret = wlan_hdd_validate_context(hdd_ctx);
19827 	if (ret)
19828 		return -EINVAL;
19829 
19830 	status = wlansap_query_radar_history(hdd_ctx->mac_handle,
19831 					     &radar_history, &hist_count);
19832 	if (!QDF_IS_STATUS_SUCCESS(status))
19833 		return -EINVAL;
19834 
19835 	len = get_radar_history_evt_len(hist_count);
19836 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
19837 	if (!reply_skb) {
19838 		ret = -ENOMEM;
19839 		goto err;
19840 	}
19841 
19842 	ch_array = nla_nest_start(
19843 			reply_skb, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES);
19844 	if (!ch_array) {
19845 		ret = -ENOMEM;
19846 		goto err;
19847 	}
19848 
19849 	for (idx = 0; idx < hist_count; idx++) {
19850 		ch_element = nla_nest_start(reply_skb, idx);
19851 		if (!ch_element) {
19852 			ret = -ENOMEM;
19853 			goto err;
19854 		}
19855 
19856 		if (nla_put_u32(reply_skb,
19857 				QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ,
19858 				radar_history[idx].ch_freq)) {
19859 			ret = -ENOMEM;
19860 			goto err;
19861 		}
19862 
19863 		if (wlan_cfg80211_nla_put_u64(
19864 			reply_skb,
19865 			QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP,
19866 			radar_history[idx].time)) {
19867 			ret = -ENOMEM;
19868 			goto err;
19869 		}
19870 
19871 		if (radar_history[idx].radar_found &&
19872 		    nla_put_flag(
19873 			reply_skb,
19874 			QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED)) {
19875 			ret = -ENOMEM;
19876 			goto err;
19877 		}
19878 
19879 		nla_nest_end(reply_skb, ch_element);
19880 	}
19881 	nla_nest_end(reply_skb, ch_array);
19882 	qdf_mem_free(radar_history);
19883 
19884 	ret = wlan_cfg80211_vendor_cmd_reply(reply_skb);
19885 	hdd_debug("get radar history count %d, ret %d", hist_count, ret);
19886 
19887 	return ret;
19888 err:
19889 	qdf_mem_free(radar_history);
19890 	wlan_cfg80211_vendor_free_skb(reply_skb);
19891 	hdd_debug("get radar history error %d", ret);
19892 
19893 	return ret;
19894 }
19895 
19896 /**
19897  * wlan_hdd_cfg80211_get_radar_history() - get radar history
19898  * @wiphy: wiphy pointer
19899  * @wdev: pointer to struct wireless_dev
19900  * @data: pointer to incoming NL vendor data
19901  * @data_len: length of @data
19902  *
19903  * Return: 0 on success; error number otherwise.
19904  */
19905 static int wlan_hdd_cfg80211_get_radar_history(struct wiphy *wiphy,
19906 					       struct wireless_dev *wdev,
19907 					       const void *data,
19908 					       int data_len)
19909 {
19910 	int errno;
19911 	struct osif_vdev_sync *vdev_sync;
19912 
19913 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19914 	if (errno)
19915 		return errno;
19916 
19917 	errno = __wlan_hdd_cfg80211_get_radar_history(wiphy, wdev,
19918 						      data, data_len);
19919 
19920 	osif_vdev_sync_op_stop(vdev_sync);
19921 
19922 	return errno;
19923 }
19924 
19925 #define FEATURE_RADAR_HISTORY_VENDOR_COMMANDS				\
19926 {									\
19927 	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
19928 	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY,	\
19929 	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
19930 		WIPHY_VENDOR_CMD_NEED_NETDEV |				\
19931 		WIPHY_VENDOR_CMD_NEED_RUNNING,				\
19932 	.doit = wlan_hdd_cfg80211_get_radar_history,			\
19933 	vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)			\
19934 },
19935 #else
19936 #define FEATURE_RADAR_HISTORY_VENDOR_COMMANDS
19937 #endif
19938 
19939 const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
19940 	{
19941 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
19942 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
19943 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
19944 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
19945 		.doit = is_driver_dfs_capable,
19946 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
19947 	},
19948 	{
19949 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
19950 		.info.subcmd =
19951 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
19952 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
19953 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
19954 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
19955 		.doit = wlan_hdd_cfg80211_extscan_get_valid_channels,
19956 		vendor_command_policy(
19957 				wlan_hdd_extscan_get_valid_channels_policy,
19958 				EXTSCAN_PARAM_MAX)
19959 	},
19960 #ifdef WLAN_FEATURE_STATS_EXT
19961 	{
19962 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
19963 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
19964 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
19965 			 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
19966 		.doit = wlan_hdd_cfg80211_stats_ext_request,
19967 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
19968 	},
19969 #endif
19970 
19971 	{
19972 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
19973 		.info.subcmd =
19974 			QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS,
19975 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
19976 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
19977 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
19978 		.doit = wlan_hdd_cfg80211_connected_chan_stats_req,
19979 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
19980 	},
19981 
19982 	FEATURE_EXTSCAN_VENDOR_COMMANDS
19983 
19984 	FEATURE_LL_STATS_VENDOR_COMMANDS
19985 
19986 	{
19987 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
19988 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
19989 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
19990 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
19991 		.doit = wlan_hdd_cfg80211_get_supported_features,
19992 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
19993 	},
19994 	{
19995 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
19996 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
19997 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
19998 			WIPHY_VENDOR_CMD_NEED_NETDEV |
19999 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20000 		.doit = wlan_hdd_cfg80211_set_scanning_mac_oui,
20001 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20002 	},
20003 
20004 	FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
20005 
20006 	{
20007 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20008 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
20009 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20010 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20011 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20012 		.doit = wlan_hdd_cfg80211_disable_dfs_chan_scan,
20013 		vendor_command_policy(wlan_hdd_set_no_dfs_flag_config_policy,
20014 				      QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX)
20015 	},
20016 	{
20017 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20018 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
20019 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20020 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20021 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20022 		.doit = wlan_hdd_cfg80211_handle_wisa_cmd,
20023 		vendor_command_policy(wlan_hdd_wisa_cmd_policy,
20024 				      QCA_WLAN_VENDOR_ATTR_WISA_MAX)
20025 	},
20026 
20027 	FEATURE_STATION_INFO_VENDOR_COMMANDS
20028 
20029 	{
20030 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20031 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
20032 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20033 				WIPHY_VENDOR_CMD_NEED_NETDEV |
20034 				WIPHY_VENDOR_CMD_NEED_RUNNING,
20035 		.doit = wlan_hdd_cfg80211_do_acs,
20036 		vendor_command_policy(wlan_hdd_cfg80211_do_acs_policy,
20037 				      QCA_WLAN_VENDOR_ATTR_ACS_MAX)
20038 	},
20039 
20040 	{
20041 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20042 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
20043 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20044 			WIPHY_VENDOR_CMD_NEED_NETDEV,
20045 		.doit = wlan_hdd_cfg80211_get_features,
20046 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20047 	},
20048 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
20049 	{
20050 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20051 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
20052 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20053 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20054 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20055 		.doit = wlan_hdd_cfg80211_keymgmt_set_key,
20056 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20057 	},
20058 #endif
20059 	{
20060 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20061 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
20062 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20063 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20064 		.doit = wlan_hdd_cfg80211_get_wifi_info,
20065 		vendor_command_policy(qca_wlan_vendor_get_wifi_info_policy,
20066 				      QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX)
20067 	},
20068 	{
20069 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20070 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
20071 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20072 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20073 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20074 		.doit = wlan_hdd_cfg80211_wifi_configuration_set,
20075 		vendor_command_policy(wlan_hdd_wifi_config_policy,
20076 				      QCA_WLAN_VENDOR_ATTR_CONFIG_MAX)
20077 	},
20078 	{
20079 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20080 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION,
20081 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20082 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20083 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20084 		.doit = wlan_hdd_cfg80211_wifi_configuration_get,
20085 		vendor_command_policy(wlan_hdd_wifi_config_policy,
20086 				      QCA_WLAN_VENDOR_ATTR_CONFIG_MAX)
20087 	},
20088 
20089 	FEATURE_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION
20090 #ifdef WLAN_SUPPORT_TWT
20091 	FEATURE_VENDOR_SUBCMD_WIFI_CONFIG_TWT
20092 #endif
20093 
20094 	{
20095 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20096 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
20097 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20098 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20099 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20100 		.doit = wlan_hdd_cfg80211_set_ext_roam_params,
20101 		vendor_command_policy(wlan_hdd_set_roam_param_policy,
20102 				      QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX)
20103 	},
20104 	{
20105 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20106 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG,
20107 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20108 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20109 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20110 		.doit = wlan_hdd_cfg80211_set_ratemask_config,
20111 		vendor_command_policy(wlan_hdd_set_ratemask_param_policy,
20112 				      QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX)
20113 	},
20114 	{
20115 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20116 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
20117 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20118 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20119 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20120 		.doit = wlan_hdd_cfg80211_wifi_logger_start,
20121 		vendor_command_policy(
20122 				qca_wlan_vendor_wifi_logger_start_policy,
20123 				QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX)
20124 	},
20125 	{
20126 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20127 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
20128 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV,
20129 		.doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data,
20130 		vendor_command_policy(
20131 			qca_wlan_vendor_wifi_logger_get_ring_data_policy,
20132 			QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX)
20133 	},
20134 	{
20135 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20136 		.info.subcmd =
20137 			QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
20138 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20139 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20140 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20141 		.doit = wlan_hdd_cfg80211_get_preferred_freq_list,
20142 		vendor_command_policy(
20143 			get_preferred_freq_list_policy,
20144 			QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX)
20145 	},
20146 	{
20147 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20148 		.info.subcmd =
20149 			QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
20150 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20151 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20152 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20153 		.doit = wlan_hdd_cfg80211_set_probable_oper_channel,
20154 		vendor_command_policy(
20155 				set_probable_oper_channel_policy,
20156 				QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX)
20157 	},
20158 
20159 	FEATURE_HANDLE_TSF_VENDOR_COMMANDS
20160 
20161 #ifdef FEATURE_WLAN_TDLS
20162 	{
20163 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20164 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
20165 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20166 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20167 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20168 		.doit = wlan_hdd_cfg80211_get_tdls_capabilities,
20169 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20170 	},
20171 #endif
20172 #ifdef WLAN_FEATURE_OFFLOAD_PACKETS
20173 	{
20174 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20175 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
20176 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20177 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20178 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20179 		.doit = wlan_hdd_cfg80211_offloaded_packets,
20180 		vendor_command_policy(offloaded_packet_policy,
20181 				      QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX)
20182 	},
20183 #endif
20184 	FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
20185 	FEATURE_OEM_DATA_VENDOR_COMMANDS
20186 	FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS
20187 
20188 #ifdef WLAN_NS_OFFLOAD
20189 	{
20190 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20191 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
20192 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20193 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20194 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20195 		.doit = wlan_hdd_cfg80211_set_ns_offload,
20196 		vendor_command_policy(ns_offload_set_policy,
20197 				      QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX)
20198 	},
20199 #endif /* WLAN_NS_OFFLOAD */
20200 	{
20201 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20202 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
20203 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20204 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20205 		.doit = wlan_hdd_cfg80211_get_logger_supp_feature,
20206 		vendor_command_policy(get_logger_set_policy,
20207 				      QCA_WLAN_VENDOR_ATTR_LOGGER_MAX)
20208 	},
20209 
20210 	FEATURE_TRIGGER_SCAN_VENDOR_COMMANDS
20211 
20212 	/* Vendor abort scan */
20213 	FEATURE_ABORT_SCAN_VENDOR_COMMANDS
20214 
20215 	/* OCB commands */
20216 	FEATURE_OCB_VENDOR_COMMANDS
20217 
20218 	{
20219 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20220 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
20221 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20222 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20223 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20224 		.doit = wlan_hdd_cfg80211_get_link_properties,
20225 		vendor_command_policy(wlan_hdd_get_link_properties_policy,
20226 				      QCA_WLAN_VENDOR_ATTR_MAX)
20227 	},
20228 
20229 	FEATURE_OTA_TEST_VENDOR_COMMANDS
20230 
20231 	FEATURE_LFR_SUBNET_DETECT_VENDOR_COMMANDS
20232 
20233 	FEATURE_TX_POWER_VENDOR_COMMANDS
20234 
20235 	FEATURE_APF_OFFLOAD_VENDOR_COMMANDS
20236 
20237 	{
20238 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20239 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
20240 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20241 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20242 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20243 		.doit = wlan_hdd_cfg80211_acs_dfs_mode,
20244 		vendor_command_policy(wlan_hdd_set_acs_dfs_config_policy,
20245 				      QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX)
20246 	},
20247 	{
20248 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20249 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
20250 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20251 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20252 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20253 		.doit = wlan_hdd_cfg80211_sta_roam_policy,
20254 		vendor_command_policy(
20255 			wlan_hdd_set_sta_roam_config_policy,
20256 			QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX)
20257 	},
20258 
20259 	{
20260 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20261 		.info.subcmd =
20262 			QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_POLICY,
20263 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20264 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20265 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20266 		.doit = wlan_hdd_cfg80211_concurrent_session_policy,
20267 		vendor_command_policy(
20268 			wlan_hdd_set_concurrent_session_policy,
20269 			QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX)
20270 	},
20271 
20272 #ifdef FEATURE_WLAN_CH_AVOID
20273 	{
20274 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20275 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
20276 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20277 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20278 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20279 		.doit = wlan_hdd_cfg80211_avoid_freq,
20280 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20281 	},
20282 #endif
20283 	{
20284 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20285 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
20286 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20287 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20288 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20289 		.doit = wlan_hdd_cfg80211_sap_configuration_set,
20290 		vendor_command_policy(wlan_hdd_sap_config_policy,
20291 				      QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX)
20292 	},
20293 
20294 	FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
20295 
20296 	FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
20297 	{
20298 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20299 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
20300 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20301 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20302 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20303 		.doit = wlan_hdd_cfg80211_get_wakelock_stats,
20304 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20305 	},
20306 	{
20307 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20308 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
20309 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20310 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20311 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20312 		.doit = wlan_hdd_cfg80211_get_bus_size,
20313 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20314 	},
20315 	{
20316 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20317 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
20318 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20319 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20320 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20321 		.doit = wlan_hdd_cfg80211_update_vendor_channel,
20322 		vendor_command_policy(acs_chan_config_policy,
20323 				      QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX)
20324 	},
20325 	{
20326 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20327 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
20328 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20329 					WIPHY_VENDOR_CMD_NEED_NETDEV |
20330 					WIPHY_VENDOR_CMD_NEED_RUNNING,
20331 		.doit = wlan_hdd_cfg80211_setband,
20332 		vendor_command_policy(setband_policy, QCA_WLAN_VENDOR_ATTR_MAX)
20333 	},
20334 	{
20335 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20336 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GETBAND,
20337 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20338 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20339 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20340 		.doit = wlan_hdd_cfg80211_getband,
20341 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20342 	},
20343 	{
20344 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20345 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
20346 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20347 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20348 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20349 		.doit = wlan_hdd_cfg80211_set_fast_roaming,
20350 		vendor_command_policy(qca_wlan_vendor_attr,
20351 				      QCA_WLAN_VENDOR_ATTR_MAX)
20352 	},
20353 	FEATURE_DISA_VENDOR_COMMANDS
20354 	FEATURE_TDLS_VENDOR_COMMANDS
20355 	FEATURE_SAR_LIMITS_VENDOR_COMMANDS
20356 	BCN_RECV_FEATURE_VENDOR_COMMANDS
20357 	FEATURE_VENDOR_SUBCMD_SET_TRACE_LEVEL
20358 #ifdef WLAN_FEATURE_LINK_LAYER_STATS
20359 	{
20360 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20361 		.info.subcmd =
20362 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
20363 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20364 				 WIPHY_VENDOR_CMD_NEED_NETDEV |
20365 				 WIPHY_VENDOR_CMD_NEED_RUNNING,
20366 		.doit = wlan_hdd_cfg80211_ll_stats_ext_set_param,
20367 		vendor_command_policy(qca_wlan_vendor_ll_ext_policy,
20368 				      QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX)
20369 	},
20370 #endif
20371 	FEATURE_VENDOR_SUBCMD_NUD_STATS_SET
20372 	{
20373 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20374 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
20375 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20376 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20377 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20378 		.doit = wlan_hdd_cfg80211_get_nud_stats,
20379 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20380 	},
20381 
20382 	FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
20383 	FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
20384 	FEATURE_CFR_VENDOR_COMMANDS
20385 	FEATURE_11AX_VENDOR_COMMANDS
20386 
20387 	{
20388 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20389 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
20390 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20391 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20392 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20393 		.doit = wlan_hdd_cfg80211_get_chain_rssi,
20394 		vendor_command_policy(get_chain_rssi_policy,
20395 				      QCA_WLAN_VENDOR_ATTR_MAX)
20396 	},
20397 	{
20398 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20399 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS,
20400 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20401 			WIPHY_VENDOR_CMD_NEED_NETDEV,
20402 		.doit = wlan_hdd_cfg80211_get_usable_channel,
20403 		vendor_command_policy(get_usable_channel_policy,
20404 				      QCA_WLAN_VENDOR_ATTR_MAX)
20405 	},
20406 	FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
20407 	FEATURE_NAN_VENDOR_COMMANDS
20408 	FEATURE_FW_STATE_COMMANDS
20409 	FEATURE_COEX_CONFIG_COMMANDS
20410 	FEATURE_MPTA_HELPER_COMMANDS
20411 	FEATURE_HW_CAPABILITY_COMMANDS
20412 	FEATURE_THERMAL_VENDOR_COMMANDS
20413 	FEATURE_BTC_CHAIN_MODE_COMMANDS
20414 	FEATURE_WMM_COMMANDS
20415 	FEATURE_GPIO_CFG_VENDOR_COMMANDS
20416 	FEATURE_MEDIUM_ASSESS_VENDOR_COMMANDS
20417 	FEATURE_RADAR_HISTORY_VENDOR_COMMANDS
20418 	FEATURE_AVOID_FREQ_EXT_VENDOR_COMMANDS
20419 	FEATURE_MDNS_OFFLOAD_VENDOR_COMMANDS
20420 
20421 	FEATURE_GREEN_AP_LOW_LATENCY_PWR_SAVE_COMMANDS
20422 
20423 #if defined(WLAN_FEATURE_PKT_CAPTURE) || defined(WLAN_FEATURE_LOCAL_PKT_CAPTURE)
20424 	FEATURE_MONITOR_MODE_VENDOR_COMMANDS
20425 #endif
20426 
20427 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
20428 	{
20429 	.info.vendor_id = QCA_NL80211_VENDOR_ID,
20430 	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS,
20431 	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20432 		 WIPHY_VENDOR_CMD_NEED_NETDEV |
20433 		 WIPHY_VENDOR_CMD_NEED_RUNNING,
20434 	.doit = wlan_hdd_cfg80211_set_roam_events,
20435 	vendor_command_policy(set_roam_events_policy,
20436 			      QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX)
20437 	},
20438 #endif
20439 	FEATURE_ROAM_STATS_COMMANDS
20440 	FEATURE_WIFI_POS_11AZ_AUTH_COMMANDS
20441 	FEATURE_WIFI_POS_SET_SECURE_RANGING_CONTEXT_COMMANDS
20442 	FEATURE_MCC_QUOTA_VENDOR_COMMANDS
20443 	FEATURE_PEER_FLUSH_VENDOR_COMMANDS
20444 	{
20445 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20446 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RADIO_COMBINATION_MATRIX,
20447 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20448 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20449 		.doit = wlan_hdd_cfg80211_get_radio_combination_matrix,
20450 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20451 	},
20452 	FEATURE_COAP_OFFLOAD_COMMANDS
20453 	FEATURE_ML_LINK_STATE_COMMANDS
20454 	FEATURE_AFC_VENDOR_COMMANDS
20455 };
20456 
20457 struct hdd_context *hdd_cfg80211_wiphy_alloc(void)
20458 {
20459 	struct wiphy *wiphy;
20460 	struct hdd_context *hdd_ctx;
20461 
20462 	hdd_enter();
20463 
20464 	wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, sizeof(*hdd_ctx));
20465 	if (!wiphy) {
20466 		hdd_err("failed to allocate wiphy!");
20467 		return NULL;
20468 	}
20469 
20470 	hdd_ctx = wiphy_priv(wiphy);
20471 	hdd_ctx->wiphy = wiphy;
20472 
20473 	return hdd_ctx;
20474 }
20475 
20476 int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx,
20477 				  struct wiphy *wiphy,
20478 				  enum band_info new_band)
20479 {
20480 	int i, j;
20481 	enum channel_state channel_state;
20482 
20483 	hdd_enter();
20484 
20485 	for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
20486 
20487 		if (!wiphy->bands[i])
20488 			continue;
20489 
20490 		for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
20491 			struct ieee80211_supported_band *band = wiphy->bands[i];
20492 
20493 			channel_state = wlan_reg_get_channel_state_for_pwrmode(
20494 					hdd_ctx->pdev,
20495 					band->channels[j].center_freq,
20496 					REG_CURRENT_PWR_MODE);
20497 
20498 			if (HDD_NL80211_BAND_2GHZ == i &&
20499 			    BAND_5G == new_band) {
20500 				/* 5G only */
20501 #ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
20502 				/* Enable Social channels for P2P */
20503 				if (WLAN_HDD_IS_SOCIAL_CHANNEL
20504 					    (band->channels[j].center_freq)
20505 				    && CHANNEL_STATE_ENABLE ==
20506 				    channel_state)
20507 					band->channels[j].flags &=
20508 						~IEEE80211_CHAN_DISABLED;
20509 				else
20510 #endif
20511 				band->channels[j].flags |=
20512 					IEEE80211_CHAN_DISABLED;
20513 				continue;
20514 			} else if (HDD_NL80211_BAND_5GHZ == i &&
20515 				   BAND_2G == new_band) {
20516 				/* 2G only */
20517 				band->channels[j].flags |=
20518 					IEEE80211_CHAN_DISABLED;
20519 				continue;
20520 			}
20521 
20522 			if (CHANNEL_STATE_DISABLE != channel_state)
20523 				band->channels[j].flags &=
20524 					~IEEE80211_CHAN_DISABLED;
20525 		}
20526 	}
20527 	return 0;
20528 }
20529 
20530 #if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
20531 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
20532 static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
20533 {
20534 	wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
20535 	wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
20536 }
20537 #else
20538 static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
20539 {
20540 }
20541 #endif
20542 
20543 #define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
20544 
20545 #if defined(CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME) || \
20546 		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
20547 /**
20548  * wlan_hdd_cfg80211_action_frame_randomization_init() - Randomize SA of MA
20549  * frames
20550  * @wiphy: Pointer to wiphy
20551  *
20552  * This function is used to indicate the support of source mac address
20553  * randomization of management action frames
20554  *
20555  * Return: None
20556  */
20557 static void
20558 wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
20559 {
20560 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA);
20561 }
20562 #else
20563 static void
20564 wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
20565 {
20566 }
20567 #endif
20568 
20569 #if defined(WLAN_FEATURE_FILS_SK) && \
20570 	(defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
20571 		 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
20572 static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
20573 {
20574 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
20575 }
20576 #else
20577 static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
20578 {
20579 }
20580 #endif
20581 
20582 #if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
20583 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
20584 static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
20585 {
20586 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
20587 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
20588 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
20589 }
20590 #else
20591 static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
20592 {
20593 }
20594 #endif
20595 
20596 #if defined(CFG80211_BIGTK_CONFIGURATION_SUPPORT) || \
20597 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
20598 static void wlan_hdd_cfg80211_set_bigtk_flags(struct wiphy *wiphy)
20599 {
20600 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION);
20601 }
20602 #else
20603 static void wlan_hdd_cfg80211_set_bigtk_flags(struct wiphy *wiphy)
20604 {
20605 }
20606 #endif
20607 
20608 #if defined(CFG80211_OCV_CONFIGURATION_SUPPORT) || \
20609 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
20610 static void wlan_hdd_cfg80211_set_ocv_flags(struct wiphy *wiphy)
20611 {
20612 	wiphy_ext_feature_set(wiphy,
20613 			      NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION);
20614 }
20615 #else
20616 static void wlan_hdd_cfg80211_set_ocv_flags(struct wiphy *wiphy)
20617 {
20618 }
20619 #endif
20620 
20621 #if defined(CFG80211_SCAN_OCE_CAPABILITY_SUPPORT) || \
20622 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
20623 static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
20624 {
20625 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME);
20626 	wiphy_ext_feature_set(wiphy,
20627 			      NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP);
20628 	wiphy_ext_feature_set(wiphy,
20629 			      NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
20630 	wiphy_ext_feature_set(
20631 		wiphy, NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION);
20632 }
20633 #else
20634 static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
20635 {
20636 }
20637 #endif
20638 
20639 #if defined(WLAN_FEATURE_SAE) && \
20640 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
20641 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
20642 /**
20643  * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
20644  * @wiphy: Pointer to wiphy
20645  *
20646  * This function is used to indicate the support of SAE
20647  *
20648  * Return: None
20649  */
20650 static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
20651 {
20652 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
20653 
20654 	if (ucfg_fwol_get_sae_enable(hdd_ctx->psoc))
20655 		wiphy->features |= NL80211_FEATURE_SAE;
20656 }
20657 #else
20658 static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
20659 {
20660 }
20661 #endif
20662 
20663 #if defined(CFG80211_SAE_AUTH_TA_ADDR_SUPPORT)
20664 static void wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(struct wiphy *wiphy)
20665 {
20666 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AUTH_TX_RANDOM_TA);
20667 }
20668 #else
20669 static void wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(struct wiphy *wiphy)
20670 {
20671 }
20672 #endif
20673 
20674 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
20675 	defined(CFG80211_DFS_OFFLOAD_BACKPORT)
20676 static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
20677 {
20678 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
20679 }
20680 #else
20681 static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
20682 {
20683 	wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
20684 }
20685 #endif
20686 
20687 #ifdef WLAN_FEATURE_DSRC
20688 static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
20689 					     int *num_ch, int *ch_len)
20690 {
20691 	*num_ch = QDF_ARRAY_SIZE(hdd_channels_dot11p);
20692 	*ch_len = sizeof(hdd_channels_dot11p);
20693 }
20694 
20695 static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
20696 {
20697 	if (!ch_arr_len)
20698 		return;
20699 	qdf_mem_copy(ch_ptr, &hdd_channels_dot11p[0], ch_arr_len);
20700 }
20701 
20702 static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
20703 					    int *num_ch, int *ch_len)
20704 {
20705 	*num_ch = 0;
20706 	*ch_len = 0;
20707 }
20708 
20709 static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
20710 {
20711 }
20712 
20713 /**
20714  * wlan_hdd_populate_5dot9_chan_info() - Populate 5.9 GHz chan info in hdd
20715  * context
20716  * @hdd_ctx: pointer to hdd context
20717  * @index: 5.9 GHz channel beginning index in chan_info of @hdd_ctx
20718  *
20719  * Return: Number of 5.9 GHz channels populated
20720  */
20721 static uint32_t
20722 wlan_hdd_populate_5dot9_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
20723 {
20724 	return 0;
20725 }
20726 
20727 #else
20728 
20729 static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
20730 					     int *num_ch, int *ch_len)
20731 {
20732 	*num_ch = 0;
20733 	*ch_len = 0;
20734 }
20735 
20736 static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
20737 {
20738 }
20739 
20740 static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
20741 					    int *num_ch, int *ch_len)
20742 {
20743 	*num_ch = QDF_ARRAY_SIZE(hdd_5dot9_ghz_ch);
20744 	*ch_len = sizeof(hdd_5dot9_ghz_ch);
20745 }
20746 
20747 static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
20748 {
20749 	if (!ch_arr_len)
20750 		return;
20751 	qdf_mem_copy(ch_ptr, &hdd_5dot9_ghz_ch[0], ch_arr_len);
20752 }
20753 
20754 /**
20755  * wlan_hdd_populate_5dot9_chan_info() - Populate 5.9 GHz chan info in hdd
20756  * context
20757  * @hdd_ctx: pointer to hdd context
20758  * @index: 5.9 GHz channel beginning index in chan_info of @hdd_ctx
20759  *
20760  * Return: Number of 5.9 GHz channels populated
20761  */
20762 static uint32_t
20763 wlan_hdd_populate_5dot9_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
20764 {
20765 	uint32_t num_5dot9_ch, i;
20766 	struct scan_chan_info *chan_info;
20767 
20768 	num_5dot9_ch = QDF_ARRAY_SIZE(hdd_5dot9_ghz_ch);
20769 	chan_info = hdd_ctx->chan_info;
20770 
20771 	for (i = 0; i < num_5dot9_ch; i++)
20772 		chan_info[index + i].freq = hdd_5dot9_ghz_ch[i].center_freq;
20773 
20774 	return num_5dot9_ch;
20775 }
20776 
20777 #endif
20778 
20779 #if defined(WLAN_FEATURE_11AX) && \
20780 	(defined(CFG80211_SBAND_IFTYPE_DATA_BACKPORT) || \
20781 	 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)))
20782 #if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
20783 	   (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
20784 static QDF_STATUS
20785 wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
20786 {
20787 	hdd_ctx->iftype_data_6g =
20788 			qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_6g) *
20789 				       EHT_OPMODE_SUPPORTED);
20790 
20791 	if (!hdd_ctx->iftype_data_6g)
20792 		return QDF_STATUS_E_NOMEM;
20793 
20794 	return QDF_STATUS_SUCCESS;
20795 }
20796 
20797 static void
20798 wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
20799 {
20800 	qdf_mem_free(hdd_ctx->iftype_data_6g);
20801 	hdd_ctx->iftype_data_6g = NULL;
20802 }
20803 #else
20804 static inline QDF_STATUS
20805 wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
20806 {
20807 	return QDF_STATUS_SUCCESS;
20808 }
20809 
20810 static inline void
20811 wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
20812 {
20813 }
20814 #endif
20815 
20816 static QDF_STATUS
20817 wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
20818 {
20819 	hdd_ctx->iftype_data_2g =
20820 			qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_2g) *
20821 				       EHT_OPMODE_SUPPORTED);
20822 
20823 	if (!hdd_ctx->iftype_data_2g)
20824 		return QDF_STATUS_E_NOMEM;
20825 
20826 	hdd_ctx->iftype_data_5g =
20827 			qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_5g) *
20828 				       EHT_OPMODE_SUPPORTED);
20829 	if (!hdd_ctx->iftype_data_5g) {
20830 		qdf_mem_free(hdd_ctx->iftype_data_2g);
20831 		hdd_ctx->iftype_data_2g = NULL;
20832 		return QDF_STATUS_E_NOMEM;
20833 	}
20834 
20835 	if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc_6ghz(hdd_ctx))) {
20836 		qdf_mem_free(hdd_ctx->iftype_data_5g);
20837 		qdf_mem_free(hdd_ctx->iftype_data_2g);
20838 		hdd_ctx->iftype_data_2g = NULL;
20839 		hdd_ctx->iftype_data_5g = NULL;
20840 		return QDF_STATUS_E_NOMEM;
20841 	}
20842 
20843 	return QDF_STATUS_SUCCESS;
20844 }
20845 
20846 static void
20847 wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
20848 {
20849 	wlan_hdd_iftype_data_mem_free_6ghz(hdd_ctx);
20850 	qdf_mem_free(hdd_ctx->iftype_data_5g);
20851 	qdf_mem_free(hdd_ctx->iftype_data_2g);
20852 	hdd_ctx->iftype_data_5g = NULL;
20853 	hdd_ctx->iftype_data_2g = NULL;
20854 }
20855 #else
20856 static QDF_STATUS
20857 wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
20858 
20859 {
20860 	return QDF_STATUS_SUCCESS;
20861 }
20862 
20863 static inline void
20864 wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
20865 {
20866 }
20867 #endif
20868 
20869 #if defined(WLAN_FEATURE_NAN) && \
20870 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
20871 static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
20872 {
20873 	wiphy->interface_modes |= BIT(NL80211_IFTYPE_NAN);
20874 }
20875 #else
20876 static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
20877 {
20878 }
20879 #endif
20880 
20881 #if defined(WLAN_FEATURE_NAN) && \
20882 	   (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
20883 static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
20884 {
20885 	wiphy->nan_supported_bands =
20886 		BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ);
20887 }
20888 #else
20889 static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
20890 {
20891 }
20892 #endif
20893 
20894 #if defined(WLAN_FEATURE_NAN) && defined(WLAN_EXT_FEATURE_SECURE_NAN)
20895 /**
20896  * wlan_hdd_set_nan_secure_mode - Populate Secure NAN supported by driver
20897  * @wiphy: wiphy
20898  *
20899  * Return: void
20900  */
20901 static void wlan_hdd_set_nan_secure_mode(struct wiphy *wiphy)
20902 {
20903 	if (sme_is_feature_supported_by_fw(SECURE_NAN))
20904 		wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SECURE_NAN);
20905 }
20906 #else
20907 static void wlan_hdd_set_nan_secure_mode(struct wiphy *wiphy)
20908 {
20909 }
20910 #endif
20911 
20912 /**
20913  * wlan_hdd_update_akm_suit_info() - Populate akm suits supported by driver
20914  * @wiphy: wiphy
20915  *
20916  * Return: void
20917  */
20918 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) || \
20919 	defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
20920 static void
20921 wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
20922 {
20923 	wiphy->iftype_akm_suites = wlan_hdd_akm_suites;
20924 	wiphy->num_iftype_akm_suites = QDF_ARRAY_SIZE(wlan_hdd_akm_suites);
20925 }
20926 #else
20927 static void
20928 wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
20929 {
20930 }
20931 #endif
20932 
20933 #ifdef CFG80211_CTRL_FRAME_SRC_ADDR_TA_ADDR
20934 static void wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy *wiphy)
20935 {
20936 	wiphy_ext_feature_set(wiphy,
20937 			      NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
20938 	wiphy_ext_feature_set(wiphy,
20939 			      NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH);
20940 }
20941 #else
20942 static void wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy *wiphy)
20943 {
20944 }
20945 #endif
20946 
20947 #ifdef WLAN_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA
20948 /**
20949  * wlan_hdd_set_auth_deauth_random_ta_feature_flag() - set feature flag for
20950  * random address for auth and deauth frames to the kernel.
20951  * @wiphy: wiphy
20952  *
20953  * Return: void
20954  */
20955 static void wlan_hdd_set_auth_deauth_random_ta_feature_flag(struct wiphy *wiphy)
20956 {
20957 	wiphy_ext_feature_set(wiphy,
20958 			      NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA);
20959 }
20960 #else
20961 static void wlan_hdd_set_auth_deauth_random_ta_feature_flag(struct wiphy *wiphy)
20962 {
20963 }
20964 #endif
20965 
20966 #ifdef CFG80211_MULTI_AKM_CONNECT_SUPPORT
20967 static void
20968 wlan_hdd_update_max_connect_akm(struct wiphy *wiphy)
20969 {
20970 	wiphy->max_num_akm_suites = WLAN_CM_MAX_CONNECT_AKMS;
20971 }
20972 #else
20973 static void
20974 wlan_hdd_update_max_connect_akm(struct wiphy *wiphy)
20975 {
20976 }
20977 #endif
20978 
20979 #ifdef NL80211_EXT_FEATURE_PUNCT_SUPPORT
20980 /**
20981  * wlan_hdd_set_ext_feature_punct() - set feature flag for puncture
20982  * @wiphy: wiphy
20983  *
20984  * Return: void
20985  */
20986 static void wlan_hdd_set_ext_feature_punct(struct wiphy *wiphy)
20987 {
20988 	hdd_debug("enable puncture cap");
20989 	wiphy_ext_feature_set(wiphy,
20990 			      NL80211_EXT_FEATURE_PUNCT);
20991 }
20992 #else
20993 static inline void wlan_hdd_set_ext_feature_punct(struct wiphy *wiphy)
20994 {
20995 }
20996 #endif
20997 
20998 /*
20999  * FUNCTION: wlan_hdd_cfg80211_init
21000  * This function is called by hdd_wlan_startup()
21001  * during initialization.
21002  * This function is used to initialize and register wiphy structure.
21003  */
21004 int wlan_hdd_cfg80211_init(struct device *dev,
21005 			   struct wiphy *wiphy, struct hdd_config *config)
21006 {
21007 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
21008 	uint32_t *cipher_suites;
21009 	hdd_enter();
21010 
21011 	/* Now bind the underlying wlan device with wiphy */
21012 	set_wiphy_dev(wiphy, dev);
21013 
21014 	wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
21015 	wlan_hdd_update_akm_suit_info(wiphy);
21016 	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
21017 			| WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
21018 			| WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
21019 #ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
21020 			| WIPHY_FLAG_4ADDR_STATION
21021 #endif
21022 			| WIPHY_FLAG_OFFCHAN_TX
21023 			| WIPHY_FLAG_NETNS_OK;
21024 
21025 	if (ucfg_pmo_get_suspend_mode(hdd_ctx->psoc) == PMO_SUSPEND_WOW) {
21026 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
21027 		wiphy->wowlan = &wowlan_support_cfg80211_init;
21028 #else
21029 		wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
21030 		wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
21031 		wiphy->wowlan.pattern_min_len = 1;
21032 		wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
21033 #endif
21034 	}
21035 
21036 #ifdef FEATURE_WLAN_TDLS
21037 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
21038 			| WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
21039 #endif
21040 
21041 	wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
21042 
21043 	wlan_scan_cfg80211_add_connected_pno_support(wiphy);
21044 
21045 	wiphy->max_scan_ssids = MAX_SCAN_SSID;
21046 
21047 	wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
21048 
21049 	wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
21050 
21051 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
21052 				 | BIT(NL80211_IFTYPE_P2P_CLIENT)
21053 				 | BIT(NL80211_IFTYPE_P2P_GO)
21054 				 | BIT(NL80211_IFTYPE_AP)
21055 				 | BIT(NL80211_IFTYPE_MONITOR);
21056 
21057 	wlan_hdd_set_nan_if_mode(wiphy);
21058 
21059 	/*
21060 	 * In case of static linked driver at the time of driver unload,
21061 	 * module exit doesn't happens. Module cleanup helps in cleaning
21062 	 * of static memory.
21063 	 * If driver load happens statically, at the time of driver unload,
21064 	 * wiphy flags don't get reset because of static memory.
21065 	 * It's better not to store channel in static memory.
21066 	 * The memory is for channels of struct wiphy and shouldn't be
21067 	 * released during stop modules. So if it's allocated in active
21068 	 * domain, the memory leak detector would catch the leak during
21069 	 * stop modules. To avoid this,alloc in init domain in advance.
21070 	 */
21071 	hdd_ctx->channels_2ghz = qdf_mem_malloc(band_2_ghz_channels_size);
21072 	if (!hdd_ctx->channels_2ghz)
21073 		return -ENOMEM;
21074 
21075 	hdd_ctx->channels_5ghz = qdf_mem_malloc(band_5_ghz_channels_size);
21076 	if (!hdd_ctx->channels_5ghz)
21077 		goto mem_fail_5g;
21078 
21079 	if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc(hdd_ctx)))
21080 		goto mem_fail_iftype_data;
21081 
21082 	/*Initialise the supported cipher suite details */
21083 	if (ucfg_fwol_get_gcmp_enable(hdd_ctx->psoc)) {
21084 		cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
21085 					       sizeof(hdd_gcmp_cipher_suits));
21086 		if (!cipher_suites)
21087 			goto mem_fail_cipher_suites;
21088 		wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
21089 			 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
21090 		qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
21091 			     sizeof(hdd_cipher_suites));
21092 		qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
21093 			     &hdd_gcmp_cipher_suits,
21094 			     sizeof(hdd_gcmp_cipher_suits));
21095 	} else {
21096 		cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
21097 		if (!cipher_suites)
21098 			goto mem_fail_cipher_suites;
21099 		wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
21100 		qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
21101 			     sizeof(hdd_cipher_suites));
21102 	}
21103 	wiphy->cipher_suites = cipher_suites;
21104 	cipher_suites = NULL;
21105 	/*signal strength in mBm (100*dBm) */
21106 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
21107 	wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
21108 
21109 	wiphy->n_vendor_commands = ARRAY_SIZE(hdd_wiphy_vendor_commands);
21110 	wiphy->vendor_commands = hdd_wiphy_vendor_commands;
21111 
21112 	wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
21113 	wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
21114 
21115 #ifdef QCA_HT_2040_COEX
21116 	wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
21117 #endif
21118 	wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
21119 
21120 	wiphy->features |= NL80211_FEATURE_VIF_TXPOWER;
21121 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
21122 	defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
21123 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
21124 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
21125 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
21126 #endif
21127 
21128 	hdd_add_channel_switch_support(&wiphy->flags);
21129 	wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
21130 
21131 	wlan_hdd_update_max_connect_akm(wiphy);
21132 
21133 	wlan_hdd_cfg80211_action_frame_randomization_init(wiphy);
21134 	wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(wiphy);
21135 
21136 	wlan_hdd_set_nan_supported_bands(wiphy);
21137 
21138 	wlan_hdd_update_eapol_over_nl80211_flags(wiphy);
21139 
21140 	wlan_hdd_set_auth_deauth_random_ta_feature_flag(wiphy);
21141 	wlan_hdd_set_ext_feature_punct(wiphy);
21142 
21143 	hdd_exit();
21144 	return 0;
21145 
21146 mem_fail_cipher_suites:
21147 	wlan_hdd_iftype_data_mem_free(hdd_ctx);
21148 mem_fail_iftype_data:
21149 	qdf_mem_free(hdd_ctx->channels_5ghz);
21150 	hdd_ctx->channels_5ghz = NULL;
21151 mem_fail_5g:
21152 	hdd_err("Not enough memory to allocate channels");
21153 	qdf_mem_free(hdd_ctx->channels_2ghz);
21154 	hdd_ctx->channels_2ghz = NULL;
21155 
21156 	return -ENOMEM;
21157 }
21158 
21159 /**
21160  * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
21161  * @wiphy: the wiphy to validate against
21162  *
21163  * this function deinit cfg80211 and cleanup the
21164  * memory allocated in wlan_hdd_cfg80211_init also
21165  * reset the global reg params.
21166  *
21167  * Return: void
21168  */
21169 void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
21170 {
21171 	int i;
21172 	const uint32_t *cipher_suites;
21173 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
21174 
21175 	for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
21176 		if (wiphy->bands[i] &&
21177 		   (wiphy->bands[i]->channels))
21178 			wiphy->bands[i]->channels = NULL;
21179 	}
21180 	wlan_hdd_iftype_data_mem_free(hdd_ctx);
21181 	qdf_mem_free(hdd_ctx->channels_5ghz);
21182 	qdf_mem_free(hdd_ctx->channels_2ghz);
21183 	hdd_ctx->channels_2ghz = NULL;
21184 	hdd_ctx->channels_5ghz = NULL;
21185 
21186 	cipher_suites = wiphy->cipher_suites;
21187 	wiphy->cipher_suites = NULL;
21188 	wiphy->n_cipher_suites = 0;
21189 	qdf_mem_free((uint32_t *)cipher_suites);
21190 	cipher_suites = NULL;
21191 	hdd_reset_global_reg_params();
21192 }
21193 
21194 /**
21195  * wlan_hdd_update_ht_cap() - update HT capabilities for supported bands
21196  * @hdd_ctx: HDD context
21197  *
21198  * this function will update HT capabilities for supported bands
21199  *
21200  * Return: void
21201  */
21202 static void wlan_hdd_update_ht_cap(struct hdd_context *hdd_ctx)
21203 {
21204 	struct mlme_ht_capabilities_info ht_cap_info = {0};
21205 	QDF_STATUS status;
21206 	uint32_t channel_bonding_mode;
21207 	struct ieee80211_supported_band *band_2g;
21208 	struct ieee80211_supported_band *band_5g;
21209 	uint8_t i;
21210 
21211 	status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
21212 	if (QDF_STATUS_SUCCESS != status)
21213 		hdd_err("could not get HT capability info");
21214 
21215 	band_2g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ];
21216 	band_5g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ];
21217 
21218 	if (band_2g) {
21219 		if (ht_cap_info.tx_stbc)
21220 			band_2g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
21221 
21222 		if (!sme_is_feature_supported_by_fw(DOT11AC)) {
21223 			band_2g->vht_cap.vht_supported = 0;
21224 			band_2g->vht_cap.cap = 0;
21225 		}
21226 
21227 		if (!ht_cap_info.short_gi_20_mhz)
21228 			band_2g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
21229 
21230 		for (i = 0; i < hdd_ctx->num_rf_chains; i++)
21231 			band_2g->ht_cap.mcs.rx_mask[i] = 0xff;
21232 
21233 		/*
21234 		 * According to mcs_nss HT MCS parameters highest data rate for
21235 		 * Nss = 1 is 150 Mbps
21236 		 */
21237 		band_2g->ht_cap.mcs.rx_highest =
21238 				cpu_to_le16(150 * hdd_ctx->num_rf_chains);
21239 	}
21240 
21241 	if (band_5g) {
21242 		if (ht_cap_info.tx_stbc)
21243 			band_5g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
21244 
21245 		if (!sme_is_feature_supported_by_fw(DOT11AC)) {
21246 			band_5g->vht_cap.vht_supported = 0;
21247 			band_5g->vht_cap.cap = 0;
21248 		}
21249 
21250 		if (!ht_cap_info.short_gi_20_mhz)
21251 			band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
21252 
21253 		if (!ht_cap_info.short_gi_40_mhz)
21254 			band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
21255 
21256 		ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
21257 						   &channel_bonding_mode);
21258 		if (!channel_bonding_mode)
21259 			band_5g->ht_cap.cap &=
21260 					~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
21261 
21262 		for (i = 0; i < hdd_ctx->num_rf_chains; i++)
21263 			band_5g->ht_cap.mcs.rx_mask[i] = 0xff;
21264 		/*
21265 		 * According to mcs_nss HT MCS parameters highest data rate for
21266 		 * Nss = 1 is 150 Mbps
21267 		 */
21268 		band_5g->ht_cap.mcs.rx_highest =
21269 				cpu_to_le16(150 * hdd_ctx->num_rf_chains);
21270 	}
21271 }
21272 
21273 /**
21274  * wlan_hdd_update_band_cap_in_wiphy() - update channel flags based on band cap
21275  * @hdd_ctx: HDD context
21276  *
21277  * This function updates the channel flags based on the band capability set
21278  * in the MLME CFG
21279  *
21280  * Return: void
21281  */
21282 static void wlan_hdd_update_band_cap_in_wiphy(struct hdd_context *hdd_ctx)
21283 {
21284 	int i, j;
21285 	uint32_t band_capability;
21286 	QDF_STATUS status;
21287 	struct ieee80211_supported_band *band;
21288 
21289 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
21290 	if (QDF_IS_STATUS_ERROR(status)) {
21291 		hdd_err("Failed to get MLME Band Capability");
21292 		return;
21293 	}
21294 
21295 	for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
21296 		if (!hdd_ctx->wiphy->bands[i])
21297 			continue;
21298 
21299 		for (j = 0; j < hdd_ctx->wiphy->bands[i]->n_channels; j++) {
21300 			band = hdd_ctx->wiphy->bands[i];
21301 
21302 			if (HDD_NL80211_BAND_2GHZ == i &&
21303 			    BIT(REG_BAND_5G) == band_capability) {
21304 				/* 5G only */
21305 #ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
21306 				/* Enable social channels for P2P */
21307 				if (WLAN_HDD_IS_SOCIAL_CHANNEL
21308 				    (band->channels[j].center_freq))
21309 					band->channels[j].flags &=
21310 						~IEEE80211_CHAN_DISABLED;
21311 				else
21312 #endif
21313 				band->channels[j].flags |=
21314 					IEEE80211_CHAN_DISABLED;
21315 				continue;
21316 			} else if (HDD_NL80211_BAND_5GHZ == i &&
21317 				   BIT(REG_BAND_2G) == band_capability) {
21318 				/* 2G only */
21319 				band->channels[j].flags |=
21320 					IEEE80211_CHAN_DISABLED;
21321 				continue;
21322 			}
21323 		}
21324 	}
21325 }
21326 
21327 #ifdef FEATURE_WLAN_ESE
21328 /**
21329  * wlan_hdd_update_lfr_wiphy() - update LFR flag based on configures
21330  * @hdd_ctx: HDD context
21331  *
21332  * This function updates the LFR flag based on LFR configures
21333  *
21334  * Return: void
21335  */
21336 static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
21337 {
21338 	bool fast_transition_enabled;
21339 	bool lfr_enabled;
21340 	bool ese_enabled;
21341 	bool roam_offload;
21342 
21343 	ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
21344 					     &fast_transition_enabled);
21345 	ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
21346 	ucfg_mlme_is_ese_enabled(hdd_ctx->psoc, &ese_enabled);
21347 	ucfg_mlme_get_roaming_offload(hdd_ctx->psoc, &roam_offload);
21348 	if (fast_transition_enabled || lfr_enabled || ese_enabled ||
21349 	    roam_offload)
21350 		hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
21351 }
21352 #else
21353 static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
21354 {
21355 	bool fast_transition_enabled;
21356 	bool lfr_enabled;
21357 	bool roam_offload;
21358 
21359 	ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
21360 					     &fast_transition_enabled);
21361 	ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
21362 	ucfg_mlme_get_roaming_offload(hdd_ctx->psoc, &roam_offload);
21363 	if (fast_transition_enabled || lfr_enabled || roam_offload)
21364 		hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
21365 }
21366 #endif
21367 
21368 #if defined (CFG80211_SA_QUERY_OFFLOAD_SUPPORT) || \
21369 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
21370 /**
21371  * wlan_hdd_set_sa_query_offload_wiphy() - set sa query offload cap in sme cap
21372  * @hdd_ctx: HDD context
21373  *
21374  * This function set sa query offload cap for ap sme capabilities in wiphy
21375  *
21376  * Return: void
21377  */
21378 static void wlan_hdd_set_sa_query_offload_wiphy(struct hdd_context *hdd_ctx)
21379 {
21380 	hdd_ctx->wiphy->ap_sme_capa |= NL80211_AP_SME_SA_QUERY_OFFLOAD;
21381 }
21382 
21383 /**
21384  * wlan_hdd_update_ap_sme_cap_wiphy() - update ap sme capabilities in wiphy
21385  * @hdd_ctx: HDD context
21386  *
21387  * This function update ap sme capabilities in wiphy
21388  *
21389  * Return: void
21390  */
21391 static void wlan_hdd_update_ap_sme_cap_wiphy(struct hdd_context *hdd_ctx)
21392 {
21393 	wlan_hdd_set_sa_query_offload_wiphy(hdd_ctx);
21394 }
21395 #else
21396 static void wlan_hdd_update_ap_sme_cap_wiphy(struct hdd_context *hdd_ctx)
21397 {
21398 }
21399 #endif
21400 
21401 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
21402 static inline
21403 void wlan_hdd_set_mlo_wiphy_ext_feature(struct wiphy *wiphy,
21404 					struct hdd_context *hdd_ctx)
21405 {
21406 	bool eht_capab;
21407 
21408 	wlan_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
21409 	if (!eht_capab)
21410 		return;
21411 
21412 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
21413 }
21414 #else
21415 static inline
21416 void wlan_hdd_set_mlo_wiphy_ext_feature(struct wiphy *wiphy,
21417 					struct hdd_context *hdd_ctx)
21418 {
21419 }
21420 #endif
21421 
21422 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
21423 static inline
21424 void wlan_hdd_set_ext_kek_kck_support(struct wiphy *wiphy)
21425 {
21426 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK;
21427 }
21428 #else
21429 static inline
21430 void wlan_hdd_set_ext_kek_kck_support(struct wiphy *wiphy)
21431 {
21432 }
21433 #endif
21434 
21435 #ifdef NL80211_KCK_EXT_LEN_32
21436 static inline
21437 void wlan_hdd_set_32bytes_kck_support(struct wiphy *wiphy)
21438 {
21439 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_EXT_KCK_32;
21440 }
21441 #else
21442 static inline
21443 void wlan_hdd_set_32bytes_kck_support(struct wiphy *wiphy)
21444 {
21445 }
21446 #endif
21447 
21448 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
21449 static void wlan_hdd_set_vlan_offload(struct hdd_context *hdd_ctx)
21450 {
21451 	if (ucfg_mlme_is_multipass_sap(hdd_ctx->psoc))
21452 		wiphy_ext_feature_set(hdd_ctx->wiphy,
21453 				      NL80211_EXT_FEATURE_VLAN_OFFLOAD);
21454 }
21455 #else
21456 static void wlan_hdd_set_vlan_offload(struct hdd_context *hdd_ctx)
21457 {
21458 }
21459 #endif
21460 
21461 /*
21462  * In this function, wiphy structure is updated after QDF
21463  * initialization. In wlan_hdd_cfg80211_init, only the
21464  * default values will be initialized. The final initialization
21465  * of all required members can be done here.
21466  */
21467 void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
21468 {
21469 	int value = 0;
21470 	bool fils_enabled, mac_spoofing_enabled;
21471 	bool dfs_master_capable = true, is_oce_sta_enabled = false;
21472 	QDF_STATUS status;
21473 	struct wiphy *wiphy = hdd_ctx->wiphy;
21474 	uint8_t allow_mcc_go_diff_bi = 0, enable_mcc = 0;
21475 	bool is_bigtk_supported;
21476 	bool is_ocv_supported;
21477 	uint8_t iface_num;
21478 
21479 	if (!wiphy) {
21480 		hdd_err("Invalid wiphy");
21481 		return;
21482 	}
21483 	ucfg_mlme_get_sap_max_peers(hdd_ctx->psoc, &value);
21484 	hdd_ctx->wiphy->max_ap_assoc_sta = value;
21485 	wlan_hdd_update_ht_cap(hdd_ctx);
21486 	wlan_hdd_update_band_cap_in_wiphy(hdd_ctx);
21487 	wlan_hdd_update_lfr_wiphy(hdd_ctx);
21488 	wlan_hdd_update_ap_sme_cap_wiphy(hdd_ctx);
21489 
21490 	fils_enabled = 0;
21491 	status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc,
21492 						 &fils_enabled);
21493 	if (QDF_IS_STATUS_ERROR(status))
21494 		hdd_err("could not get fils enabled info");
21495 	if (fils_enabled)
21496 		wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy);
21497 
21498 	status = ucfg_mlme_get_dfs_master_capability(hdd_ctx->psoc,
21499 						     &dfs_master_capable);
21500 	if (QDF_IS_STATUS_SUCCESS(status) && dfs_master_capable)
21501 		wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy);
21502 
21503 
21504 	status = ucfg_mlme_get_bigtk_support(hdd_ctx->psoc,
21505 					     &is_bigtk_supported);
21506 
21507 	if (QDF_IS_STATUS_SUCCESS(status) && is_bigtk_supported)
21508 		wlan_hdd_cfg80211_set_bigtk_flags(wiphy);
21509 
21510 	status = ucfg_mlme_get_ocv_support(hdd_ctx->psoc,
21511 					   &is_ocv_supported);
21512 	if (QDF_IS_STATUS_SUCCESS(status) && is_ocv_supported)
21513 		wlan_hdd_cfg80211_set_ocv_flags(wiphy);
21514 
21515 	status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc,
21516 						    &is_oce_sta_enabled);
21517 	if (QDF_IS_STATUS_ERROR(status))
21518 		hdd_err("could not get OCE STA enable info");
21519 	if (is_oce_sta_enabled)
21520 		wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(wiphy);
21521 
21522 	wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy);
21523 
21524 	if (QDF_STATUS_SUCCESS !=
21525 	    ucfg_policy_mgr_get_allow_mcc_go_diff_bi(hdd_ctx->psoc,
21526 						     &allow_mcc_go_diff_bi))
21527 		hdd_err("can't get mcc_go_diff_bi value, use default");
21528 
21529 	if (QDF_STATUS_SUCCESS !=
21530 	    ucfg_mlme_get_mcc_feature(hdd_ctx->psoc, &enable_mcc))
21531 		hdd_err("can't get enable_mcc value, use default");
21532 
21533 	if (hdd_ctx->config->advertise_concurrent_operation) {
21534 		if (enable_mcc) {
21535 			int i;
21536 
21537 			for (i = 0;
21538 			     i < ARRAY_SIZE(wlan_hdd_iface_combination);
21539 			     i++) {
21540 				if (!allow_mcc_go_diff_bi)
21541 					wlan_hdd_iface_combination[i].
21542 					beacon_int_infra_match = true;
21543 			}
21544 		}
21545 
21546 		if (!ucfg_policy_mgr_is_fw_supports_dbs(hdd_ctx->psoc)) {
21547 			wiphy->iface_combinations =
21548 						wlan_hdd_derived_combination;
21549 			iface_num = ARRAY_SIZE(wlan_hdd_derived_combination);
21550 		} else {
21551 			wiphy->iface_combinations = wlan_hdd_iface_combination;
21552 			iface_num = ARRAY_SIZE(wlan_hdd_iface_combination);
21553 		}
21554 
21555 		wiphy->n_iface_combinations = iface_num;
21556 	}
21557 
21558 	mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
21559 	if (mac_spoofing_enabled)
21560 		wlan_hdd_cfg80211_scan_randomization_init(wiphy);
21561 
21562 	wlan_wifi_pos_cfg80211_set_wiphy_ext_feature(wiphy, hdd_ctx->psoc);
21563 	wlan_hdd_set_mlo_wiphy_ext_feature(wiphy, hdd_ctx);
21564 	wlan_hdd_set_ext_kek_kck_support(wiphy);
21565 	wlan_hdd_set_32bytes_kck_support(wiphy);
21566 	wlan_hdd_set_nan_secure_mode(wiphy);
21567 	wlan_hdd_set_vlan_offload(hdd_ctx);
21568 }
21569 
21570 /**
21571  * wlan_hdd_update_11n_mode - update 11n mode
21572  * @hdd_ctx: hdd ccontext
21573  *
21574  * this function updated 11n mode in hdd cfg and UMAC
21575  *
21576  * Return: void
21577  */
21578 void wlan_hdd_update_11n_mode(struct hdd_context *hdd_ctx)
21579 {
21580 	struct hdd_config *cfg = hdd_ctx->config;
21581 
21582 	if (sme_is_feature_supported_by_fw(DOT11AC)) {
21583 		hdd_debug("support 11ac");
21584 	} else {
21585 		hdd_debug("not support 11ac");
21586 		if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
21587 		    (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
21588 			cfg->dot11Mode = eHDD_DOT11_MODE_11n;
21589 			ucfg_mlme_set_sap_11ac_override(hdd_ctx->psoc, 0);
21590 			ucfg_mlme_set_go_11ac_override(hdd_ctx->psoc, 0);
21591 		}
21592 	}
21593 }
21594 
21595 QDF_STATUS wlan_hdd_update_wiphy_supported_band(struct hdd_context *hdd_ctx)
21596 {
21597 	int len_5g_ch, num_ch;
21598 	int num_dsrc_ch, len_dsrc_ch, num_srd_ch, len_srd_ch;
21599 	bool is_vht_for_24ghz = false;
21600 	QDF_STATUS status;
21601 	struct hdd_config *cfg = hdd_ctx->config;
21602 	struct wiphy *wiphy = hdd_ctx->wiphy;
21603 
21604 	if (wiphy->registered)
21605 		return QDF_STATUS_SUCCESS;
21606 
21607 	if (hdd_is_2g_supported(hdd_ctx)) {
21608 		if (!hdd_ctx->channels_2ghz)
21609 			return QDF_STATUS_E_NOMEM;
21610 		wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
21611 		wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
21612 							hdd_ctx->channels_2ghz;
21613 		qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
21614 			     &hdd_channels_2_4_ghz[0],
21615 			     sizeof(hdd_channels_2_4_ghz));
21616 
21617 		status = ucfg_mlme_get_vht_for_24ghz(hdd_ctx->psoc,
21618 						     &is_vht_for_24ghz);
21619 		if (QDF_IS_STATUS_ERROR(status))
21620 			hdd_err("could not get VHT capability");
21621 
21622 		if (is_vht_for_24ghz &&
21623 		    sme_is_feature_supported_by_fw(DOT11AC) &&
21624 		    (cfg->dot11Mode == eHDD_DOT11_MODE_AUTO ||
21625 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY ||
21626 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ac ||
21627 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ax ||
21628 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY))
21629 			wlan_hdd_band_2_4_ghz.vht_cap.vht_supported = 1;
21630 	}
21631 	if (!hdd_is_5g_supported(hdd_ctx) ||
21632 	    (eHDD_DOT11_MODE_11b == cfg->dot11Mode) ||
21633 	    (eHDD_DOT11_MODE_11g == cfg->dot11Mode) ||
21634 	    (eHDD_DOT11_MODE_11b_ONLY == cfg->dot11Mode) ||
21635 	    (eHDD_DOT11_MODE_11g_ONLY == cfg->dot11Mode))
21636 		return QDF_STATUS_SUCCESS;
21637 
21638 	if (!hdd_ctx->channels_5ghz)
21639 		return QDF_STATUS_E_NOMEM;
21640 	wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
21641 	wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels = hdd_ctx->channels_5ghz;
21642 	wlan_hdd_get_num_dsrc_ch_and_len(cfg, &num_dsrc_ch, &len_dsrc_ch);
21643 	wlan_hdd_get_num_srd_ch_and_len(cfg, &num_srd_ch, &len_srd_ch);
21644 	num_ch = QDF_ARRAY_SIZE(hdd_channels_5_ghz) + num_dsrc_ch + num_srd_ch;
21645 	len_5g_ch = sizeof(hdd_channels_5_ghz);
21646 
21647 	wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels = num_ch;
21648 	qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels,
21649 		     &hdd_channels_5_ghz[0], len_5g_ch);
21650 	if (num_dsrc_ch)
21651 		wlan_hdd_copy_dsrc_ch((char *)wiphy->bands[
21652 				      HDD_NL80211_BAND_5GHZ]->channels +
21653 				      len_5g_ch, len_dsrc_ch);
21654 	if (num_srd_ch)
21655 		wlan_hdd_copy_srd_ch((char *)wiphy->bands[
21656 				     HDD_NL80211_BAND_5GHZ]->channels +
21657 				     len_5g_ch, len_srd_ch);
21658 
21659 	if (cfg->dot11Mode != eHDD_DOT11_MODE_AUTO &&
21660 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ac &&
21661 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ac_ONLY &&
21662 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ax &&
21663 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ax_ONLY)
21664 		 wlan_hdd_band_5_ghz.vht_cap.vht_supported = 0;
21665 
21666 	if (cfg->dot11Mode == eHDD_DOT11_MODE_AUTO ||
21667 	    cfg->dot11Mode == eHDD_DOT11_MODE_11ax ||
21668 	    cfg->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY)
21669 		hdd_init_6ghz(hdd_ctx);
21670 
21671 	return QDF_STATUS_SUCCESS;
21672 }
21673 
21674 /* In this function we are registering wiphy. */
21675 int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
21676 {
21677 	int ret;
21678 
21679 	hdd_enter();
21680 	ret = wiphy_register(wiphy);
21681 	/* Register our wiphy dev with cfg80211 */
21682 	if (ret < 0) {
21683 		hdd_err("wiphy register failed %d", ret);
21684 		return -EIO;
21685 	}
21686 
21687 	hdd_exit();
21688 	return 0;
21689 }
21690 
21691 /* This function registers for all frame which supplicant is interested in */
21692 int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
21693 {
21694 	mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
21695 	/* Register for all P2P action, public action etc frames */
21696 	uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
21697 	QDF_STATUS status = QDF_STATUS_E_INVAL;
21698 
21699 	hdd_enter();
21700 	if (adapter->device_mode == QDF_FTM_MODE) {
21701 		hdd_info("No need to register frames in FTM mode");
21702 		return 0;
21703 	}
21704 
21705 	if (!mac_handle) {
21706 		hdd_err("mac_handle is NULL, failed to register frames");
21707 		goto ret_status;
21708 	}
21709 
21710 	/* Register frame indication call back */
21711 	status = sme_register_mgmt_frame_ind_callback(mac_handle,
21712 						      hdd_indicate_mgmt_frame);
21713 	if (status != QDF_STATUS_SUCCESS) {
21714 		hdd_err("Failed to register hdd_indicate_mgmt_frame");
21715 		goto ret_status;
21716 	}
21717 
21718 	/* Right now we are registering these frame when driver is getting
21719 	 * initialized. Once we will move to 2.6.37 kernel, in which we have
21720 	 * frame register ops, we will move this code as a part of that
21721 	 */
21722 
21723 	/* GAS Initial Request */
21724 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21725 					 (uint8_t *) GAS_INITIAL_REQ,
21726 					 GAS_INITIAL_REQ_SIZE);
21727 	if (status != QDF_STATUS_SUCCESS) {
21728 		hdd_err("Failed to register GAS_INITIAL_REQ");
21729 		goto ret_status;
21730 	}
21731 
21732 	/* GAS Initial Response */
21733 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21734 					 (uint8_t *) GAS_INITIAL_RSP,
21735 					 GAS_INITIAL_RSP_SIZE);
21736 	if (status != QDF_STATUS_SUCCESS) {
21737 		hdd_err("Failed to register GAS_INITIAL_RSP");
21738 		goto dereg_gas_initial_req;
21739 	}
21740 
21741 	/* GAS Comeback Request */
21742 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21743 					 (uint8_t *) GAS_COMEBACK_REQ,
21744 					 GAS_COMEBACK_REQ_SIZE);
21745 	if (status != QDF_STATUS_SUCCESS) {
21746 		hdd_err("Failed to register GAS_COMEBACK_REQ");
21747 		goto dereg_gas_initial_rsp;
21748 	}
21749 
21750 	/* GAS Comeback Response */
21751 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21752 					 (uint8_t *) GAS_COMEBACK_RSP,
21753 					 GAS_COMEBACK_RSP_SIZE);
21754 	if (status != QDF_STATUS_SUCCESS) {
21755 		hdd_err("Failed to register GAS_COMEBACK_RSP");
21756 		goto dereg_gas_comeback_req;
21757 	}
21758 
21759 	/* WNM BSS Transition Request frame */
21760 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21761 					 (uint8_t *) WNM_BSS_ACTION_FRAME,
21762 					 WNM_BSS_ACTION_FRAME_SIZE);
21763 	if (status != QDF_STATUS_SUCCESS) {
21764 		hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
21765 		goto dereg_gas_comeback_rsp;
21766 	}
21767 
21768 	/* WNM-Notification */
21769 	status = sme_register_mgmt_frame(mac_handle,
21770 					 adapter->deflink->vdev_id, type,
21771 					 (uint8_t *) WNM_NOTIFICATION_FRAME,
21772 					 WNM_NOTIFICATION_FRAME_SIZE);
21773 	if (status != QDF_STATUS_SUCCESS) {
21774 		hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
21775 		goto dereg_wnm_bss_action_frm;
21776 	}
21777 
21778 	return 0;
21779 
21780 dereg_wnm_bss_action_frm:
21781 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21782 				  (uint8_t *) WNM_BSS_ACTION_FRAME,
21783 				  WNM_BSS_ACTION_FRAME_SIZE);
21784 dereg_gas_comeback_rsp:
21785 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21786 				  (uint8_t *) GAS_COMEBACK_RSP,
21787 				  GAS_COMEBACK_RSP_SIZE);
21788 dereg_gas_comeback_req:
21789 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21790 				  (uint8_t *) GAS_COMEBACK_REQ,
21791 				  GAS_COMEBACK_REQ_SIZE);
21792 dereg_gas_initial_rsp:
21793 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21794 				  (uint8_t *) GAS_INITIAL_RSP,
21795 				  GAS_INITIAL_RSP_SIZE);
21796 dereg_gas_initial_req:
21797 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21798 				  (uint8_t *) GAS_INITIAL_REQ,
21799 				  GAS_INITIAL_REQ_SIZE);
21800 ret_status:
21801 	return qdf_status_to_os_return(status);
21802 }
21803 
21804 void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
21805 {
21806 	mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
21807 	/* Deregister for all P2P action, public action etc frames */
21808 	uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
21809 
21810 	hdd_enter();
21811 
21812 	if (!mac_handle) {
21813 		hdd_err("mac_handle is NULL, failed to deregister frames");
21814 		return;
21815 	}
21816 
21817 	/* Right now we are registering these frame when driver is getting
21818 	 * initialized. Once we will move to 2.6.37 kernel, in which we have
21819 	 * frame register ops, we will move this code as a part of that
21820 	 */
21821 
21822 	/* GAS Initial Request */
21823 
21824 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21825 				  (uint8_t *) GAS_INITIAL_REQ,
21826 				  GAS_INITIAL_REQ_SIZE);
21827 
21828 	/* GAS Initial Response */
21829 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21830 				  (uint8_t *) GAS_INITIAL_RSP,
21831 				  GAS_INITIAL_RSP_SIZE);
21832 
21833 	/* GAS Comeback Request */
21834 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21835 				  (uint8_t *) GAS_COMEBACK_REQ,
21836 				  GAS_COMEBACK_REQ_SIZE);
21837 
21838 	/* GAS Comeback Response */
21839 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21840 				  (uint8_t *) GAS_COMEBACK_RSP,
21841 				  GAS_COMEBACK_RSP_SIZE);
21842 
21843 	/* P2P Public Action */
21844 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21845 				  (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
21846 				  P2P_PUBLIC_ACTION_FRAME_SIZE);
21847 
21848 	/* P2P Action */
21849 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
21850 				  (uint8_t *) P2P_ACTION_FRAME,
21851 				  P2P_ACTION_FRAME_SIZE);
21852 
21853 	/* WNM-Notification */
21854 	sme_deregister_mgmt_frame(mac_handle, adapter->deflink->vdev_id, type,
21855 				  (uint8_t *) WNM_NOTIFICATION_FRAME,
21856 				  WNM_NOTIFICATION_FRAME_SIZE);
21857 }
21858 
21859 bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
21860 {
21861 	const uint8_t *vendor_ie;
21862 
21863 	if (length < 2) {
21864 		hdd_debug("bss size is less than expected");
21865 		return true;
21866 	}
21867 	if (!ies) {
21868 		hdd_debug("invalid IE pointer");
21869 		return true;
21870 	}
21871 	vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
21872 				VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
21873 	if (vendor_ie) {
21874 		hdd_debug("AP can't support immediate powersave. defer it");
21875 		return false;
21876 	}
21877 	return true;
21878 }
21879 
21880 QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_context *hdd_ctx,
21881 					       uint32_t ch_freq)
21882 {
21883 	bool value = 0;
21884 	uint32_t i;
21885 	struct regulatory_channel *cur_chan_list;
21886 	QDF_STATUS status;
21887 
21888 	status = ucfg_mlme_get_sap_allow_all_channels(hdd_ctx->psoc, &value);
21889 	if (status != QDF_STATUS_SUCCESS)
21890 		hdd_err("Unable to fetch sap allow all channels");
21891 	status = QDF_STATUS_E_INVAL;
21892 	if (value) {
21893 		/* Validate the channel */
21894 		for (i = CHAN_ENUM_2412; i < NUM_CHANNELS; i++) {
21895 			if (ch_freq == WLAN_REG_CH_TO_FREQ(i)) {
21896 				status = QDF_STATUS_SUCCESS;
21897 				break;
21898 			}
21899 		}
21900 	} else {
21901 		cur_chan_list = qdf_mem_malloc(NUM_CHANNELS *
21902 				sizeof(struct regulatory_channel));
21903 		if (!cur_chan_list)
21904 			return QDF_STATUS_E_NOMEM;
21905 
21906 		if (wlan_reg_get_secondary_current_chan_list(
21907 		    hdd_ctx->pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
21908 			qdf_mem_free(cur_chan_list);
21909 			return QDF_STATUS_E_INVAL;
21910 		}
21911 
21912 		for (i = 0; i < NUM_CHANNELS; i++) {
21913 			if (ch_freq != cur_chan_list[i].center_freq)
21914 				continue;
21915 			if (cur_chan_list[i].state != CHANNEL_STATE_DISABLE &&
21916 			    cur_chan_list[i].state != CHANNEL_STATE_INVALID)
21917 				status = QDF_STATUS_SUCCESS;
21918 			break;
21919 		}
21920 		qdf_mem_free(cur_chan_list);
21921 	}
21922 
21923 	return status;
21924 
21925 }
21926 
21927 static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
21928 					  struct net_device *dev,
21929 					  struct bss_parameters *params)
21930 {
21931 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21932 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21933 	struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
21934 	int ret = 0;
21935 	QDF_STATUS qdf_ret_status;
21936 	mac_handle_t mac_handle;
21937 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
21938 	cdp_config_param_type vdev_param;
21939 
21940 	hdd_enter();
21941 
21942 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
21943 		hdd_err("Command not allowed in FTM mode");
21944 		return -EINVAL;
21945 	}
21946 
21947 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
21948 		return -EINVAL;
21949 
21950 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21951 		   TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
21952 		   adapter->deflink->vdev_id, params->ap_isolate);
21953 
21954 	hdd_debug("Device_mode %s(%d), ap_isolate = %d",
21955 		  qdf_opmode_str(adapter->device_mode),
21956 		  adapter->device_mode, params->ap_isolate);
21957 
21958 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21959 	ret = wlan_hdd_validate_context(hdd_ctx);
21960 	if (0 != ret)
21961 		return ret;
21962 
21963 	if (!(adapter->device_mode == QDF_SAP_MODE ||
21964 	      adapter->device_mode == QDF_P2P_GO_MODE)) {
21965 		return -EOPNOTSUPP;
21966 	}
21967 
21968 	/* ap_isolate == -1 means that in change bss, upper layer doesn't
21969 	 * want to update this parameter
21970 	 */
21971 	if (-1 != params->ap_isolate) {
21972 		ap_ctx->disable_intrabss_fwd = !!params->ap_isolate;
21973 
21974 		mac_handle = hdd_ctx->mac_handle;
21975 		qdf_ret_status = sme_ap_disable_intra_bss_fwd(
21976 						mac_handle,
21977 						adapter->deflink->vdev_id,
21978 						ap_ctx->disable_intrabss_fwd);
21979 		if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
21980 			ret = -EINVAL;
21981 
21982 		ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->pdev,
21983 					 adapter->deflink->vdev_id,
21984 					 ap_ctx->disable_intrabss_fwd);
21985 
21986 		vdev_param.cdp_vdev_param_ap_brdg_en =
21987 			!ap_ctx->disable_intrabss_fwd;
21988 		cdp_txrx_set_vdev_param(soc, adapter->deflink->vdev_id,
21989 					CDP_ENABLE_AP_BRIDGE, vdev_param);
21990 	}
21991 
21992 	hdd_exit();
21993 	return ret;
21994 }
21995 
21996 /**
21997  * hdd_change_adapter_mode() - change @adapter's operating mode to @new_mode
21998  * @adapter: the adapter to change modes on
21999  * @new_mode: the new operating mode to change to
22000  *
22001  * Return: Errno
22002  */
22003 static int hdd_change_adapter_mode(struct hdd_adapter *adapter,
22004 				   enum QDF_OPMODE new_mode)
22005 {
22006 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22007 	struct net_device *netdev = adapter->dev;
22008 	QDF_STATUS status = QDF_STATUS_SUCCESS;
22009 
22010 	hdd_enter();
22011 
22012 	hdd_stop_adapter(hdd_ctx, adapter);
22013 	hdd_deinit_adapter(hdd_ctx, adapter, true);
22014 	adapter->device_mode = new_mode;
22015 	memset(&adapter->deflink->session, 0,
22016 	       sizeof(adapter->deflink->session));
22017 	hdd_set_station_ops(netdev);
22018 
22019 	hdd_exit();
22020 
22021 	return qdf_status_to_os_return(status);
22022 }
22023 
22024 static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
22025 					struct net_device *dev,
22026 					struct bss_parameters *params)
22027 {
22028 	int errno;
22029 	struct osif_vdev_sync *vdev_sync;
22030 
22031 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22032 	if (errno)
22033 		return errno;
22034 
22035 	errno = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
22036 
22037 	osif_vdev_sync_op_stop(vdev_sync);
22038 
22039 	return errno;
22040 }
22041 
22042 static bool hdd_is_client_mode(enum QDF_OPMODE mode)
22043 {
22044 	switch (mode) {
22045 	case QDF_STA_MODE:
22046 	case QDF_P2P_CLIENT_MODE:
22047 	case QDF_P2P_DEVICE_MODE:
22048 		return true;
22049 	default:
22050 		return false;
22051 	}
22052 }
22053 
22054 static bool hdd_is_ap_mode(enum QDF_OPMODE mode)
22055 {
22056 	switch (mode) {
22057 	case QDF_SAP_MODE:
22058 	case QDF_P2P_GO_MODE:
22059 		return true;
22060 	default:
22061 		return false;
22062 	}
22063 }
22064 
22065 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
22066 	!defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
22067 static QDF_STATUS
22068 hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter)
22069 {
22070 	int i;
22071 	QDF_STATUS status;
22072 	struct hdd_adapter *link_adapter;
22073 	struct hdd_mlo_adapter_info *mlo_adapter_info;
22074 	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
22075 	struct qdf_mac_addr link_addr[WLAN_MAX_ML_BSS_LINKS] = {0};
22076 
22077 	status = hdd_derive_link_address_from_mld(hdd_ctx->psoc,
22078 						  &adapter->mld_addr,
22079 						  &link_addr[0],
22080 						  WLAN_MAX_ML_BSS_LINKS);
22081 	if (QDF_IS_STATUS_ERROR(status))
22082 		return status;
22083 
22084 	mlo_adapter_info = &adapter->mlo_adapter_info;
22085 	for (i = 0; i < WLAN_MAX_MLD; i++) {
22086 		link_adapter = mlo_adapter_info->link_adapter[i];
22087 		qdf_copy_macaddr(&adapter->link_info[i].link_addr,
22088 				 &link_addr[i]);
22089 		if (!link_adapter)
22090 			continue;
22091 
22092 		ucfg_dp_update_intf_mac(hdd_ctx->psoc, &link_adapter->mac_addr,
22093 					&link_addr[i],
22094 					link_adapter->deflink->vdev);
22095 		qdf_copy_macaddr(&link_adapter->mac_addr, &link_addr[i]);
22096 	}
22097 	qdf_copy_macaddr(&adapter->link_info[i].link_addr, &link_addr[i]);
22098 
22099 	return QDF_STATUS_SUCCESS;
22100 }
22101 #else
22102 static inline QDF_STATUS
22103 hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter)
22104 {
22105 	return QDF_STATUS_SUCCESS;
22106 }
22107 #endif
22108 
22109 /**
22110  * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
22111  * @wiphy: Pointer to the wiphy structure
22112  * @ndev: Pointer to the net device
22113  * @type: Interface type
22114  * @flags: Flags for change interface
22115  * @params: Pointer to change interface parameters
22116  *
22117  * Return: 0 for success, error number on failure.
22118  */
22119 static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
22120 					    struct net_device *ndev,
22121 					    enum nl80211_iftype type,
22122 					    u32 *flags,
22123 					    struct vif_params *params)
22124 {
22125 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
22126 	struct hdd_context *hdd_ctx;
22127 	bool iff_up = ndev->flags & IFF_UP;
22128 	enum QDF_OPMODE new_mode;
22129 	bool ap_random_bssid_enabled;
22130 	QDF_STATUS status;
22131 	int errno;
22132 	uint8_t mac_addr[QDF_MAC_ADDR_SIZE];
22133 	bool eht_capab;
22134 	struct wlan_hdd_link_info *link_info = adapter->deflink;
22135 
22136 	hdd_enter();
22137 
22138 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
22139 		hdd_err("Command not allowed in FTM mode");
22140 		return -EINVAL;
22141 	}
22142 
22143 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22144 	errno = wlan_hdd_validate_context(hdd_ctx);
22145 	if (errno)
22146 		return errno;
22147 
22148 	if (wlan_hdd_is_mon_concurrency())
22149 		return -EINVAL;
22150 
22151 	if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
22152 		return -EINVAL;
22153 
22154 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22155 		   TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
22156 		   link_info->vdev_id, type);
22157 
22158 	status = hdd_nl_to_qdf_iface_type(type, &new_mode);
22159 	if (QDF_IS_STATUS_ERROR(status))
22160 		return qdf_status_to_os_return(status);
22161 
22162 	/* A userspace issue leads to it sending a 'change to station mode'
22163 	 * request on a "p2p" device, expecting the driver do execute a 'change
22164 	 * to p2p-device mode' request instead. The (unfortunate) work around
22165 	 * here is implemented by overriding the new mode if the net_device name
22166 	 * starts with "p2p" and the requested mode was station.
22167 	 */
22168 	if (strnstr(ndev->name, "p2p", 3) && new_mode == QDF_STA_MODE)
22169 		new_mode = QDF_P2P_DEVICE_MODE;
22170 
22171 	hdd_debug("Changing mode for '%s' from %s to %s",
22172 		  ndev->name,
22173 		  qdf_opmode_str(adapter->device_mode),
22174 		  qdf_opmode_str(new_mode));
22175 
22176 	errno = hdd_trigger_psoc_idle_restart(hdd_ctx);
22177 	if (errno) {
22178 		hdd_err("Failed to restart psoc; errno:%d", errno);
22179 		return -EINVAL;
22180 	}
22181 
22182 	/* Reset the current device mode bit mask */
22183 	policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
22184 
22185 	if (hdd_is_client_mode(adapter->device_mode)) {
22186 		if (adapter->device_mode == QDF_STA_MODE)
22187 			hdd_cleanup_conn_info(link_info);
22188 
22189 		if (hdd_is_client_mode(new_mode)) {
22190 			errno = hdd_change_adapter_mode(adapter, new_mode);
22191 			if (errno) {
22192 				hdd_err("change intf mode fail %d", errno);
22193 				goto err;
22194 			}
22195 		} else if (hdd_is_ap_mode(new_mode)) {
22196 			if (new_mode == QDF_P2P_GO_MODE)
22197 				wlan_hdd_cleanup_remain_on_channel_ctx(link_info);
22198 
22199 			hdd_stop_adapter(hdd_ctx, adapter);
22200 			hdd_deinit_adapter(hdd_ctx, adapter, true);
22201 			memset(&link_info->session, 0,
22202 			       sizeof(link_info->session));
22203 			adapter->device_mode = new_mode;
22204 
22205 			status = ucfg_mlme_get_ap_random_bssid_enable(
22206 						hdd_ctx->psoc,
22207 						&ap_random_bssid_enabled);
22208 			if (QDF_IS_STATUS_ERROR(status))
22209 				return qdf_status_to_os_return(status);
22210 
22211 			if (adapter->device_mode == QDF_SAP_MODE &&
22212 			    ap_random_bssid_enabled) {
22213 				/* To meet Android requirements create
22214 				 * a randomized MAC address of the
22215 				 * form 02:1A:11:Fx:xx:xx
22216 				 */
22217 				memcpy(mac_addr, ndev->dev_addr,
22218 				       QDF_MAC_ADDR_SIZE);
22219 
22220 				get_random_bytes(&mac_addr[3], 3);
22221 				mac_addr[0] = 0x02;
22222 				mac_addr[1] = 0x1A;
22223 				mac_addr[2] = 0x11;
22224 				mac_addr[3] |= 0xF0;
22225 				memcpy(adapter->mac_addr.bytes, mac_addr,
22226 				       QDF_MAC_ADDR_SIZE);
22227 				qdf_net_update_net_device_dev_addr(ndev,
22228 								   mac_addr,
22229 								   QDF_MAC_ADDR_SIZE);
22230 
22231 				pr_info("wlan: Generated HotSpot BSSID "
22232 					QDF_MAC_ADDR_FMT "\n",
22233 					QDF_MAC_ADDR_REF(ndev->dev_addr));
22234 			}
22235 			hdd_set_ap_ops(adapter->dev);
22236 		} else {
22237 			hdd_err("Changing to device mode '%s' is not supported",
22238 				qdf_opmode_str(new_mode));
22239 			errno = -EOPNOTSUPP;
22240 			goto err;
22241 		}
22242 	} else if (hdd_is_ap_mode(adapter->device_mode)) {
22243 		if (hdd_is_client_mode(new_mode)) {
22244 			errno = hdd_change_adapter_mode(adapter, new_mode);
22245 			if (errno) {
22246 				hdd_err("change mode fail %d", errno);
22247 				goto err;
22248 			}
22249 		} else if (hdd_is_ap_mode(new_mode)) {
22250 			adapter->device_mode = new_mode;
22251 
22252 			/* avoid starting the adapter, since it never stopped */
22253 			iff_up = false;
22254 		} else {
22255 			hdd_err("Changing to device mode '%s' is not supported",
22256 				qdf_opmode_str(new_mode));
22257 			errno = -EOPNOTSUPP;
22258 			goto err;
22259 		}
22260 	} else {
22261 		hdd_err("Changing from device mode '%s' is not supported",
22262 			qdf_opmode_str(adapter->device_mode));
22263 		errno = -EOPNOTSUPP;
22264 		goto err;
22265 	}
22266 
22267 	ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
22268 	if (eht_capab && hdd_adapter_is_ml_adapter(adapter)) {
22269 		switch (adapter->device_mode) {
22270 		case QDF_SAP_MODE:
22271 			hdd_adapter_set_sl_ml_adapter(adapter);
22272 			adapter->active_links = 0x1;
22273 			break;
22274 		case QDF_STA_MODE:
22275 			hdd_adapter_clear_sl_ml_adapter(adapter);
22276 
22277 			status = hdd_adapter_update_mac_on_mode_change(adapter);
22278 			if (QDF_IS_STATUS_ERROR(status))
22279 				goto err;
22280 
22281 			adapter->active_links =
22282 					(1 << adapter->num_links_on_create) - 1;
22283 			break;
22284 		default:
22285 			hdd_adapter_clear_sl_ml_adapter(adapter);
22286 			adapter->active_links = 0x1;
22287 			break;
22288 		}
22289 	}
22290 
22291 	/* restart the adapter if it was up before the change iface request */
22292 	if (iff_up) {
22293 		errno = hdd_start_adapter(adapter, true);
22294 		if (errno) {
22295 			hdd_err("Failed to start adapter");
22296 			errno = -EINVAL;
22297 			goto err;
22298 		}
22299 	}
22300 
22301 	ndev->ieee80211_ptr->iftype = type;
22302 	hdd_lpass_notify_mode_change(link_info);
22303 err:
22304 	/* Set bitmask based on updated value */
22305 	policy_mgr_set_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
22306 
22307 	hdd_exit();
22308 
22309 	return errno;
22310 }
22311 
22312 static int _wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
22313 					   struct net_device *net_dev,
22314 					   enum nl80211_iftype type,
22315 					   u32 *flags,
22316 					   struct vif_params *params)
22317 {
22318 	int errno;
22319 	struct osif_vdev_sync *vdev_sync;
22320 
22321 	errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
22322 	if (errno)
22323 		goto err;
22324 
22325 	errno = __wlan_hdd_cfg80211_change_iface(wiphy, net_dev, type,
22326 						 flags, params);
22327 
22328 	osif_vdev_sync_trans_stop(vdev_sync);
22329 
22330 	return errno;
22331 err:
22332 	/* In the SSR case, errno will be -EINVAL from
22333 	 * __dsc_vdev_can_trans with qdf_is_recovering()
22334 	 * is true, only change -EINVAL to -EBUSY to make
22335 	 * wpa_supplicant has chance to retry mode switch.
22336 	 * Meanwhile do not touch the errno from
22337 	 * __wlan_hdd_cfg80211_change_iface with this
22338 	 * change.
22339 	 */
22340 	if (errno && errno != -EAGAIN && errno != -EBUSY)
22341 		errno = -EBUSY;
22342 	return errno;
22343 }
22344 
22345 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
22346 /**
22347  * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
22348  * @wiphy: Pointer to the wiphy structure
22349  * @ndev: Pointer to the net device
22350  * @type: Interface type
22351  * @flags: Flags for change interface
22352  * @params: Pointer to change interface parameters
22353  *
22354  * Return: 0 for success, error number on failure.
22355  */
22356 static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
22357 					  struct net_device *ndev,
22358 					  enum nl80211_iftype type,
22359 					  u32 *flags,
22360 					  struct vif_params *params)
22361 {
22362 	return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
22363 					       flags, params);
22364 }
22365 #else
22366 static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
22367 					  struct net_device *ndev,
22368 					  enum nl80211_iftype type,
22369 					  struct vif_params *params)
22370 {
22371 	return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
22372 					       &params->flags, params);
22373 }
22374 #endif /* KERNEL_VERSION(4, 12, 0) */
22375 
22376 QDF_STATUS wlan_hdd_send_sta_authorized_event(
22377 					struct hdd_adapter *adapter,
22378 					struct hdd_context *hdd_ctx,
22379 					const struct qdf_mac_addr *mac_addr)
22380 {
22381 	struct sk_buff *vendor_event;
22382 	QDF_STATUS status;
22383 	struct nl80211_sta_flag_update sta_flags;
22384 
22385 	hdd_enter();
22386 	if (!hdd_ctx) {
22387 		hdd_err("HDD context is null");
22388 		return QDF_STATUS_E_INVAL;
22389 	}
22390 
22391 	vendor_event =
22392 		wlan_cfg80211_vendor_event_alloc(
22393 			hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) +
22394 			QDF_MAC_ADDR_SIZE + NLMSG_HDRLEN,
22395 			QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX,
22396 			GFP_KERNEL);
22397 	if (!vendor_event) {
22398 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
22399 		return QDF_STATUS_E_FAILURE;
22400 	}
22401 
22402 	qdf_mem_zero(&sta_flags, sizeof(sta_flags));
22403 
22404 	sta_flags.mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
22405 	sta_flags.set = true;
22406 
22407 	status = nla_put(vendor_event,
22408 			 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS,
22409 			 sizeof(struct  nl80211_sta_flag_update),
22410 			 &sta_flags);
22411 	if (status) {
22412 		hdd_err("STA flag put fails");
22413 		wlan_cfg80211_vendor_free_skb(vendor_event);
22414 		return QDF_STATUS_E_FAILURE;
22415 	}
22416 	status = nla_put(vendor_event,
22417 			 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR,
22418 			 QDF_MAC_ADDR_SIZE, mac_addr->bytes);
22419 	if (status) {
22420 		hdd_err("STA MAC put fails");
22421 		wlan_cfg80211_vendor_free_skb(vendor_event);
22422 		return QDF_STATUS_E_FAILURE;
22423 	}
22424 
22425 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
22426 
22427 	hdd_exit();
22428 	return QDF_STATUS_SUCCESS;
22429 }
22430 
22431 #ifdef QCA_MULTIPASS_SUPPORT
22432 static int
22433 wlan_hdd_set_peer_vlan_config(struct hdd_adapter *adapter,
22434 			      struct wlan_objmgr_vdev *vdev,
22435 			      uint8_t *mac_addr,
22436 			      uint8_t vlan_id)
22437 {
22438 	ol_txrx_soc_handle soc_txrx_handle;
22439 	cdp_config_param_type val;
22440 	QDF_STATUS status;
22441 
22442 	soc_txrx_handle = wlan_psoc_get_dp_handle(wlan_vdev_get_psoc(vdev));
22443 
22444 	cdp_peer_set_vlan_id(soc_txrx_handle,
22445 			     wlan_vdev_get_id(vdev),
22446 			     mac_addr, vlan_id);
22447 
22448 	val.cdp_peer_param_isolation = true;
22449 
22450 	cdp_txrx_set_peer_param(soc_txrx_handle,
22451 				wlan_vdev_get_id(vdev),
22452 				mac_addr,
22453 				CDP_CONFIG_ISOLATION,
22454 				val);
22455 
22456 	status = ucfg_mlme_peer_config_vlan(vdev, mac_addr);
22457 	if (QDF_IS_STATUS_ERROR(status))
22458 		return -EINVAL;
22459 
22460 	return 0;
22461 }
22462 
22463 static void
22464 wlan_hdd_set_vlan_id(struct hdd_sta_info_obj *sta_info_list,
22465 		     uint8_t *mac, struct station_parameters *params)
22466 {
22467 	struct hdd_station_info *sta_info;
22468 
22469 	if (!params->vlan_id)
22470 		return;
22471 
22472 	sta_info =
22473 	hdd_get_sta_info_by_mac(sta_info_list,
22474 				mac,
22475 				STA_INFO_SOFTAP_GET_STA_INFO);
22476 	if (!sta_info) {
22477 		hdd_err("Failed to find right station MAC: "
22478 			  QDF_MAC_ADDR_FMT,
22479 			  QDF_MAC_ADDR_REF(mac));
22480 		return;
22481 	}
22482 
22483 	sta_info->vlan_id = params->vlan_id;
22484 
22485 	hdd_put_sta_info_ref(sta_info_list, &sta_info, true,
22486 			     STA_INFO_SOFTAP_GET_STA_INFO);
22487 }
22488 
22489 static QDF_STATUS
22490 wlan_hdd_set_vlan_config(struct hdd_adapter *adapter,
22491 			 uint8_t *mac)
22492 {
22493 	int ret;
22494 	struct hdd_station_info *sta_info;
22495 
22496 	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
22497 					   (uint8_t *)mac,
22498 					   STA_INFO_SOFTAP_GET_STA_INFO);
22499 
22500 	if (!sta_info) {
22501 		hdd_err("Failed to find right station MAC:"
22502 			QDF_MAC_ADDR_FMT,
22503 			QDF_MAC_ADDR_REF((uint8_t *)mac));
22504 			return QDF_STATUS_E_INVAL;
22505 	}
22506 
22507 	if (!sta_info->vlan_id) {
22508 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
22509 				     true,
22510 				     STA_INFO_SOFTAP_GET_STA_INFO);
22511 		return QDF_STATUS_E_INVAL;
22512 	}
22513 
22514 	ret = wlan_hdd_set_peer_vlan_config(adapter,
22515 					    adapter->deflink->vdev,
22516 					    mac,
22517 					    sta_info->vlan_id);
22518 	if (ret < 0) {
22519 		hdd_err("Unable to send peer vlan config");
22520 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
22521 				     true,
22522 				     STA_INFO_SOFTAP_GET_STA_INFO);
22523 		return QDF_STATUS_E_INVAL;
22524 	}
22525 
22526 	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
22527 			     true,  STA_INFO_SOFTAP_GET_STA_INFO);
22528 
22529 	return QDF_STATUS_SUCCESS;
22530 }
22531 #else
22532 static inline void
22533 wlan_hdd_set_vlan_id(struct hdd_sta_info_obj *sta_info_list,
22534 		     uint8_t *mac, struct station_parameters *params)
22535 {
22536 }
22537 
22538 static inline QDF_STATUS
22539 wlan_hdd_set_vlan_config(struct hdd_adapter *adapter,
22540 			 uint8_t *mac)
22541 {
22542 	return QDF_STATUS_SUCCESS;
22543 }
22544 #endif
22545 /**
22546  * __wlan_hdd_change_station() - change station
22547  * @wiphy: Pointer to the wiphy structure
22548  * @dev: Pointer to the net device.
22549  * @mac: bssid
22550  * @params: Pointer to station parameters
22551  *
22552  * Return: 0 for success, error number on failure.
22553  */
22554 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
22555 static int __wlan_hdd_change_station(struct wiphy *wiphy,
22556 				   struct net_device *dev,
22557 				   const uint8_t *mac,
22558 				   struct station_parameters *params)
22559 #else
22560 static int __wlan_hdd_change_station(struct wiphy *wiphy,
22561 				   struct net_device *dev,
22562 				   uint8_t *mac,
22563 				   struct station_parameters *params)
22564 #endif
22565 {
22566 	QDF_STATUS status = QDF_STATUS_SUCCESS;
22567 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22568 	struct hdd_context *hdd_ctx;
22569 	struct hdd_station_ctx *sta_ctx;
22570 	struct hdd_ap_ctx *ap_ctx;
22571 	struct qdf_mac_addr sta_macaddr;
22572 	int ret;
22573 
22574 	hdd_enter();
22575 
22576 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
22577 		hdd_err("Command not allowed in FTM mode");
22578 		return -EINVAL;
22579 	}
22580 
22581 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22582 		   TRACE_CODE_HDD_CHANGE_STATION,
22583 		   adapter->deflink->vdev_id, params->listen_interval);
22584 
22585 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
22586 		return -EINVAL;
22587 
22588 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22589 	ret = wlan_hdd_validate_context(hdd_ctx);
22590 	if (0 != ret)
22591 		return ret;
22592 
22593 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
22594 
22595 	qdf_mem_copy(sta_macaddr.bytes, mac, QDF_MAC_ADDR_SIZE);
22596 
22597 	wlan_hdd_set_vlan_id(&adapter->sta_info_list, (uint8_t *)mac, params);
22598 
22599 	if ((adapter->device_mode == QDF_SAP_MODE) ||
22600 	    (adapter->device_mode == QDF_P2P_GO_MODE)) {
22601 		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
22602 			ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
22603 			/*
22604 			 * For Encrypted SAP session, this will be done as
22605 			 * part of eSAP_STA_SET_KEY_EVENT
22606 			 */
22607 
22608 			if (ucfg_mlme_is_multipass_sap(hdd_ctx->psoc)) {
22609 				status =
22610 				wlan_hdd_set_vlan_config(adapter,
22611 							 (uint8_t *)mac);
22612 				if (QDF_IS_STATUS_ERROR(status))
22613 					return 0;
22614 			}
22615 
22616 			if (ap_ctx->encryption_type !=
22617 			    eCSR_ENCRYPT_TYPE_NONE) {
22618 				hdd_debug("Encrypt type %d, not setting peer authorized now",
22619 					  ap_ctx->encryption_type);
22620 				return 0;
22621 			}
22622 
22623 			status =
22624 				hdd_softap_change_sta_state(adapter,
22625 							    &sta_macaddr,
22626 							    OL_TXRX_PEER_STATE_AUTH);
22627 
22628 			if (status != QDF_STATUS_SUCCESS) {
22629 				hdd_debug("Not able to change TL state to AUTHENTICATED");
22630 				return -EINVAL;
22631 			}
22632 			status = wlan_hdd_send_sta_authorized_event(
22633 								adapter,
22634 								hdd_ctx,
22635 								&sta_macaddr);
22636 			if (status != QDF_STATUS_SUCCESS) {
22637 				return -EINVAL;
22638 			}
22639 		}
22640 	} else if ((adapter->device_mode == QDF_STA_MODE) ||
22641 		   (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
22642 		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
22643 #if defined(FEATURE_WLAN_TDLS)
22644 			struct wlan_objmgr_vdev *vdev;
22645 
22646 			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
22647 							   WLAN_OSIF_TDLS_ID);
22648 			if (!vdev)
22649 				return -EINVAL;
22650 			ret = wlan_cfg80211_tdls_update_peer(vdev, mac, params);
22651 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
22652 #endif
22653 		}
22654 	}
22655 	hdd_exit();
22656 	return ret;
22657 }
22658 
22659 /**
22660  * wlan_hdd_change_station() - cfg80211 change station handler function
22661  * @wiphy: Pointer to the wiphy structure
22662  * @dev: Pointer to the net device.
22663  * @mac: bssid
22664  * @params: Pointer to station parameters
22665  *
22666  * This is the cfg80211 change station handler function which invokes
22667  * the internal function @__wlan_hdd_change_station with
22668  * SSR protection.
22669  *
22670  * Return: 0 for success, error number on failure.
22671  */
22672 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
22673 static int wlan_hdd_change_station(struct wiphy *wiphy,
22674 				   struct net_device *dev,
22675 				   const u8 *mac,
22676 				   struct station_parameters *params)
22677 #else
22678 static int wlan_hdd_change_station(struct wiphy *wiphy,
22679 				   struct net_device *dev,
22680 				   u8 *mac,
22681 				   struct station_parameters *params)
22682 #endif
22683 {
22684 	int errno;
22685 	struct osif_vdev_sync *vdev_sync;
22686 
22687 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22688 	if (errno)
22689 		return errno;
22690 
22691 	errno = __wlan_hdd_change_station(wiphy, dev, mac, params);
22692 
22693 	osif_vdev_sync_op_stop(vdev_sync);
22694 
22695 	return errno;
22696 }
22697 
22698 #ifdef FEATURE_WLAN_ESE
22699 static bool hdd_is_krk_enc_type(uint32_t cipher_type)
22700 {
22701 	if (cipher_type == WLAN_CIPHER_SUITE_KRK)
22702 		return true;
22703 
22704 	return false;
22705 }
22706 #else
22707 static bool hdd_is_krk_enc_type(uint32_t cipher_type)
22708 {
22709 	return false;
22710 }
22711 #endif
22712 
22713 #if defined(FEATURE_WLAN_ESE) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
22714 static bool hdd_is_btk_enc_type(uint32_t cipher_type)
22715 {
22716 	if (cipher_type == WLAN_CIPHER_SUITE_BTK)
22717 		return true;
22718 
22719 	return false;
22720 }
22721 #else
22722 static bool hdd_is_btk_enc_type(uint32_t cipher_type)
22723 {
22724 	return false;
22725 }
22726 #endif
22727 
22728 #ifdef WLAN_FEATURE_11BE_MLO
22729 struct wlan_objmgr_vdev *wlan_key_get_link_vdev(struct hdd_adapter *adapter,
22730 						wlan_objmgr_ref_dbgid id,
22731 						int link_id)
22732 {
22733 	struct wlan_objmgr_vdev *vdev, *link_vdev;
22734 
22735 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, id);
22736 	if (!vdev)
22737 		return NULL;
22738 
22739 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
22740 		return vdev;
22741 
22742 	link_vdev = mlo_get_vdev_by_link_id(vdev, link_id);
22743 	hdd_objmgr_put_vdev_by_user(vdev, id);
22744 
22745 	return link_vdev;
22746 }
22747 
22748 void wlan_key_put_link_vdev(struct wlan_objmgr_vdev *link_vdev,
22749 			    wlan_objmgr_ref_dbgid id)
22750 {
22751 	if (!wlan_vdev_mlme_is_mlo_vdev(link_vdev)) {
22752 		hdd_objmgr_put_vdev_by_user(link_vdev, id);
22753 		return;
22754 	}
22755 
22756 	mlo_release_vdev_ref(link_vdev);
22757 }
22758 #else
22759 struct wlan_objmgr_vdev *wlan_key_get_link_vdev(struct hdd_adapter *adapter,
22760 						wlan_objmgr_ref_dbgid id,
22761 						int link_id)
22762 {
22763 	struct wlan_objmgr_vdev *vdev;
22764 
22765 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, id);
22766 	if (!vdev)
22767 		return NULL;
22768 
22769 	return vdev;
22770 }
22771 
22772 void wlan_key_put_link_vdev(struct wlan_objmgr_vdev *link_vdev,
22773 			    wlan_objmgr_ref_dbgid id)
22774 {
22775 	hdd_objmgr_put_vdev_by_user(link_vdev, id);
22776 }
22777 #endif
22778 
22779 /*
22780  * FUNCTION: __wlan_hdd_cfg80211_get_key
22781  * This function is used to get the key information
22782  */
22783 
22784 static int wlan_hdd_add_key_sap(struct wlan_hdd_link_info *link_info,
22785 				bool pairwise, u8 key_index,
22786 				enum wlan_crypto_cipher_type cipher)
22787 {
22788 	struct wlan_objmgr_vdev *vdev;
22789 	int errno = 0;
22790 	struct hdd_hostapd_state *hostapd_state =
22791 		WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info);
22792 
22793 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
22794 	if (!vdev)
22795 		return -EINVAL;
22796 
22797 	/* Do not send install key when sap restart is in progress. If there is
22798 	 * critical channel request handling going on, fw will stop that request
22799 	 * and will not send restart response
22800 	 */
22801 	if (wlan_vdev_is_restart_progress(vdev) == QDF_STATUS_SUCCESS) {
22802 		hdd_err("vdev: %d restart in progress", wlan_vdev_get_id(vdev));
22803 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
22804 		return -EINVAL;
22805 	}
22806 
22807 	if (hostapd_state->bss_state == BSS_START) {
22808 		errno =
22809 		wlan_cfg80211_crypto_add_key(vdev,
22810 					     (pairwise ?
22811 					      WLAN_CRYPTO_KEY_TYPE_UNICAST :
22812 					      WLAN_CRYPTO_KEY_TYPE_GROUP),
22813 					     key_index, true);
22814 		if (!errno)
22815 			wma_update_set_key(link_info->vdev_id, pairwise,
22816 					   key_index, cipher);
22817 	}
22818 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
22819 
22820 	return errno;
22821 }
22822 
22823 static int wlan_hdd_add_key_sta(struct wlan_objmgr_pdev *pdev,
22824 				struct wlan_hdd_link_info *link_info,
22825 				bool pairwise, u8 key_index, bool *ft_mode)
22826 {
22827 	struct wlan_objmgr_vdev *vdev;
22828 	int errno;
22829 	QDF_STATUS status;
22830 	struct hdd_adapter *adapter = link_info->adapter;
22831 
22832 	/* The supplicant may attempt to set the PTK once
22833 	 * pre-authentication is done. Save the key in the
22834 	 * UMAC and install it after association
22835 	 */
22836 	status = ucfg_cm_check_ft_status(pdev, link_info->vdev_id);
22837 	if (status == QDF_STATUS_SUCCESS) {
22838 		*ft_mode = true;
22839 		return 0;
22840 	}
22841 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
22842 	if (!vdev)
22843 		return -EINVAL;
22844 	errno = wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
22845 					     WLAN_CRYPTO_KEY_TYPE_UNICAST :
22846 					     WLAN_CRYPTO_KEY_TYPE_GROUP),
22847 					     key_index, true);
22848 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
22849 	if (!errno && adapter->send_mode_change) {
22850 		wlan_hdd_send_mode_change_event();
22851 		adapter->send_mode_change = false;
22852 	}
22853 
22854 	return errno;
22855 }
22856 
22857 #ifdef WLAN_FEATURE_11BE_MLO
22858 static void
22859 wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc *psoc,
22860 			    struct hdd_adapter *adapter,
22861 			    struct wlan_objmgr_vdev *vdev,
22862 			    bool pairwise)
22863 {
22864 	struct qdf_mac_addr *link_addr;
22865 	uint8_t link_id;
22866 
22867 	if (adapter->device_mode != QDF_STA_MODE)
22868 		return;
22869 
22870 	if (pairwise &&
22871 	    wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
22872 	    mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
22873 					      wlan_vdev_get_id(vdev))) {
22874 		link_addr =
22875 		(struct qdf_mac_addr *)wlan_vdev_mlme_get_linkaddr(vdev);
22876 
22877 		if (!link_addr) {
22878 			crypto_err("link_addr NULL");
22879 			return;
22880 		}
22881 		link_id = wlan_vdev_get_link_id(vdev);
22882 		wlan_crypto_free_key_by_link_id(psoc, link_addr, link_id);
22883 	}
22884 }
22885 
22886 #else
22887 
22888 static void
22889 wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc *psoc,
22890 			    struct hdd_adapter *adapter,
22891 			    struct wlan_objmgr_vdev *vdev,
22892 			    bool pairwise)
22893 {
22894 }
22895 #endif
22896 
22897 #ifdef WLAN_FEATURE_11BE_MLO
22898 QDF_STATUS
22899 wlan_hdd_mlo_copy_partner_addr_from_mlie(struct wlan_objmgr_vdev *vdev,
22900 					 struct qdf_mac_addr *partner_mac)
22901 {
22902 	int i;
22903 	QDF_STATUS status;
22904 	struct wlan_mlo_dev_context *mlo_dev_ctx;
22905 	struct wlan_mlo_sta *sta_ctx;
22906 	struct mlo_link_info *partner_link_info;
22907 	struct element_info *assoc_rsp;
22908 	const uint8_t *ie_data_ptr;
22909 	size_t ie_data_len, ml_ie_len = 0;
22910 	uint8_t *ml_ie = NULL;
22911 	bool found = false;
22912 	struct mlo_partner_info partner_info = {0};
22913 
22914 	if (!vdev)
22915 		return QDF_STATUS_E_NULL_VALUE;
22916 
22917 	mlo_dev_ctx = vdev->mlo_dev_ctx;
22918 	if (!mlo_dev_ctx)
22919 		return QDF_STATUS_E_INVAL;
22920 
22921 	sta_ctx = mlo_dev_ctx->sta_ctx;
22922 	if (!sta_ctx)
22923 		return QDF_STATUS_E_INVAL;
22924 
22925 	mlo_dev_lock_acquire(mlo_dev_ctx);
22926 	assoc_rsp = &sta_ctx->assoc_rsp;
22927 
22928 	if (!assoc_rsp->len || !assoc_rsp->ptr ||
22929 	    assoc_rsp->len <= WLAN_ASSOC_RSP_IES_OFFSET) {
22930 		mlo_dev_lock_release(mlo_dev_ctx);
22931 		return QDF_STATUS_E_INVAL;
22932 	}
22933 
22934 	ie_data_len = assoc_rsp->len - WLAN_ASSOC_RSP_IES_OFFSET;
22935 	ie_data_ptr = assoc_rsp->ptr + WLAN_ASSOC_RSP_IES_OFFSET;
22936 	status = util_find_mlie((uint8_t *)ie_data_ptr, ie_data_len,
22937 				&ml_ie, &ml_ie_len);
22938 
22939 	if (QDF_IS_STATUS_ERROR(status) || !ml_ie) {
22940 		mlo_dev_lock_release(mlo_dev_ctx);
22941 		hdd_debug("ML IE not found %d", status);
22942 		return status;
22943 	}
22944 
22945 	status = util_get_bvmlie_persta_partner_info(ml_ie, ml_ie_len,
22946 						     &partner_info);
22947 	if (QDF_IS_STATUS_ERROR(status)) {
22948 		mlo_dev_lock_release(mlo_dev_ctx);
22949 		hdd_err("Unable to find per-sta profile in ML IE");
22950 		return status;
22951 	}
22952 	mlo_dev_lock_release(mlo_dev_ctx);
22953 
22954 	for (i = 0; i < partner_info.num_partner_links; i++) {
22955 		partner_link_info = &partner_info.partner_link_info[i];
22956 		if (partner_link_info->link_id == vdev->vdev_mlme.mlo_link_id) {
22957 			qdf_copy_macaddr(partner_mac,
22958 					 &partner_link_info->link_addr);
22959 			found = true;
22960 			break;
22961 		}
22962 	}
22963 
22964 	if (!partner_info.num_partner_links || !found)
22965 		status = QDF_STATUS_E_NOENT;
22966 
22967 	return status;
22968 }
22969 #endif
22970 
22971 #if defined(QCA_MULTIPASS_SUPPORT) && \
22972 	(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
22973 static void
22974 wlan_hdd_set_vlan_groupkey(ol_txrx_soc_handle soc_txrx_handle, uint16_t vdev_id,
22975 			   struct key_params *params, uint8_t key_index)
22976 {
22977 	if (params->vlan_id)
22978 		cdp_set_vlan_groupkey(soc_txrx_handle, vdev_id,
22979 				      params->vlan_id, key_index);
22980 }
22981 
22982 static int
22983 wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
22984 		  struct key_params *params, uint8_t key_index,
22985 		  uint8_t *vlan_key_idx)
22986 {
22987 	struct wlan_objmgr_psoc *psoc = NULL;
22988 	ol_txrx_soc_handle soc_txrx_handle;
22989 	uint16_t *vlan_map = sap_ctx->vlan_map;
22990 	uint8_t found = 0;
22991 	bool keyindex_valid;
22992 	int i = 0;
22993 
22994 	psoc = wlan_vdev_get_psoc(vdev);
22995 	if (!psoc) {
22996 		hdd_err("Unable to get psoc");
22997 		return -EINVAL;
22998 	}
22999 
23000 	for (i = 0; i < (MAX_VLAN * 2); i += 2) {
23001 		if (!vlan_map[i] || !vlan_map[i + 1]) {
23002 			found = 1;
23003 			break;
23004 		} else if ((vlan_map[i] == params->vlan_id) ||
23005 			   (vlan_map[i + 1] == params->vlan_id)) {
23006 			vlan_map[i] = 0;
23007 			vlan_map[i + 1] = 0;
23008 			found = 1;
23009 			break;
23010 		}
23011 	}
23012 
23013 	keyindex_valid = (i + key_index - 1) < (2 * MAX_VLAN) ? true : false;
23014 
23015 	if (found && keyindex_valid) {
23016 		soc_txrx_handle = wlan_psoc_get_dp_handle(psoc);
23017 		vlan_map[i + key_index - 1] = params->vlan_id;
23018 		wlan_hdd_set_vlan_groupkey(soc_txrx_handle,
23019 					   wlan_vdev_get_id(vdev),
23020 					   params,
23021 					   (i / 2) + 1);
23022 		*vlan_key_idx = (i + key_index - 1 + 8);
23023 		return 0;
23024 	}
23025 
23026 	hdd_err("Unable to find group key mapping for vlan_id: %d",
23027 		params->vlan_id);
23028 	return -EINVAL;
23029 }
23030 #else
23031 static int
23032 wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
23033 		  struct key_params *params, uint8_t key_index,
23034 		  uint8_t *vlan_key_idx)
23035 {
23036 	return key_index;
23037 }
23038 #endif
23039 
23040 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
23041 static void wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev *vdev,
23042 					       struct hdd_context *hdd_ctx,
23043 					       u8 key_index, bool pairwise,
23044 					       struct key_params *params)
23045 {
23046 	struct mlo_link_info *mlo_link_info;
23047 	uint8_t link_info_iter = 0;
23048 
23049 	mlo_link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[0];
23050 	for (link_info_iter = 0; link_info_iter < WLAN_MAX_ML_BSS_LINKS;
23051 	     link_info_iter++, mlo_link_info++) {
23052 		if (qdf_is_macaddr_zero(&mlo_link_info->ap_link_addr) ||
23053 		    mlo_link_info->link_id == 0xFF)
23054 			continue;
23055 			hdd_debug(" Add pairwise key link id  %d ",
23056 				  mlo_link_info->link_id);
23057 			wlan_cfg80211_store_link_key(
23058 				hdd_ctx->psoc, key_index,
23059 				(pairwise ? WLAN_CRYPTO_KEY_TYPE_UNICAST :
23060 				WLAN_CRYPTO_KEY_TYPE_GROUP),
23061 				(uint8_t *)mlo_link_info->ap_link_addr.bytes,
23062 				params, &mlo_link_info->link_addr,
23063 				mlo_link_info->link_id);
23064 	}
23065 }
23066 
23067 static bool
23068 wlan_hdd_mlo_defer_set_keys(struct hdd_adapter *adapter,
23069 			    struct wlan_objmgr_vdev *vdev,
23070 			    struct qdf_mac_addr *mac_address)
23071 {
23072 	if (!adapter)
23073 		return false;
23074 
23075 	if (!vdev)
23076 		return false;
23077 
23078 	if ((adapter->device_mode == QDF_STA_MODE) &&
23079 	    ((!wlan_cm_is_vdev_connected(vdev)) ||
23080 	    (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
23081 	     mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
23082 					       wlan_vdev_get_id(vdev))))) {
23083 		hdd_debug("MLO:Defer set keys for vdev %d", wlan_vdev_get_id(vdev));
23084 		return true;
23085 	}
23086 
23087 	return false;
23088 }
23089 
23090 #else
23091 
23092 static void wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev *vdev,
23093 					       struct hdd_context *hdd_ctx,
23094 					       u8 key_index, bool pairwise,
23095 					       struct key_params *params)
23096 {
23097 }
23098 
23099 static bool
23100 wlan_hdd_mlo_defer_set_keys(struct hdd_adapter *adapter,
23101 			    struct wlan_objmgr_vdev *vdev,
23102 			    struct qdf_mac_addr *mac_address)
23103 {
23104 	return false;
23105 }
23106 
23107 #endif
23108 
23109 static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
23110 				 struct wlan_objmgr_vdev *vdev, u8 key_index,
23111 				 bool pairwise, const u8 *mac_addr,
23112 				 struct key_params *params, int link_id,
23113 				 struct wlan_hdd_link_info *link_info)
23114 {
23115 	QDF_STATUS status;
23116 	struct wlan_objmgr_peer *peer;
23117 	struct hdd_context *hdd_ctx;
23118 	struct qdf_mac_addr mac_address;
23119 	int32_t cipher_cap, ucast_cipher = 0;
23120 	int errno = 0;
23121 	enum wlan_crypto_cipher_type cipher;
23122 	bool ft_mode = false;
23123 	uint8_t keyidx;
23124 	struct hdd_ap_ctx *hdd_ap_ctx;
23125 	struct sap_context *sap_ctx;
23126 	struct hdd_adapter *adapter = link_info->adapter;
23127 
23128 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23129 
23130 	if (hdd_is_btk_enc_type(params->cipher))
23131 		return sme_add_key_btk(mac_handle, wlan_vdev_get_id(vdev),
23132 				       params->key, params->key_len);
23133 	if (hdd_is_krk_enc_type(params->cipher))
23134 		return sme_add_key_krk(mac_handle, wlan_vdev_get_id(vdev),
23135 				       params->key, params->key_len);
23136 
23137 	if (!pairwise && ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) ||
23138 	   (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE))) {
23139 		peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_ID);
23140 		if (peer) {
23141 			qdf_mem_copy(mac_address.bytes,
23142 				     wlan_peer_get_macaddr(peer),
23143 				     QDF_MAC_ADDR_SIZE);
23144 			wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
23145 		} else if (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
23146 			   adapter->device_mode == QDF_STA_MODE) {
23147 			status = wlan_objmgr_vdev_try_get_ref(vdev,
23148 							      WLAN_MLO_MGR_ID);
23149 			if (QDF_IS_STATUS_ERROR(status)) {
23150 				hdd_err("Failed to get vdev ref");
23151 				return qdf_status_to_os_return(status);
23152 			}
23153 			status = wlan_hdd_mlo_copy_partner_addr_from_mlie(
23154 							vdev, &mac_address);
23155 			mlo_release_vdev_ref(vdev);
23156 			if (QDF_IS_STATUS_ERROR(status)) {
23157 				hdd_err("Failed to get peer address from ML IEs");
23158 				return qdf_status_to_os_return(status);
23159 			}
23160 			goto done;
23161 		} else {
23162 			hdd_err("Peer is null return");
23163 			return -EINVAL;
23164 		}
23165 
23166 		status = mlo_get_link_mac_addr_from_reassoc_rsp(vdev,
23167 								&mac_address);
23168 		if (QDF_IS_STATUS_ERROR(status)) {
23169 			peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
23170 								WLAN_OSIF_ID);
23171 			if (!peer) {
23172 				hdd_err("Peer is null return");
23173 				return -EINVAL;
23174 			}
23175 			qdf_mem_copy(mac_address.bytes,
23176 				     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
23177 			wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
23178 		}
23179 	} else {
23180 		if (mac_addr)
23181 			qdf_mem_copy(mac_address.bytes,
23182 				     mac_addr,
23183 				     QDF_MAC_ADDR_SIZE);
23184 	}
23185 
23186 done:
23187 	wlan_hdd_mlo_link_free_keys(hdd_ctx->psoc, adapter, vdev, pairwise);
23188 	if (pairwise && adapter->device_mode == QDF_STA_MODE &&
23189 	    wlan_vdev_mlme_is_mlo_vdev(vdev) &&
23190 	    !wlan_vdev_mlme_is_tdls_vdev(vdev)) {
23191 		wlan_hdd_mlo_link_add_pairwise_key(vdev, hdd_ctx, key_index,
23192 						   pairwise, params);
23193 
23194 	} else {
23195 		errno = wlan_cfg80211_store_key(
23196 					vdev, key_index,
23197 					(pairwise ?
23198 					WLAN_CRYPTO_KEY_TYPE_UNICAST :
23199 					WLAN_CRYPTO_KEY_TYPE_GROUP),
23200 					mac_address.bytes, params);
23201 	}
23202 
23203 	if (wlan_hdd_mlo_defer_set_keys(adapter, vdev, &mac_address))
23204 		return 0;
23205 
23206 	cipher_cap = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_CIPHER_CAP);
23207 	if (errno)
23208 		return errno;
23209 	cipher = osif_nl_to_crypto_cipher_type(params->cipher);
23210 	QDF_SET_PARAM(ucast_cipher, cipher);
23211 	if (pairwise)
23212 		wma_set_peer_ucast_cipher(mac_address.bytes,
23213 					  ucast_cipher, cipher_cap);
23214 
23215 	cdp_peer_flush_frags(cds_get_context(QDF_MODULE_ID_SOC),
23216 			     wlan_vdev_get_id(vdev), mac_address.bytes);
23217 
23218 	switch (adapter->device_mode) {
23219 	case QDF_SAP_MODE:
23220 	case QDF_P2P_GO_MODE:
23221 		hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
23222 		if (hdd_ap_ctx->during_auth_offload) {
23223 			hdd_err("don't need install key during auth");
23224 			return -EINVAL;
23225 		}
23226 
23227 		keyidx = key_index;
23228 
23229 		if (ucfg_mlme_is_multipass_sap(hdd_ctx->psoc) &&
23230 		    params->vlan_id) {
23231 			sap_ctx = hdd_ap_ctx->sap_context;
23232 			errno = wlan_hdd_add_vlan(vdev, sap_ctx, params,
23233 						  key_index, &keyidx);
23234 			if (errno < 0)
23235 				return errno;
23236 		}
23237 
23238 		errno = wlan_hdd_add_key_sap(link_info, pairwise,
23239 					     keyidx, cipher);
23240 
23241 		break;
23242 	case QDF_STA_MODE:
23243 	case QDF_P2P_CLIENT_MODE:
23244 	case QDF_NAN_DISC_MODE:
23245 		errno = wlan_hdd_add_key_sta(hdd_ctx->pdev, link_info, pairwise,
23246 					     key_index, &ft_mode);
23247 		if (ft_mode)
23248 			return 0;
23249 		break;
23250 	default:
23251 		break;
23252 	}
23253 	if (!errno && (adapter->device_mode != QDF_SAP_MODE))
23254 		wma_update_set_key(wlan_vdev_get_id(vdev), pairwise, key_index,
23255 				   cipher);
23256 
23257 	hdd_exit();
23258 	return errno;
23259 }
23260 
23261 #ifdef WLAN_FEATURE_11BE_MLO
23262 QDF_STATUS wlan_hdd_send_key_vdev(struct wlan_objmgr_vdev *vdev,
23263 				  u8 key_index, bool pairwise,
23264 				  enum wlan_crypto_cipher_type cipher_type)
23265 {
23266 	struct wlan_objmgr_peer *peer;
23267 	struct qdf_mac_addr mac_address;
23268 	int32_t cipher_cap, ucast_cipher = 0;
23269 	QDF_STATUS status = QDF_STATUS_SUCCESS;
23270 	int errno;
23271 	bool ft_mode = false;
23272 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
23273 	uint8_t vdev_id;
23274 	struct wlan_hdd_link_info *link_info;
23275 
23276 	if (!hdd_ctx) {
23277 		hdd_err("hdd_ctx is NULL");
23278 		return QDF_STATUS_E_NULL_VALUE;
23279 	}
23280 
23281 	vdev_id = wlan_vdev_get_id(vdev);
23282 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
23283 	if (!link_info) {
23284 		hdd_err("adapter is NULL for vdev %d", vdev_id);
23285 		return QDF_STATUS_E_NULL_VALUE;
23286 	}
23287 
23288 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) {
23289 		hdd_debug("vdev opmode is not STA mode");
23290 		return QDF_STATUS_E_INVAL;
23291 	}
23292 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_ID);
23293 	if (!peer) {
23294 		hdd_err("Peer is null return");
23295 		return QDF_STATUS_E_NULL_VALUE;
23296 	}
23297 	qdf_mem_copy(mac_address.bytes,
23298 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
23299 	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
23300 
23301 	cipher_cap = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_CIPHER_CAP);
23302 	QDF_SET_PARAM(ucast_cipher, cipher_type);
23303 	if (pairwise)
23304 		wma_set_peer_ucast_cipher(mac_address.bytes,
23305 					  ucast_cipher, cipher_cap);
23306 
23307 	cdp_peer_flush_frags(cds_get_context(QDF_MODULE_ID_SOC),
23308 			     vdev_id, mac_address.bytes);
23309 
23310 	errno = wlan_hdd_add_key_sta(hdd_ctx->pdev, link_info,
23311 				     pairwise, key_index, &ft_mode);
23312 	if (ft_mode)
23313 		return QDF_STATUS_SUCCESS;
23314 
23315 	if (!errno)
23316 		wma_update_set_key(vdev_id, pairwise, key_index, cipher_type);
23317 	else
23318 		status = QDF_STATUS_E_FAILURE;
23319 
23320 	return status;
23321 }
23322 #endif
23323 
23324 #if defined(WLAN_FEATURE_11BE_MLO) && \
23325 defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT)
23326 struct wlan_objmgr_peer *
23327 wlan_hdd_ml_sap_get_peer(struct wlan_objmgr_vdev *vdev,
23328 			 const uint8_t *peer_mld)
23329 {
23330 	struct wlan_mlo_dev_context *ap_mlo_dev_ctx;
23331 	struct wlan_mlo_peer_list *mlo_peer_list;
23332 	struct wlan_mlo_peer_context *ml_peer;
23333 	struct wlan_mlo_link_peer_entry *peer_entry;
23334 	int i, pdev_id;
23335 	uint8_t *peer_mac;
23336 	struct wlan_objmgr_pdev *pdev;
23337 	struct wlan_objmgr_psoc *psoc;
23338 	struct wlan_objmgr_peer *peer = NULL;
23339 
23340 	if (!vdev)
23341 		return NULL;
23342 
23343 	pdev = wlan_vdev_get_pdev(vdev);
23344 
23345 	if (!pdev)
23346 		return NULL;
23347 
23348 	psoc = wlan_pdev_get_psoc(pdev);
23349 
23350 	if (!psoc)
23351 		return NULL;
23352 
23353 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
23354 
23355 	ap_mlo_dev_ctx = vdev->mlo_dev_ctx;
23356 	mlo_dev_lock_acquire(ap_mlo_dev_ctx);
23357 	mlo_peer_list = &ap_mlo_dev_ctx->mlo_peer_list;
23358 	ml_peerlist_lock_acquire(mlo_peer_list);
23359 	ml_peer = mlo_get_mlpeer(ap_mlo_dev_ctx,
23360 				 (struct qdf_mac_addr *)peer_mld);
23361 	if (!ml_peer) {
23362 		/* Peer is a legacy STA client, check peer list.
23363 		 * Treat the MLD address as legacy MAC address
23364 		 */
23365 		peer = wlan_objmgr_get_peer(psoc, pdev_id,
23366 					    peer_mld, WLAN_OSIF_ID);
23367 		goto out;
23368 	}
23369 
23370 	mlo_peer_lock_acquire(ml_peer);
23371 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
23372 		peer_entry = &ml_peer->peer_list[i];
23373 		if (!peer_entry)
23374 			continue;
23375 		/* Checking for VDEV match which will
23376 		 * be used for multiple VDEV case.
23377 		 */
23378 		if (vdev == wlan_peer_get_vdev(peer_entry->link_peer)) {
23379 			peer_mac = &peer_entry->link_peer->macaddr[0];
23380 			peer = wlan_objmgr_get_peer(psoc, pdev_id, peer_mac,
23381 						    WLAN_OSIF_ID);
23382 			break;
23383 		}
23384 	}
23385 	mlo_peer_lock_release(ml_peer);
23386 
23387 out:
23388 	ml_peerlist_lock_release(mlo_peer_list);
23389 	mlo_dev_lock_release(ap_mlo_dev_ctx);
23390 
23391 	return peer;
23392 }
23393 
23394 static int wlan_hdd_add_key_all_mlo_vdev(mac_handle_t mac_handle,
23395 					 struct wlan_objmgr_vdev *vdev,
23396 					 u8 key_index, bool pairwise,
23397 					 const u8 *mac_addr,
23398 					 struct key_params *params, int link_id,
23399 					 struct hdd_adapter *adapter)
23400 {
23401 	QDF_STATUS status;
23402 	struct hdd_context *hdd_ctx;
23403 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
23404 	struct wlan_objmgr_vdev *link_vdev;
23405 	struct qdf_mac_addr peer_mac;
23406 	struct wlan_objmgr_peer *peer = NULL;
23407 	int errno = 0;
23408 	uint16_t link, vdev_count = 0;
23409 	uint8_t vdev_id;
23410 	struct wlan_hdd_link_info *link_info;
23411 
23412 	/* if vdev mlme is mlo & pairwaise is set to true set same info for
23413 	 * both the links.
23414 	 */
23415 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23416 
23417 	mlo_sta_get_vdev_list(vdev, &vdev_count, wlan_vdev_list);
23418 	for (link = 0; link < vdev_count; link++) {
23419 		link_vdev = wlan_vdev_list[link];
23420 		vdev_id = wlan_vdev_get_id(link_vdev);
23421 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
23422 		if (!link_info) {
23423 			mlo_release_vdev_ref(link_vdev);
23424 			continue;
23425 		}
23426 		peer = NULL;
23427 		switch (adapter->device_mode) {
23428 		case QDF_SAP_MODE:
23429 			if (wlan_vdev_mlme_is_mlo_vdev(link_vdev))
23430 				peer = wlan_hdd_ml_sap_get_peer(
23431 						link_vdev,
23432 						mac_addr);
23433 			break;
23434 		case QDF_STA_MODE:
23435 		default:
23436 			status = mlo_get_link_mac_addr_from_reassoc_rsp(link_vdev,
23437 									&peer_mac);
23438 			if (QDF_IS_STATUS_ERROR(status))
23439 				peer = wlan_objmgr_vdev_try_get_bsspeer(link_vdev,
23440 									WLAN_OSIF_ID);
23441 			else
23442 				goto add_key;
23443 			break;
23444 		}
23445 
23446 		if (peer) {
23447 			qdf_mem_copy(peer_mac.bytes,
23448 				     wlan_peer_get_macaddr(peer),
23449 				     QDF_MAC_ADDR_SIZE);
23450 			wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
23451 
23452 		} else if (wlan_vdev_mlme_is_mlo_link_vdev(link_vdev) &&
23453 			   adapter->device_mode == QDF_STA_MODE) {
23454 			status = wlan_hdd_mlo_copy_partner_addr_from_mlie(
23455 							link_vdev, &peer_mac);
23456 			if (QDF_IS_STATUS_ERROR(status)) {
23457 				hdd_err("Failed to get peer address from ML IEs");
23458 				mlo_release_vdev_ref(link_vdev);
23459 				continue;
23460 			}
23461 		} else {
23462 			hdd_err("Peer is null");
23463 			mlo_release_vdev_ref(link_vdev);
23464 			continue;
23465 		}
23466 
23467 add_key:
23468 		errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
23469 					      pairwise, peer_mac.bytes,
23470 					      params, link_id, link_info);
23471 		mlo_release_vdev_ref(link_vdev);
23472 	}
23473 
23474 	return errno;
23475 }
23476 
23477 static int wlan_add_key_standby_link(struct hdd_adapter *adapter,
23478 				     struct wlan_objmgr_vdev *vdev,
23479 				     int link_id, u8 key_index,
23480 				     bool pairwise, struct key_params *params)
23481 {
23482 	int errno = 0;
23483 	struct hdd_context *hdd_ctx;
23484 	struct mlo_link_info *mlo_link_info;
23485 
23486 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23487 
23488 	mlo_link_info = mlo_mgr_get_ap_link_by_link_id(vdev, link_id);
23489 	if (!mlo_link_info)
23490 		return QDF_STATUS_E_FAILURE;
23491 
23492 	errno = wlan_cfg80211_store_link_key(
23493 			hdd_ctx->psoc, key_index,
23494 			(pairwise ? WLAN_CRYPTO_KEY_TYPE_UNICAST :
23495 			WLAN_CRYPTO_KEY_TYPE_GROUP),
23496 			(uint8_t *)mlo_link_info->ap_link_addr.bytes,
23497 			params,
23498 			&mlo_link_info->link_addr,
23499 			link_id);
23500 	return errno;
23501 }
23502 
23503 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
23504 				     struct wlan_objmgr_vdev *vdev,
23505 				     u8 key_index, bool pairwise,
23506 				     const u8 *mac_addr,
23507 				     struct key_params *params, int link_id,
23508 				     struct hdd_adapter *adapter)
23509 {
23510 	int errno = 0;
23511 	struct wlan_objmgr_vdev *link_vdev;
23512 	struct hdd_context *hdd_ctx;
23513 	uint8_t vdev_id;
23514 	QDF_STATUS status;
23515 	struct wlan_hdd_link_info *link_info;
23516 
23517 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
23518 		return errno;
23519 
23520 	vdev_id = wlan_vdev_get_id(vdev);
23521 	if (pairwise &&
23522 	    mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
23523 					      vdev_id)) {
23524 		status = mlo_roam_link_connect_notify(adapter->hdd_ctx->psoc,
23525 						      vdev_id);
23526 		if (QDF_IS_STATUS_ERROR(status)) {
23527 			hdd_err("Posting of link connect request failed");
23528 			return -EINVAL;
23529 		}
23530 	}
23531 
23532 	link_vdev = ucfg_tdls_get_tdls_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
23533 	if (pairwise && link_id == -1 && !link_vdev)
23534 		return wlan_hdd_add_key_all_mlo_vdev(mac_handle, vdev,
23535 						     key_index, pairwise,
23536 						     mac_addr, params,
23537 						     link_id, adapter);
23538 
23539 	if (pairwise && link_id == -1 && link_vdev) {
23540 		hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23541 		link_info =
23542 		      hdd_get_link_info_by_vdev(hdd_ctx,
23543 						wlan_vdev_get_id(link_vdev));
23544 		link_id = wlan_vdev_get_link_id(link_vdev);
23545 		if (!link_info) {
23546 			ucfg_tdls_put_tdls_link_vdev(link_vdev,
23547 						     WLAN_OSIF_TDLS_ID);
23548 			hdd_err("couldn't set tdls key, link_id %d", link_id);
23549 			return -EINVAL;
23550 		}
23551 
23552 		errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
23553 					      pairwise, mac_addr, params,
23554 					      link_id, link_info);
23555 		ucfg_tdls_put_tdls_link_vdev(link_vdev, WLAN_OSIF_TDLS_ID);
23556 
23557 		return errno;
23558 	}
23559 
23560 	if (link_vdev)
23561 		ucfg_tdls_put_tdls_link_vdev(link_vdev, WLAN_OSIF_TDLS_ID);
23562 
23563 	if (wlan_vdev_get_link_id(adapter->deflink->vdev) == link_id) {
23564 		hdd_debug("add_key for same vdev: %d",
23565 			  adapter->deflink->vdev_id);
23566 		return wlan_hdd_add_key_vdev(mac_handle, vdev, key_index,
23567 					     pairwise, mac_addr, params,
23568 					     link_id, adapter->deflink);
23569 	}
23570 
23571 	link_vdev = wlan_key_get_link_vdev(adapter, WLAN_MLO_MGR_ID, link_id);
23572 	if (!link_vdev) {
23573 		hdd_err("couldn't get vdev for link_id :%d", link_id);
23574 		errno = wlan_add_key_standby_link(adapter, vdev, link_id,
23575 						  key_index, pairwise, params);
23576 		return errno;
23577 	}
23578 
23579 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23580 	link_info = hdd_get_link_info_by_vdev(hdd_ctx,
23581 					      wlan_vdev_get_id(link_vdev));
23582 	if (!link_info) {
23583 		hdd_err("couldn't set key for link_id:%d", link_id);
23584 		goto release_ref;
23585 	}
23586 
23587 	errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
23588 				      pairwise, mac_addr, params,
23589 				      link_id, link_info);
23590 
23591 release_ref:
23592 	wlan_key_put_link_vdev(link_vdev, WLAN_MLO_MGR_ID);
23593 	return errno;
23594 }
23595 #elif defined(CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV)
23596 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
23597 				     struct wlan_objmgr_vdev *vdev,
23598 				     u8 key_index, bool pairwise,
23599 				     const u8 *mac_addr,
23600 				     struct key_params *params, int link_id,
23601 				     struct hdd_adapter *adapter)
23602 {
23603 	return wlan_hdd_add_key_vdev(mac_handle, vdev, key_index,
23604 				     pairwise, mac_addr, params,
23605 				     link_id, adapter->deflink);
23606 }
23607 #else
23608 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
23609 				     struct wlan_objmgr_vdev *vdev,
23610 				     u8 key_index, bool pairwise,
23611 				     const u8 *mac_addr,
23612 				     struct key_params *params, int link_id,
23613 				     struct hdd_adapter *adapter)
23614 {
23615 	return 0;
23616 }
23617 #endif
23618 
23619 static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
23620 				       struct net_device *ndev,
23621 				       u8 key_index, bool pairwise,
23622 				       const u8 *mac_addr,
23623 				       struct key_params *params, int link_id)
23624 {
23625 	struct hdd_context *hdd_ctx;
23626 	mac_handle_t mac_handle;
23627 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
23628 	struct wlan_objmgr_vdev *vdev;
23629 	int errno;
23630 
23631 	hdd_enter();
23632 
23633 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
23634 		hdd_err("Command not allowed in FTM mode");
23635 		return -EINVAL;
23636 	}
23637 
23638 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
23639 		return -EINVAL;
23640 
23641 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
23642 		   TRACE_CODE_HDD_CFG80211_ADD_KEY,
23643 		   adapter->deflink->vdev_id, params->key_len);
23644 
23645 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23646 	errno = wlan_hdd_validate_context(hdd_ctx);
23647 	if (errno)
23648 		return errno;
23649 
23650 	hdd_debug("converged Device_mode %s(%d) index %d, pairwise %d link_id %d",
23651 		  qdf_opmode_str(adapter->device_mode),
23652 		  adapter->device_mode, key_index, pairwise, link_id);
23653 	mac_handle = hdd_ctx->mac_handle;
23654 
23655 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
23656 	if (!vdev)
23657 		return -EINVAL;
23658 
23659 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
23660 		errno = wlan_hdd_add_key_vdev(mac_handle, vdev, key_index,
23661 					      pairwise, mac_addr, params,
23662 					      link_id, adapter->deflink);
23663 	else
23664 		errno = wlan_hdd_add_key_mlo_vdev(mac_handle, vdev, key_index,
23665 						  pairwise, mac_addr, params,
23666 						  link_id, adapter);
23667 
23668 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
23669 
23670 	return errno;
23671 }
23672 
23673 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
23674 #ifdef CFG80211_SET_KEY_WITH_SRC_MAC
23675 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
23676 				     struct wireless_dev *wdev,
23677 				     u8 key_index, bool pairwise,
23678 				     const u8 *src_addr,
23679 				     const u8 *mac_addr,
23680 				     struct key_params *params)
23681 #else
23682 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
23683 				     struct wireless_dev *wdev,
23684 				     u8 key_index, bool pairwise,
23685 				     const u8 *mac_addr,
23686 				     struct key_params *params)
23687 #endif
23688 {
23689 	int errno = -EINVAL;
23690 	struct osif_vdev_sync *vdev_sync;
23691 	struct hdd_adapter *adapter = qdf_container_of(wdev,
23692 						   struct hdd_adapter,
23693 						   wdev);
23694 	/* Legacy purposes */
23695 	int link_id = -1;
23696 
23697 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
23698 		return errno;
23699 
23700 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
23701 	if (errno)
23702 		return errno;
23703 
23704 	errno = __wlan_hdd_cfg80211_add_key(wiphy, adapter->dev, key_index,
23705 					    pairwise, mac_addr, params,
23706 					    link_id);
23707 
23708 	osif_vdev_sync_op_stop(vdev_sync);
23709 
23710 	return errno;
23711 }
23712 #elif defined(CFG80211_SET_KEY_WITH_SRC_MAC)
23713 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
23714 				     struct net_device *ndev,
23715 				     u8 key_index, bool pairwise,
23716 				     const u8 *src_addr,
23717 				     const u8 *mac_addr,
23718 				     struct key_params *params)
23719 {
23720 	int errno;
23721 	int link_id = -1;
23722 	struct osif_vdev_sync *vdev_sync;
23723 
23724 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
23725 	if (errno)
23726 		return errno;
23727 
23728 	errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
23729 					    mac_addr, params, link_id);
23730 
23731 	osif_vdev_sync_op_stop(vdev_sync);
23732 
23733 	return errno;
23734 }
23735 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
23736 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
23737 				     struct net_device *ndev,
23738 				     int link_id, u8 key_index, bool pairwise,
23739 				     const u8 *mac_addr,
23740 				     struct key_params *params)
23741 {
23742 	int errno;
23743 	struct osif_vdev_sync *vdev_sync;
23744 
23745 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
23746 	if (errno)
23747 		return errno;
23748 
23749 	errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
23750 					    mac_addr, params, link_id);
23751 
23752 	osif_vdev_sync_op_stop(vdev_sync);
23753 
23754 	return errno;
23755 }
23756 #else
23757 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
23758 				     struct net_device *ndev,
23759 				     u8 key_index, bool pairwise,
23760 				     const u8 *mac_addr,
23761 				     struct key_params *params)
23762 {
23763 	int errno, link_id = -1;
23764 	struct osif_vdev_sync *vdev_sync;
23765 
23766 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
23767 	if (errno)
23768 		return errno;
23769 
23770 	errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
23771 					    mac_addr, params, link_id);
23772 
23773 	osif_vdev_sync_op_stop(vdev_sync);
23774 
23775 	return errno;
23776 }
23777 #endif
23778 
23779 static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
23780 				       struct net_device *ndev,
23781 				       int link_id,
23782 				       u8 key_index, bool pairwise,
23783 				       const u8 *mac_addr, void *cookie,
23784 				       void (*callback)(void *cookie,
23785 							struct key_params *)
23786 				       )
23787 {
23788 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
23789 	struct key_params params;
23790 	eCsrEncryptionType enc_type;
23791 	int32_t ucast_cipher = 0;
23792 	struct wlan_objmgr_vdev *link_vdev;
23793 
23794 	hdd_enter();
23795 
23796 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
23797 		hdd_err("Command not allowed in FTM mode");
23798 		return -EINVAL;
23799 	}
23800 
23801 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
23802 		return -EINVAL;
23803 
23804 	hdd_debug("Device_mode %s(%d)",
23805 		  qdf_opmode_str(adapter->device_mode), adapter->device_mode);
23806 
23807 	memset(&params, 0, sizeof(params));
23808 
23809 	if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX +
23810 			  WLAN_CRYPTO_MAXBIGTKKEYIDX)) {
23811 		hdd_err("Invalid key index: %d", key_index);
23812 		return -EINVAL;
23813 	}
23814 
23815 	link_vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
23816 	if (!link_vdev) {
23817 		hdd_err("Invalid vdev for link_id :%d", link_id);
23818 		return -EINVAL;
23819 	}
23820 
23821 	if (link_vdev)
23822 		ucast_cipher = wlan_crypto_get_param(link_vdev,
23823 						WLAN_CRYPTO_PARAM_UCAST_CIPHER);
23824 
23825 	sme_fill_enc_type(&enc_type, ucast_cipher);
23826 
23827 	switch (enc_type) {
23828 	case eCSR_ENCRYPT_TYPE_NONE:
23829 		params.cipher = IW_AUTH_CIPHER_NONE;
23830 		break;
23831 
23832 	case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
23833 	case eCSR_ENCRYPT_TYPE_WEP40:
23834 		params.cipher = WLAN_CIPHER_SUITE_WEP40;
23835 		break;
23836 
23837 	case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
23838 	case eCSR_ENCRYPT_TYPE_WEP104:
23839 		params.cipher = WLAN_CIPHER_SUITE_WEP104;
23840 		break;
23841 
23842 	case eCSR_ENCRYPT_TYPE_TKIP:
23843 		params.cipher = WLAN_CIPHER_SUITE_TKIP;
23844 		break;
23845 
23846 	case eCSR_ENCRYPT_TYPE_AES:
23847 		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
23848 		break;
23849 	case eCSR_ENCRYPT_TYPE_AES_GCMP:
23850 		params.cipher = WLAN_CIPHER_SUITE_GCMP;
23851 		break;
23852 	case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
23853 		params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
23854 		break;
23855 	default:
23856 		params.cipher = IW_AUTH_CIPHER_NONE;
23857 		break;
23858 	}
23859 
23860 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
23861 		   TRACE_CODE_HDD_CFG80211_GET_KEY,
23862 		   wlan_vdev_get_id(link_vdev), params.cipher);
23863 
23864 	params.key_len = 0;
23865 	params.seq_len = 0;
23866 	params.seq = NULL;
23867 	params.key = NULL;
23868 	callback(cookie, &params);
23869 
23870 	wlan_key_put_link_vdev(link_vdev, WLAN_OSIF_ID);
23871 	hdd_exit();
23872 	return 0;
23873 }
23874 
23875 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
23876 static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
23877 				     struct wireless_dev *wdev,
23878 				     u8 key_index, bool pairwise,
23879 				     const u8 *mac_addr, void *cookie,
23880 				     void (*callback)(void *cookie,
23881 						      struct key_params *)
23882 				     )
23883 {
23884 	int errno = -EINVAL;
23885 	struct osif_vdev_sync *vdev_sync;
23886 	struct hdd_adapter *adapter = qdf_container_of(wdev,
23887 						   struct hdd_adapter,
23888 						   wdev);
23889 	int link_id = -1;
23890 
23891 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
23892 		return errno;
23893 
23894 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
23895 	if (errno)
23896 		return errno;
23897 
23898 	errno = __wlan_hdd_cfg80211_get_key(wiphy, adapter->dev, link_id,
23899 					    key_index,
23900 					    pairwise, mac_addr, cookie,
23901 					    callback);
23902 
23903 	osif_vdev_sync_op_stop(vdev_sync);
23904 
23905 	return errno;
23906 }
23907 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
23908 static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
23909 				     struct net_device *ndev,
23910 				     int link_id, u8 key_index, bool pairwise,
23911 				     const u8 *mac_addr, void *cookie,
23912 				     void (*callback)(void *cookie,
23913 						      struct key_params *)
23914 				     )
23915 {
23916 	int errno;
23917 	struct osif_vdev_sync *vdev_sync;
23918 
23919 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
23920 	if (errno)
23921 		return errno;
23922 
23923 	errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, link_id, key_index,
23924 					    pairwise, mac_addr, cookie,
23925 					    callback);
23926 
23927 	osif_vdev_sync_op_stop(vdev_sync);
23928 
23929 	return errno;
23930 }
23931 #else
23932 static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
23933 				     struct net_device *ndev,
23934 				     u8 key_index, bool pairwise,
23935 				     const u8 *mac_addr, void *cookie,
23936 				     void (*callback)(void *cookie,
23937 						      struct key_params *)
23938 				     )
23939 {
23940 	int errno;
23941 	int link_id = -1;
23942 	struct osif_vdev_sync *vdev_sync;
23943 
23944 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
23945 	if (errno)
23946 		return errno;
23947 
23948 	errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, link_id, key_index,
23949 					    pairwise, mac_addr, cookie,
23950 					    callback);
23951 
23952 	osif_vdev_sync_op_stop(vdev_sync);
23953 
23954 	return errno;
23955 }
23956 #endif
23957 
23958 /**
23959  * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
23960  * @wiphy: wiphy interface context
23961  * @ndev: pointer to net device
23962  * @key_index: Key index used in 802.11 frames
23963  * @pairwise: true if it is pairwise key
23964  * @mac_addr: Peer address
23965  *
23966  * This function is required for cfg80211_ops API.
23967  * It is used to delete the key information
23968  * Underlying hardware implementation does not have API to delete the
23969  * encryption key for normal peers. Currently delete keys are supported
23970  * only for PASN peers.
23971  * For other peers, it is automatically deleted when the peer is
23972  * removed. Hence this function currently does nothing.
23973  * Future implementation may interpret delete key operation to
23974  * replacing the key with a random junk value, effectively making it
23975  * useless.
23976  *
23977  * Return: status code, always 0.
23978  */
23979 
23980 static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
23981 				       struct net_device *ndev,
23982 				       u8 key_index,
23983 				       bool pairwise, const u8 *mac_addr)
23984 {
23985 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
23986 	struct wlan_objmgr_peer *peer;
23987 	struct qdf_mac_addr peer_mac;
23988 	enum wlan_peer_type peer_type;
23989 	QDF_STATUS status = QDF_STATUS_SUCCESS;
23990 	int ret;
23991 
23992 	hdd_enter();
23993 
23994 	if (!mac_addr) {
23995 		hdd_debug("Peer mac address is NULL");
23996 		hdd_exit();
23997 		return 0;
23998 	}
23999 
24000 	ret = wlan_hdd_validate_context(hdd_ctx);
24001 	if (ret)
24002 		return ret;
24003 
24004 	qdf_mem_copy(peer_mac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
24005 	if (qdf_is_macaddr_zero(&peer_mac) ||
24006 	    qdf_is_macaddr_broadcast(&peer_mac)) {
24007 		hdd_err("Invalid mac address");
24008 		ret = -EINVAL;
24009 		goto err;
24010 	}
24011 
24012 	peer = wlan_objmgr_get_peer_by_mac(hdd_ctx->psoc, peer_mac.bytes,
24013 					   WLAN_OSIF_ID);
24014 	if (peer) {
24015 		peer_type = wlan_peer_get_peer_type(peer);
24016 		if (peer_type == WLAN_PEER_RTT_PASN) {
24017 			status = wifi_pos_send_pasn_peer_deauth(hdd_ctx->psoc,
24018 								&peer_mac);
24019 			if (QDF_IS_STATUS_ERROR(status))
24020 				hdd_err("send_pasn_peer_deauth failed");
24021 
24022 			ret = qdf_status_to_os_return(status);
24023 		}
24024 		wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
24025 	}
24026 err:
24027 	hdd_exit();
24028 
24029 	return ret;
24030 }
24031 
24032 /**
24033  * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
24034  * @wiphy: Pointer to wiphy structure.
24035  * @wdev: Pointer to wireless_dev structure.
24036  * @key_index: key index
24037  * @pairwise: pairwise
24038  * @mac_addr: mac address
24039  *
24040  * This is the cfg80211 delete key handler function which invokes
24041  * the internal function @__wlan_hdd_cfg80211_del_key with
24042  * SSR protection.
24043  *
24044  * Return: 0 for success, error number on failure.
24045  */
24046 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24047 static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
24048 				     struct wireless_dev *wdev,
24049 				     u8 key_index,
24050 				     bool pairwise, const u8 *mac_addr)
24051 {
24052 	int errno = -EINVAL;
24053 	struct osif_vdev_sync *vdev_sync;
24054 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24055 						   struct hdd_adapter,
24056 						   wdev);
24057 
24058 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24059 		return errno;
24060 
24061 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24062 	if (errno)
24063 		return errno;
24064 
24065 	errno = __wlan_hdd_cfg80211_del_key(wiphy, adapter->dev, key_index,
24066 					    pairwise, mac_addr);
24067 
24068 	osif_vdev_sync_op_stop(vdev_sync);
24069 
24070 	return errno;
24071 }
24072 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
24073 static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
24074 				     struct net_device *dev,
24075 				     int link_id, u8 key_index,
24076 				     bool pairwise, const u8 *mac_addr)
24077 {
24078 	int errno;
24079 	struct osif_vdev_sync *vdev_sync;
24080 
24081 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
24082 	if (errno)
24083 		return errno;
24084 
24085 	errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
24086 					    pairwise, mac_addr);
24087 
24088 	osif_vdev_sync_op_stop(vdev_sync);
24089 
24090 	return errno;
24091 }
24092 #else
24093 static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
24094 				     struct net_device *dev,
24095 				     u8 key_index, bool pairwise,
24096 				     const u8 *mac_addr)
24097 {
24098 	int errno;
24099 	struct osif_vdev_sync *vdev_sync;
24100 
24101 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
24102 	if (errno)
24103 		return errno;
24104 
24105 	errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
24106 					    pairwise, mac_addr);
24107 
24108 	osif_vdev_sync_op_stop(vdev_sync);
24109 
24110 	return errno;
24111 }
24112 #endif
24113 static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
24114 					       struct net_device *ndev,
24115 					       int link_id,
24116 					       u8 key_index,
24117 					       bool unicast, bool multicast)
24118 {
24119 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
24120 	struct hdd_context *hdd_ctx;
24121 	struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
24122 	struct hdd_ap_ctx *ap_ctx;
24123 	struct wlan_crypto_key *crypto_key;
24124 	struct wlan_objmgr_vdev *vdev;
24125 	int ret;
24126 	QDF_STATUS status;
24127 
24128 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
24129 		hdd_err("Command not allowed in FTM mode");
24130 		return -EINVAL;
24131 	}
24132 
24133 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24134 		return -EINVAL;
24135 
24136 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
24137 		   TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
24138 		   adapter->deflink->vdev_id, key_index);
24139 
24140 	hdd_debug("Device_mode %s(%d) key_index = %d",
24141 		  qdf_opmode_str(adapter->device_mode),
24142 		  adapter->device_mode, key_index);
24143 
24144 	if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX +
24145 			  WLAN_CRYPTO_MAXBIGTKKEYIDX)) {
24146 		hdd_err("Invalid key index: %d", key_index);
24147 		return -EINVAL;
24148 	}
24149 
24150 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24151 	ret = wlan_hdd_validate_context(hdd_ctx);
24152 
24153 	if (0 != ret)
24154 		return ret;
24155 
24156 	vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
24157 	if (!vdev)
24158 		return -EINVAL;
24159 
24160 	crypto_key = wlan_crypto_get_key(vdev, key_index);
24161 	if (!crypto_key) {
24162 		hdd_err("Invalid NULL key info");
24163 		ret = -EINVAL;
24164 		goto out;
24165 	}
24166 	hdd_debug("unicast %d, multicast %d cipher %d",
24167 		  unicast, multicast, crypto_key->cipher_type);
24168 	if (!IS_WEP_CIPHER(crypto_key->cipher_type)) {
24169 		ret = 0;
24170 		goto out;
24171 	}
24172 
24173 	if ((adapter->device_mode == QDF_STA_MODE) ||
24174 	    (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
24175 		ret =
24176 		wlan_cfg80211_crypto_add_key(vdev,
24177 					     (unicast ?
24178 					      WLAN_CRYPTO_KEY_TYPE_UNICAST :
24179 					      WLAN_CRYPTO_KEY_TYPE_GROUP),
24180 					     key_index, true);
24181 		wma_update_set_key(adapter->deflink->vdev_id, unicast,
24182 				   key_index, crypto_key->cipher_type);
24183 	}
24184 
24185 	if (adapter->device_mode == QDF_SAP_MODE ||
24186 	    adapter->device_mode == QDF_P2P_GO_MODE) {
24187 		status = wlan_cfg80211_set_default_key(vdev, key_index,
24188 						       &bssid);
24189 		if (QDF_IS_STATUS_ERROR(status)) {
24190 			hdd_err("ret fail status %d", ret);
24191 			ret = -EINVAL;
24192 			goto out;
24193 		}
24194 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
24195 		ap_ctx->wep_def_key_idx = key_index;
24196 	}
24197 
24198 out:
24199 	wlan_key_put_link_vdev(vdev, WLAN_OSIF_ID);
24200 	return ret;
24201 }
24202 
24203 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24204 static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
24205 					     struct wireless_dev *wdev,
24206 					     u8 key_index,
24207 					     bool unicast, bool multicast)
24208 {
24209 	int errno = -EINVAL;
24210 	struct osif_vdev_sync *vdev_sync;
24211 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24212 						   struct hdd_adapter,
24213 						   wdev);
24214 	int link_id = -1;
24215 
24216 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24217 		return errno;
24218 
24219 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24220 	if (errno)
24221 		return errno;
24222 
24223 	errno = __wlan_hdd_cfg80211_set_default_key(wiphy, adapter->dev,
24224 						    link_id, key_index,
24225 						    unicast, multicast);
24226 
24227 	osif_vdev_sync_op_stop(vdev_sync);
24228 
24229 	return errno;
24230 }
24231 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
24232 static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
24233 					     struct net_device *ndev,
24234 					     int link_id, u8 key_index,
24235 					     bool unicast, bool multicast)
24236 {
24237 	int errno;
24238 	struct osif_vdev_sync *vdev_sync;
24239 
24240 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24241 	if (errno)
24242 		return errno;
24243 
24244 	errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, link_id,
24245 						    key_index, unicast,
24246 						    multicast);
24247 
24248 	osif_vdev_sync_op_stop(vdev_sync);
24249 
24250 	return errno;
24251 }
24252 #else
24253 static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
24254 					     struct net_device *ndev,
24255 					     u8 key_index,
24256 					     bool unicast, bool multicast)
24257 {
24258 	int errno;
24259 	int link_id = -1;
24260 	struct osif_vdev_sync *vdev_sync;
24261 
24262 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24263 	if (errno)
24264 		return errno;
24265 
24266 	errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, link_id,
24267 						    key_index, unicast,
24268 						    multicast);
24269 
24270 	osif_vdev_sync_op_stop(vdev_sync);
24271 
24272 	return errno;
24273 }
24274 #endif
24275 
24276 #if defined (CFG80211_BIGTK_CONFIGURATION_SUPPORT) || \
24277 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
24278 static int _wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
24279 						     struct net_device *ndev,
24280 						     u8 key_index)
24281 {
24282 	hdd_enter();
24283 	return 0;
24284 }
24285 
24286 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24287 static int wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
24288 						    struct wireless_dev *wdev,
24289 						    u8 key_index)
24290 {
24291 	int errno = -EINVAL;
24292 	struct osif_vdev_sync *vdev_sync;
24293 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24294 						   struct hdd_adapter,
24295 						   wdev);
24296 
24297 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24298 		return errno;
24299 
24300 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24301 	if (errno)
24302 		return errno;
24303 
24304 	errno = _wlan_hdd_cfg80211_set_default_beacon_key(wiphy, adapter->dev,
24305 							  key_index);
24306 
24307 	osif_vdev_sync_op_stop(vdev_sync);
24308 
24309 	return errno;
24310 }
24311 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
24312 static int wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
24313 						    struct net_device *ndev,
24314 						    int link_id, u8 key_index)
24315 {
24316 	int errno;
24317 	struct osif_vdev_sync *vdev_sync;
24318 
24319 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24320 	if (errno)
24321 		return errno;
24322 
24323 	errno = _wlan_hdd_cfg80211_set_default_beacon_key(wiphy, ndev,
24324 							  key_index);
24325 
24326 	osif_vdev_sync_op_stop(vdev_sync);
24327 
24328 	return errno;
24329 }
24330 #else
24331 static int wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
24332 						    struct net_device *ndev,
24333 						    u8 key_index)
24334 {
24335 	int errno;
24336 	struct osif_vdev_sync *vdev_sync;
24337 
24338 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24339 	if (errno)
24340 		return errno;
24341 
24342 	errno = _wlan_hdd_cfg80211_set_default_beacon_key(wiphy, ndev,
24343 							  key_index);
24344 
24345 	osif_vdev_sync_op_stop(vdev_sync);
24346 
24347 	return errno;
24348 }
24349 #endif
24350 #endif
24351 
24352 #ifdef FEATURE_MONITOR_MODE_SUPPORT
24353 static
24354 void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
24355 			   uint32_t op_freq,
24356 			   struct ch_params *ch_params)
24357 {
24358 	struct hdd_station_ctx *station_ctx =
24359 			 WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
24360 	struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
24361 	enum hdd_dot11_mode hdd_dot11_mode;
24362 	uint8_t ini_dot11_mode =
24363 			(WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
24364 
24365 	hdd_debug("Dot11Mode is %u", ini_dot11_mode);
24366 	switch (ini_dot11_mode) {
24367 	case eHDD_DOT11_MODE_AUTO:
24368 #ifdef WLAN_FEATURE_11BE
24369 	case eHDD_DOT11_MODE_11be:
24370 	case eHDD_DOT11_MODE_11be_ONLY:
24371 		if (sme_is_feature_supported_by_fw(DOT11BE))
24372 			hdd_dot11_mode = eHDD_DOT11_MODE_11be;
24373 		else
24374 #endif
24375 		if (sme_is_feature_supported_by_fw(DOT11AX))
24376 			hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
24377 		else if (sme_is_feature_supported_by_fw(DOT11AC))
24378 			hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
24379 		else
24380 			hdd_dot11_mode = eHDD_DOT11_MODE_11n;
24381 		break;
24382 	case eHDD_DOT11_MODE_11ax:
24383 	case eHDD_DOT11_MODE_11ax_ONLY:
24384 		if (sme_is_feature_supported_by_fw(DOT11AX))
24385 			hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
24386 		else if (sme_is_feature_supported_by_fw(DOT11AC))
24387 			hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
24388 		else
24389 			hdd_dot11_mode = eHDD_DOT11_MODE_11n;
24390 		break;
24391 	case eHDD_DOT11_MODE_11ac:
24392 	case eHDD_DOT11_MODE_11ac_ONLY:
24393 		if (sme_is_feature_supported_by_fw(DOT11AC))
24394 			hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
24395 		else
24396 			hdd_dot11_mode = eHDD_DOT11_MODE_11n;
24397 		break;
24398 	case eHDD_DOT11_MODE_11n:
24399 	case eHDD_DOT11_MODE_11n_ONLY:
24400 		hdd_dot11_mode = eHDD_DOT11_MODE_11n;
24401 		break;
24402 	default:
24403 		hdd_dot11_mode = ini_dot11_mode;
24404 		break;
24405 	}
24406 	ch_info->channel_width = ch_params->ch_width;
24407 	ch_info->phy_mode =
24408 		hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
24409 	ch_info->freq = op_freq;
24410 	ch_info->cb_mode = ch_params->ch_width;
24411 	hdd_debug("ch_info width %d, phymode %d channel freq %d",
24412 		  ch_info->channel_width, ch_info->phy_mode,
24413 		  ch_info->freq);
24414 }
24415 #else
24416 static
24417 void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
24418 			   uint32_t op_freq,
24419 			   struct ch_params *ch_params)
24420 {
24421 }
24422 #endif
24423 
24424 void hdd_select_cbmode(struct hdd_adapter *adapter, qdf_freq_t oper_freq,
24425 		       qdf_freq_t sec_ch_2g_freq, struct ch_params *ch_params)
24426 {
24427 	uint32_t sec_ch_freq = 0;
24428 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24429 
24430 	/*
24431 	 * CDS api expects secondary channel for calculating
24432 	 * the channel params
24433 	 */
24434 	if (ch_params->ch_width == CH_WIDTH_40MHZ &&
24435 	    WLAN_REG_IS_24GHZ_CH_FREQ(oper_freq)) {
24436 		if (sec_ch_2g_freq) {
24437 			sec_ch_freq = sec_ch_2g_freq;
24438 		} else {
24439 			if (oper_freq >= 2412 && oper_freq <= 2432)
24440 				sec_ch_freq = oper_freq + 20;
24441 			else if (oper_freq >= 2437 && oper_freq <= 2472)
24442 				sec_ch_freq = oper_freq - 20;
24443 		}
24444 	}
24445 
24446 	/* This call decides required channel bonding mode */
24447 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev, oper_freq,
24448 						sec_ch_freq, ch_params,
24449 						REG_CURRENT_PWR_MODE);
24450 
24451 	if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE ||
24452 	    policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
24453 		hdd_mon_select_cbmode(adapter, oper_freq, ch_params);
24454 }
24455 
24456 /**
24457  * wlan_hdd_cfg80211_connect() - cfg80211 connect api
24458  * @wiphy: Pointer to wiphy
24459  * @ndev: Pointer to network device
24460  * @req: Pointer to cfg80211 connect request
24461  *
24462  * Return: 0 for success, non-zero for failure
24463  */
24464 static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
24465 				     struct net_device *ndev,
24466 				     struct cfg80211_connect_params *req)
24467 {
24468 	int errno;
24469 	struct osif_vdev_sync *vdev_sync;
24470 
24471 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24472 	if (errno)
24473 		return errno;
24474 
24475 	errno = wlan_hdd_cm_connect(wiphy, ndev, req);
24476 
24477 	osif_vdev_sync_op_stop(vdev_sync);
24478 
24479 	return errno;
24480 }
24481 
24482 /**
24483  * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
24484  * @wiphy: Pointer to wiphy
24485  * @dev: Pointer to network device
24486  * @reason: Disconnect reason code
24487  *
24488  * Return: 0 for success, non-zero for failure
24489  */
24490 static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
24491 					struct net_device *dev, u16 reason)
24492 {
24493 	int errno;
24494 	struct osif_vdev_sync *vdev_sync;
24495 
24496 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
24497 	if (errno)
24498 		return errno;
24499 
24500 	errno = wlan_hdd_cm_disconnect(wiphy, dev, reason);
24501 
24502 	osif_vdev_sync_op_stop(vdev_sync);
24503 
24504 	return errno;
24505 }
24506 
24507 /**
24508  * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
24509  * @wiphy: Pointer to wiphy
24510  * @changed: Parameters changed
24511  *
24512  * This function is used to set the phy parameters. RTS Threshold/FRAG
24513  * Threshold/Retry Count etc.
24514  *
24515  * Return: 0 for success, non-zero for failure
24516  */
24517 static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
24518 						u32 changed)
24519 {
24520 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
24521 	int status;
24522 
24523 	hdd_enter();
24524 
24525 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
24526 		hdd_err("Command not allowed in FTM mode");
24527 		return -EINVAL;
24528 	}
24529 
24530 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
24531 		   TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
24532 		   NO_SESSION, wiphy->rts_threshold);
24533 
24534 	status = wlan_hdd_validate_context(hdd_ctx);
24535 
24536 	if (0 != status)
24537 		return status;
24538 
24539 	if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
24540 		u32 rts_threshold = (wiphy->rts_threshold == -1) ?
24541 				     cfg_max(CFG_RTS_THRESHOLD) :
24542 				     wiphy->rts_threshold;
24543 
24544 		if ((cfg_min(CFG_RTS_THRESHOLD) > rts_threshold) ||
24545 		    (cfg_max(CFG_RTS_THRESHOLD) < rts_threshold)) {
24546 			hdd_err("Invalid RTS Threshold value: %u",
24547 				rts_threshold);
24548 			return -EINVAL;
24549 		}
24550 
24551 		if (0 != ucfg_mlme_set_rts_threshold(hdd_ctx->psoc,
24552 		    rts_threshold)) {
24553 			hdd_err("mlme_set_rts_threshold failed for val %u",
24554 				rts_threshold);
24555 			return -EIO;
24556 		}
24557 
24558 		hdd_debug("set rts threshold %u", rts_threshold);
24559 	}
24560 
24561 	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
24562 		u16 frag_threshold = (wiphy->frag_threshold == -1) ?
24563 				     cfg_max(CFG_FRAG_THRESHOLD) :
24564 				     wiphy->frag_threshold;
24565 
24566 		if ((cfg_min(CFG_FRAG_THRESHOLD) > frag_threshold) ||
24567 		    (cfg_max(CFG_FRAG_THRESHOLD) < frag_threshold)) {
24568 			hdd_err("Invalid frag_threshold value %hu",
24569 				frag_threshold);
24570 			return -EINVAL;
24571 		}
24572 
24573 		if (0 != ucfg_mlme_set_frag_threshold(hdd_ctx->psoc,
24574 						      frag_threshold)) {
24575 			hdd_err("mlme_set_frag_threshold failed for val %hu",
24576 				frag_threshold);
24577 			return -EIO;
24578 		}
24579 
24580 		hdd_debug("set frag threshold %hu", frag_threshold);
24581 	}
24582 
24583 	hdd_exit();
24584 	return 0;
24585 }
24586 
24587 /**
24588  * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
24589  * @wiphy: Pointer to wiphy
24590  * @changed: Parameters changed
24591  *
24592  * Return: 0 for success, non-zero for failure
24593  */
24594 static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
24595 {
24596 	struct osif_psoc_sync *psoc_sync;
24597 	int errno;
24598 
24599 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
24600 	if (errno)
24601 		return errno;
24602 
24603 	errno = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
24604 
24605 	osif_psoc_sync_op_stop(psoc_sync);
24606 
24607 	return errno;
24608 }
24609 
24610 /**
24611  * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
24612  *				     key
24613  * @wiphy: Pointer to wiphy
24614  * @netdev: Pointer to network device
24615  * @key_index: Key index
24616  *
24617  * Return: 0
24618  */
24619 static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
24620 					   struct net_device *netdev,
24621 					   u8 key_index)
24622 {
24623 	hdd_enter();
24624 	return 0;
24625 }
24626 
24627 /**
24628  * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
24629  *				wlan_hdd_set_default_mgmt_key
24630  * @wiphy: pointer to wiphy
24631  * @wdev: pointer to wireless_device structure
24632  * @key_index: key index
24633  *
24634  * Return: 0 on success, error number on failure
24635  */
24636 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24637 static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
24638 					 struct wireless_dev *wdev,
24639 					 u8 key_index)
24640 {
24641 	int errno = -EINVAL;
24642 	struct osif_vdev_sync *vdev_sync;
24643 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24644 						   struct hdd_adapter,
24645 						   wdev);
24646 
24647 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24648 		return errno;
24649 
24650 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24651 	if (errno)
24652 		return errno;
24653 
24654 	errno = __wlan_hdd_set_default_mgmt_key(wiphy, adapter->dev, key_index);
24655 
24656 	osif_vdev_sync_op_stop(vdev_sync);
24657 
24658 	return errno;
24659 }
24660 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
24661 static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
24662 					 struct net_device *netdev,
24663 					 int link_id, u8 key_index)
24664 {
24665 	int errno;
24666 	struct osif_vdev_sync *vdev_sync;
24667 
24668 	errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
24669 	if (errno)
24670 		return errno;
24671 
24672 	errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
24673 
24674 	osif_vdev_sync_op_stop(vdev_sync);
24675 
24676 	return errno;
24677 }
24678 #else
24679 static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
24680 					 struct net_device *netdev,
24681 					 u8 key_index)
24682 {
24683 	int errno;
24684 	struct osif_vdev_sync *vdev_sync;
24685 
24686 	errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
24687 	if (errno)
24688 		return errno;
24689 
24690 	errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
24691 
24692 	osif_vdev_sync_op_stop(vdev_sync);
24693 
24694 	return errno;
24695 }
24696 #endif
24697 
24698 /*
24699  * Default val of cwmin, this value is used to override the
24700  * incorrect user set value
24701  */
24702 #define DEFAULT_CWMIN 15
24703 
24704 /*
24705  * Default val of cwmax, this value is used to override the
24706  * incorrect user set value
24707  */
24708 #define DEFAULT_CWMAX 1023
24709 
24710 /**
24711  * __wlan_hdd_set_txq_params() - implementation of set tx queue params
24712  *				to configure internal EDCA parameters
24713  * @wiphy: Pointer to wiphy
24714  * @dev: Pointer to network device
24715  * @params: Pointer to tx queue parameters
24716  *
24717  * Return: 0
24718  */
24719 static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
24720 				   struct net_device *dev,
24721 				   struct ieee80211_txq_params *params)
24722 {
24723 	QDF_STATUS status;
24724 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
24725 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24726 	mac_handle_t mac_handle;
24727 	tSirMacEdcaParamRecord txq_edca_params;
24728 	static const uint8_t ieee_ac_to_qca_ac[] = {
24729 		[IEEE80211_AC_VO] = QCA_WLAN_AC_VO,
24730 		[IEEE80211_AC_VI] = QCA_WLAN_AC_VI,
24731 		[IEEE80211_AC_BE] = QCA_WLAN_AC_BE,
24732 		[IEEE80211_AC_BK] = QCA_WLAN_AC_BK,
24733 	};
24734 
24735 	hdd_enter();
24736 
24737 	if (wlan_hdd_validate_context(hdd_ctx))
24738 		return -EINVAL;
24739 
24740 	mac_handle = hdd_ctx->mac_handle;
24741 	if (params->cwmin == 0 || params->cwmin > DEFAULT_CWMAX)
24742 		params->cwmin = DEFAULT_CWMIN;
24743 
24744 	if (params->cwmax < params->cwmin || params->cwmax > DEFAULT_CWMAX)
24745 		params->cwmax = DEFAULT_CWMAX;
24746 
24747 	txq_edca_params.cw.min = convert_cw(params->cwmin);
24748 	txq_edca_params.cw.max = convert_cw(params->cwmax);
24749 	txq_edca_params.aci.aifsn = params->aifs;
24750 	/* The txop is multiple of 32us units */
24751 	txq_edca_params.txoplimit = params->txop;
24752 	txq_edca_params.aci.aci =
24753 			ieee_ac_to_qca_ac[params->ac];
24754 
24755 	status = sme_update_session_txq_edca_params(mac_handle,
24756 						    adapter->deflink->vdev_id,
24757 						    &txq_edca_params);
24758 
24759 	hdd_exit();
24760 	return qdf_status_to_os_return(status);
24761 }
24762 
24763 /**
24764  * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
24765  * @wiphy: pointer to wiphy
24766  * @dev: pointer to net_device structure
24767  * @params: pointer to ieee80211_txq_params
24768  *
24769  * Return: 0 on success, error number on failure
24770  */
24771 static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
24772 				   struct net_device *dev,
24773 				   struct ieee80211_txq_params *params)
24774 {
24775 	int errno;
24776 	struct osif_vdev_sync *vdev_sync;
24777 
24778 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
24779 	if (errno)
24780 		return errno;
24781 
24782 	errno = __wlan_hdd_set_txq_params(wiphy, dev, params);
24783 
24784 	osif_vdev_sync_op_stop(vdev_sync);
24785 
24786 	return errno;
24787 }
24788 
24789 /**
24790  * hdd_softap_deauth_current_sta() - Deauth current sta
24791  * @adapter: pointer to adapter structure
24792  * @sta_info: pointer to the current station info structure
24793  * @hapd_state: pointer to hostapd state structure
24794  * @param: pointer to del sta params
24795  *
24796  * Return: QDF_STATUS on success, corresponding QDF failure status on failure
24797  */
24798 static
24799 QDF_STATUS hdd_softap_deauth_current_sta(struct hdd_adapter *adapter,
24800 					 struct hdd_station_info *sta_info,
24801 					 struct hdd_hostapd_state *hapd_state,
24802 					 struct csr_del_sta_params *param)
24803 {
24804 	qdf_event_t *disassoc_event = &hapd_state->qdf_sta_disassoc_event;
24805 	struct hdd_context *hdd_ctx;
24806 	QDF_STATUS qdf_status;
24807 	struct hdd_station_info *tmp = NULL;
24808 
24809 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24810 	if (!hdd_ctx) {
24811 		hdd_err("hdd_ctx is NULL");
24812 		return QDF_STATUS_E_INVAL;
24813 	}
24814 
24815 	qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
24816 
24817 	if (!qdf_is_macaddr_broadcast(&param->peerMacAddr))
24818 		sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
24819 					    adapter->deflink->vdev_id,
24820 					    (uint8_t *)&param->peerMacAddr,
24821 					    param->reason_code, 0);
24822 
24823 	qdf_status = hdd_softap_sta_deauth(adapter, param);
24824 
24825 	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
24826 		if (qdf_is_macaddr_broadcast(&sta_info->sta_mac)) {
24827 			hdd_for_each_sta_ref_safe(
24828 					adapter->sta_info_list,
24829 					sta_info, tmp,
24830 					STA_INFO_SOFTAP_DEAUTH_CURRENT_STA) {
24831 				sta_info->is_deauth_in_progress = true;
24832 				hdd_put_sta_info_ref(
24833 					&adapter->sta_info_list,
24834 					&sta_info, true,
24835 					STA_INFO_SOFTAP_DEAUTH_CURRENT_STA);
24836 			}
24837 		} else {
24838 			sta_info->is_deauth_in_progress = true;
24839 		}
24840 		qdf_status = qdf_wait_for_event_completion(
24841 						disassoc_event,
24842 						SME_PEER_DISCONNECT_TIMEOUT);
24843 		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
24844 			hdd_warn("Deauth time expired");
24845 	} else {
24846 		sta_info->is_deauth_in_progress = false;
24847 		hdd_debug("STA removal failed for ::" QDF_MAC_ADDR_FMT,
24848 			  QDF_MAC_ADDR_REF(sta_info->sta_mac.bytes));
24849 		return QDF_STATUS_E_NOENT;
24850 	}
24851 	return QDF_STATUS_SUCCESS;
24852 }
24853 
24854 QDF_STATUS hdd_softap_deauth_all_sta(struct hdd_adapter *adapter,
24855 				     struct hdd_hostapd_state *hapd_state,
24856 				     struct csr_del_sta_params *param)
24857 {
24858 	QDF_STATUS status;
24859 	bool is_sap_bcast_deauth_enabled = false;
24860 	struct hdd_context *hdd_ctx;
24861 	struct hdd_station_info *sta_info, *tmp = NULL;
24862 
24863 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24864 	if (!hdd_ctx) {
24865 		hdd_err("hdd_ctx is NULL");
24866 		return QDF_STATUS_E_INVAL;
24867 	}
24868 
24869 	ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc,
24870 					       &is_sap_bcast_deauth_enabled);
24871 
24872 	hdd_debug("sap_bcast_deauth_enabled %d", is_sap_bcast_deauth_enabled);
24873 
24874 	if (is_sap_bcast_deauth_enabled) {
24875 		struct hdd_station_info bcast_sta_info;
24876 
24877 		qdf_set_macaddr_broadcast(&bcast_sta_info.sta_mac);
24878 		return hdd_softap_deauth_current_sta(adapter, &bcast_sta_info,
24879 						     hapd_state, param);
24880 	}
24881 
24882 	hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp,
24883 				  STA_INFO_SOFTAP_DEAUTH_ALL_STA) {
24884 		if (!sta_info->is_deauth_in_progress) {
24885 			hdd_debug("Delete STA with MAC:" QDF_MAC_ADDR_FMT,
24886 				  QDF_MAC_ADDR_REF(sta_info->sta_mac.bytes));
24887 
24888 			if (QDF_IS_ADDR_BROADCAST(sta_info->sta_mac.bytes)) {
24889 				hdd_put_sta_info_ref(&adapter->sta_info_list,
24890 						&sta_info, true,
24891 						STA_INFO_SOFTAP_DEAUTH_ALL_STA);
24892 				continue;
24893 			}
24894 
24895 			qdf_mem_copy(param->peerMacAddr.bytes,
24896 				     sta_info->sta_mac.bytes,
24897 				     QDF_MAC_ADDR_SIZE);
24898 			status =
24899 			    hdd_softap_deauth_current_sta(adapter, sta_info,
24900 							  hapd_state, param);
24901 			if (QDF_IS_STATUS_ERROR(status)) {
24902 				hdd_put_sta_info_ref(
24903 						&adapter->sta_info_list,
24904 						&sta_info, true,
24905 						STA_INFO_SOFTAP_DEAUTH_ALL_STA);
24906 				if (tmp)
24907 					hdd_put_sta_info_ref(
24908 						&adapter->sta_info_list,
24909 						&tmp, true,
24910 						STA_INFO_SOFTAP_DEAUTH_ALL_STA);
24911 				return status;
24912 			}
24913 		}
24914 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
24915 				     STA_INFO_SOFTAP_DEAUTH_ALL_STA);
24916 	}
24917 
24918 	return QDF_STATUS_SUCCESS;
24919 }
24920 
24921 /**
24922  * __wlan_hdd_cfg80211_del_station() - delete station v2
24923  * @wiphy: Pointer to wiphy
24924  * @dev: Underlying net device
24925  * @param: Pointer to delete station parameter
24926  *
24927  * Return: 0 for success, non-zero for failure
24928  */
24929 static
24930 int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
24931 				    struct net_device *dev,
24932 				    struct csr_del_sta_params *param)
24933 {
24934 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
24935 	struct hdd_context *hdd_ctx;
24936 	struct hdd_hostapd_state *hapd_state;
24937 	uint8_t *mac;
24938 	struct hdd_station_info *sta_info;
24939 
24940 	hdd_enter();
24941 
24942 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
24943 		hdd_err("Command not allowed in FTM mode");
24944 		return -EINVAL;
24945 	}
24946 
24947 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24948 		return -EINVAL;
24949 
24950 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
24951 		   TRACE_CODE_HDD_CFG80211_DEL_STA,
24952 		   adapter->deflink->vdev_id, adapter->device_mode);
24953 
24954 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24955 	if (!hdd_ctx) {
24956 		hdd_err("hdd_ctx is NULL");
24957 		return -EINVAL;
24958 	}
24959 
24960 	mac = (uint8_t *) param->peerMacAddr.bytes;
24961 
24962 	if (QDF_SAP_MODE != adapter->device_mode &&
24963 	    QDF_P2P_GO_MODE != adapter->device_mode)
24964 		goto fn_end;
24965 
24966 	hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
24967 	if (!hapd_state) {
24968 		hdd_err("Hostapd State is Null");
24969 		return 0;
24970 	}
24971 
24972 	if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac)) {
24973 		if (!QDF_IS_STATUS_SUCCESS(hdd_softap_deauth_all_sta(adapter,
24974 								     hapd_state,
24975 								     param)))
24976 			goto fn_end;
24977 	} else {
24978 		if (param->reason_code == REASON_1X_AUTH_FAILURE) {
24979 			struct wlan_objmgr_vdev *vdev;
24980 
24981 			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
24982 							   WLAN_DP_ID);
24983 			if (vdev) {
24984 				ucfg_dp_softap_check_wait_for_tx_eap_pkt(vdev,
24985 						(struct qdf_mac_addr *)mac);
24986 				hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
24987 			}
24988 		}
24989 
24990 		sta_info = hdd_get_sta_info_by_mac(
24991 						&adapter->sta_info_list,
24992 						mac,
24993 						STA_INFO_CFG80211_DEL_STATION);
24994 
24995 		if (!sta_info) {
24996 			hdd_debug("Skip DEL STA as this is not used::"
24997 				  QDF_MAC_ADDR_FMT,
24998 				  QDF_MAC_ADDR_REF(mac));
24999 			return -ENOENT;
25000 		}
25001 
25002 		if (sta_info->is_deauth_in_progress) {
25003 			hdd_debug("Skip DEL STA as deauth is in progress::"
25004 				  QDF_MAC_ADDR_FMT,
25005 				  QDF_MAC_ADDR_REF(mac));
25006 			hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
25007 					     true,
25008 					     STA_INFO_CFG80211_DEL_STATION);
25009 			return -ENOENT;
25010 		}
25011 
25012 		hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_FMT,
25013 			  QDF_MAC_ADDR_REF(mac));
25014 		hdd_softap_deauth_current_sta(adapter, sta_info, hapd_state,
25015 					      param);
25016 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
25017 				     STA_INFO_CFG80211_DEL_STATION);
25018 	}
25019 
25020 fn_end:
25021 	hdd_exit();
25022 	return 0;
25023 }
25024 
25025 #if defined(USE_CFG80211_DEL_STA_V2)
25026 int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac)
25027 {
25028 	struct station_del_parameters del_sta;
25029 
25030 	del_sta.mac = mac;
25031 	del_sta.subtype = IEEE80211_STYPE_DEAUTH >> 4;
25032 	del_sta.reason_code = WLAN_REASON_DEAUTH_LEAVING;
25033 
25034 	return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
25035 					     adapter->dev, &del_sta);
25036 }
25037 #else
25038 int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac)
25039 {
25040 	return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
25041 					     adapter->dev, mac);
25042 }
25043 #endif
25044 
25045 /**
25046  * _wlan_hdd_cfg80211_del_station() - delete station entry handler
25047  * @wiphy: Pointer to wiphy
25048  * @dev: net_device to operate against
25049  * @mac: binary mac address
25050  * @reason_code: reason for the deauthorization/disassociation
25051  * @subtype: management frame subtype to indicate removal
25052  *
25053  * Return: Errno
25054  */
25055 static int _wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
25056 					  struct net_device *dev,
25057 					  const uint8_t *mac,
25058 					  uint16_t reason_code,
25059 					  uint8_t subtype)
25060 {
25061 	int errno;
25062 	struct csr_del_sta_params delStaParams;
25063 	struct osif_vdev_sync *vdev_sync;
25064 
25065 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25066 	if (errno)
25067 		return errno;
25068 
25069 	wlansap_populate_del_sta_params(mac, reason_code, subtype,
25070 					&delStaParams);
25071 	errno = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
25072 
25073 	osif_vdev_sync_op_stop(vdev_sync);
25074 
25075 	return errno;
25076 }
25077 
25078 #ifdef USE_CFG80211_DEL_STA_V2
25079 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
25080 				  struct net_device *dev,
25081 				  struct station_del_parameters *param)
25082 {
25083 	if (!param)
25084 		return -EINVAL;
25085 
25086 	return _wlan_hdd_cfg80211_del_station(wiphy, dev, param->mac,
25087 					      param->reason_code,
25088 					      param->subtype);
25089 }
25090 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
25091 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
25092 				  const uint8_t *mac)
25093 {
25094 	uint16_t reason = REASON_DEAUTH_NETWORK_LEAVING;
25095 	uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
25096 
25097 	return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
25098 }
25099 #else
25100 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
25101 				  uint8_t *mac)
25102 {
25103 	uint16_t reason = REASON_DEAUTH_NETWORK_LEAVING;
25104 	uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
25105 
25106 	return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
25107 }
25108 #endif
25109 
25110 #ifdef CFG80211_LINK_STA_PARAMS_PRESENT
25111 static inline
25112 uint8_t wlan_hdd_get_link_id(struct station_parameters *params)
25113 {
25114 	return params->link_sta_params.link_id;
25115 }
25116 #else
25117 static inline
25118 uint8_t wlan_hdd_get_link_id(struct station_parameters *params)
25119 {
25120 	return 255;
25121 }
25122 #endif
25123 /**
25124  * __wlan_hdd_cfg80211_add_station() - add station
25125  * @wiphy: Pointer to wiphy
25126  * @dev: Pointer to network device
25127  * @mac: Pointer to station mac address
25128  * @params: Pointer to add station parameter
25129  *
25130  * Return: 0 for success, non-zero for failure
25131  */
25132 static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
25133 					   struct net_device *dev,
25134 					   const uint8_t *mac,
25135 					   struct station_parameters *params)
25136 {
25137 	int status = -EPERM;
25138 #ifdef FEATURE_WLAN_TDLS
25139 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25140 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
25141 	u32 mask, set;
25142 	uint8_t link_id;
25143 
25144 	hdd_enter();
25145 
25146 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25147 		hdd_err("Command not allowed in FTM mode");
25148 		return -EINVAL;
25149 	}
25150 
25151 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25152 		return -EINVAL;
25153 
25154 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25155 		   TRACE_CODE_HDD_CFG80211_ADD_STA,
25156 		   adapter->deflink->vdev_id, params->listen_interval);
25157 
25158 	if (0 != wlan_hdd_validate_context(hdd_ctx))
25159 		return -EINVAL;
25160 
25161 	mask = params->sta_flags_mask;
25162 	set = params->sta_flags_set;
25163 	link_id = wlan_hdd_get_link_id(params);
25164 	hdd_debug("mask 0x%x set 0x%x link_id %d " QDF_MAC_ADDR_FMT, mask, set,
25165 		  link_id, QDF_MAC_ADDR_REF(mac));
25166 
25167 	if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
25168 		if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
25169 			status = wlan_cfg80211_tdls_add_peer_mlo(adapter,
25170 								 mac, link_id);
25171 		}
25172 	}
25173 #endif
25174 	hdd_exit();
25175 	return status;
25176 }
25177 
25178 /**
25179  * wlan_hdd_cfg80211_add_station() - add station
25180  * @wiphy: Pointer to wiphy
25181  * @dev: Pointer to network device
25182  * @mac: Pointer to station mac address
25183  * @params: Pointer to add station parameter
25184  *
25185  * Return: 0 for success, non-zero for failure
25186  */
25187 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
25188 static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
25189 					 struct net_device *dev,
25190 					 const uint8_t *mac,
25191 					 struct station_parameters *params)
25192 #else
25193 static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
25194 					 struct net_device *dev, uint8_t *mac,
25195 					 struct station_parameters *params)
25196 #endif
25197 {
25198 	int errno;
25199 	struct osif_vdev_sync *vdev_sync;
25200 
25201 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25202 	if (errno)
25203 		return errno;
25204 
25205 	errno = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
25206 
25207 	osif_vdev_sync_op_stop(vdev_sync);
25208 
25209 	return errno;
25210 }
25211 
25212 #if (defined(CFG80211_CONFIG_PMKSA_TIMER_PARAMS_SUPPORT) || \
25213 	     (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)))
25214 static inline void
25215 hdd_fill_pmksa_lifetime(struct cfg80211_pmksa *pmksa,
25216 			struct wlan_crypto_pmksa *pmk_cache)
25217 {
25218 	pmk_cache->pmk_lifetime = pmksa->pmk_lifetime;
25219 	if (pmk_cache->pmk_lifetime > WLAN_CRYPTO_MAX_PMKID_LIFETIME)
25220 		pmk_cache->pmk_lifetime = WLAN_CRYPTO_MAX_PMKID_LIFETIME;
25221 
25222 	pmk_cache->pmk_lifetime_threshold = pmksa->pmk_reauth_threshold;
25223 	if (pmk_cache->pmk_lifetime_threshold >=
25224 	    WLAN_CRYPTO_MAX_PMKID_LIFETIME_THRESHOLD)
25225 		pmk_cache->pmk_lifetime_threshold =
25226 			WLAN_CRYPTO_MAX_PMKID_LIFETIME_THRESHOLD - 1;
25227 
25228 	hdd_debug("PMKSA: lifetime:%d threshold:%d",  pmk_cache->pmk_lifetime,
25229 		  pmk_cache->pmk_lifetime_threshold);
25230 }
25231 #else
25232 static inline void
25233 hdd_fill_pmksa_lifetime(struct cfg80211_pmksa *pmksa,
25234 			struct wlan_crypto_pmksa *src_pmk_cache)
25235 {}
25236 #endif
25237 
25238 static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
25239 					   struct wlan_crypto_pmksa *pmk_cache)
25240 {
25241 	QDF_STATUS result;
25242 	struct wlan_crypto_pmksa *pmksa;
25243 	struct wlan_objmgr_vdev *vdev;
25244 	mac_handle_t mac_handle;
25245 	struct hdd_context *hdd_ctx;
25246 
25247 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25248 	if (!hdd_ctx) {
25249 		hdd_err("HDD context is null");
25250 		return QDF_STATUS_E_INVAL;
25251 	}
25252 
25253 	if (wlan_hdd_validate_context(hdd_ctx))
25254 		return QDF_STATUS_E_INVAL;
25255 	mac_handle = hdd_ctx->mac_handle;
25256 
25257 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
25258 	if (!vdev)
25259 		return QDF_STATUS_E_FAILURE;
25260 
25261 	pmksa = qdf_mem_malloc(sizeof(*pmksa));
25262 	if (!pmksa) {
25263 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
25264 		return QDF_STATUS_E_NOMEM;
25265 	}
25266 
25267 	if (!pmk_cache->ssid_len) {
25268 		qdf_copy_macaddr(&pmksa->bssid, &pmk_cache->bssid);
25269 	} else {
25270 		qdf_mem_copy(pmksa->ssid, pmk_cache->ssid, pmk_cache->ssid_len);
25271 		qdf_mem_copy(pmksa->cache_id, pmk_cache->cache_id,
25272 			     WLAN_CACHE_ID_LEN);
25273 		pmksa->ssid_len = pmk_cache->ssid_len;
25274 	}
25275 	qdf_mem_copy(pmksa->pmkid, pmk_cache->pmkid, PMKID_LEN);
25276 	qdf_mem_copy(pmksa->pmk, pmk_cache->pmk, pmk_cache->pmk_len);
25277 	pmksa->pmk_len = pmk_cache->pmk_len;
25278 	pmksa->pmk_entry_ts = qdf_get_system_timestamp();
25279 	pmksa->pmk_lifetime = pmk_cache->pmk_lifetime;
25280 	pmksa->pmk_lifetime_threshold = pmk_cache->pmk_lifetime_threshold;
25281 
25282 	result = wlan_crypto_set_del_pmksa(vdev, pmksa, true);
25283 	if (result != QDF_STATUS_SUCCESS) {
25284 		qdf_mem_zero(pmksa, sizeof(*pmksa));
25285 		qdf_mem_free(pmksa);
25286 	}
25287 
25288 	if (result == QDF_STATUS_SUCCESS && pmk_cache->pmk_len) {
25289 		sme_roam_set_psk_pmk(mac_handle, pmksa,
25290 				     adapter->deflink->vdev_id, false);
25291 		sme_set_pmk_cache_ft(mac_handle, adapter->deflink->vdev_id,
25292 				     pmk_cache);
25293 	}
25294 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
25295 
25296 	return result;
25297 }
25298 
25299 static QDF_STATUS wlan_hdd_del_pmksa_cache(struct hdd_adapter *adapter,
25300 					   struct wlan_crypto_pmksa *pmk_cache)
25301 {
25302 	QDF_STATUS result;
25303 	struct wlan_crypto_pmksa pmksa;
25304 	struct wlan_objmgr_vdev *vdev;
25305 
25306 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
25307 	if (!vdev)
25308 		return QDF_STATUS_E_FAILURE;
25309 
25310 	qdf_mem_zero(&pmksa, sizeof(pmksa));
25311 	if (!pmk_cache->ssid_len) {
25312 		qdf_copy_macaddr(&pmksa.bssid, &pmk_cache->bssid);
25313 	} else {
25314 		qdf_mem_copy(pmksa.ssid, pmk_cache->ssid, pmk_cache->ssid_len);
25315 		qdf_mem_copy(pmksa.cache_id, pmk_cache->cache_id,
25316 			     WLAN_CACHE_ID_LEN);
25317 		pmksa.ssid_len = pmk_cache->ssid_len;
25318 	}
25319 
25320 	result = wlan_crypto_set_del_pmksa(vdev, &pmksa, false);
25321 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
25322 
25323 	return result;
25324 }
25325 
25326 QDF_STATUS wlan_hdd_flush_pmksa_cache(struct wlan_hdd_link_info *link_info)
25327 {
25328 	QDF_STATUS result;
25329 	struct wlan_objmgr_vdev *vdev;
25330 
25331 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
25332 	if (!vdev)
25333 		return QDF_STATUS_E_FAILURE;
25334 
25335 	result = wlan_crypto_set_del_pmksa(vdev, NULL, false);
25336 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
25337 
25338 	if (QDF_IS_STATUS_ERROR(result))
25339 		hdd_debug("Cannot flush PMKIDCache");
25340 
25341 	return result;
25342 }
25343 
25344 #if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
25345 	 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
25346 /*
25347  * wlan_hdd_is_pmksa_valid: API to validate pmksa
25348  * @pmksa: pointer to cfg80211_pmksa structure
25349  *
25350  * Return: True if valid else false
25351  */
25352 static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
25353 {
25354 	if (!pmksa->bssid) {
25355 		hdd_warn("bssid is NULL");
25356 		if (!pmksa->ssid || !pmksa->cache_id) {
25357 			hdd_err("either ssid or cache_id are NULL");
25358 			return false;
25359 		}
25360 	}
25361 	return true;
25362 }
25363 
25364 /*
25365  * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
25366  * @adapter: Pointer to hdd adapter
25367  * @pmk_cache: pmk that needs to be updated
25368  * @pmksa: pmk from supplicant
25369  * @is_delete: Bool to decide set or delete PMK
25370  * Return: None
25371  */
25372 static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
25373 				struct wlan_crypto_pmksa *pmk_cache,
25374 				struct cfg80211_pmksa *pmksa, bool is_delete)
25375 {
25376 	if (pmksa->bssid) {
25377 		hdd_debug("%s PMKSA for " QDF_MAC_ADDR_FMT,
25378 			  is_delete ? "Delete" : "Set",
25379 			  QDF_MAC_ADDR_REF(pmksa->bssid));
25380 		qdf_mem_copy(pmk_cache->bssid.bytes,
25381 			     pmksa->bssid, QDF_MAC_ADDR_SIZE);
25382 	} else {
25383 		qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, pmksa->ssid_len);
25384 		qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
25385 			     CACHE_ID_LEN);
25386 		pmk_cache->ssid_len = pmksa->ssid_len;
25387 		hdd_debug("%s PMKSA for ssid " QDF_SSID_FMT " cache_id %x %x",
25388 			  is_delete ? "Delete" : "Set",
25389 			  QDF_SSID_REF(pmk_cache->ssid_len, pmk_cache->ssid),
25390 			  pmk_cache->cache_id[0],
25391 			  pmk_cache->cache_id[1]);
25392 	}
25393 	qdf_mem_copy(pmk_cache->pmkid, pmksa->pmkid, PMKID_LEN);
25394 
25395 	hdd_fill_pmksa_lifetime(pmksa, pmk_cache);
25396 
25397 	if (is_delete)
25398 		return;
25399 
25400 	if (pmksa->pmk_len && (pmksa->pmk_len <= MAX_PMK_LEN)) {
25401 		qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
25402 		pmk_cache->pmk_len = pmksa->pmk_len;
25403 	} else
25404 		hdd_err("Invalid pmk len is %zu", pmksa->pmk_len);
25405 }
25406 #else
25407 /*
25408  * wlan_hdd_is_pmksa_valid: API to validate pmksa
25409  * @pmksa: pointer to cfg80211_pmksa structure
25410  *
25411  * Return: True if valid else false
25412  */
25413 static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
25414 {
25415 	if (!pmksa->bssid) {
25416 		hdd_err("both bssid is NULL %pK", pmksa->bssid);
25417 		return false;
25418 	}
25419 	return true;
25420 }
25421 
25422 /*
25423  * hdd_fill_pmksa_info: API to update struct wlan_crypto_pmksa from
25424  * cfg80211_pmksa
25425  * @adapter: Pointer to hdd adapter
25426  * @pmk_cache: pmk which needs to be updated
25427  * @pmksa: pmk from supplicant
25428  * @is_delete: Bool to decide whether to set or delete PMK
25429  *
25430  * Return: None
25431  */
25432 static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
25433 				struct wlan_crypto_pmksa *pmk_cache,
25434 				struct cfg80211_pmksa *pmksa, bool is_delete)
25435 {
25436 	mac_handle_t mac_handle;
25437 
25438 	hdd_debug("%s PMKSA for " QDF_MAC_ADDR_FMT, is_delete ? "Delete" : "Set",
25439 		  QDF_MAC_ADDR_REF(pmksa->bssid));
25440 	qdf_mem_copy(pmk_cache->bssid.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
25441 
25442 	if (is_delete)
25443 		return;
25444 	mac_handle = hdd_adapter_get_mac_handle(adapter);
25445 	sme_get_pmk_info(mac_handle, adapter->deflink->vdev_id, pmk_cache);
25446 	qdf_mem_copy(pmk_cache->pmkid, pmksa->pmkid, PMKID_LEN);
25447 }
25448 #endif
25449 
25450 /**
25451  * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
25452  * @wiphy: Pointer to wiphy
25453  * @dev: Pointer to network device
25454  * @pmksa: Pointer to set pmksa parameter
25455  *
25456  * Return: 0 for success, non-zero for failure
25457  */
25458 static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
25459 					 struct net_device *dev,
25460 					 struct cfg80211_pmksa *pmksa)
25461 {
25462 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25463 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25464 	QDF_STATUS result = QDF_STATUS_SUCCESS;
25465 	int status;
25466 	struct wlan_crypto_pmksa *pmk_cache;
25467 
25468 	hdd_enter();
25469 
25470 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25471 		hdd_err("Command not allowed in FTM mode");
25472 		return -EINVAL;
25473 	}
25474 
25475 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25476 		return -EINVAL;
25477 
25478 	if (!pmksa) {
25479 		hdd_err("pmksa is NULL");
25480 		return -EINVAL;
25481 	}
25482 
25483 	if (!pmksa->pmkid) {
25484 		hdd_err("pmksa->pmkid(%pK) is NULL",
25485 		       pmksa->pmkid);
25486 		return -EINVAL;
25487 	}
25488 
25489 	if (!wlan_hdd_is_pmksa_valid(pmksa))
25490 		return -EINVAL;
25491 
25492 	status = wlan_hdd_validate_context(hdd_ctx);
25493 
25494 	if (0 != status)
25495 		return status;
25496 
25497 	pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
25498 	if (!pmk_cache)
25499 		return -ENOMEM;
25500 
25501 	hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, false);
25502 
25503 	/*
25504 	 * Add to the PMKSA Cache in CSR
25505 	 * PMKSA cache will be having following
25506 	 * 1. pmkid id
25507 	 * 2. pmk
25508 	 * 3. bssid or cache identifier
25509 	 */
25510 	result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
25511 
25512 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25513 		   TRACE_CODE_HDD_CFG80211_SET_PMKSA,
25514 		   adapter->deflink->vdev_id, result);
25515 
25516 	if (QDF_IS_STATUS_SUCCESS(result) || result == QDF_STATUS_E_EXISTS)
25517 		sme_set_del_pmkid_cache(hdd_ctx->psoc,
25518 					adapter->deflink->vdev_id,
25519 					pmk_cache, true);
25520 
25521 	qdf_mem_zero(pmk_cache, sizeof(*pmk_cache));
25522 
25523 	qdf_mem_free(pmk_cache);
25524 	hdd_exit();
25525 
25526 	return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
25527 }
25528 
25529 /**
25530  * wlan_hdd_cfg80211_set_pmksa() - set pmksa
25531  * @wiphy: Pointer to wiphy
25532  * @dev: Pointer to network device
25533  * @pmksa: Pointer to set pmksa parameter
25534  *
25535  * Return: 0 for success, non-zero for failure
25536  */
25537 static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
25538 				       struct net_device *dev,
25539 				       struct cfg80211_pmksa *pmksa)
25540 {
25541 	int errno;
25542 	struct osif_vdev_sync *vdev_sync;
25543 
25544 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25545 	if (errno)
25546 		return errno;
25547 
25548 	errno = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
25549 
25550 	osif_vdev_sync_op_stop(vdev_sync);
25551 
25552 	return errno;
25553 }
25554 
25555 /**
25556  * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
25557  * @wiphy: Pointer to wiphy
25558  * @dev: Pointer to network device
25559  * @pmksa: Pointer to pmksa parameter
25560  *
25561  * Return: 0 for success, non-zero for failure
25562  */
25563 static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
25564 					 struct net_device *dev,
25565 					 struct cfg80211_pmksa *pmksa)
25566 {
25567 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25568 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25569 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
25570 	int status = 0;
25571 	struct wlan_crypto_pmksa *pmk_cache;
25572 
25573 	hdd_enter();
25574 
25575 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25576 		hdd_err("Command not allowed in FTM mode");
25577 		return -EINVAL;
25578 	}
25579 
25580 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25581 		return -EINVAL;
25582 
25583 	if (!pmksa) {
25584 		hdd_err("pmksa is NULL");
25585 		return -EINVAL;
25586 	}
25587 
25588 	if (!wlan_hdd_is_pmksa_valid(pmksa))
25589 		return -EINVAL;
25590 
25591 	status = wlan_hdd_validate_context(hdd_ctx);
25592 
25593 	if (0 != status)
25594 		return status;
25595 
25596 	pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
25597 	if (!pmk_cache)
25598 		return -ENOMEM;
25599 
25600 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25601 		   TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
25602 		   adapter->deflink->vdev_id, 0);
25603 
25604 	hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, true);
25605 
25606 	qdf_status = wlan_hdd_del_pmksa_cache(adapter, pmk_cache);
25607 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
25608 		if (!pmksa->bssid)
25609 			hdd_err("Failed to delete PMKSA for null bssid");
25610 		else
25611 			hdd_err("Failed to delete PMKSA for " QDF_MAC_ADDR_FMT,
25612 				QDF_MAC_ADDR_REF(pmksa->bssid));
25613 		status = -EINVAL;
25614 	} else {
25615 		/* clear single_pmk_info information */
25616 		sme_clear_sae_single_pmk_info(hdd_ctx->psoc,
25617 					      adapter->deflink->vdev_id,
25618 					      pmk_cache);
25619 
25620 		/* Send the delete pmkid command to firmware */
25621 		sme_set_del_pmkid_cache(hdd_ctx->psoc,
25622 					adapter->deflink->vdev_id,
25623 					pmk_cache, false);
25624 	}
25625 
25626 	qdf_mem_zero(pmk_cache, sizeof(*pmk_cache));
25627 	qdf_mem_free(pmk_cache);
25628 
25629 	hdd_exit();
25630 
25631 	return status;
25632 }
25633 
25634 /**
25635  * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
25636  * @wiphy: Pointer to wiphy
25637  * @dev: Pointer to network device
25638  * @pmksa: Pointer to pmksa parameter
25639  *
25640  * Return: 0 for success, non-zero for failure
25641  */
25642 static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
25643 				       struct net_device *dev,
25644 				       struct cfg80211_pmksa *pmksa)
25645 {
25646 	int errno;
25647 	struct osif_vdev_sync *vdev_sync;
25648 
25649 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25650 	if (errno)
25651 		return errno;
25652 
25653 	errno = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
25654 
25655 	osif_vdev_sync_op_stop(vdev_sync);
25656 
25657 	return errno;
25658 
25659 }
25660 
25661 /**
25662  * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
25663  * @wiphy: Pointer to wiphy
25664  * @dev: Pointer to network device
25665  *
25666  * Return: 0 for success, non-zero for failure
25667  */
25668 static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
25669 					   struct net_device *dev)
25670 {
25671 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25672 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25673 	int errno;
25674 	QDF_STATUS status;
25675 
25676 	hdd_enter();
25677 
25678 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25679 		hdd_err("Command not allowed in FTM mode");
25680 		return -EINVAL;
25681 	}
25682 
25683 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25684 		return -EINVAL;
25685 
25686 	hdd_debug("Flushing PMKSA");
25687 
25688 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25689 	errno  = wlan_hdd_validate_context(hdd_ctx);
25690 	if (errno)
25691 		return errno;
25692 
25693 	status = wlan_hdd_flush_pmksa_cache(adapter->deflink);
25694 	if (status == QDF_STATUS_E_NOSUPPORT)
25695 		errno = -EOPNOTSUPP;
25696 	else if (QDF_IS_STATUS_ERROR(status))
25697 		errno = -EINVAL;
25698 
25699 	sme_set_del_pmkid_cache(hdd_ctx->psoc, adapter->deflink->vdev_id,
25700 				NULL, false);
25701 	hdd_exit();
25702 	return errno;
25703 }
25704 
25705 /**
25706  * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
25707  * @wiphy: Pointer to wiphy
25708  * @dev: Pointer to network device
25709  *
25710  * Return: 0 for success, non-zero for failure
25711  */
25712 static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
25713 					 struct net_device *dev)
25714 {
25715 	int errno;
25716 	struct osif_vdev_sync *vdev_sync;
25717 
25718 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25719 	if (errno)
25720 		return errno;
25721 
25722 	errno = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
25723 
25724 	osif_vdev_sync_op_stop(vdev_sync);
25725 
25726 	return errno;
25727 }
25728 
25729 #if defined(KERNEL_SUPPORT_11R_CFG80211)
25730 /**
25731  * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
25732  * @wiphy: Pointer to wiphy
25733  * @dev: Pointer to network device
25734  * @ftie: Pointer to fast transition ie parameter
25735  *
25736  * Return: 0 for success, non-zero for failure
25737  */
25738 static int
25739 __wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
25740 				  struct net_device *dev,
25741 				  struct cfg80211_update_ft_ies_params *ftie)
25742 {
25743 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
25744 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25745 	int status;
25746 
25747 	hdd_enter();
25748 
25749 	status = wlan_hdd_validate_context(hdd_ctx);
25750 	if (status)
25751 		return status;
25752 
25753 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25754 		hdd_err("Command not allowed in FTM mode");
25755 		return -EINVAL;
25756 	}
25757 
25758 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25759 		return -EINVAL;
25760 
25761 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25762 		   TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
25763 		   adapter->deflink->vdev_id, 0);
25764 
25765 	/* Added for debug on reception of Re-assoc Req. */
25766 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
25767 		hdd_err("Called with Ie of length = %zu when not associated",
25768 		       ftie->ie_len);
25769 		hdd_err("Should be Re-assoc Req IEs");
25770 	}
25771 	hdd_debug("called with Ie of length = %zu", ftie->ie_len);
25772 
25773 	ucfg_cm_set_ft_ies(hdd_ctx->pdev, adapter->deflink->vdev_id,
25774 			   (const u8 *)ftie->ie, ftie->ie_len);
25775 	hdd_exit();
25776 	return 0;
25777 }
25778 
25779 /**
25780  * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
25781  * @wiphy: Pointer to wiphy
25782  * @dev: Pointer to network device
25783  * @ftie: Pointer to fast transition ie parameter
25784  *
25785  * Return: 0 for success, non-zero for failure
25786  */
25787 static int
25788 wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
25789 				struct net_device *dev,
25790 				struct cfg80211_update_ft_ies_params *ftie)
25791 {
25792 	int errno;
25793 	struct osif_vdev_sync *vdev_sync;
25794 
25795 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25796 	if (errno)
25797 		return errno;
25798 
25799 	errno = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
25800 
25801 	osif_vdev_sync_op_stop(vdev_sync);
25802 
25803 	return errno;
25804 }
25805 #endif
25806 
25807 #if defined(CFG80211_EXTERNAL_DH_UPDATE_SUPPORT) || \
25808 (LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0))
25809 /**
25810  * __wlan_hdd_cfg80211_update_owe_info() - update OWE info
25811  * @wiphy: Pointer to wiphy
25812  * @dev: Pointer to network device
25813  * @owe_info: Pointer to OWE info
25814  *
25815  * Return: 0 for success, non-zero for failure
25816  */
25817 static int
25818 __wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
25819 				    struct net_device *dev,
25820 				    struct cfg80211_update_owe_info *owe_info)
25821 {
25822 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
25823 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25824 	QDF_STATUS status;
25825 	int errno;
25826 	struct sap_context *sap_ctx;
25827 
25828 	hdd_enter_dev(dev);
25829 
25830 	errno = wlan_hdd_validate_context(hdd_ctx);
25831 	if (errno)
25832 		return errno;
25833 
25834 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25835 		hdd_err("Command not allowed in FTM mode");
25836 		return -EINVAL;
25837 	}
25838 
25839 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25840 		return -EINVAL;
25841 
25842 	hdd_debug("owe_status %d", owe_info->status);
25843 
25844 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink);
25845 	status = wlansap_update_owe_info(sap_ctx, owe_info->peer, owe_info->ie,
25846 					 owe_info->ie_len, owe_info->status);
25847 	if (QDF_IS_STATUS_ERROR(status)) {
25848 		hdd_err("Failed to update OWE info");
25849 		errno = qdf_status_to_os_return(status);
25850 	}
25851 
25852 	hdd_exit();
25853 	return errno;
25854 }
25855 
25856 /**
25857  * wlan_hdd_cfg80211_update_owe_info() - update OWE info
25858  * @wiphy: Pointer to wiphy
25859  * @net_dev: Pointer to network device
25860  * @owe_info: Pointer to OWE info
25861  *
25862  * Return: 0 for success, non-zero for failure
25863  */
25864 static int
25865 wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
25866 				  struct net_device *net_dev,
25867 				  struct cfg80211_update_owe_info *owe_info)
25868 {
25869 	struct osif_vdev_sync *vdev_sync;
25870 	int errno;
25871 
25872 	errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
25873 	if (errno)
25874 		return errno;
25875 
25876 	errno = __wlan_hdd_cfg80211_update_owe_info(wiphy, net_dev, owe_info);
25877 
25878 	osif_vdev_sync_op_stop(vdev_sync);
25879 
25880 	return errno;
25881 }
25882 #endif
25883 
25884 void wlan_hdd_cfg80211_update_replay_counter_cb(
25885 		void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
25886 
25887 {
25888 	struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
25889 	uint8_t temp_replay_counter[8];
25890 	int i;
25891 	uint8_t *p;
25892 
25893 	hdd_enter();
25894 
25895 	if (!adapter) {
25896 		hdd_err("HDD adapter is Null");
25897 		goto out;
25898 	}
25899 
25900 	if (!gtk_rsp_param) {
25901 		hdd_err("gtk_rsp_param is Null");
25902 		goto out;
25903 	}
25904 
25905 	if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
25906 		hdd_err("wlan Failed to get replay counter value");
25907 		goto out;
25908 	}
25909 
25910 	hdd_debug("updated replay counter: %llu from fwr",
25911 		gtk_rsp_param->replay_counter);
25912 	/* convert little to big endian since supplicant works on big endian */
25913 	p = (uint8_t *)&gtk_rsp_param->replay_counter;
25914 	for (i = 0; i < 8; i++)
25915 		temp_replay_counter[7 - i] = (uint8_t) p[i];
25916 
25917 	hdd_debug("gtk_rsp_param bssid "QDF_MAC_ADDR_FMT,
25918 		  QDF_MAC_ADDR_REF(gtk_rsp_param->bssid.bytes));
25919 	/* Update replay counter to NL */
25920 	cfg80211_gtk_rekey_notify(adapter->dev,
25921 					gtk_rsp_param->bssid.bytes,
25922 					temp_replay_counter, GFP_KERNEL);
25923 out:
25924 	hdd_exit();
25925 
25926 }
25927 
25928 #ifdef WLAN_FEATURE_GTK_OFFLOAD
25929 /**
25930  * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
25931  * @gtk_req: Pointer to GTK request
25932  * @data: Pointer to rekey data
25933  *
25934  * Return: none
25935  */
25936 #if (defined(CFG80211_REKEY_DATA_KEK_LEN) || \
25937 	LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
25938 static
25939 void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
25940 			   struct cfg80211_gtk_rekey_data *data)
25941 {
25942 	qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
25943 	gtk_req->kek_len = data->kek_len;
25944 }
25945 #else
25946 static
25947 void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
25948 			   struct cfg80211_gtk_rekey_data *data)
25949 {
25950 	qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
25951 	gtk_req->kek_len = NL80211_KEK_LEN;
25952 }
25953 #endif
25954 
25955 /**
25956  * wlan_hdd_copy_gtk_kck - Copy the KCK from GTK rekey data to GTK request
25957  * @gtk_req: Pointer to GTK request
25958  * @data: Pointer to rekey data
25959  *
25960  * Return: None
25961  */
25962 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
25963 static
25964 void wlan_hdd_copy_gtk_kck(struct pmo_gtk_req *gtk_req,
25965 			   struct cfg80211_gtk_rekey_data *data)
25966 {
25967 	qdf_mem_copy(gtk_req->kck, data->kck, data->kck_len);
25968 	gtk_req->kck_len = data->kck_len;
25969 }
25970 #else
25971 static
25972 void wlan_hdd_copy_gtk_kck(struct pmo_gtk_req *gtk_req,
25973 			   struct cfg80211_gtk_rekey_data *data)
25974 {
25975 	qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
25976 	gtk_req->kck_len = NL80211_KCK_LEN;
25977 }
25978 #endif
25979 /**
25980  * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
25981  * @wiphy: Pointer to wiphy
25982  * @dev: Pointer to network device
25983  * @data: Pointer to rekey data
25984  *
25985  * This function is used to offload GTK rekeying job to the firmware.
25986  *
25987  * Return: 0 for success, non-zero for failure
25988  */
25989 static
25990 int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
25991 		struct net_device *dev,
25992 		struct cfg80211_gtk_rekey_data *data)
25993 {
25994 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25995 	int result, i;
25996 	struct pmo_gtk_req *gtk_req = NULL;
25997 	struct hdd_context *hdd_ctx =  WLAN_HDD_GET_CTX(adapter);
25998 	uint8_t *buf;
25999 	struct wlan_objmgr_vdev *vdev;
26000 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
26001 
26002 	hdd_enter();
26003 
26004 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26005 		hdd_err("Command not allowed in FTM mode");
26006 		result = -EINVAL;
26007 		goto out;
26008 	}
26009 
26010 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) {
26011 		result = -EINVAL;
26012 		goto out;
26013 	}
26014 
26015 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26016 		   TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
26017 		   adapter->deflink->vdev_id, adapter->device_mode);
26018 
26019 	result = wlan_hdd_validate_context(hdd_ctx);
26020 	if (0 != result)
26021 		goto out;
26022 
26023 	gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
26024 	if (!gtk_req) {
26025 		result = -ENOMEM;
26026 		goto out;
26027 	}
26028 
26029 	/* convert big to little endian since driver work on little endian */
26030 	buf = (uint8_t *)&gtk_req->replay_counter;
26031 	for (i = 0; i < 8; i++)
26032 		buf[7 - i] = data->replay_ctr[i];
26033 
26034 	hdd_debug("current replay counter: %llu in user space",
26035 		gtk_req->replay_counter);
26036 
26037 	wlan_hdd_copy_gtk_kek(gtk_req, data);
26038 	wlan_hdd_copy_gtk_kck(gtk_req, data);
26039 
26040 	gtk_req->is_fils_connection = hdd_is_fils_connection(hdd_ctx, adapter);
26041 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
26042 					   WLAN_OSIF_POWER_ID);
26043 	if (!vdev) {
26044 		result = -EINVAL;
26045 		goto out;
26046 	}
26047 	status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
26048 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
26049 	if (status != QDF_STATUS_SUCCESS) {
26050 		hdd_err("Failed to cache GTK Offload");
26051 		result = qdf_status_to_os_return(status);
26052 	}
26053 out:
26054 	if (gtk_req)
26055 		qdf_mem_free(gtk_req);
26056 	hdd_exit();
26057 
26058 	return result;
26059 }
26060 
26061 /**
26062  * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
26063  * @wiphy: Pointer to wiphy
26064  * @dev: Pointer to network device
26065  * @data: Pointer to rekey data
26066  *
26067  * This function is used to offload GTK rekeying job to the firmware.
26068  *
26069  * Return: 0 for success, non-zero for failure
26070  */
26071 static
26072 int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
26073 				     struct net_device *dev,
26074 				     struct cfg80211_gtk_rekey_data *data)
26075 {
26076 	int errno;
26077 	struct osif_vdev_sync *vdev_sync;
26078 
26079 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26080 	if (errno)
26081 		return errno;
26082 
26083 	errno = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
26084 
26085 	osif_vdev_sync_op_stop(vdev_sync);
26086 
26087 	return errno;
26088 }
26089 #endif /* WLAN_FEATURE_GTK_OFFLOAD */
26090 
26091 /**
26092  * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
26093  * @wiphy: Pointer to wiphy
26094  * @dev: Pointer to network device
26095  * @params: Pointer to access control parameter
26096  *
26097  * Return: 0 for success, non-zero for failure
26098  */
26099 static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
26100 					 struct net_device *dev,
26101 					 const struct cfg80211_acl_data *params)
26102 {
26103 	int i;
26104 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26105 	struct hdd_hostapd_state *hostapd_state;
26106 	struct sap_config *config;
26107 	struct hdd_context *hdd_ctx;
26108 	int status;
26109 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
26110 
26111 	hdd_enter();
26112 
26113 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26114 		hdd_err("Command not allowed in FTM mode");
26115 		return -EINVAL;
26116 	}
26117 
26118 	if (!params) {
26119 		hdd_err("params is Null");
26120 		return -EINVAL;
26121 	}
26122 
26123 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26124 	status = wlan_hdd_validate_context(hdd_ctx);
26125 
26126 	if (0 != status)
26127 		return status;
26128 
26129 	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
26130 
26131 	if (!hostapd_state) {
26132 		hdd_err("hostapd_state is Null");
26133 		return -EINVAL;
26134 	}
26135 
26136 	hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
26137 		params->n_acl_entries);
26138 
26139 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26140 		   TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
26141 		   adapter->deflink->vdev_id, adapter->device_mode);
26142 
26143 	if (QDF_SAP_MODE == adapter->device_mode) {
26144 		config = &adapter->deflink->session.ap.sap_config;
26145 
26146 		/* default value */
26147 		config->num_accept_mac = 0;
26148 		config->num_deny_mac = 0;
26149 
26150 		/**
26151 		 * access control policy
26152 		 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
26153 		 *   listed in hostapd.deny file.
26154 		 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
26155 		 *   listed in hostapd.accept file.
26156 		 */
26157 		if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
26158 			config->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
26159 		} else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
26160 			   params->acl_policy) {
26161 			config->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
26162 		} else {
26163 			hdd_warn("Acl Policy : %d is not supported",
26164 				params->acl_policy);
26165 			return -ENOTSUPP;
26166 		}
26167 
26168 		if (eSAP_DENY_UNLESS_ACCEPTED == config->SapMacaddr_acl) {
26169 			config->num_accept_mac = params->n_acl_entries;
26170 			for (i = 0; i < params->n_acl_entries; i++) {
26171 				hdd_debug("** Add ACL MAC entry %i in WhiletList :"
26172 					QDF_MAC_ADDR_FMT, i,
26173 					QDF_MAC_ADDR_REF(
26174 						params->mac_addrs[i].addr));
26175 
26176 				qdf_mem_copy(&config->accept_mac[i],
26177 					     params->mac_addrs[i].addr,
26178 					     QDF_MAC_ADDR_SIZE);
26179 			}
26180 		} else if (eSAP_ACCEPT_UNLESS_DENIED == config->SapMacaddr_acl) {
26181 			config->num_deny_mac = params->n_acl_entries;
26182 			for (i = 0; i < params->n_acl_entries; i++) {
26183 				hdd_debug("** Add ACL MAC entry %i in DenyList :"
26184 					QDF_MAC_ADDR_FMT, i,
26185 					QDF_MAC_ADDR_REF(
26186 						params->mac_addrs[i].addr));
26187 
26188 				qdf_mem_copy(&config->deny_mac[i],
26189 					     params->mac_addrs[i].addr,
26190 					     QDF_MAC_ADDR_SIZE);
26191 			}
26192 		}
26193 		qdf_status = wlansap_set_mac_acl(
26194 			WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink), config);
26195 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
26196 			hdd_err("SAP Set Mac Acl fail");
26197 			return -EINVAL;
26198 		}
26199 	} else {
26200 		hdd_debug("Invalid device_mode %s(%d)",
26201 			  qdf_opmode_str(adapter->device_mode),
26202 			  adapter->device_mode);
26203 		return -EINVAL;
26204 	}
26205 	hdd_exit();
26206 	return 0;
26207 }
26208 
26209 /**
26210  * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
26211  *				__wlan_hdd_cfg80211_set_mac_acl
26212  * @wiphy: pointer to wiphy structure
26213  * @dev: pointer to net_device
26214  * @params: pointer to cfg80211_acl_data
26215  *
26216  * Return; 0 on success, error number otherwise
26217  */
26218 static int
26219 wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
26220 			      struct net_device *dev,
26221 			      const struct cfg80211_acl_data *params)
26222 {
26223 	int errno;
26224 	struct osif_vdev_sync *vdev_sync;
26225 
26226 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26227 	if (errno)
26228 		return errno;
26229 
26230 	errno = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
26231 
26232 	osif_vdev_sync_op_stop(vdev_sync);
26233 
26234 	return errno;
26235 }
26236 
26237 #ifdef WLAN_NL80211_TESTMODE
26238 #ifdef FEATURE_WLAN_LPHB
26239 /**
26240  * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
26241  * @hdd_ctx: Pointer to hdd context
26242  * @lphb_ind: Pointer to low power heart beat indication parameter
26243  *
26244  * Return: none
26245  */
26246 static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
26247 		struct pmo_lphb_rsp *lphb_ind)
26248 {
26249 	struct sk_buff *skb;
26250 
26251 	hdd_debug("LPHB indication arrived");
26252 
26253 	if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
26254 		return;
26255 
26256 	if (!lphb_ind) {
26257 		hdd_err("invalid argument lphbInd");
26258 		return;
26259 	}
26260 
26261 	skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
26262 			wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
26263 	if (!skb) {
26264 		hdd_err("LPHB timeout, NL buffer alloc fail");
26265 		return;
26266 	}
26267 
26268 	if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
26269 		hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
26270 		goto nla_put_failure;
26271 	}
26272 	if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
26273 		hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
26274 		goto nla_put_failure;
26275 	}
26276 	if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
26277 			lphb_ind)) {
26278 		hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
26279 		goto nla_put_failure;
26280 	}
26281 	cfg80211_testmode_event(skb, GFP_ATOMIC);
26282 	return;
26283 
26284 nla_put_failure:
26285 	hdd_err("NLA Put fail");
26286 	kfree_skb(skb);
26287 }
26288 #endif /* FEATURE_WLAN_LPHB */
26289 
26290 /**
26291  * __wlan_hdd_cfg80211_testmode() - test mode
26292  * @wiphy: Pointer to wiphy
26293  * @data: Data pointer
26294  * @len: Data length
26295  *
26296  * Return: 0 for success, non-zero for failure
26297  */
26298 static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
26299 					void *data, int len)
26300 {
26301 	struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
26302 	int err;
26303 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
26304 
26305 	hdd_enter();
26306 
26307 	err = wlan_hdd_validate_context(hdd_ctx);
26308 	if (err)
26309 		return err;
26310 
26311 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
26312 		hdd_err("Driver Modules are closed");
26313 		return -EINVAL;
26314 	}
26315 
26316 	err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
26317 				      len, wlan_hdd_tm_policy);
26318 	if (err) {
26319 		hdd_err("Testmode INV ATTR");
26320 		return err;
26321 	}
26322 
26323 	if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
26324 		hdd_err("Testmode INV CMD");
26325 		return -EINVAL;
26326 	}
26327 
26328 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26329 		   TRACE_CODE_HDD_CFG80211_TESTMODE,
26330 		   NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
26331 
26332 	switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
26333 #ifdef FEATURE_WLAN_LPHB
26334 	/* Low Power Heartbeat configuration request */
26335 	case WLAN_HDD_TM_CMD_WLAN_HB:
26336 	{
26337 		int buf_len;
26338 		void *buf;
26339 		struct pmo_lphb_req *hb_params = NULL;
26340 		struct pmo_lphb_req *hb_params_temp = NULL;
26341 		QDF_STATUS status;
26342 
26343 		if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
26344 			hdd_err("Testmode INV DATA");
26345 			return -EINVAL;
26346 		}
26347 
26348 		buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
26349 		buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
26350 		if (buf_len < sizeof(*hb_params_temp)) {
26351 			hdd_err("Invalid buffer length for TM_ATTR_DATA");
26352 			return -EINVAL;
26353 		}
26354 
26355 		hb_params_temp = (struct pmo_lphb_req *) buf;
26356 		if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
26357 		    && (hb_params_temp->params.lphb_tcp_params.
26358 			time_period_sec == 0))
26359 			return -EINVAL;
26360 
26361 		if (buf_len > sizeof(*hb_params)) {
26362 			hdd_err("buf_len=%d exceeded hb_params size limit",
26363 				buf_len);
26364 			return -ERANGE;
26365 		}
26366 
26367 		hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
26368 				sizeof(*hb_params));
26369 		if (!hb_params)
26370 			return -ENOMEM;
26371 
26372 		qdf_mem_zero(hb_params, sizeof(*hb_params));
26373 		qdf_mem_copy(hb_params, buf, buf_len);
26374 		status = ucfg_pmo_lphb_config_req(
26375 					hdd_ctx->psoc,
26376 					hb_params, (void *)hdd_ctx,
26377 					wlan_hdd_cfg80211_lphb_ind_handler);
26378 		if (status != QDF_STATUS_SUCCESS)
26379 			hdd_err("LPHB Config Fail, disable");
26380 
26381 		qdf_mem_free(hb_params);
26382 		return 0;
26383 	}
26384 #endif /* FEATURE_WLAN_LPHB */
26385 
26386 #if  defined(QCA_WIFI_FTM)
26387 	case WLAN_HDD_TM_CMD_WLAN_FTM:
26388 	{
26389 		if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) {
26390 			hdd_err("FTM Command not allowed in mission mode, mode %d",
26391 				hdd_get_conparam());
26392 			return -EINVAL;
26393 		}
26394 
26395 		err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->pdev,
26396 						     data, len);
26397 		break;
26398 	}
26399 #endif
26400 	default:
26401 		hdd_err("command: %d not supported",
26402 			nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
26403 		return -EOPNOTSUPP;
26404 	}
26405 
26406 	hdd_exit();
26407 	return err;
26408 }
26409 
26410 /**
26411  * wlan_hdd_cfg80211_testmode() - test mode
26412  * @wiphy: Pointer to wiphy
26413  * @wdev: Pointer to wireless device
26414  * @data: Data pointer
26415  * @len: Data length
26416  *
26417  * Return: 0 for success, non-zero for failure
26418  */
26419 static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
26420 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
26421 				      struct wireless_dev *wdev,
26422 #endif
26423 				      void *data, int len)
26424 {
26425 	struct osif_psoc_sync *psoc_sync;
26426 	int errno;
26427 
26428 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
26429 	if (errno)
26430 		return errno;
26431 
26432 	errno = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
26433 
26434 	osif_psoc_sync_op_stop(psoc_sync);
26435 
26436 	return errno;
26437 }
26438 
26439 #endif /* CONFIG_NL80211_TESTMODE */
26440 
26441 #ifdef QCA_HT_2040_COEX
26442 /**
26443  * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
26444  * @wiphy: Pointer to wiphy
26445  * @dev: Pointer to network device
26446  * @chandef: Pointer to channel definition parameter
26447  *
26448  * Return: 0 for success, non-zero for failure
26449  */
26450 static int
26451 __wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
26452 					 struct net_device *dev,
26453 					 struct cfg80211_chan_def *chandef)
26454 {
26455 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26456 	struct hdd_context *hdd_ctx;
26457 	QDF_STATUS status;
26458 	int retval = 0;
26459 	enum nl80211_channel_type channel_type;
26460 
26461 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26462 		hdd_err("Command not allowed in FTM mode");
26463 		return -EINVAL;
26464 	}
26465 
26466 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26467 		return -EINVAL;
26468 
26469 	if (!(adapter->device_mode == QDF_SAP_MODE ||
26470 	      adapter->device_mode == QDF_P2P_GO_MODE))
26471 		return -EOPNOTSUPP;
26472 
26473 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26474 	status = wlan_hdd_validate_context(hdd_ctx);
26475 	if (status)
26476 		return status;
26477 
26478 	if (chandef->width < NL80211_CHAN_WIDTH_80)
26479 		channel_type = cfg80211_get_chandef_type(chandef);
26480 	else
26481 		channel_type = NL80211_CHAN_HT40PLUS;
26482 	hdd_debug("Channel width changed to %d ", channel_type);
26483 
26484 	/* Change SAP ht2040 mode */
26485 	status = hdd_set_sap_ht2040_mode(adapter, channel_type);
26486 	if (status != QDF_STATUS_SUCCESS) {
26487 		hdd_err("Cannot set SAP HT20/40 mode!");
26488 		retval = -EINVAL;
26489 	}
26490 
26491 	return retval;
26492 }
26493 
26494 /**
26495  * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
26496  * @wiphy: Pointer to wiphy
26497  * @dev: Pointer to network device
26498  * @link_id: Link id for which channel width has to be applied
26499  * @chandef: Pointer to channel definition parameter
26500  *
26501  * Return: 0 for success, non-zero for failure
26502  */
26503 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
26504 static int
26505 wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
26506 				       struct net_device *dev,
26507 				       unsigned int link_id,
26508 				       struct cfg80211_chan_def *chandef)
26509 #else
26510 static int
26511 wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
26512 				       struct net_device *dev,
26513 				       struct cfg80211_chan_def *chandef)
26514 #endif
26515 {
26516 	int errno;
26517 	struct osif_vdev_sync *vdev_sync;
26518 
26519 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26520 	if (errno)
26521 		return errno;
26522 
26523 	errno = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
26524 
26525 	osif_vdev_sync_op_stop(vdev_sync);
26526 
26527 	return errno;
26528 }
26529 #endif
26530 
26531 #ifdef CHANNEL_SWITCH_SUPPORTED
26532 /**
26533  * __wlan_hdd_cfg80211_channel_switch()- function to switch
26534  * channel in SAP/GO
26535  * @wiphy:  wiphy pointer
26536  * @dev: dev pointer.
26537  * @csa_params: Change channel params
26538  *
26539  * This function is called to switch channel in SAP/GO
26540  *
26541  * Return: 0 if success else return non zero
26542  */
26543 static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
26544 				struct net_device *dev,
26545 				struct cfg80211_csa_settings *csa_params)
26546 {
26547 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26548 	struct hdd_context *hdd_ctx;
26549 	int ret;
26550 	enum phy_ch_width ch_width;
26551 	bool status;
26552 	struct hdd_hostapd_state *hostapd_state;
26553 
26554 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26555 		return -EINVAL;
26556 
26557 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26558 	ret = wlan_hdd_validate_context(hdd_ctx);
26559 
26560 	if (0 != ret)
26561 		return ret;
26562 
26563 	if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
26564 		(QDF_SAP_MODE != adapter->device_mode))
26565 		return -ENOTSUPP;
26566 
26567 	status = policy_mgr_is_sap_allowed_on_dfs_freq(
26568 					hdd_ctx->pdev,
26569 					adapter->deflink->vdev_id,
26570 					csa_params->chandef.chan->center_freq);
26571 	if (!status)
26572 		return -EINVAL;
26573 
26574 	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->deflink->vdev_id,
26575 				    CSA_REASON_USER_INITIATED);
26576 
26577 	ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
26578 	hdd_debug("Freq %d width %d ch_width %d",
26579 		  csa_params->chandef.chan->center_freq,
26580 		  csa_params->chandef.width, ch_width);
26581 	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
26582 	qdf_event_reset(&hostapd_state->qdf_event);
26583 
26584 	ret =
26585 	    hdd_softap_set_channel_change(dev,
26586 					  csa_params->chandef.chan->center_freq,
26587 					  ch_width, false);
26588 	if (ret) {
26589 		hdd_err("CSA failed to %d, ret %d",
26590 			csa_params->chandef.chan->center_freq, ret);
26591 		return ret;
26592 	}
26593 
26594 	status = qdf_wait_for_event_completion(&hostapd_state->qdf_event,
26595 					       SME_CMD_START_BSS_TIMEOUT);
26596 	if (QDF_IS_STATUS_ERROR(status))
26597 		hdd_err("wait for qdf_event failed!!");
26598 	else
26599 		hdd_debug("csa done");
26600 
26601 	return ret;
26602 }
26603 
26604 /**
26605  * wlan_hdd_cfg80211_channel_switch()- function to switch
26606  * channel in SAP/GO
26607  * @wiphy:  wiphy pointer
26608  * @dev: dev pointer.
26609  * @csa_params: Change channel params
26610  *
26611  * This function is called to switch channel in SAP/GO
26612  *
26613  * Return: 0 if success else return non zero
26614  */
26615 static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
26616 				struct net_device *dev,
26617 				struct cfg80211_csa_settings *csa_params)
26618 {
26619 	int errno;
26620 	struct osif_vdev_sync *vdev_sync;
26621 
26622 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26623 	if (errno)
26624 		return errno;
26625 
26626 	errno = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
26627 
26628 	osif_vdev_sync_op_stop(vdev_sync);
26629 
26630 	return errno;
26631 }
26632 #endif
26633 
26634 int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
26635 					   uint32_t chan_freq,
26636 					   enum policy_mgr_conn_update_reason reason)
26637 {
26638 	QDF_STATUS status;
26639 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26640 
26641 	hdd_enter();
26642 
26643 	status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
26644 	if (!QDF_IS_STATUS_SUCCESS(status))
26645 		hdd_err("clearing event failed");
26646 
26647 	status = policy_mgr_current_connections_update(
26648 			hdd_ctx->psoc, adapter->deflink->vdev_id,
26649 			chan_freq, reason, POLICY_MGR_DEF_REQ_ID);
26650 	switch (status) {
26651 	case QDF_STATUS_E_FAILURE:
26652 		/*
26653 		 * QDF_STATUS_E_FAILURE indicates that some error has occurred
26654 		 * while changing the hw mode
26655 		 */
26656 		hdd_err("ERROR: connections update failed!!");
26657 		return -EINVAL;
26658 
26659 	case QDF_STATUS_SUCCESS:
26660 		/*
26661 		 * QDF_STATUS_SUCCESS indicates that HW mode change has been
26662 		 * triggered and wait for it to finish.
26663 		 */
26664 		status = policy_mgr_wait_for_connection_update(
26665 						hdd_ctx->psoc);
26666 		if (!QDF_IS_STATUS_SUCCESS(status)) {
26667 			hdd_err("ERROR: qdf wait for event failed!!");
26668 			return -EINVAL;
26669 		}
26670 		if (QDF_MONITOR_MODE == adapter->device_mode)
26671 			hdd_info("Monitor mode:channel freq:%d (SMM->DBS)", chan_freq);
26672 		break;
26673 
26674 	default:
26675 		/*
26676 		 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
26677 		 * required, so caller can proceed further.
26678 		 */
26679 		break;
26680 
26681 	}
26682 	hdd_exit();
26683 
26684 	return 0;
26685 }
26686 
26687 #ifdef FEATURE_MONITOR_MODE_SUPPORT
26688 /**
26689  * __wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
26690  * @wiphy: Handle to struct wiphy to get handle to module context.
26691  * @chandef: Contains information about the capture channel to be set.
26692  *
26693  * This interface is called if and only if monitor mode interface alone is
26694  * active.
26695  *
26696  * Return: 0 success or error code on failure.
26697  */
26698 static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
26699 				       struct cfg80211_chan_def *chandef)
26700 {
26701 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
26702 	struct hdd_adapter *adapter;
26703 	struct hdd_station_ctx *sta_ctx;
26704 	struct hdd_mon_set_ch_info *ch_info;
26705 	QDF_STATUS status;
26706 	mac_handle_t mac_handle;
26707 	struct qdf_mac_addr bssid;
26708 	struct channel_change_req *req;
26709 	struct ch_params ch_params = {0};
26710 	int ret;
26711 	enum channel_state chan_freq_state;
26712 	uint8_t max_fw_bw;
26713 	enum phy_ch_width ch_width;
26714 	qdf_freq_t sec_ch_2g_freq = 0;
26715 
26716 	hdd_enter();
26717 
26718 	ret = wlan_hdd_validate_context(hdd_ctx);
26719 	if (ret)
26720 		return ret;
26721 
26722 	mac_handle = hdd_ctx->mac_handle;
26723 
26724 	adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
26725 	if (!adapter)
26726 		return -EIO;
26727 
26728 	hdd_debug("%s: set monitor mode freq %d",
26729 		  adapter->dev->name, chandef->chan->center_freq);
26730 
26731 	/* Verify channel state before accepting this request */
26732 	chan_freq_state =
26733 		wlan_reg_get_channel_state_for_pwrmode(
26734 						hdd_ctx->pdev,
26735 						chandef->chan->center_freq,
26736 						REG_CURRENT_PWR_MODE);
26737 	if (chan_freq_state == CHANNEL_STATE_DISABLE ||
26738 	    chan_freq_state == CHANNEL_STATE_INVALID) {
26739 		hdd_err("Invalid chan freq received for monitor mode aborting");
26740 		return -EINVAL;
26741 	}
26742 
26743 	/* Verify the BW before accepting this request */
26744 	ch_width = hdd_map_nl_chan_width(chandef->width);
26745 
26746 	if (ch_width > CH_WIDTH_10MHZ ||
26747 	   (!cds_is_sub_20_mhz_enabled() && ch_width > CH_WIDTH_160MHZ)) {
26748 		hdd_err("invalid BW received %d", ch_width);
26749 		return -EINVAL;
26750 	}
26751 
26752 	max_fw_bw = sme_get_vht_ch_width();
26753 
26754 	if ((ch_width == CH_WIDTH_160MHZ &&
26755 	    max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) ||
26756 	    (ch_width == CH_WIDTH_80P80MHZ &&
26757 	    max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)) {
26758 		hdd_err("FW does not support this BW %d max BW supported %d",
26759 			ch_width, max_fw_bw);
26760 		return -EINVAL;
26761 	}
26762 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
26763 	ch_info = &sta_ctx->ch_info;
26764 
26765 	if (WLAN_REG_IS_24GHZ_CH_FREQ(chandef->chan->center_freq) &&
26766 	    chandef->width == NL80211_CHAN_WIDTH_40 &&
26767 	    chandef->center_freq1) {
26768 		if (chandef->center_freq1 > chandef->chan->center_freq)
26769 			sec_ch_2g_freq = chandef->chan->center_freq + 20;
26770 		else if (chandef->center_freq1 < chandef->chan->center_freq)
26771 			sec_ch_2g_freq = chandef->chan->center_freq - 20;
26772 	}
26773 	hdd_debug("set mon ch:width=%d, freq %d sec_ch_2g_freq=%d",
26774 		  chandef->width, chandef->chan->center_freq, sec_ch_2g_freq);
26775 	qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
26776 		     QDF_MAC_ADDR_SIZE);
26777 
26778 	ch_params.ch_width = ch_width;
26779 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
26780 						chandef->chan->center_freq,
26781 						sec_ch_2g_freq, &ch_params,
26782 						REG_CURRENT_PWR_MODE);
26783 	if (wlan_hdd_change_hw_mode_for_given_chnl(adapter,
26784 						   chandef->chan->center_freq,
26785 						   POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
26786 		hdd_err("Failed to change hw mode");
26787 		return -EINVAL;
26788 	}
26789 
26790 	if (adapter->monitor_mode_vdev_up_in_progress) {
26791 		hdd_err_rl("monitor mode vdev up in progress");
26792 		return -EBUSY;
26793 	}
26794 
26795 	status = qdf_event_reset(&adapter->qdf_monitor_mode_vdev_up_event);
26796 	if (QDF_IS_STATUS_ERROR(status)) {
26797 		hdd_err_rl("failed to reinit monitor mode vdev up event");
26798 		return qdf_status_to_os_return(status);
26799 	}
26800 	adapter->monitor_mode_vdev_up_in_progress = true;
26801 
26802 	qdf_mem_zero(&ch_params, sizeof(struct ch_params));
26803 
26804 	req = qdf_mem_malloc(sizeof(struct channel_change_req));
26805 	if (!req)
26806 		return -ENOMEM;
26807 
26808 	req->vdev_id = adapter->deflink->vdev_id;
26809 	req->target_chan_freq = chandef->chan->center_freq;
26810 	req->ch_width = ch_width;
26811 
26812 	ch_params.ch_width = ch_width;
26813 	hdd_select_cbmode(adapter, chandef->chan->center_freq, sec_ch_2g_freq,
26814 			  &ch_params);
26815 
26816 	req->sec_ch_offset = ch_params.sec_ch_offset;
26817 	req->center_freq_seg0 = ch_params.center_freq_seg0;
26818 	req->center_freq_seg1 = ch_params.center_freq_seg1;
26819 
26820 	sme_fill_channel_change_request(mac_handle, req, ch_info->phy_mode);
26821 	status = sme_send_channel_change_req(mac_handle, req);
26822 	qdf_mem_free(req);
26823 
26824 	if (status) {
26825 		hdd_err_rl("Failed to set sme_RoamChannel for monitor mode status: %d",
26826 			   status);
26827 		adapter->monitor_mode_vdev_up_in_progress = false;
26828 		ret = qdf_status_to_os_return(status);
26829 		return ret;
26830 	}
26831 
26832 	/* block on a completion variable until vdev up success*/
26833 	status = qdf_wait_for_event_completion(
26834 				       &adapter->qdf_monitor_mode_vdev_up_event,
26835 					WLAN_MONITOR_MODE_VDEV_UP_EVT);
26836 	if (QDF_IS_STATUS_ERROR(status)) {
26837 		hdd_err_rl("monitor vdev up event time out vdev id: %d",
26838 			  adapter->deflink->vdev_id);
26839 		if (adapter->qdf_monitor_mode_vdev_up_event.force_set)
26840 			/*
26841 			 * SSR/PDR has caused shutdown, which has
26842 			 * forcefully set the event.
26843 			 */
26844 			hdd_err_rl("monitor mode vdev up event forcefully set");
26845 		else if (status == QDF_STATUS_E_TIMEOUT)
26846 			hdd_err_rl("monitor mode vdev up timed out");
26847 		else
26848 			hdd_err_rl("Failed monitor mode vdev up(status-%d)",
26849 				  status);
26850 
26851 		adapter->monitor_mode_vdev_up_in_progress = false;
26852 		return qdf_status_to_os_return(status);
26853 	}
26854 
26855 	hdd_exit();
26856 
26857 	return 0;
26858 }
26859 
26860 /**
26861  * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
26862  * @wiphy: Handle to struct wiphy to get handle to module context.
26863  * @chandef: Contains information about the capture channel to be set.
26864  *
26865  * This interface is called if and only if monitor mode interface alone is
26866  * active.
26867  *
26868  * Return: 0 success or error code on failure.
26869  */
26870 static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
26871 				       struct cfg80211_chan_def *chandef)
26872 {
26873 	struct osif_psoc_sync *psoc_sync;
26874 	int errno;
26875 
26876 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
26877 	if (errno)
26878 		return errno;
26879 
26880 	errno = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
26881 
26882 	osif_psoc_sync_op_stop(psoc_sync);
26883 
26884 	return errno;
26885 }
26886 #endif
26887 
26888 #define CNT_DIFF(cur, prev) \
26889 	((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
26890 #define MAX_COUNT 0xffffffff
26891 static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
26892 			struct scan_chan_info *chan,
26893 			struct scan_chan_info *info, uint32_t cmd_flag)
26894 {
26895 	if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
26896 	   (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
26897 		hdd_err("cmd flag is invalid: %d", info->cmd_flag);
26898 
26899 	mutex_lock(&hdd_ctx->chan_info_lock);
26900 
26901 	if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
26902 		qdf_mem_zero(chan, sizeof(*chan));
26903 
26904 	chan->freq = info->freq;
26905 	chan->noise_floor = info->noise_floor;
26906 	chan->clock_freq = info->clock_freq;
26907 	chan->cmd_flag = info->cmd_flag;
26908 	chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
26909 
26910 	chan->rx_clear_count =
26911 			CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
26912 
26913 	chan->tx_frame_count =
26914 			CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
26915 
26916 	mutex_unlock(&hdd_ctx->chan_info_lock);
26917 
26918 }
26919 #undef CNT_DIFF
26920 #undef MAX_COUNT
26921 
26922 #ifndef UPDATE_ASSOC_IE
26923 #define UPDATE_ASSOC_IE BIT(0)
26924 #endif
26925 
26926 #ifndef UPDATE_FILS_ERP_INFO
26927 #define UPDATE_FILS_ERP_INFO BIT(1)
26928 #endif
26929 
26930 #ifndef UPDATE_FILS_AUTH_TYPE
26931 #define UPDATE_FILS_AUTH_TYPE BIT(2)
26932 #endif
26933 
26934 #if defined(WLAN_FEATURE_FILS_SK) &&\
26935 	(defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) ||\
26936 		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))) &&\
26937 	(defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
26938 		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
26939 static inline int
26940 hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
26941 				    struct hdd_context *hdd_ctx,
26942 				    struct cfg80211_connect_params *req,
26943 				    uint32_t changed)
26944 {
26945 	uint8_t *buf;
26946 	QDF_STATUS status;
26947 	enum wlan_fils_auth_type auth_type;
26948 	struct wlan_fils_con_info *fils_info;
26949 	int ret = 0;
26950 
26951 	fils_info = qdf_mem_malloc(sizeof(*fils_info));
26952 	if (!fils_info)
26953 		return -EINVAL;
26954 
26955 	fils_info->is_fils_connection = true;
26956 	if (changed & UPDATE_FILS_ERP_INFO) {
26957 		fils_info->username_len = req->fils_erp_username_len +
26958 					    sizeof(char) +
26959 					    req->fils_erp_realm_len;
26960 		if (fils_info->username_len >
26961 		    WLAN_CM_FILS_MAX_KEYNAME_NAI_LENGTH) {
26962 			hdd_err("Key NAI Length %d",
26963 				fils_info->username_len);
26964 			ret = -EINVAL;
26965 			goto free_mem;
26966 		}
26967 		if (req->fils_erp_username_len && req->fils_erp_username) {
26968 			buf = fils_info->username;
26969 			qdf_mem_copy(buf, req->fils_erp_username,
26970 				     req->fils_erp_username_len);
26971 			buf += req->fils_erp_username_len;
26972 			*buf++ = '@';
26973 			qdf_mem_copy(buf, req->fils_erp_realm,
26974 				     req->fils_erp_realm_len);
26975 		}
26976 
26977 		fils_info->next_seq_num = req->fils_erp_next_seq_num + 1;
26978 		fils_info->rrk_len = req->fils_erp_rrk_len;
26979 
26980 		if (fils_info->rrk_len > WLAN_CM_FILS_MAX_RRK_LENGTH) {
26981 			hdd_err("r_rk_length is invalid %d",
26982 				fils_info->rrk_len);
26983 			ret = -EINVAL;
26984 			goto free_mem;
26985 		}
26986 
26987 		if (req->fils_erp_rrk_len && req->fils_erp_rrk)
26988 			qdf_mem_copy(fils_info->rrk, req->fils_erp_rrk,
26989 				     fils_info->rrk_len);
26990 
26991 		fils_info->realm_len = req->fils_erp_realm_len;
26992 		if (fils_info->realm_len > WLAN_CM_FILS_MAX_REALM_LEN) {
26993 			hdd_err("Invalid fils realm len %d",
26994 				fils_info->realm_len);
26995 			ret = -EINVAL;
26996 			goto free_mem;
26997 		}
26998 		if (req->fils_erp_realm_len && req->fils_erp_realm)
26999 			qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
27000 				     fils_info->realm_len);
27001 	}
27002 
27003 	if (changed & UPDATE_FILS_AUTH_TYPE) {
27004 		auth_type = osif_cm_get_fils_auth_type(req->auth_type);
27005 		if (auth_type == FILS_PK_MAX) {
27006 			hdd_err("invalid auth type for fils %d",
27007 				req->auth_type);
27008 			ret = -EINVAL;
27009 			goto free_mem;
27010 		}
27011 
27012 		fils_info->auth_type = auth_type;
27013 	}
27014 
27015 	hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
27016 		  changed, fils_info->is_fils_connection,
27017 		  fils_info->username_len);
27018 	/*
27019 	 * Update the FILS config from adapter->roam_profile to
27020 	 * csr_session
27021 	 */
27022 	status = ucfg_cm_update_fils_config(hdd_ctx->psoc,
27023 					    adapter->deflink->vdev_id,
27024 					    fils_info);
27025 	if (QDF_IS_STATUS_ERROR(status))
27026 		hdd_err("Update FILS connect params failed %d", status);
27027 free_mem:
27028 	qdf_mem_free(fils_info);
27029 
27030 	return ret;
27031 }
27032 #else
27033 static inline int
27034 hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
27035 				    struct hdd_context *hdd_ctx,
27036 				    struct cfg80211_connect_params *req,
27037 				    uint32_t changed)
27038 {
27039 	return -EINVAL;
27040 }
27041 #endif
27042 
27043 #if defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
27044 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
27045 
27046 /**
27047  * __wlan_hdd_cfg80211_update_connect_params - update connect params
27048  * @wiphy: Handle to struct wiphy to get handle to module context.
27049  * @dev: Pointer to network device
27050  * @req: Pointer to connect params
27051  * @changed: Bitmap used to indicate the changed params
27052  *
27053  * Update the connect parameters while connected to a BSS. The updated
27054  * parameters can be used by driver/firmware for subsequent BSS selection
27055  * (roaming) decisions and to form the Authentication/(Re)Association
27056  * Request frames. This call does not request an immediate disassociation
27057  * or reassociation with the current BSS, i.e., this impacts only
27058  * subsequent (re)associations. The bits in changed are defined in enum
27059  * cfg80211_connect_params_changed
27060  *
27061  * Return: zero for success, non-zero for failure
27062  */
27063 static int
27064 __wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
27065 					  struct net_device *dev,
27066 					  struct cfg80211_connect_params *req,
27067 					  uint32_t changed)
27068 {
27069 	int ret;
27070 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
27071 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
27072 	QDF_STATUS status;
27073 	mac_handle_t mac_handle;
27074 	struct element_info assoc_ie;
27075 
27076 	hdd_enter_dev(dev);
27077 
27078 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
27079 		return -EINVAL;
27080 
27081 	ret = wlan_hdd_validate_context(hdd_ctx);
27082 	if (ret)
27083 		return -EINVAL;
27084 
27085 	mac_handle = hdd_ctx->mac_handle;
27086 
27087 	if (changed & UPDATE_ASSOC_IE) {
27088 		assoc_ie.len = req->ie_len;
27089 		assoc_ie.ptr = (uint8_t *)req->ie;
27090 		/*
27091 		 * Update this assoc IE received from user space to
27092 		 * umac. RSO command will pick up the assoc
27093 		 * IEs to be sent to firmware from the umac.
27094 		 */
27095 		ucfg_cm_update_session_assoc_ie(hdd_ctx->psoc,
27096 						adapter->deflink->vdev_id,
27097 						&assoc_ie);
27098 	}
27099 
27100 	if ((changed & UPDATE_FILS_ERP_INFO) ||
27101 	    (changed & UPDATE_FILS_AUTH_TYPE)) {
27102 		ret = hdd_update_connect_params_fils_info(adapter, hdd_ctx,
27103 							  req, changed);
27104 		if (ret)
27105 			return -EINVAL;
27106 
27107 		if (!hdd_ctx->is_fils_roaming_supported) {
27108 			hdd_debug("FILS roaming support %d",
27109 				  hdd_ctx->is_fils_roaming_supported);
27110 			return 0;
27111 		}
27112 	}
27113 
27114 	if (changed) {
27115 		status = sme_send_rso_connect_params(mac_handle,
27116 						     adapter->deflink->vdev_id);
27117 		if (QDF_IS_STATUS_ERROR(status))
27118 			hdd_err("Update connect params to fw failed %d",
27119 				status);
27120 	}
27121 
27122 	return 0;
27123 }
27124 
27125 /**
27126  * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
27127  *                __wlan_hdd_cfg80211_update_connect_params
27128  * @wiphy: Pointer to wiphy structure
27129  * @dev: Pointer to net_device
27130  * @req: Pointer to connect params
27131  * @changed: flags used to indicate the changed params
27132  *
27133  * Return: zero for success, non-zero for failure
27134  */
27135 static int
27136 wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
27137 					struct net_device *dev,
27138 					struct cfg80211_connect_params *req,
27139 					uint32_t changed)
27140 {
27141 	int errno;
27142 	struct osif_vdev_sync *vdev_sync;
27143 
27144 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27145 	if (errno)
27146 		return errno;
27147 
27148 	errno = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
27149 							  req, changed);
27150 
27151 	osif_vdev_sync_op_stop(vdev_sync);
27152 
27153 	return errno;
27154 }
27155 #endif
27156 
27157 #if defined(WLAN_FEATURE_SAE) && \
27158 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
27159 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
27160 #if (defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT) || \
27161 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
27162 /**
27163  * wlan_hdd_extauth_cache_pmkid() - Extract and cache pmkid
27164  * @adapter: hdd vdev/net_device context
27165  * @mac_handle: Handle to the MAC
27166  * @params: Pointer to external auth params.
27167  *
27168  * Extract the PMKID and BSS from external auth params and add to the
27169  * PMKSA Cache in CSR.
27170  */
27171 static void
27172 wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
27173 			     mac_handle_t mac_handle,
27174 			     struct cfg80211_external_auth_params *params)
27175 {
27176 	struct wlan_crypto_pmksa *pmk_cache;
27177 	QDF_STATUS result;
27178 
27179 	if (params->pmkid) {
27180 		pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
27181 		if (!pmk_cache)
27182 			return;
27183 
27184 		qdf_mem_copy(pmk_cache->bssid.bytes, params->bssid,
27185 			     QDF_MAC_ADDR_SIZE);
27186 		qdf_mem_copy(pmk_cache->pmkid, params->pmkid,
27187 			     PMKID_LEN);
27188 		result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
27189 		if (!QDF_IS_STATUS_SUCCESS(result))
27190 			hdd_debug("external_auth: Failed to cache PMKID");
27191 
27192 		qdf_mem_free(pmk_cache);
27193 	}
27194 
27195 }
27196 
27197 /**
27198  * wlan_hdd_extauth_copy_pmkid() - Copy the pmkid received from the
27199  * external authentication command received from the userspace.
27200  * @params: pointer to auth params
27201  * @pmkid: Pointer to destination pmkid buffer to be filled
27202  *
27203  * The caller should ensure that destination pmkid buffer is not NULL.
27204  *
27205  * Return: None
27206  */
27207 static void
27208 wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
27209 			    uint8_t *pmkid)
27210 {
27211 	if (params->pmkid)
27212 		qdf_mem_copy(pmkid, params->pmkid, PMKID_LEN);
27213 }
27214 
27215 #else
27216 static void
27217 wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
27218 			     mac_handle_t mac_handle,
27219 			     struct cfg80211_external_auth_params *params)
27220 {}
27221 
27222 static void
27223 wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
27224 			    uint8_t *pmkid)
27225 {}
27226 #endif
27227 /**
27228  * __wlan_hdd_cfg80211_external_auth() - Handle external auth
27229  *
27230  * @wiphy: Pointer to wireless phy
27231  * @dev: net device
27232  * @params: Pointer to external auth params.
27233  * Return: 0 on success, negative errno on failure
27234  *
27235  * Userspace sends status of the external authentication(e.g., SAE) with a peer.
27236  * The message carries BSSID of the peer and auth status (WLAN_STATUS_SUCCESS/
27237  * WLAN_STATUS_UNSPECIFIED_FAILURE) in params.
27238  * Userspace may send PMKID in params, which can be used for
27239  * further connections.
27240  */
27241 static int
27242 __wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
27243 				  struct net_device *dev,
27244 				  struct cfg80211_external_auth_params *params)
27245 {
27246 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
27247 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
27248 	int ret;
27249 	mac_handle_t mac_handle;
27250 	struct qdf_mac_addr peer_mac_addr;
27251 	uint8_t pmkid[PMKID_LEN] = {0};
27252 
27253 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
27254 		hdd_err("Command not allowed in FTM mode");
27255 		return -EPERM;
27256 	}
27257 
27258 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
27259 		return -EINVAL;
27260 
27261 	ret = wlan_hdd_validate_context(hdd_ctx);
27262 	if (ret)
27263 		return ret;
27264 
27265 	hdd_debug("external_auth status: %d peer mac: " QDF_MAC_ADDR_FMT,
27266 		  params->status, QDF_MAC_ADDR_REF(params->bssid));
27267 	mac_handle = hdd_ctx->mac_handle;
27268 	qdf_mem_copy(peer_mac_addr.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
27269 
27270 	wlan_hdd_extauth_cache_pmkid(adapter, mac_handle, params);
27271 
27272 	wlan_hdd_extauth_copy_pmkid(params, pmkid);
27273 	sme_handle_sae_msg(mac_handle, adapter->deflink->vdev_id,
27274 			   params->status, peer_mac_addr, pmkid);
27275 
27276 	return ret;
27277 }
27278 
27279 /**
27280  * wlan_hdd_cfg80211_external_auth() - Handle external auth
27281  * @wiphy: Pointer to wireless phy
27282  * @dev: net device
27283  * @params: Pointer to external auth params
27284  *
27285  * Return: 0 on success, negative errno on failure
27286  */
27287 static int
27288 wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
27289 				struct net_device *dev,
27290 				struct cfg80211_external_auth_params *params)
27291 {
27292 	int errno;
27293 	struct osif_vdev_sync *vdev_sync;
27294 
27295 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27296 	if (errno)
27297 		return errno;
27298 
27299 	errno = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
27300 
27301 	osif_vdev_sync_op_stop(vdev_sync);
27302 
27303 	return errno;
27304 }
27305 #endif
27306 
27307 #if defined(WLAN_FEATURE_NAN) && \
27308 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
27309 static int
27310 wlan_hdd_cfg80211_start_nan(struct wiphy *wiphy, struct wireless_dev *wdev,
27311 			    struct cfg80211_nan_conf *conf)
27312 {
27313 	return -EOPNOTSUPP;
27314 }
27315 
27316 static void
27317 wlan_hdd_cfg80211_stop_nan(struct wiphy *wiphy, struct wireless_dev *wdev)
27318 {
27319 }
27320 
27321 static int wlan_hdd_cfg80211_add_nan_func(struct wiphy *wiphy,
27322 					  struct wireless_dev *wdev,
27323 					  struct cfg80211_nan_func *nan_func)
27324 {
27325 	return -EOPNOTSUPP;
27326 }
27327 
27328 static void wlan_hdd_cfg80211_del_nan_func(struct wiphy *wiphy,
27329 					   struct wireless_dev *wdev,
27330 					   u64 cookie)
27331 {
27332 }
27333 
27334 static int wlan_hdd_cfg80211_nan_change_conf(struct wiphy *wiphy,
27335 					     struct wireless_dev *wdev,
27336 					     struct cfg80211_nan_conf *conf,
27337 					     u32 changes)
27338 {
27339 	return -EOPNOTSUPP;
27340 }
27341 #endif
27342 
27343 /**
27344  * wlan_hdd_get_ch_width_from_chan_info - get ch_width as per num channel
27345  * present in scan event
27346  * @info: struct scan_chan_info
27347  *
27348  * Return: phy_ch_width.
27349  */
27350 static enum phy_ch_width
27351 wlan_hdd_get_ch_width_from_chan_info(struct scan_chan_info *info)
27352 {
27353 	enum phy_ch_width scanned_ch_width;
27354 
27355 	switch (info->subband_info.num_chan) {
27356 	case 1:
27357 		scanned_ch_width = CH_WIDTH_20MHZ;
27358 		break;
27359 	case 2:
27360 		scanned_ch_width = CH_WIDTH_40MHZ;
27361 		break;
27362 	case 4:
27363 		scanned_ch_width = CH_WIDTH_80MHZ;
27364 		break;
27365 	case 8:
27366 		scanned_ch_width = CH_WIDTH_160MHZ;
27367 		break;
27368 	default:
27369 		scanned_ch_width = CH_WIDTH_INVALID;
27370 		break;
27371 	}
27372 
27373 	return scanned_ch_width;
27374 }
27375 
27376 /**
27377  * wlan_hdd_fill_subband_scan_info - Fill subband channel info
27378  * @hdd_ctx: hdd context
27379  * @info: struct scan_chan_info
27380  * @chan: scan channel info
27381  *
27382  * update channel info into HDD context on scan done
27383  *
27384  * Return: None.
27385  */
27386 static void wlan_hdd_fill_subband_scan_info(struct hdd_context *hdd_ctx,
27387 					    struct scan_chan_info *info,
27388 					    struct scan_chan_info *chan)
27389 {
27390 	uint8_t idx, info_index, freq_info_num;
27391 	enum phy_ch_width scanned_ch_width;
27392 	const struct bonded_channel_freq *range = NULL;
27393 	qdf_freq_t start_freq, end_freq, sec_2g_freq;
27394 	uint8_t vdev_id = info->subband_info.vdev_id;
27395 	struct assoc_channel_info assoc_chan_info;
27396 
27397 	scanned_ch_width = wlan_hdd_get_ch_width_from_chan_info(info);
27398 	if (scanned_ch_width == CH_WIDTH_INVALID) {
27399 		hdd_debug("vdev %d: Invalid scanned_ch_width", vdev_id);
27400 		return;
27401 	}
27402 
27403 	if (scanned_ch_width == CH_WIDTH_20MHZ) {
27404 		start_freq = info->freq;
27405 		end_freq = info->freq;
27406 	} else if (wlan_reg_is_24ghz_ch_freq(info->freq) &&
27407 		   scanned_ch_width == CH_WIDTH_40MHZ) {
27408 		ucfg_cm_get_associated_ch_info(hdd_ctx->psoc, vdev_id,
27409 					       scanned_ch_width,
27410 					       &assoc_chan_info);
27411 		sec_2g_freq = assoc_chan_info.sec_2g_freq;
27412 		if (!sec_2g_freq) {
27413 			mlme_debug("vdev %d : Invalid sec 2g freq for freq:%d",
27414 				   info->subband_info.vdev_id, info->freq);
27415 			return;
27416 		}
27417 
27418 		hdd_debug("vdev %d :assoc freq %d sec_2g_freq:%d, bw %d",
27419 			  info->subband_info.vdev_id, info->freq,
27420 			  sec_2g_freq, scanned_ch_width);
27421 		if (info->freq > sec_2g_freq) {
27422 			start_freq = sec_2g_freq;
27423 			end_freq = info->freq;
27424 		} else {
27425 			start_freq = info->freq;
27426 			end_freq = sec_2g_freq;
27427 		}
27428 	} else {
27429 		range = wlan_reg_get_bonded_chan_entry(info->freq,
27430 						       scanned_ch_width, 0);
27431 		if (!range) {
27432 			hdd_err("vdev %d: bonded_chan_array is NULL for freq %d, ch_width %d",
27433 				vdev_id, info->freq, scanned_ch_width);
27434 			return;
27435 		}
27436 		start_freq = range->start_freq;
27437 		end_freq = range->end_freq;
27438 	}
27439 
27440 	freq_info_num = info->subband_info.num_chan;
27441 	info_index = 0;
27442 
27443 	hdd_debug("vdev %d: freq :%d bw %d, range [%d-%d], num_freq:%d",
27444 		  vdev_id, info->freq, scanned_ch_width, start_freq,
27445 		  end_freq, freq_info_num);
27446 
27447 	for (idx = 0; idx < NUM_CHANNELS; idx++) {
27448 		if (chan[idx].freq == 0)
27449 			continue;
27450 
27451 		if (start_freq > end_freq || info_index >= freq_info_num ||
27452 		    info_index >= MAX_WIDE_BAND_SCAN_CHAN)
27453 			break;
27454 
27455 		if (chan[idx].freq == start_freq) {
27456 			/*update channel info as per cca busy info */
27457 			info->freq = start_freq;
27458 			info->rx_clear_count =
27459 			   info->subband_info.cca_busy_subband_info[info_index];
27460 
27461 			hdd_update_chan_info(hdd_ctx, &chan[idx], info,
27462 					     info->cmd_flag);
27463 
27464 			hdd_debug("updated info for freq:%u rcc:%d at index:%d",
27465 				  chan[idx].freq, chan[idx].rx_clear_count,
27466 				  idx);
27467 			start_freq += BW_20_MHZ;
27468 			info_index++;
27469 		}
27470 	}
27471 }
27472 
27473 /**
27474  * wlan_hdd_chan_info_cb() - channel info callback
27475  * @info: struct scan_chan_info
27476  *
27477  * Store channel info into HDD context
27478  *
27479  * Return: None.
27480  */
27481 static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
27482 {
27483 	struct hdd_context *hdd_ctx;
27484 	struct scan_chan_info *chan;
27485 	uint8_t idx;
27486 
27487 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
27488 	if (wlan_hdd_validate_context(hdd_ctx) != 0)
27489 		return;
27490 
27491 	if (!hdd_ctx->chan_info) {
27492 		hdd_err("chan_info is NULL");
27493 		return;
27494 	}
27495 
27496 	chan = hdd_ctx->chan_info;
27497 
27498 	if (info->subband_info.is_wide_band_scan) {
27499 		wlan_hdd_fill_subband_scan_info(hdd_ctx, info, chan);
27500 		return;
27501 	}
27502 
27503 	for (idx = 0; idx < NUM_CHANNELS; idx++) {
27504 		if (chan[idx].freq == info->freq) {
27505 			hdd_update_chan_info(hdd_ctx, &chan[idx], info,
27506 				info->cmd_flag);
27507 			hdd_debug("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
27508 				  chan[idx].cmd_flag, chan[idx].freq,
27509 				  chan[idx].noise_floor,
27510 				  chan[idx].cycle_count,
27511 				  chan[idx].rx_clear_count,
27512 				  chan[idx].clock_freq, chan[idx].cmd_flag,
27513 				  chan[idx].tx_frame_count, idx);
27514 			if (chan[idx].freq == 0)
27515 				break;
27516 
27517 		}
27518 	}
27519 }
27520 
27521 /**
27522  * wlan_hdd_init_chan_info() - init chan info in hdd context
27523  * @hdd_ctx: HDD context pointer
27524  *
27525  * Return: none
27526  */
27527 void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
27528 {
27529 	uint32_t num_2g, num_5g, index = 0;
27530 	mac_handle_t mac_handle;
27531 
27532 	hdd_ctx->chan_info = NULL;
27533 	if (!ucfg_scan_is_snr_monitor_enabled(hdd_ctx->psoc)) {
27534 		hdd_debug("SNR monitoring is disabled");
27535 		return;
27536 	}
27537 
27538 	hdd_ctx->chan_info =
27539 		qdf_mem_malloc(sizeof(struct scan_chan_info)
27540 					* NUM_CHANNELS);
27541 	if (!hdd_ctx->chan_info)
27542 		return;
27543 	mutex_init(&hdd_ctx->chan_info_lock);
27544 
27545 	num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
27546 	for (; index < num_2g; index++) {
27547 		hdd_ctx->chan_info[index].freq =
27548 			hdd_channels_2_4_ghz[index].center_freq;
27549 	}
27550 
27551 	num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
27552 	for (; (index - num_2g) < num_5g; index++)
27553 		hdd_ctx->chan_info[index].freq =
27554 			hdd_channels_5_ghz[index - num_2g].center_freq;
27555 
27556 	index = num_2g + num_5g;
27557 	index += wlan_hdd_populate_5dot9_chan_info(hdd_ctx, index);
27558 	index += wlan_hdd_populate_6g_chan_info(hdd_ctx, index);
27559 	hdd_debug("Number of channels populated : %d", index);
27560 
27561 	mac_handle = hdd_ctx->mac_handle;
27562 	sme_set_chan_info_callback(mac_handle, &wlan_hdd_chan_info_cb);
27563 }
27564 
27565 /**
27566  * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
27567  * @hdd_ctx: hdd context pointer
27568  *
27569  * Return: none
27570  */
27571 void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
27572 {
27573 	struct scan_chan_info *chan;
27574 
27575 	chan = hdd_ctx->chan_info;
27576 	hdd_ctx->chan_info = NULL;
27577 	if (chan)
27578 		qdf_mem_free(chan);
27579 }
27580 
27581 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) || defined(CFG80211_11BE_BASIC)
27582 #define SET_RATE_INFO_BW_320 RATE_INFO_BW_320
27583 #else
27584 #define SET_RATE_INFO_BW_320 RATE_INFO_BW_160
27585 #endif
27586 
27587 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
27588 static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
27589 {
27590 	switch (hdd_bw) {
27591 	case HDD_RATE_BW_5:
27592 		return RATE_INFO_BW_5;
27593 	case HDD_RATE_BW_10:
27594 		return RATE_INFO_BW_10;
27595 	case HDD_RATE_BW_20:
27596 		return RATE_INFO_BW_20;
27597 	case HDD_RATE_BW_40:
27598 		return RATE_INFO_BW_40;
27599 	case HDD_RATE_BW_80:
27600 		return RATE_INFO_BW_80;
27601 	case HDD_RATE_BW_160:
27602 		return RATE_INFO_BW_160;
27603 	case HDD_RATE_BW_320:
27604 		return SET_RATE_INFO_BW_320;
27605 	}
27606 
27607 	hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
27608 
27609 	return RATE_INFO_BW_20;
27610 }
27611 
27612 void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
27613 {
27614 	info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
27615 }
27616 #else
27617 static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
27618 {
27619 	switch (hdd_bw) {
27620 	case HDD_RATE_BW_5:
27621 	case HDD_RATE_BW_10:
27622 	case HDD_RATE_BW_20:
27623 		return (enum rate_info_flags)0;
27624 	case HDD_RATE_BW_40:
27625 		return RATE_INFO_FLAGS_40_MHZ_WIDTH;
27626 	case HDD_RATE_BW_80:
27627 		return RATE_INFO_FLAGS_80_MHZ_WIDTH;
27628 	case HDD_RATE_BW_160:
27629 		return RATE_INFO_FLAGS_160_MHZ_WIDTH;
27630 	}
27631 
27632 	hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
27633 
27634 	return (enum rate_info_flags)0;
27635 }
27636 
27637 void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
27638 {
27639 	const enum rate_info_flags all_bws =
27640 		RATE_INFO_FLAGS_40_MHZ_WIDTH |
27641 		RATE_INFO_FLAGS_80_MHZ_WIDTH |
27642 		RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
27643 		RATE_INFO_FLAGS_160_MHZ_WIDTH;
27644 
27645 	info->flags &= ~all_bws;
27646 	info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
27647 }
27648 #endif
27649 
27650 #if defined(CFG80211_EXTERNAL_DH_UPDATE_SUPPORT) || \
27651 (LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0))
27652 
27653 #ifdef WLAN_MLD_AP_OWE_INFO_SUPPORT
27654 static void
27655 hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter *adapter,
27656 			    struct cfg80211_update_owe_info *owe_info,
27657 			    uint8_t *peer_mac)
27658 {
27659 	bool is_mlo_vdev;
27660 	struct wlan_objmgr_peer *peer;
27661 	struct wlan_objmgr_vdev *vdev;
27662 	uint8_t *peer_mld_addr;
27663 
27664 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
27665 	if (!vdev)
27666 		return;
27667 
27668 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
27669 	if (is_mlo_vdev)
27670 		owe_info->link_id = wlan_vdev_get_link_id(vdev);
27671 	else
27672 		owe_info->link_id = -1;
27673 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
27674 
27675 	if (!is_mlo_vdev)
27676 		return;
27677 
27678 	peer = wlan_objmgr_get_peer_by_mac(adapter->hdd_ctx->psoc,
27679 					   peer_mac, WLAN_OSIF_ID);
27680 	if (!peer) {
27681 		hdd_err("Peer not found with MAC " QDF_MAC_ADDR_FMT,
27682 			QDF_MAC_ADDR_REF(peer_mac));
27683 		return;
27684 	}
27685 
27686 	peer_mld_addr = wlan_peer_mlme_get_mldaddr(peer);
27687 	qdf_mem_copy(&owe_info->peer_mld_addr[0], peer_mld_addr, ETH_ALEN);
27688 	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
27689 }
27690 #elif defined(CFG80211_MLD_AP_STA_CONNECT_UPSTREAM_SUPPORT)
27691 static void
27692 hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter *adapter,
27693 			    struct cfg80211_update_owe_info *owe_info,
27694 			    uint8_t *peer_mac)
27695 {
27696 	bool is_mlo_vdev;
27697 	struct wlan_objmgr_peer *peer;
27698 	struct wlan_objmgr_vdev *vdev;
27699 	uint8_t *peer_mld_addr;
27700 
27701 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
27702 					   WLAN_HDD_ID_OBJ_MGR);
27703 	if (!vdev)
27704 		return;
27705 
27706 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
27707 	if (!is_mlo_vdev) {
27708 		owe_info->assoc_link_id = -1;
27709 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
27710 		return;
27711 	}
27712 
27713 	owe_info->assoc_link_id = wlan_vdev_get_link_id(vdev);
27714 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
27715 
27716 	peer = wlan_objmgr_get_peer_by_mac(adapter->hdd_ctx->psoc,
27717 					   peer_mac, WLAN_HDD_ID_OBJ_MGR);
27718 	if (!peer) {
27719 		hdd_err("Peer not found with MAC " QDF_MAC_ADDR_FMT,
27720 			QDF_MAC_ADDR_REF(peer_mac));
27721 		return;
27722 	}
27723 
27724 	peer_mld_addr = wlan_peer_mlme_get_mldaddr(peer);
27725 	qdf_mem_copy(&owe_info->peer_mld_addr[0], peer_mld_addr, ETH_ALEN);
27726 	wlan_objmgr_peer_release_ref(peer, WLAN_HDD_ID_OBJ_MGR);
27727 }
27728 #else
27729 static void
27730 hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter *adapter,
27731 			    struct cfg80211_update_owe_info *owe_info,
27732 			    uint8_t *peer_mac)
27733 {
27734 }
27735 #endif
27736 
27737 void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
27738 				    uint8_t sta_addr[],
27739 				    uint8_t *owe_ie,
27740 				    uint32_t owe_ie_len)
27741 {
27742 	struct cfg80211_update_owe_info owe_info;
27743 	struct net_device *dev = adapter->dev;
27744 
27745 	hdd_enter_dev(dev);
27746 
27747 	qdf_mem_zero(&owe_info, sizeof(owe_info));
27748 	qdf_mem_copy(owe_info.peer, sta_addr, ETH_ALEN);
27749 	hdd_ml_sap_owe_fill_ml_info(adapter, &owe_info, sta_addr);
27750 	owe_info.ie = owe_ie;
27751 	owe_info.ie_len = owe_ie_len;
27752 
27753 	cfg80211_update_owe_info_event(dev, &owe_info, GFP_KERNEL);
27754 
27755 	hdd_exit();
27756 }
27757 #endif
27758 
27759 #define MAX_PDEV_TXRX_PARAMS 2
27760 /* params being sent:
27761  * 1.wmi_pdev_param_tx_chain_mask
27762  * 2.wmi_pdev_param_rx_chain_mask
27763  */
27764 static int __wlan_hdd_cfg80211_set_chainmask(struct wiphy *wiphy,
27765 					     uint32_t tx_mask,
27766 					     uint32_t rx_mask)
27767 {
27768 	int ret;
27769 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
27770 	enum hdd_chain_mode chains;
27771 	struct dev_set_param setparam[MAX_PDEV_TXRX_PARAMS] = {};
27772 	uint8_t index = 0;
27773 
27774 	ret = wlan_hdd_validate_context(hdd_ctx);
27775 	if (ret)
27776 		return -EINVAL;
27777 
27778 	if (hdd_ctx->num_rf_chains != HDD_ANTENNA_MODE_2X2 ||
27779 	    !ucfg_mlme_is_chain_mask_supported(hdd_ctx->psoc)) {
27780 		hdd_info_rl("Chainmask can't be configured, num of rf chain %d",
27781 			    hdd_ctx->num_rf_chains);
27782 		return -ENOTSUPP;
27783 	}
27784 	chains = HDD_CHAIN_MODE_2X2;
27785 	if (!tx_mask || tx_mask > chains || !rx_mask || rx_mask > chains) {
27786 		hdd_err_rl("Invalid masks. txMask: %d rxMask: %d num_rf_chains: %d",
27787 			   tx_mask, rx_mask, hdd_ctx->num_rf_chains);
27788 
27789 		return -EINVAL;
27790 	}
27791 
27792 	if (sme_validate_txrx_chain_mask(wmi_pdev_param_tx_chain_mask, tx_mask))
27793 		return -EINVAL;
27794 
27795 	ret = mlme_check_index_setparam(
27796 				setparam, wmi_pdev_param_tx_chain_mask,
27797 				tx_mask, index++, MAX_PDEV_TXRX_PARAMS);
27798 	if (QDF_IS_STATUS_ERROR(ret)) {
27799 		hdd_err("failed at wmi_pdev_param_tx_chain_mask");
27800 		return -EINVAL;
27801 	}
27802 
27803 	if (sme_validate_txrx_chain_mask(wmi_pdev_param_rx_chain_mask, rx_mask))
27804 		return -EINVAL;
27805 
27806 	ret = mlme_check_index_setparam(
27807 				setparam, wmi_pdev_param_rx_chain_mask,
27808 				rx_mask, index++, MAX_PDEV_TXRX_PARAMS);
27809 	if (QDF_IS_STATUS_ERROR(ret)) {
27810 		hdd_err("failed at wmi_pdev_param_rx_chain_mask");
27811 		return -EINVAL;
27812 	}
27813 
27814 	ret = wma_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
27815 						  WMI_PDEV_ID_SOC, setparam,
27816 						  index);
27817 	if (QDF_IS_STATUS_ERROR(ret))
27818 		hdd_err("failed to send TX, RX chain mask params");
27819 
27820 	return ret;
27821 }
27822 
27823 static int wlan_hdd_cfg80211_set_chainmask(struct wiphy *wiphy,
27824 					   uint32_t tx_mask,
27825 					   uint32_t rx_mask)
27826 {
27827 	struct osif_psoc_sync *psoc_sync;
27828 	int errno;
27829 
27830 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
27831 	if (errno)
27832 		return errno;
27833 
27834 	errno = __wlan_hdd_cfg80211_set_chainmask(wiphy, tx_mask, rx_mask);
27835 	osif_psoc_sync_op_stop(psoc_sync);
27836 
27837 	return errno;
27838 }
27839 
27840 static int __wlan_hdd_cfg80211_get_chainmask(struct wiphy *wiphy,
27841 					     uint32_t *tx_mask,
27842 					     uint32_t *rx_mask)
27843 
27844 {
27845 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
27846 	int ret;
27847 
27848 	ret = wlan_hdd_validate_context(hdd_ctx);
27849 	if (ret)
27850 		return -EINVAL;
27851 
27852 	*tx_mask = wma_cli_get_command(0, wmi_pdev_param_tx_chain_mask,
27853 				       PDEV_CMD);
27854 	*rx_mask = wma_cli_get_command(0, wmi_pdev_param_rx_chain_mask,
27855 				       PDEV_CMD);
27856 
27857 	/* if 0 return max value as 0 mean no set cmnd received yet */
27858 	if (!*tx_mask)
27859 		*tx_mask = hdd_ctx->num_rf_chains == HDD_ANTENNA_MODE_2X2 ?
27860 				HDD_CHAIN_MODE_2X2 : HDD_CHAIN_MODE_1X1;
27861 	if (!*rx_mask)
27862 		*rx_mask = hdd_ctx->num_rf_chains == HDD_ANTENNA_MODE_2X2 ?
27863 				HDD_CHAIN_MODE_2X2 : HDD_CHAIN_MODE_1X1;
27864 	hdd_debug("tx_mask: %d rx_mask: %d", *tx_mask, *rx_mask);
27865 
27866 	return 0;
27867 }
27868 
27869 static int wlan_hdd_cfg80211_get_chainmask(struct wiphy *wiphy,
27870 					   uint32_t *tx_mask,
27871 					   uint32_t *rx_mask)
27872 {
27873 	struct osif_psoc_sync *psoc_sync;
27874 	int errno;
27875 
27876 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
27877 	if (errno)
27878 		return errno;
27879 
27880 	errno = __wlan_hdd_cfg80211_get_chainmask(wiphy, tx_mask, rx_mask);
27881 	osif_psoc_sync_op_stop(psoc_sync);
27882 
27883 	return errno;
27884 }
27885 
27886 enum qca_wlan_802_11_mode
27887 hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode)
27888 {
27889 	switch (mode) {
27890 	case eCSR_CFG_DOT11_MODE_11A:
27891 		return QCA_WLAN_802_11_MODE_11A;
27892 	case eCSR_CFG_DOT11_MODE_11B:
27893 		return QCA_WLAN_802_11_MODE_11B;
27894 	case eCSR_CFG_DOT11_MODE_11G:
27895 		return QCA_WLAN_802_11_MODE_11G;
27896 	case eCSR_CFG_DOT11_MODE_11N:
27897 		return QCA_WLAN_802_11_MODE_11N;
27898 	case eCSR_CFG_DOT11_MODE_11AC:
27899 		return QCA_WLAN_802_11_MODE_11AC;
27900 	case eCSR_CFG_DOT11_MODE_11G_ONLY:
27901 		return QCA_WLAN_802_11_MODE_11G;
27902 	case eCSR_CFG_DOT11_MODE_11N_ONLY:
27903 		return QCA_WLAN_802_11_MODE_11N;
27904 	case eCSR_CFG_DOT11_MODE_11AC_ONLY:
27905 		return QCA_WLAN_802_11_MODE_11AC;
27906 	case eCSR_CFG_DOT11_MODE_11AX:
27907 		return QCA_WLAN_802_11_MODE_11AX;
27908 	case eCSR_CFG_DOT11_MODE_11AX_ONLY:
27909 		return QCA_WLAN_802_11_MODE_11AX;
27910 	case eCSR_CFG_DOT11_MODE_11BE:
27911 	case eCSR_CFG_DOT11_MODE_11BE_ONLY:
27912 		return QCA_WLAN_802_11_MODE_11BE;
27913 	case eCSR_CFG_DOT11_MODE_ABG:
27914 	case eCSR_CFG_DOT11_MODE_AUTO:
27915 	default:
27916 		return QCA_WLAN_802_11_MODE_INVALID;
27917 	}
27918 }
27919 
27920 bool hdd_is_legacy_connection(struct wlan_hdd_link_info *link_info)
27921 {
27922 	struct hdd_station_ctx *sta_ctx;
27923 	int connection_mode = QCA_WLAN_802_11_MODE_INVALID;
27924 	enum csr_cfgdot11mode cfgmode;
27925 	uint16_t tdls_connected_peer;
27926 
27927 	tdls_connected_peer = hdd_get_tdls_connected_peer_count(link_info);
27928 	if (tdls_connected_peer)
27929 		return false;
27930 
27931 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
27932 	cfgmode = sta_ctx->conn_info.dot11mode;
27933 	connection_mode = hdd_convert_cfgdot11mode_to_80211mode(cfgmode);
27934 	if (connection_mode == QCA_WLAN_802_11_MODE_11A ||
27935 	    connection_mode == QCA_WLAN_802_11_MODE_11B ||
27936 	    connection_mode == QCA_WLAN_802_11_MODE_11G)
27937 		return true;
27938 	else
27939 		return false;
27940 }
27941 
27942 static int __wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
27943 					   struct wireless_dev *wdev,
27944 					   struct cfg80211_chan_def *chandef,
27945 					   int link_id)
27946 {
27947 	struct net_device *dev = wdev->netdev;
27948 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
27949 	struct hdd_context *hdd_ctx;
27950 	bool is_legacy_phymode = false;
27951 	struct wlan_objmgr_vdev *vdev;
27952 	uint32_t chan_freq;
27953 	struct wlan_hdd_link_info *link_info;
27954 	uint8_t vdev_id;
27955 	enum phy_ch_width ch_width;
27956 	enum wlan_phymode peer_phymode;
27957 	struct hdd_station_ctx *sta_ctx;
27958 	struct ch_params ch_params = {0};
27959 
27960 	hdd_enter_dev(wdev->netdev);
27961 
27962 	if (hdd_validate_adapter(adapter))
27963 		return -EINVAL;
27964 
27965 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
27966 	if (wlan_hdd_validate_context(hdd_ctx))
27967 		return -EINVAL;
27968 
27969 	if ((adapter->device_mode == QDF_STA_MODE) ||
27970 	    (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
27971 
27972 		if (!hdd_cm_is_vdev_associated(adapter->deflink))
27973 			return -EINVAL;
27974 
27975 		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
27976 		if (sta_ctx->conn_info.dot11mode < eCSR_CFG_DOT11_MODE_11N)
27977 			is_legacy_phymode = true;
27978 
27979 	} else if ((adapter->device_mode == QDF_SAP_MODE) ||
27980 			(adapter->device_mode == QDF_P2P_GO_MODE)) {
27981 		struct hdd_ap_ctx *ap_ctx;
27982 
27983 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
27984 
27985 		if (!test_bit(SOFTAP_BSS_STARTED,
27986 			      &adapter->deflink->link_flags))
27987 			return -EINVAL;
27988 
27989 		switch (ap_ctx->sap_config.SapHw_mode) {
27990 		case eCSR_DOT11_MODE_11n:
27991 		case eCSR_DOT11_MODE_11n_ONLY:
27992 		case eCSR_DOT11_MODE_11ac:
27993 		case eCSR_DOT11_MODE_11ac_ONLY:
27994 		case eCSR_DOT11_MODE_11ax:
27995 		case eCSR_DOT11_MODE_11ax_ONLY:
27996 			is_legacy_phymode = false;
27997 			break;
27998 		default:
27999 			is_legacy_phymode = true;
28000 			break;
28001 		}
28002 	} else {
28003 		return -EINVAL;
28004 	}
28005 
28006 	vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
28007 	if (!vdev)
28008 		return -EINVAL;
28009 
28010 	if (adapter->device_mode == QDF_STA_MODE) {
28011 		vdev_id = wlan_vdev_get_id(vdev);
28012 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
28013 		if (!link_info || !hdd_cm_is_vdev_associated(link_info)) {
28014 			wlan_key_put_link_vdev(vdev, WLAN_OSIF_ID);
28015 			return -EBUSY;
28016 		}
28017 		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
28018 	}
28019 
28020 	chan_freq = vdev->vdev_mlme.des_chan->ch_freq;
28021 	chandef->center_freq1 = vdev->vdev_mlme.des_chan->ch_cfreq1;
28022 	chandef->center_freq2 = 0;
28023 	chandef->chan = ieee80211_get_channel(wiphy, chan_freq);
28024 
28025 	ch_width = vdev->vdev_mlme.des_chan->ch_width;
28026 	if (adapter->device_mode == QDF_STA_MODE ||
28027 	    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
28028 		/* For STA/P2P CLI get the peer pymode as, in some IOT
28029 		 * cases VDEV BW will not be same as peer BW
28030 		 */
28031 		mlme_get_peer_phymode(hdd_ctx->psoc,
28032 				      sta_ctx->conn_info.bssid.bytes,
28033 				      &peer_phymode);
28034 		ch_width = wlan_mlme_get_ch_width_from_phymode(peer_phymode);
28035 	}
28036 
28037 	ch_params.ch_width = ch_width;
28038 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
28039 						chan_freq, 0, &ch_params,
28040 						REG_CURRENT_PWR_MODE);
28041 	chandef->center_freq1 = ch_params.mhz_freq_seg0;
28042 
28043 	switch (ch_width) {
28044 	case CH_WIDTH_20MHZ:
28045 		if (is_legacy_phymode)
28046 			chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
28047 		else
28048 			chandef->width = NL80211_CHAN_WIDTH_20;
28049 		break;
28050 	case CH_WIDTH_40MHZ:
28051 		chandef->width = NL80211_CHAN_WIDTH_40;
28052 		break;
28053 	case CH_WIDTH_80MHZ:
28054 		chandef->width = NL80211_CHAN_WIDTH_80;
28055 		break;
28056 	case CH_WIDTH_160MHZ:
28057 		chandef->width = NL80211_CHAN_WIDTH_160;
28058 		/* Set center_freq1 to center frequency of complete 160MHz */
28059 		chandef->center_freq1 = vdev->vdev_mlme.des_chan->ch_cfreq2;
28060 		break;
28061 	case CH_WIDTH_80P80MHZ:
28062 		chandef->width = NL80211_CHAN_WIDTH_80P80;
28063 		chandef->center_freq2 = vdev->vdev_mlme.des_chan->ch_cfreq2;
28064 		break;
28065 	case CH_WIDTH_5MHZ:
28066 		chandef->width = NL80211_CHAN_WIDTH_5;
28067 		break;
28068 	case CH_WIDTH_10MHZ:
28069 		chandef->width = NL80211_CHAN_WIDTH_10;
28070 		break;
28071 	default:
28072 		chandef->width = NL80211_CHAN_WIDTH_20;
28073 		break;
28074 	}
28075 
28076 	wlan_hdd_set_chandef(vdev, chandef);
28077 
28078 	wlan_key_put_link_vdev(vdev, WLAN_OSIF_ID);
28079 
28080 	hdd_debug("primary_freq:%d, ch_width:%d, center_freq1:%d, center_freq2:%d",
28081 		  chan_freq, chandef->width, chandef->center_freq1,
28082 		  chandef->center_freq2);
28083 	return 0;
28084 }
28085 
28086 /**
28087  * wlan_hdd_cfg80211_get_channel() - API to process cfg80211 get_channel request
28088  * @wiphy: Pointer to wiphy
28089  * @wdev: Pointer to wireless device
28090  * @link_id: Channel link ID
28091  * @chandef: Pointer to channel definition
28092  *
28093  * Return: 0 for success, non zero for failure
28094  */
28095 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
28096 static int wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
28097 					 struct wireless_dev *wdev,
28098 					 unsigned int link_id,
28099 					 struct cfg80211_chan_def *chandef)
28100 {
28101 	int errno;
28102 	struct osif_vdev_sync *vdev_sync;
28103 
28104 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
28105 	if (errno)
28106 		return errno;
28107 
28108 	errno = __wlan_hdd_cfg80211_get_channel(wiphy, wdev, chandef, link_id);
28109 
28110 	osif_vdev_sync_op_stop(vdev_sync);
28111 
28112 	return errno;
28113 }
28114 #else
28115 static int wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
28116 					 struct wireless_dev *wdev,
28117 					 struct cfg80211_chan_def *chandef)
28118 {
28119 	int errno;
28120 	struct osif_vdev_sync *vdev_sync;
28121 	/* Legacy purposes */
28122 	int link_id = -1;
28123 
28124 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
28125 	if (errno)
28126 		return errno;
28127 
28128 	errno = __wlan_hdd_cfg80211_get_channel(wiphy, wdev, chandef, link_id);
28129 
28130 	osif_vdev_sync_op_stop(vdev_sync);
28131 
28132 	return errno;
28133 }
28134 #endif
28135 
28136 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
28137 static int
28138 hdd_check_he_bitmask_for_single_rate(enum nl80211_band band,
28139 				     const struct cfg80211_bitrate_mask *mask)
28140 {
28141 	int he_rates = 0, i;
28142 
28143 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].he_mcs); i++)
28144 		he_rates += qdf_get_hweight16(mask->control[band].he_mcs[i]);
28145 
28146 	return he_rates;
28147 }
28148 
28149 static void
28150 hdd_get_he_bitrate_params_for_band(enum nl80211_band band,
28151 				   const struct cfg80211_bitrate_mask *mask,
28152 				   uint8_t *nss, uint8_t *rate_index,
28153 				   int *bit_rate)
28154 {
28155 	int i;
28156 
28157 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].he_mcs); i++) {
28158 		if (qdf_get_hweight16(mask->control[band].he_mcs[i]) == 1) {
28159 			*nss = i;
28160 			*rate_index = (ffs(mask->control[band].he_mcs[i]) - 1);
28161 			*bit_rate = hdd_assemble_rate_code(WMI_RATE_PREAMBLE_HE,
28162 							   *nss, *rate_index);
28163 			break;
28164 		}
28165 	}
28166 }
28167 #else
28168 static inline int
28169 hdd_check_he_bitmask_for_single_rate(enum nl80211_band band,
28170 				     const struct cfg80211_bitrate_mask *mask)
28171 {
28172 	return 0;
28173 }
28174 
28175 static inline void
28176 hdd_get_he_bitrate_params_for_band(enum nl80211_band band,
28177 				   const struct cfg80211_bitrate_mask *mask,
28178 				   uint8_t *nss, uint8_t *rate_index,
28179 				   int *bit_rate)
28180 
28181 {
28182 }
28183 #endif
28184 
28185 static bool hdd_check_bitmask_for_single_rate(enum nl80211_band band,
28186 				const struct cfg80211_bitrate_mask *mask)
28187 {
28188 	int num_rates = 0, i;
28189 
28190 	num_rates += qdf_get_hweight32(mask->control[band].legacy);
28191 
28192 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].ht_mcs); i++)
28193 		num_rates += qdf_get_hweight8(mask->control[band].ht_mcs[i]);
28194 
28195 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].vht_mcs); i++)
28196 		num_rates += qdf_get_hweight16(mask->control[band].vht_mcs[i]);
28197 
28198 	num_rates += hdd_check_he_bitmask_for_single_rate(band, mask);
28199 
28200 	return num_rates ? true : false;
28201 }
28202 
28203 static int __wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
28204 						struct net_device *dev,
28205 						const u8 *peer,
28206 				       const struct cfg80211_bitrate_mask *mask)
28207 {
28208 	enum nl80211_band band;
28209 	int errno;
28210 	struct hdd_adapter *adapter = netdev_priv(dev);
28211 	uint8_t nss, i;
28212 	int bit_rate = -1;
28213 	uint8_t rate_index;
28214 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
28215 	uint8_t vdev_id;
28216 	u8 gi_val = 0;
28217 #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
28218 	uint8_t auto_rate_he_gi = 0;
28219 #endif
28220 
28221 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
28222 	    QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
28223 		hdd_err("Command not allowed in mode");
28224 		return -EINVAL;
28225 	}
28226 
28227 	errno = hdd_validate_adapter(adapter);
28228 	if (errno)
28229 		return errno;
28230 
28231 	errno = wlan_hdd_validate_context(hdd_ctx);
28232 	if (errno)
28233 		return errno;
28234 
28235 	vdev_id = adapter->deflink->vdev_id;
28236 
28237 	for (band = NL80211_BAND_2GHZ; band <= NL80211_BAND_5GHZ; band++) {
28238 		/* Support configuring only one bitrate */
28239 		if (!hdd_check_bitmask_for_single_rate(band, mask)) {
28240 			hdd_err("Multiple bitrate set not supported for band %u",
28241 				band);
28242 			errno = -EINVAL;
28243 			continue;
28244 		}
28245 
28246 		if (!qdf_get_hweight32(mask->control[band].legacy)) {
28247 			hdd_err("Legacy bit rate setting not supported for band %u",
28248 				band);
28249 			errno = -EINVAL;
28250 			continue;
28251 		}
28252 
28253 		for (i = 0;
28254 			i < QDF_ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
28255 			if (qdf_get_hweight8(mask->control[band].ht_mcs[i])
28256 									== 1) {
28257 				nss = i;
28258 				rate_index =
28259 				      (ffs(mask->control[band].ht_mcs[i]) - 1);
28260 				bit_rate = hdd_assemble_rate_code(
28261 						WMI_RATE_PREAMBLE_HT,
28262 						nss, rate_index);
28263 				goto configure_fw;
28264 			}
28265 		}
28266 
28267 		for (i = 0;
28268 			i < QDF_ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
28269 			if (qdf_get_hweight16(mask->control[band].vht_mcs[i])
28270 									== 1) {
28271 				nss = i;
28272 				rate_index =
28273 				     (ffs(mask->control[band].vht_mcs[i]) - 1);
28274 				bit_rate = hdd_assemble_rate_code(
28275 						WMI_RATE_PREAMBLE_VHT,
28276 						nss, rate_index);
28277 				goto configure_fw;
28278 			}
28279 		}
28280 
28281 		if (qdf_get_hweight32(mask->control[band].legacy) == 1) {
28282 			rate_index = (ffs(mask->control[band].legacy) - 1);
28283 			nss = 0;
28284 			if (band == NL80211_BAND_5GHZ)
28285 				rate_index += 4;
28286 			if (rate_index >= 0 && rate_index < 4)
28287 				bit_rate = hdd_assemble_rate_code(
28288 					WMI_RATE_PREAMBLE_CCK, nss,
28289 					hdd_legacy_rates[rate_index].hw_value);
28290 			else if (rate_index >= 4 && rate_index < 12)
28291 				bit_rate = hdd_assemble_rate_code(
28292 					WMI_RATE_PREAMBLE_OFDM, nss,
28293 					hdd_legacy_rates[rate_index].hw_value);
28294 		}
28295 
28296 		hdd_get_he_bitrate_params_for_band(band, mask, &nss,
28297 						   &rate_index, &bit_rate);
28298 
28299 configure_fw:
28300 		if (bit_rate != -1) {
28301 			hdd_debug("wmi_vdev_param_fixed_rate val %d", bit_rate);
28302 
28303 			errno = wma_cli_set_command(adapter->deflink->vdev_id,
28304 						    wmi_vdev_param_fixed_rate,
28305 						    bit_rate, VDEV_CMD);
28306 
28307 			if (errno)
28308 				hdd_err("Failed to set firmware, errno %d",
28309 					errno);
28310 		}
28311 
28312 
28313 #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
28314 		if (NL80211_RATE_INFO_HE_GI_0_8 == mask->control[band].he_gi) {
28315 			auto_rate_he_gi = AUTO_RATE_GI_800NS;
28316 			gi_val = 1;
28317 		} else if (NL80211_RATE_INFO_HE_GI_1_6 ==
28318 			   mask->control[band].he_gi) {
28319 			auto_rate_he_gi = AUTO_RATE_GI_1600NS;
28320 			gi_val = 2;
28321 		} else if (NL80211_RATE_INFO_HE_GI_3_2 ==
28322 			   mask->control[band].he_gi) {
28323 			auto_rate_he_gi = AUTO_RATE_GI_3200NS;
28324 			gi_val = 3;
28325 		}
28326 		if (auto_rate_he_gi) {
28327 			errno = sme_set_auto_rate_he_sgi(
28328 						hdd_ctx->mac_handle,
28329 						adapter->deflink->vdev_id,
28330 						auto_rate_he_gi);
28331 			if (errno)
28332 				hdd_err("auto rate GI %d set fail, status %d",
28333 					auto_rate_he_gi, errno);
28334 
28335 			errno = sme_update_ht_config(
28336 					hdd_ctx->mac_handle,
28337 					adapter->deflink->vdev_id,
28338 					WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ,
28339 					gi_val);
28340 
28341 			if (errno) {
28342 				hdd_err("cfg set failed, value %d status %d",
28343 					gi_val, errno);
28344 			}
28345 		} else
28346 #endif
28347 		if (mask->control[band].gi) {
28348 			if (NL80211_TXRATE_FORCE_SGI == mask->control[band].gi)
28349 				gi_val = 0;
28350 			else
28351 				gi_val = 1;
28352 
28353 			errno = sme_update_ht_config(
28354 					hdd_ctx->mac_handle,
28355 					adapter->deflink->vdev_id,
28356 					WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ,
28357 					gi_val);
28358 
28359 			if (errno)
28360 				hdd_err("cfg set failed, value %d status %d",
28361 					mask->control[band].gi, errno);
28362 		}
28363 	}
28364 
28365 	return errno;
28366 }
28367 
28368 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
28369 static int wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
28370 					      struct net_device *netdev,
28371 					      unsigned int link_id,
28372 					      const u8 *peer,
28373 				       const struct cfg80211_bitrate_mask *mask)
28374 #else
28375 static int wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
28376 					      struct net_device *netdev,
28377 					      const u8 *peer,
28378 				       const struct cfg80211_bitrate_mask *mask)
28379 #endif
28380 {
28381 	int errno;
28382 	struct osif_vdev_sync *vdev_sync;
28383 
28384 	errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
28385 	if (errno) {
28386 		hdd_err("vdev_sync_op_start failure");
28387 		return errno;
28388 	}
28389 
28390 	errno = __wlan_hdd_cfg80211_set_bitrate_mask(wiphy, netdev, peer,
28391 						     mask);
28392 
28393 	osif_vdev_sync_op_stop(vdev_sync);
28394 
28395 	return errno;
28396 }
28397 
28398 static int __wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
28399 					       struct net_device *dev,
28400 					       const u8 *buf, size_t len,
28401 					       const u8 *src, const u8 *dest,
28402 						__be16 proto, bool unencrypted)
28403 {
28404 	qdf_nbuf_t nbuf;
28405 	struct ethhdr *ehdr;
28406 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
28407 
28408 	hdd_enter();
28409 
28410 	nbuf = dev_alloc_skb(len + sizeof(struct ethhdr));
28411 	if (!nbuf)
28412 		return -ENOMEM;
28413 
28414 	skb_reserve(nbuf, sizeof(struct ethhdr));
28415 	skb_put_data(nbuf, buf, len);
28416 	ehdr = skb_push(nbuf, sizeof(struct ethhdr));
28417 	qdf_mem_copy(ehdr->h_dest, dest, ETH_ALEN);
28418 
28419 	if (!src || qdf_is_macaddr_zero((struct qdf_mac_addr *)src))
28420 		qdf_mem_copy(ehdr->h_source, adapter->mac_addr.bytes, ETH_ALEN);
28421 	else
28422 		qdf_mem_copy(ehdr->h_source, src, ETH_ALEN);
28423 
28424 	ehdr->h_proto = proto;
28425 
28426 	nbuf->dev = dev;
28427 	nbuf->protocol = htons(ETH_P_PAE);
28428 	skb_reset_network_header(nbuf);
28429 	skb_reset_mac_header(nbuf);
28430 
28431 	netif_tx_lock(dev);
28432 	skb_set_queue_mapping(nbuf, hdd_wmm_select_queue(dev, nbuf));
28433 	dev->netdev_ops->ndo_start_xmit(nbuf, dev);
28434 	netif_tx_unlock(dev);
28435 
28436 	hdd_exit();
28437 	return 0;
28438 }
28439 
28440 static int _wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
28441 					      struct net_device *dev,
28442 					      const u8 *buf, size_t len,
28443 					      const u8 *src, const u8 *dest,
28444 					      __be16 proto, bool unencrypted)
28445 {
28446 	int errno;
28447 	struct osif_vdev_sync *vdev_sync;
28448 
28449 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
28450 	if (errno)
28451 		return errno;
28452 
28453 	errno = __wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len, src,
28454 						    dest, proto, unencrypted);
28455 
28456 	osif_vdev_sync_op_stop(vdev_sync);
28457 
28458 	return errno;
28459 }
28460 
28461 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || \
28462 	defined(CFG80211_TX_CONTROL_PORT_LINK_SUPPORT))
28463 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
28464 					     struct net_device *dev,
28465 					     const u8 *buf,
28466 					     size_t len,
28467 					     const u8 *dest, const __be16 proto,
28468 					     bool unencrypted, int link_id,
28469 					     u64 *cookie)
28470 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
28471 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
28472 					     struct net_device *dev,
28473 					     const u8 *buf, size_t len,
28474 					     const u8 *dest, __be16 proto,
28475 					     bool unencrypted, u64 *cookie)
28476 #else
28477 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
28478 					     struct net_device *dev,
28479 					     const u8 *buf, size_t len,
28480 					     const u8 *dest, __be16 proto,
28481 					     bool unencrypted)
28482 #endif
28483 {
28484 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
28485 
28486 	return _wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len,
28487 						  adapter->mac_addr.bytes,
28488 						  dest, proto, unencrypted);
28489 }
28490 
28491 #if defined(CFG80211_CTRL_FRAME_SRC_ADDR_TA_ADDR)
28492 bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
28493 				       u8 *ta_addr,
28494 				       struct sk_buff *skb,
28495 				       bool unencrypted)
28496 {
28497 	return cfg80211_rx_control_port(dev, ta_addr, skb, unencrypted);
28498 }
28499 #else
28500 bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
28501 				       u8 *ta_addr,
28502 				       struct sk_buff *skb,
28503 				       bool unencrypted)
28504 {
28505 	return false;
28506 }
28507 #endif
28508 
28509 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
28510 static int
28511 wlan_hdd_cfg80211_add_intf_link(struct wiphy *wiphy, struct wireless_dev *wdev,
28512 				unsigned int link_id)
28513 {
28514 	return 0;
28515 }
28516 
28517 static void
28518 wlan_hdd_cfg80211_del_intf_link(struct wiphy *wiphy, struct wireless_dev *wdev,
28519 				unsigned int link_id)
28520 {
28521 }
28522 #endif
28523 
28524 #if defined(WLAN_FEATURE_11BE_MLO)
28525 #if defined(WLAN_TID_LINK_MAP_SUPPORT)
28526 #define MAX_T2LM_INFO 2
28527 
28528 static void wlan_hdd_print_t2lm_info(struct cfg80211_mlo_tid_map *map)
28529 {
28530 	int i;
28531 
28532 	hdd_debug("T2LM info send to userspace");
28533 	hdd_debug("default mapping: %d", map->default_map);
28534 	for (i = 0; i < T2LM_MAX_NUM_TIDS; i++)
28535 		hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
28536 			  i, map->t2lmap[i].downlink, map->t2lmap[i].uplink);
28537 }
28538 
28539 static void wlan_hdd_fill_bidir_t2lm(struct wlan_t2lm_info *t2lm,
28540 				     struct tid_link_map *t2lmap)
28541 {
28542 	uint8_t tid;
28543 
28544 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
28545 		t2lmap[tid].downlink = t2lm->ieee_link_map_tid[tid];
28546 		t2lmap[tid].uplink = t2lm->ieee_link_map_tid[tid];
28547 	}
28548 }
28549 
28550 static void wlan_hdd_fill_dldir_t2lm(struct wlan_t2lm_info *t2lm,
28551 				     struct tid_link_map *t2lmap)
28552 {
28553 	uint8_t tid;
28554 
28555 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++)
28556 		t2lmap[tid].downlink = t2lm->ieee_link_map_tid[tid];
28557 }
28558 
28559 static void wlan_hdd_fill_uldir_t2lm(struct wlan_t2lm_info *t2lm,
28560 				     struct tid_link_map *t2lmap)
28561 {
28562 	uint8_t tid;
28563 
28564 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++)
28565 		t2lmap[tid].uplink = t2lm->ieee_link_map_tid[tid];
28566 }
28567 
28568 static void wlan_hdd_fill_map(struct wlan_t2lm_info *t2lm,
28569 			      struct cfg80211_mlo_tid_map *map, bool *found)
28570 {
28571 	if (t2lm->direction == WLAN_T2LM_INVALID_DIRECTION)
28572 		return;
28573 
28574 	map->default_map = t2lm->default_link_mapping;
28575 
28576 	switch (t2lm->direction) {
28577 	case WLAN_T2LM_BIDI_DIRECTION:
28578 		wlan_hdd_fill_bidir_t2lm(t2lm, map->t2lmap);
28579 		*found = true;
28580 		break;
28581 	case WLAN_T2LM_DL_DIRECTION:
28582 		wlan_hdd_fill_dldir_t2lm(t2lm, map->t2lmap);
28583 		*found = true;
28584 		break;
28585 	case WLAN_T2LM_UL_DIRECTION:
28586 		wlan_hdd_fill_uldir_t2lm(t2lm, map->t2lmap);
28587 		*found = true;
28588 		break;
28589 	default:
28590 		return;
28591 	}
28592 }
28593 
28594 static int wlan_hdd_fill_t2lm_response(struct wlan_t2lm_info *t2lm,
28595 				       struct cfg80211_mlo_tid_map *map)
28596 {
28597 	uint8_t i;
28598 	bool found = false;
28599 
28600 	for (i = 0; i < MAX_T2LM_INFO; i++)
28601 		wlan_hdd_fill_map(&t2lm[i], map, &found);
28602 
28603 	if (!found) {
28604 		hdd_err("T2LM info not found");
28605 		return -EINVAL;
28606 	}
28607 
28608 	wlan_hdd_print_t2lm_info(map);
28609 
28610 	return 0;
28611 }
28612 
28613 static int
28614 __wlan_hdd_cfg80211_get_t2lm_mapping_status(struct wiphy *wiphy,
28615 					    struct net_device *net_dev,
28616 					    struct cfg80211_mlo_tid_map *map)
28617 {
28618 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
28619 	struct wlan_objmgr_vdev *vdev;
28620 	struct wlan_t2lm_info *t2lm = NULL;
28621 	int ret, i;
28622 
28623 	hdd_enter();
28624 
28625 	if (hdd_validate_adapter(adapter))
28626 		return -EINVAL;
28627 
28628 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
28629 	if (!vdev) {
28630 		hdd_err("Vdev is null return");
28631 		return -EINVAL;
28632 	}
28633 
28634 	if (!wlan_cm_is_vdev_connected(vdev)) {
28635 		hdd_err("Not associated!, vdev %d", wlan_vdev_get_id(vdev));
28636 		ret = -EAGAIN;
28637 		goto vdev_release;
28638 	}
28639 
28640 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
28641 		hdd_err("failed due to non-ML connection");
28642 		ret = -EINVAL;
28643 		goto vdev_release;
28644 	}
28645 
28646 	t2lm = qdf_mem_malloc(sizeof(*t2lm) * MAX_T2LM_INFO);
28647 	if (!t2lm) {
28648 		hdd_err("mem alloc failed for t2lm");
28649 		ret = -ENOMEM;
28650 		goto vdev_release;
28651 	}
28652 
28653 	for (i = 0; i < MAX_T2LM_INFO; i++)
28654 		t2lm[i].direction = WLAN_T2LM_INVALID_DIRECTION;
28655 
28656 	ret = wlan_get_t2lm_mapping_status(vdev, t2lm);
28657 	if (ret != 0)
28658 		goto t2lm_free;
28659 
28660 	ret = wlan_hdd_fill_t2lm_response(t2lm, map);
28661 
28662 t2lm_free:
28663 	qdf_mem_free(t2lm);
28664 vdev_release:
28665 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
28666 
28667 	hdd_exit();
28668 
28669 	return ret;
28670 }
28671 
28672 static int
28673 wlan_hdd_cfg80211_get_t2lm_mapping_status(struct wiphy *wiphy,
28674 					  struct net_device *net_dev,
28675 					  struct cfg80211_mlo_tid_map *map)
28676 {
28677 	int errno;
28678 	struct osif_vdev_sync *vdev_sync;
28679 
28680 	errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
28681 	if (errno)
28682 		return errno;
28683 
28684 	errno = __wlan_hdd_cfg80211_get_t2lm_mapping_status(wiphy, net_dev, map);
28685 
28686 	osif_vdev_sync_op_stop(vdev_sync);
28687 
28688 	return errno;
28689 }
28690 
28691 QDF_STATUS hdd_tid_to_link_map(struct wlan_objmgr_vdev *vdev,
28692 			       struct wlan_t2lm_info *t2lm,
28693 			       struct net_device *dev)
28694 {
28695 	struct cfg80211_mlo_tid_map map;
28696 	bool found = false;
28697 
28698 	qdf_mem_zero(&map, sizeof(map));
28699 	wlan_hdd_fill_map(t2lm, &map, &found);
28700 	if (!found) {
28701 		hdd_debug("Failed to get t2lm info");
28702 		return QDF_STATUS_E_FAILURE;
28703 	}
28704 
28705 	wlan_hdd_print_t2lm_info(&map);
28706 	cfg80211_tid_to_link_map_change(dev, &map);
28707 	return QDF_STATUS_SUCCESS;
28708 }
28709 
28710 #else
28711 static void wlan_hdd_print_vendor_t2lm_info(struct wlan_t2lm_info *t2lm)
28712 {
28713 	int tid, value = 0;
28714 
28715 	hdd_debug("default mapping: %d", t2lm->default_link_mapping);
28716 
28717 	if (t2lm->direction == WLAN_T2LM_INVALID_DIRECTION)
28718 		return;
28719 
28720 	switch (t2lm->direction) {
28721 	case WLAN_T2LM_BIDI_DIRECTION:
28722 		for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
28723 			hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
28724 				  tid, t2lm->ieee_link_map_tid[tid],
28725 				  t2lm->ieee_link_map_tid[tid]);
28726 		}
28727 		break;
28728 	case WLAN_T2LM_DL_DIRECTION:
28729 		for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
28730 			/* Keep uplink info as 0 for downlink direction */
28731 			hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
28732 				  tid, t2lm->ieee_link_map_tid[tid], value);
28733 		}
28734 		break;
28735 	case WLAN_T2LM_UL_DIRECTION:
28736 		for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
28737 			/* Keep downlinklink info as 0 for downlink direction */
28738 			hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
28739 				  tid, value, t2lm->ieee_link_map_tid[tid]);
28740 		}
28741 		break;
28742 	default:
28743 		return;
28744 	}
28745 }
28746 
28747 QDF_STATUS hdd_tid_to_link_map(struct wlan_objmgr_vdev *vdev,
28748 			       struct wlan_t2lm_info *t2lm,
28749 			       struct net_device *dev)
28750 {
28751 	uint8_t ret;
28752 
28753 	wlan_hdd_print_vendor_t2lm_info(t2lm);
28754 	ret = wlan_hdd_send_t2lm_event(vdev, t2lm);
28755 	if (QDF_IS_STATUS_ERROR(ret)) {
28756 		hdd_debug("failed to send t2lm info to userspace");
28757 		return QDF_STATUS_E_FAILURE;
28758 	}
28759 	return QDF_STATUS_SUCCESS;
28760 }
28761 #endif
28762 
28763 QDF_STATUS hdd_mlo_dev_t2lm_notify_link_update(struct wlan_objmgr_vdev *vdev,
28764 					       struct wlan_t2lm_info *t2lm)
28765 {
28766 	struct wlan_hdd_link_info *link_info;
28767 	struct net_device *dev;
28768 	uint8_t ret;
28769 
28770 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
28771 	if (!link_info) {
28772 		hdd_err("Invalid VDEV");
28773 		return QDF_STATUS_E_FAILURE;
28774 	}
28775 
28776 	dev = link_info->adapter->dev;
28777 	hdd_enter_dev(dev);
28778 
28779 	ret = hdd_tid_to_link_map(vdev, t2lm, dev);
28780 	if (QDF_IS_STATUS_ERROR(ret)) {
28781 		hdd_debug("tid to link map change failed ");
28782 		return QDF_STATUS_E_FAILURE;
28783 	}
28784 
28785 	hdd_exit();
28786 
28787 	return QDF_STATUS_SUCCESS;
28788 }
28789 #endif
28790 
28791 static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
28792 	.add_virtual_intf = wlan_hdd_add_virtual_intf,
28793 	.del_virtual_intf = wlan_hdd_del_virtual_intf,
28794 	.change_virtual_intf = wlan_hdd_cfg80211_change_iface,
28795 	.change_station = wlan_hdd_change_station,
28796 	.start_ap = wlan_hdd_cfg80211_start_ap,
28797 	.change_beacon = wlan_hdd_cfg80211_change_beacon,
28798 	.stop_ap = wlan_hdd_cfg80211_stop_ap,
28799 	.change_bss = wlan_hdd_cfg80211_change_bss,
28800 	.add_key = wlan_hdd_cfg80211_add_key,
28801 	.get_key = wlan_hdd_cfg80211_get_key,
28802 	.del_key = wlan_hdd_cfg80211_del_key,
28803 	.set_default_key = wlan_hdd_cfg80211_set_default_key,
28804 	.scan = wlan_hdd_cfg80211_scan,
28805 	.connect = wlan_hdd_cfg80211_connect,
28806 	.disconnect = wlan_hdd_cfg80211_disconnect,
28807 	.set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
28808 	.set_tx_power = wlan_hdd_cfg80211_set_txpower,
28809 	.get_tx_power = wlan_hdd_cfg80211_get_txpower,
28810 	.remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
28811 	.cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
28812 	.mgmt_tx = wlan_hdd_mgmt_tx,
28813 	.mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
28814 	.set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
28815 #if defined (CFG80211_BIGTK_CONFIGURATION_SUPPORT) || \
28816 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
28817 	.set_default_beacon_key = wlan_hdd_cfg80211_set_default_beacon_key,
28818 #endif
28819 	.set_txq_params = wlan_hdd_set_txq_params,
28820 	.dump_station = wlan_hdd_cfg80211_dump_station,
28821 	.get_station = wlan_hdd_cfg80211_get_station,
28822 	.set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
28823 	.del_station = wlan_hdd_cfg80211_del_station,
28824 	.add_station = wlan_hdd_cfg80211_add_station,
28825 	.set_pmksa = wlan_hdd_cfg80211_set_pmksa,
28826 	.del_pmksa = wlan_hdd_cfg80211_del_pmksa,
28827 	.flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
28828 #if defined(KERNEL_SUPPORT_11R_CFG80211)
28829 	.update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
28830 #endif
28831 #if defined(CFG80211_EXTERNAL_DH_UPDATE_SUPPORT) || \
28832 (LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0))
28833 	.update_owe_info = wlan_hdd_cfg80211_update_owe_info,
28834 #endif
28835 #ifdef FEATURE_WLAN_TDLS
28836 	.tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
28837 	.tdls_oper = wlan_hdd_cfg80211_tdls_oper,
28838 #endif
28839 #ifdef WLAN_FEATURE_GTK_OFFLOAD
28840 	.set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
28841 #endif /* WLAN_FEATURE_GTK_OFFLOAD */
28842 #ifdef FEATURE_WLAN_SCAN_PNO
28843 	.sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
28844 	.sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
28845 #endif /*FEATURE_WLAN_SCAN_PNO */
28846 	.resume = wlan_hdd_cfg80211_resume_wlan,
28847 	.suspend = wlan_hdd_cfg80211_suspend_wlan,
28848 	.set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
28849 #ifdef WLAN_NL80211_TESTMODE
28850 	.testmode_cmd = wlan_hdd_cfg80211_testmode,
28851 #endif
28852 #ifdef QCA_HT_2040_COEX
28853 	.set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
28854 #endif
28855 	.dump_survey = wlan_hdd_cfg80211_dump_survey,
28856 #ifdef CHANNEL_SWITCH_SUPPORTED
28857 	.channel_switch = wlan_hdd_cfg80211_channel_switch,
28858 #endif
28859 #ifdef FEATURE_MONITOR_MODE_SUPPORT
28860 	.set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
28861 #endif
28862 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
28863 	defined(CFG80211_ABORT_SCAN)
28864 	.abort_scan = wlan_hdd_cfg80211_abort_scan,
28865 #endif
28866 #if defined(CFG80211_UPDATE_CONNECT_PARAMS) || \
28867 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
28868 	.update_connect_params = wlan_hdd_cfg80211_update_connect_params,
28869 #endif
28870 #if defined(WLAN_FEATURE_SAE) && \
28871 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
28872 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
28873 	.external_auth = wlan_hdd_cfg80211_external_auth,
28874 #endif
28875 #if defined(WLAN_FEATURE_NAN) && \
28876 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
28877 	.start_nan = wlan_hdd_cfg80211_start_nan,
28878 	.stop_nan = wlan_hdd_cfg80211_stop_nan,
28879 	.add_nan_func = wlan_hdd_cfg80211_add_nan_func,
28880 	.del_nan_func = wlan_hdd_cfg80211_del_nan_func,
28881 	.nan_change_conf = wlan_hdd_cfg80211_nan_change_conf,
28882 #endif
28883 	.set_antenna = wlan_hdd_cfg80211_set_chainmask,
28884 	.get_antenna = wlan_hdd_cfg80211_get_chainmask,
28885 	.get_channel = wlan_hdd_cfg80211_get_channel,
28886 	.set_bitrate_mask = wlan_hdd_cfg80211_set_bitrate_mask,
28887 	.tx_control_port = wlan_hdd_cfg80211_tx_control_port,
28888 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
28889 	.add_intf_link = wlan_hdd_cfg80211_add_intf_link,
28890 	.del_intf_link = wlan_hdd_cfg80211_del_intf_link,
28891 #endif
28892 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_TID_LINK_MAP_SUPPORT)
28893 	.get_link_tid_map_status = wlan_hdd_cfg80211_get_t2lm_mapping_status,
28894 #endif
28895 };
28896