xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: wlan_hdd_cfg80211.c
22  *
23  * WLAN Host Device Driver cfg80211 APIs implementation
24  *
25  */
26 
27 #include <linux/version.h>
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/init.h>
31 #include <linux/etherdevice.h>
32 #include <linux/wireless.h>
33 #include "osif_sync.h"
34 #include <wlan_hdd_includes.h>
35 #include <net/arp.h>
36 #include <net/cfg80211.h>
37 #include <net/mac80211.h>
38 #include <wlan_hdd_wowl.h>
39 #include <ani_global.h>
40 #include "sir_params.h"
41 #include "dot11f.h"
42 #include "wlan_hdd_assoc.h"
43 #include "wlan_hdd_wext.h"
44 #include "sme_api.h"
45 #include "sme_power_save_api.h"
46 #include "wlan_hdd_p2p.h"
47 #include "wlan_hdd_cfg80211.h"
48 #include "wlan_hdd_hostapd.h"
49 #include "wlan_hdd_softap_tx_rx.h"
50 #include "wlan_hdd_main.h"
51 #include "wlan_hdd_power.h"
52 #include "wlan_hdd_trace.h"
53 #include "wlan_hdd_tx_rx.h"
54 #include "qdf_str.h"
55 #include "qdf_trace.h"
56 #include "qdf_types.h"
57 #include "qdf_net_if.h"
58 #include "cds_utils.h"
59 #include "cds_sched.h"
60 #include "wlan_hdd_scan.h"
61 #include <qc_sap_ioctl.h>
62 #include "wlan_hdd_tdls.h"
63 #include "wlan_hdd_wmm.h"
64 #include "wma_types.h"
65 #include "wma.h"
66 #include "wma_twt.h"
67 #include "wlan_hdd_misc.h"
68 #include "wlan_hdd_nan.h"
69 #include "wlan_logging_sock_svc.h"
70 #include "sap_api.h"
71 #include "csr_api.h"
72 #include "pld_common.h"
73 #include "wmi_unified_param.h"
74 
75 #include <cdp_txrx_handle.h>
76 #include <wlan_cfg80211_scan.h>
77 #include <wlan_cfg80211_ftm.h>
78 
79 #include "wlan_hdd_ext_scan.h"
80 
81 #include "wlan_hdd_stats.h"
82 #include "cds_api.h"
83 #include "wlan_policy_mgr_api.h"
84 #include "qwlan_version.h"
85 
86 #include "wlan_hdd_ocb.h"
87 #include "wlan_hdd_tsf.h"
88 
89 #include "sap_internal.h"
90 
91 #include "wlan_hdd_green_ap.h"
92 
93 #include "wlan_hdd_subnet_detect.h"
94 #include <wlan_hdd_regulatory.h>
95 #include "wlan_hdd_lpass.h"
96 #include "wlan_hdd_nan_datapath.h"
97 #include "wlan_hdd_disa.h"
98 #include "wlan_osif_request_manager.h"
99 #include "wlan_hdd_he.h"
100 #ifdef FEATURE_WLAN_APF
101 #include "wlan_hdd_apf.h"
102 #endif
103 #include "wlan_hdd_fw_state.h"
104 #include "wlan_hdd_mpta_helper.h"
105 
106 #include <cdp_txrx_cmn.h>
107 #include <cdp_txrx_misc.h>
108 #include <cdp_txrx_ctrl.h>
109 #include "wlan_pmo_ucfg_api.h"
110 #include "os_if_wifi_pos.h"
111 #include "wlan_utility.h"
112 #include "wlan_reg_ucfg_api.h"
113 #include "wifi_pos_api.h"
114 #include "wlan_hdd_spectralscan.h"
115 #include "wlan_ipa_ucfg_api.h"
116 #include <wlan_cfg80211_mc_cp_stats.h>
117 #include <wlan_cp_stats_mc_ucfg_api.h>
118 #include "wlan_tdls_cfg_api.h"
119 #include "wlan_tdls_ucfg_api.h"
120 #include <wlan_hdd_bss_transition.h>
121 #include <wlan_hdd_concurrency_matrix.h>
122 #include <wlan_hdd_p2p_listen_offload.h>
123 #include <wlan_hdd_rssi_monitor.h>
124 #include <wlan_hdd_sap_cond_chan_switch.h>
125 #include <wlan_hdd_station_info.h>
126 #include <wlan_hdd_tx_power.h>
127 #include <wlan_hdd_active_tos.h>
128 #include <wlan_hdd_sar_limits.h>
129 #include <wlan_hdd_ota_test.h>
130 #include "wlan_policy_mgr_ucfg.h"
131 #include "wlan_mlme_ucfg_api.h"
132 #include "wlan_mlme_twt_ucfg_api.h"
133 #include "wlan_mlme_public_struct.h"
134 #include "wlan_extscan_ucfg_api.h"
135 #include "wlan_pmo_cfg.h"
136 #include "cfg_ucfg_api.h"
137 
138 #include "wlan_crypto_def_i.h"
139 #include "wlan_crypto_global_api.h"
140 #include "wlan_nl_to_crypto_params.h"
141 #include "wlan_crypto_global_def.h"
142 #include "cdp_txrx_cfg.h"
143 #include "wlan_hdd_object_manager.h"
144 #include "nan_ucfg_api.h"
145 #include "wlan_fwol_ucfg_api.h"
146 #include "wlan_cfg80211_crypto.h"
147 #include "wlan_cfg80211_interop_issues_ap.h"
148 #include "wlan_scan_ucfg_api.h"
149 #include "wlan_hdd_coex_config.h"
150 #include "wlan_hdd_bcn_recv.h"
151 #include "wlan_hdd_connectivity_logging.h"
152 #include "wlan_dlm_ucfg_api.h"
153 #include "wlan_hdd_hw_capability.h"
154 #include "wlan_hdd_oemdata.h"
155 #include "os_if_fwol.h"
156 #include "wlan_hdd_sta_info.h"
157 #include "sme_api.h"
158 #include "wlan_hdd_thermal.h"
159 #include <ol_defines.h>
160 #include "wlan_hdd_btc_chain_mode.h"
161 #include "os_if_nan.h"
162 #include "wlan_hdd_apf.h"
163 #include "wlan_hdd_cfr.h"
164 #include "wlan_hdd_ioctl.h"
165 #include "wlan_cm_roam_ucfg_api.h"
166 #include "hif.h"
167 #include "wlan_reg_ucfg_api.h"
168 #include "wlan_hdd_afc.h"
169 #include "wlan_hdd_twt.h"
170 #include "wlan_hdd_gpio.h"
171 #include "wlan_hdd_medium_assess.h"
172 #include "wlan_if_mgr_ucfg_api.h"
173 #include "wlan_if_mgr_public_struct.h"
174 #include "wlan_wfa_ucfg_api.h"
175 #include "wifi_pos_ucfg_i.h"
176 #include <osif_cm_util.h>
177 #include <osif_cm_req.h>
178 #include "wlan_hdd_bootup_marker.h"
179 #include "wlan_hdd_cm_api.h"
180 #include "wlan_roam_debug.h"
181 #include "wlan_hdd_avoid_freq_ext.h"
182 #include "qdf_util.h"
183 #include "wlan_hdd_mdns_offload.h"
184 #include "wlan_pkt_capture_ucfg_api.h"
185 #include "wifi_pos_public_struct.h"
186 #include "wifi_pos_pasn_api.h"
187 #include "os_if_pkt_capture.h"
188 #include "os_if_dp_local_pkt_capture.h"
189 #include "wlan_hdd_son.h"
190 #include "wlan_hdd_mcc_quota.h"
191 #include "wlan_hdd_peer_txq_flush.h"
192 #include "wlan_cfg80211_wifi_pos.h"
193 #include "wlan_osif_features.h"
194 #include "wlan_hdd_wifi_pos_pasn.h"
195 #include "wlan_coex_ucfg_api.h"
196 #include "wlan_coex_public_structs.h"
197 #include "wlan_dp_ucfg_api.h"
198 #include "os_if_dp.h"
199 #include "os_if_dp_lro.h"
200 #include "wlan_mlo_mgr_sta.h"
201 #include <wlan_mlo_mgr_peer.h>
202 #include "wlan_hdd_coap.h"
203 #include "wlan_hdd_tdls.h"
204 #include "wlan_psoc_mlme_api.h"
205 #include <utils_mlo.h>
206 #include "wlan_mlo_mgr_roam.h"
207 #include "wlan_hdd_mlo.h"
208 #include <wlan_psoc_mlme_ucfg_api.h>
209 #include "wlan_epcs_api.h"
210 #include "wlan_mlo_epcs_ucfg_api.h"
211 #include <wlan_ll_sap_ucfg_api.h>
212 #include <wlan_mlo_mgr_link_switch.h>
213 #include <wlan_hdd_ll_lt_sap.h>
214 #include "wlan_cp_stats_mc_defs.h"
215 #include "wlan_policy_mgr_ll_sap.h"
216 
217 /*
218  * A value of 100 (milliseconds) can be sent to FW.
219  * FW would enable Tx beamforming based on this.
220  */
221 #define TX_BFER_NDP_PERIODICITY 100
222 
223 #define g_mode_rates_size (12)
224 #define a_mode_rates_size (8)
225 
226 #define WLAN_WAIT_WLM_LATENCY_LEVEL 1000
227 
228 /*
229  * BIT map values for vdev_param_set_profile
230  * bit 0: 0 - XR SAP profile disabled
231  *        1 - XR SAP profile enabled
232  * bit 1: 0 - XPAN profile disabled
233  *        1 - XPAN profile enabled
234  */
235 #define AP_PROFILE_XR_ENABLE 0x1
236 #define AP_PROFILE_XPAN_ENABLE 0x2
237 
238 /**
239  * rtt_is_enabled - Macro to check if the bitmap has any RTT roles set
240  * @bitmap: The bitmap to be checked
241  */
242 #define rtt_is_enabled(bitmap) \
243 	((bitmap) & (WMI_FW_STA_RTT_INITR | \
244 		     WMI_FW_STA_RTT_RESPR | \
245 		     WMI_FW_AP_RTT_INITR | \
246 		     WMI_FW_AP_RTT_RESPR))
247 
248 /*
249  * Android CTS verifier needs atleast this much wait time (in msec)
250  */
251 #define MAX_REMAIN_ON_CHANNEL_DURATION (2000)
252 
253 #define HDD2GHZCHAN(freq, chan, flag)   {     \
254 		.band = HDD_NL80211_BAND_2GHZ, \
255 		.center_freq = (freq), \
256 		.hw_value = (chan), \
257 		.flags = (flag), \
258 		.max_antenna_gain = 0, \
259 		.max_power = 0, \
260 }
261 
262 #define HDD5GHZCHAN(freq, chan, flag)   {     \
263 		.band =  HDD_NL80211_BAND_5GHZ, \
264 		.center_freq = (freq), \
265 		.hw_value = (chan), \
266 		.flags = (flag), \
267 		.max_antenna_gain = 0, \
268 		.max_power = 0, \
269 }
270 
271 #define HDD_G_MODE_RATETAB(rate, rate_id, flag)	\
272 	{ \
273 		.bitrate = rate, \
274 		.hw_value = rate_id, \
275 		.flags = flag, \
276 	}
277 
278 #define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
279 			mode <= DFS_MODE_DEPRIORITIZE))
280 
281 #ifndef WLAN_CIPHER_SUITE_GCMP
282 #define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
283 #endif
284 #ifndef WLAN_CIPHER_SUITE_GCMP_256
285 #define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
286 #endif
287 
288 /* Default number of Simultaneous Transmit */
289 #define DEFAULT_MAX_STR_LINK_COUNT 1
290 /* Maximum number of Simultaneous Transmit */
291 #define MAX_STR_LINK_COUNT 2
292 
293 static const u32 hdd_gcmp_cipher_suits[] = {
294 	WLAN_CIPHER_SUITE_GCMP,
295 	WLAN_CIPHER_SUITE_GCMP_256,
296 };
297 
298 static const u32 hdd_cipher_suites[] = {
299 	WLAN_CIPHER_SUITE_WEP40,
300 	WLAN_CIPHER_SUITE_WEP104,
301 	WLAN_CIPHER_SUITE_TKIP,
302 #ifdef FEATURE_WLAN_ESE
303 #define WLAN_CIPHER_SUITE_BTK 0x004096fe        /* use for BTK */
304 #define WLAN_CIPHER_SUITE_KRK 0x004096ff        /* use for KRK */
305 	WLAN_CIPHER_SUITE_BTK,
306 	WLAN_CIPHER_SUITE_KRK,
307 	WLAN_CIPHER_SUITE_CCMP,
308 #else
309 	WLAN_CIPHER_SUITE_CCMP,
310 #endif
311 #ifdef FEATURE_WLAN_WAPI
312 	WLAN_CIPHER_SUITE_SMS4,
313 #endif
314 	WLAN_CIPHER_SUITE_AES_CMAC,
315 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
316 	WLAN_CIPHER_SUITE_BIP_GMAC_128,
317 	WLAN_CIPHER_SUITE_BIP_GMAC_256,
318 #endif
319 };
320 
321 static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
322 	HDD2GHZCHAN(2412, 1, 0),
323 	HDD2GHZCHAN(2417, 2, 0),
324 	HDD2GHZCHAN(2422, 3, 0),
325 	HDD2GHZCHAN(2427, 4, 0),
326 	HDD2GHZCHAN(2432, 5, 0),
327 	HDD2GHZCHAN(2437, 6, 0),
328 	HDD2GHZCHAN(2442, 7, 0),
329 	HDD2GHZCHAN(2447, 8, 0),
330 	HDD2GHZCHAN(2452, 9, 0),
331 	HDD2GHZCHAN(2457, 10, 0),
332 	HDD2GHZCHAN(2462, 11, 0),
333 	HDD2GHZCHAN(2467, 12, 0),
334 	HDD2GHZCHAN(2472, 13, 0),
335 	HDD2GHZCHAN(2484, 14, 0),
336 };
337 
338 static const struct ieee80211_channel hdd_channels_5_ghz[] = {
339 	HDD5GHZCHAN(5180, 36, 0),
340 	HDD5GHZCHAN(5200, 40, 0),
341 	HDD5GHZCHAN(5220, 44, 0),
342 	HDD5GHZCHAN(5240, 48, 0),
343 	HDD5GHZCHAN(5260, 52, 0),
344 	HDD5GHZCHAN(5280, 56, 0),
345 	HDD5GHZCHAN(5300, 60, 0),
346 	HDD5GHZCHAN(5320, 64, 0),
347 	HDD5GHZCHAN(5500, 100, 0),
348 	HDD5GHZCHAN(5520, 104, 0),
349 	HDD5GHZCHAN(5540, 108, 0),
350 	HDD5GHZCHAN(5560, 112, 0),
351 	HDD5GHZCHAN(5580, 116, 0),
352 	HDD5GHZCHAN(5600, 120, 0),
353 	HDD5GHZCHAN(5620, 124, 0),
354 	HDD5GHZCHAN(5640, 128, 0),
355 	HDD5GHZCHAN(5660, 132, 0),
356 	HDD5GHZCHAN(5680, 136, 0),
357 	HDD5GHZCHAN(5700, 140, 0),
358 	HDD5GHZCHAN(5720, 144, 0),
359 	HDD5GHZCHAN(5745, 149, 0),
360 	HDD5GHZCHAN(5765, 153, 0),
361 	HDD5GHZCHAN(5785, 157, 0),
362 	HDD5GHZCHAN(5805, 161, 0),
363 	HDD5GHZCHAN(5825, 165, 0),
364 };
365 
366 #ifdef WLAN_FEATURE_DSRC
367 static const struct ieee80211_channel hdd_channels_dot11p[] = {
368 	HDD5GHZCHAN(5852, 170, 0),
369 	HDD5GHZCHAN(5855, 171, 0),
370 	HDD5GHZCHAN(5860, 172, 0),
371 	HDD5GHZCHAN(5865, 173, 0),
372 	HDD5GHZCHAN(5870, 174, 0),
373 	HDD5GHZCHAN(5875, 175, 0),
374 	HDD5GHZCHAN(5880, 176, 0),
375 	HDD5GHZCHAN(5885, 177, 0),
376 	HDD5GHZCHAN(5890, 178, 0),
377 	HDD5GHZCHAN(5895, 179, 0),
378 	HDD5GHZCHAN(5900, 180, 0),
379 	HDD5GHZCHAN(5905, 181, 0),
380 	HDD5GHZCHAN(5910, 182, 0),
381 	HDD5GHZCHAN(5915, 183, 0),
382 	HDD5GHZCHAN(5920, 184, 0),
383 };
384 #else
385 static const struct ieee80211_channel hdd_5dot9_ghz_ch[] = {
386 	HDD5GHZCHAN(5845, 169, 0),
387 	HDD5GHZCHAN(5865, 173, 0),
388 	HDD5GHZCHAN(5885, 177, 0),
389 };
390 #endif
391 
392 #define band_2_ghz_channels_size sizeof(hdd_channels_2_4_ghz)
393 
394 #ifdef WLAN_FEATURE_DSRC
395 #define band_5_ghz_channels_size (sizeof(hdd_channels_5_ghz) + \
396 	sizeof(hdd_channels_dot11p))
397 #else
398 #define band_5_ghz_channels_size (sizeof(hdd_channels_5_ghz) + \
399 	sizeof(hdd_5dot9_ghz_ch))
400 #endif
401 
402 static struct ieee80211_rate g_mode_rates[] = {
403 	HDD_G_MODE_RATETAB(10, 0x1, 0),
404 	HDD_G_MODE_RATETAB(20, 0x2, 0),
405 	HDD_G_MODE_RATETAB(55, 0x4, 0),
406 	HDD_G_MODE_RATETAB(110, 0x8, 0),
407 	HDD_G_MODE_RATETAB(60, 0x10, 0),
408 	HDD_G_MODE_RATETAB(90, 0x20, 0),
409 	HDD_G_MODE_RATETAB(120, 0x40, 0),
410 	HDD_G_MODE_RATETAB(180, 0x80, 0),
411 	HDD_G_MODE_RATETAB(240, 0x100, 0),
412 	HDD_G_MODE_RATETAB(360, 0x200, 0),
413 	HDD_G_MODE_RATETAB(480, 0x400, 0),
414 	HDD_G_MODE_RATETAB(540, 0x800, 0),
415 };
416 
417 static struct ieee80211_rate a_mode_rates[] = {
418 	HDD_G_MODE_RATETAB(60, 0x10, 0),
419 	HDD_G_MODE_RATETAB(90, 0x20, 0),
420 	HDD_G_MODE_RATETAB(120, 0x40, 0),
421 	HDD_G_MODE_RATETAB(180, 0x80, 0),
422 	HDD_G_MODE_RATETAB(240, 0x100, 0),
423 	HDD_G_MODE_RATETAB(360, 0x200, 0),
424 	HDD_G_MODE_RATETAB(480, 0x400, 0),
425 	HDD_G_MODE_RATETAB(540, 0x800, 0),
426 };
427 
428 static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
429 	.channels = NULL,
430 	.n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
431 	.band = HDD_NL80211_BAND_2GHZ,
432 	.bitrates = g_mode_rates,
433 	.n_bitrates = g_mode_rates_size,
434 	.ht_cap.ht_supported = 1,
435 	.ht_cap.cap = IEEE80211_HT_CAP_SGI_20
436 		      | IEEE80211_HT_CAP_GRN_FLD
437 		      | IEEE80211_HT_CAP_DSSSCCK40
438 		      | IEEE80211_HT_CAP_LSIG_TXOP_PROT
439 		      | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
440 	.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
441 	.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
442 	.ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
443 	.ht_cap.mcs.rx_highest = cpu_to_le16(72),
444 	.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
445 };
446 
447 static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
448 	.channels = NULL,
449 	.n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
450 	.band = HDD_NL80211_BAND_5GHZ,
451 	.bitrates = a_mode_rates,
452 	.n_bitrates = a_mode_rates_size,
453 	.ht_cap.ht_supported = 1,
454 	.ht_cap.cap = IEEE80211_HT_CAP_SGI_20
455 		      | IEEE80211_HT_CAP_GRN_FLD
456 		      | IEEE80211_HT_CAP_DSSSCCK40
457 		      | IEEE80211_HT_CAP_LSIG_TXOP_PROT
458 		      | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
459 	.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
460 	.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
461 	.ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
462 	.ht_cap.mcs.rx_highest = cpu_to_le16(72),
463 	.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
464 	.vht_cap.vht_supported = 1,
465 };
466 
467 enum hdd_hw_rate_cck {
468 	HDD_HW_RATE_CCK_LP_11M = 0,
469 	HDD_HW_RATE_CCK_LP_5_5M,
470 	HDD_HW_RATE_CCK_LP_2M,
471 	HDD_HW_RATE_CCK_LP_1M,
472 	HDD_HW_RATE_CCK_SP_11M,
473 	HDD_HW_RATE_CCK_SP_5_5M,
474 	HDD_HW_RATE_CCK_SP_2M,
475 };
476 
477 enum hdd_hw_rate_ofdm {
478 	HDD_HW_RATE_OFDM_48M = 0,
479 	HDD_HW_RATE_OFDM_24M,
480 	HDD_HW_RATE_OFDM_12M,
481 	HDD_HW_RATE_OFDM_6M,
482 	HDD_HW_RATE_OFDM_54M,
483 	HDD_HW_RATE_OFDM_36M,
484 	HDD_HW_RATE_OFDM_18M,
485 	HDD_HW_RATE_OFDM_9M,
486 };
487 
488 static struct ieee80211_rate hdd_legacy_rates[] = {
489 	{ .bitrate = 10,
490 	  .hw_value = HDD_HW_RATE_CCK_LP_1M },
491 	{ .bitrate = 20,
492 	  .hw_value = HDD_HW_RATE_CCK_LP_2M },
493 	{ .bitrate = 55,
494 	  .hw_value = HDD_HW_RATE_CCK_LP_5_5M },
495 	{ .bitrate = 110,
496 	  .hw_value = HDD_HW_RATE_CCK_LP_11M },
497 	{ .bitrate = 60, .hw_value = HDD_HW_RATE_OFDM_6M },
498 	{ .bitrate = 90, .hw_value = HDD_HW_RATE_OFDM_9M },
499 	{ .bitrate = 120, .hw_value = HDD_HW_RATE_OFDM_12M },
500 	{ .bitrate = 180, .hw_value = HDD_HW_RATE_OFDM_18M },
501 	{ .bitrate = 240, .hw_value = HDD_HW_RATE_OFDM_24M },
502 	{ .bitrate = 360, .hw_value = HDD_HW_RATE_OFDM_36M },
503 	{ .bitrate = 480, .hw_value = HDD_HW_RATE_OFDM_48M },
504 	{ .bitrate = 540, .hw_value = HDD_HW_RATE_OFDM_54M },
505 };
506 
507 #if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
508 	(KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
509 
510 static struct ieee80211_channel hdd_channels_6_ghz[NUM_6GHZ_CHANNELS];
511 
512 static struct ieee80211_supported_band wlan_hdd_band_6_ghz = {
513 	.channels = NULL,
514 	.n_channels = 0,
515 	.band = HDD_NL80211_BAND_6GHZ,
516 	.bitrates = a_mode_rates,
517 	.n_bitrates = a_mode_rates_size,
518 };
519 
520 #define HDD_SET_6GHZCHAN(ch, freq, chan, flag)   {     \
521 		(ch).band =  HDD_NL80211_BAND_6GHZ; \
522 		(ch).center_freq = (freq); \
523 		(ch).hw_value = (chan); \
524 		(ch).flags = (flag); \
525 		(ch).max_antenna_gain = 0; \
526 		(ch).max_power = 0; \
527 }
528 
hdd_init_6ghz(struct hdd_context * hdd_ctx)529 static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
530 {
531 	uint32_t i;
532 	struct wiphy *wiphy = hdd_ctx->wiphy;
533 	struct ieee80211_channel *chlist = hdd_channels_6_ghz;
534 	uint32_t num = ARRAY_SIZE(hdd_channels_6_ghz);
535 	uint16_t base_freq;
536 	QDF_STATUS status;
537 	uint32_t band_capability;
538 
539 	hdd_enter();
540 
541 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
542 	if (QDF_IS_STATUS_ERROR(status)) {
543 		hdd_err("Failed to get MLME Band Capability");
544 		return;
545 	}
546 
547 	if (!(band_capability & (BIT(REG_BAND_6G)))) {
548 		hdd_debug("6ghz band not enabled");
549 		return;
550 	}
551 
552 	qdf_mem_zero(chlist, sizeof(*chlist) * num);
553 	base_freq = wlan_reg_min_6ghz_chan_freq();
554 
555 	for (i = 0; i < num; i++)
556 		HDD_SET_6GHZCHAN(chlist[i],
557 				 base_freq + i * 20,
558 				 wlan_reg_freq_to_chan(hdd_ctx->pdev,
559 						       base_freq + i * 20),
560 				 IEEE80211_CHAN_DISABLED);
561 	wiphy->bands[HDD_NL80211_BAND_6GHZ] = &wlan_hdd_band_6_ghz;
562 	wiphy->bands[HDD_NL80211_BAND_6GHZ]->channels = chlist;
563 	wiphy->bands[HDD_NL80211_BAND_6GHZ]->n_channels = num;
564 
565 	hdd_exit();
566 }
567 
568 /**
569  * wlan_hdd_populate_6g_chan_info() - Populate 6 GHz chan info in hdd context
570  * @hdd_ctx: pointer to hdd context
571  * @index: 6 GHz channel beginning index in chan_info of @hdd_ctx
572  *
573  * Return: Number of 6 GHz channels populated
574  */
575 static uint32_t
wlan_hdd_populate_6g_chan_info(struct hdd_context * hdd_ctx,uint32_t index)576 wlan_hdd_populate_6g_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
577 {
578 	uint32_t num_6g, i;
579 	struct scan_chan_info *chan_info;
580 
581 	if (!hdd_ctx->wiphy->bands[HDD_NL80211_BAND_6GHZ] ||
582 	    !hdd_ctx->wiphy->bands[HDD_NL80211_BAND_6GHZ]->n_channels) {
583 		hdd_debug("6GHz channel list not populated to wiphy");
584 		return 0;
585 	}
586 
587 	num_6g = QDF_ARRAY_SIZE(hdd_channels_6_ghz);
588 	chan_info = hdd_ctx->chan_info;
589 
590 	for (i = 0; i < num_6g; i++)
591 		chan_info[index + i].freq = hdd_channels_6_ghz[i].center_freq;
592 
593 	return num_6g;
594 }
595 
596 #else
hdd_init_6ghz(struct hdd_context * hdd_ctx)597 static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
598 {
599 }
600 
601 static inline uint32_t
wlan_hdd_populate_6g_chan_info(struct hdd_context * hdd_ctx,uint32_t index)602 wlan_hdd_populate_6g_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
603 {
604 	return 0;
605 }
606 #endif
607 
608 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) || \
609 	defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
610 /*akm suits supported by sta*/
611 static const u32 hdd_sta_akm_suites[] = {
612 	WLAN_AKM_SUITE_8021X,
613 	WLAN_AKM_SUITE_PSK,
614 	WLAN_AKM_SUITE_FT_8021X,
615 	WLAN_AKM_SUITE_FT_PSK,
616 	WLAN_AKM_SUITE_8021X_SHA256,
617 	WLAN_AKM_SUITE_PSK_SHA256,
618 	WLAN_AKM_SUITE_TDLS,
619 	WLAN_AKM_SUITE_SAE,
620 	WLAN_AKM_SUITE_FT_OVER_SAE,
621 	WLAN_AKM_SUITE_EAP_SHA256,
622 	WLAN_AKM_SUITE_EAP_SHA384,
623 	WLAN_AKM_SUITE_FILS_SHA256,
624 	WLAN_AKM_SUITE_FILS_SHA384,
625 	WLAN_AKM_SUITE_FT_FILS_SHA256,
626 	WLAN_AKM_SUITE_FT_FILS_SHA384,
627 	WLAN_AKM_SUITE_OWE,
628 	WLAN_AKM_SUITE_DPP_RSN,
629 	WLAN_AKM_SUITE_FT_EAP_SHA_384,
630 	RSN_AUTH_KEY_MGMT_CCKM,
631 	RSN_AUTH_KEY_MGMT_OSEN,
632 	WAPI_PSK_AKM_SUITE,
633 	WAPI_CERT_AKM_SUITE,
634 	WLAN_AKM_SUITE_SAE_EXT_KEY,
635 	WLAN_AKM_SUITE_FT_SAE_EXT_KEY,
636 };
637 
638 /*akm suits supported by AP*/
639 static const u32 hdd_ap_akm_suites[] = {
640 	WLAN_AKM_SUITE_PSK,
641 	WLAN_AKM_SUITE_SAE,
642 	WLAN_AKM_SUITE_OWE,
643 };
644 
645 /* This structure contain information what akm suits are
646  * supported for each mode
647  */
648 static const struct wiphy_iftype_akm_suites
649 	wlan_hdd_akm_suites[] = {
650 	{
651 		.iftypes_mask = BIT(NL80211_IFTYPE_STATION) |
652 				BIT(NL80211_IFTYPE_P2P_CLIENT),
653 		.akm_suites = hdd_sta_akm_suites,
654 		.n_akm_suites = (sizeof(hdd_sta_akm_suites) / sizeof(u32)),
655 	},
656 	{
657 		.iftypes_mask = BIT(NL80211_IFTYPE_AP) |
658 				BIT(NL80211_IFTYPE_P2P_GO),
659 		.akm_suites = hdd_ap_akm_suites,
660 		.n_akm_suites = (sizeof(hdd_ap_akm_suites) / sizeof(u32)),
661 	},
662 };
663 #endif
664 
665 /* This structure contain information what kind of frame are expected in
666  * TX/RX direction for each kind of interface
667  */
668 static const struct ieee80211_txrx_stypes
669 	wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
670 	[NL80211_IFTYPE_STATION] = {
671 		.tx = 0xffff,
672 		.rx = BIT(SIR_MAC_MGMT_ACTION) |
673 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
674 		      BIT(SIR_MAC_MGMT_AUTH),
675 	},
676 	[NL80211_IFTYPE_AP] = {
677 		.tx = 0xffff,
678 		.rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
679 		      BIT(SIR_MAC_MGMT_REASSOC_REQ) |
680 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
681 		      BIT(SIR_MAC_MGMT_DISASSOC) |
682 		      BIT(SIR_MAC_MGMT_AUTH) |
683 		      BIT(SIR_MAC_MGMT_DEAUTH) |
684 		      BIT(SIR_MAC_MGMT_ACTION),
685 	},
686 	[NL80211_IFTYPE_ADHOC] = {
687 		.tx = 0xffff,
688 		.rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
689 		      BIT(SIR_MAC_MGMT_REASSOC_REQ) |
690 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
691 		      BIT(SIR_MAC_MGMT_DISASSOC) |
692 		      BIT(SIR_MAC_MGMT_AUTH) |
693 		      BIT(SIR_MAC_MGMT_DEAUTH) |
694 		      BIT(SIR_MAC_MGMT_ACTION),
695 	},
696 	[NL80211_IFTYPE_P2P_CLIENT] = {
697 		.tx = 0xffff,
698 		.rx = BIT(SIR_MAC_MGMT_ACTION) |
699 		      BIT(SIR_MAC_MGMT_AUTH) |
700 		      BIT(SIR_MAC_MGMT_PROBE_REQ),
701 	},
702 	[NL80211_IFTYPE_P2P_GO] = {
703 		/* This is also same as for SoftAP */
704 		.tx = 0xffff,
705 		.rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
706 		      BIT(SIR_MAC_MGMT_REASSOC_REQ) |
707 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
708 		      BIT(SIR_MAC_MGMT_DISASSOC) |
709 		      BIT(SIR_MAC_MGMT_AUTH) |
710 		      BIT(SIR_MAC_MGMT_DEAUTH) |
711 		      BIT(SIR_MAC_MGMT_ACTION),
712 	},
713 	[NL80211_IFTYPE_NAN] = {
714 		.tx = 0xffff,
715 		.rx = BIT(SIR_MAC_MGMT_AUTH) | BIT(SIR_MAC_MGMT_ACTION),
716 	},
717 };
718 
719 /* Interface limits and combinations registered by the driver */
720 
721 /* STA ( + STA ) combination */
722 static const struct ieee80211_iface_limit
723 	wlan_hdd_sta_iface_limit[] = {
724 	{
725 		.max = 2,
726 		.types = BIT(NL80211_IFTYPE_STATION),
727 	},
728 };
729 
730 /* AP ( + AP ) combination */
731 static const struct ieee80211_iface_limit
732 	wlan_hdd_ap_iface_limit[] = {
733 	{
734 		.max = (QDF_MAX_NO_OF_SAP_MODE),
735 		.types = BIT(NL80211_IFTYPE_AP),
736 	},
737 };
738 
739 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
740 /* P2P limit */
741 static const struct ieee80211_iface_limit
742 	wlan_hdd_p2p_iface_limit[] = {
743 	{
744 		.max = 1,
745 		.types = BIT(NL80211_IFTYPE_P2P_CLIENT),
746 	},
747 	{
748 		.max = 1,
749 		.types = BIT(NL80211_IFTYPE_P2P_GO),
750 	},
751 };
752 
753 /* STA + P2P + P2P combination */
754 static const struct ieee80211_iface_limit
755 	wlan_hdd_sta_p2p_p2p_iface_limit[] = {
756 	{
757 		.max = 1,
758 		.types = BIT(NL80211_IFTYPE_STATION)
759 	},
760 	{
761 		/* Support for two identical (GO + GO or CLI + CLI)
762 		 * or dissimilar (GO + CLI) P2P interfaces
763 		 */
764 		.max = 2,
765 		.types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
766 	},
767 };
768 
769 /* STA + AP + P2P combination */
770 static const struct ieee80211_iface_limit
771 wlan_hdd_sta_ap_p2p_iface_limit[] = {
772 	{
773 	   .max = 1,
774 	   .types = BIT(NL80211_IFTYPE_STATION)
775 	},
776 	{
777 	   .max = 1,
778 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
779 	},
780 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
781 	{
782 	   .max = 1,
783 	   .types = BIT(NL80211_IFTYPE_AP)
784 	},
785 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
786 };
787 
788 /* SAP + P2P combination */
789 static const struct ieee80211_iface_limit
790 wlan_hdd_sap_p2p_iface_limit[] = {
791 	{
792 	   /* The p2p interface in SAP+P2P can be GO/CLI.
793 	    * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
794 	    */
795 	   .max = 1,
796 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
797 	},
798 	{
799 	   /* SAP+GO to support only one SAP interface */
800 	   .max = 1,
801 	   .types = BIT(NL80211_IFTYPE_AP)
802 	}
803 };
804 
805 /* P2P + P2P combination */
806 static const struct ieee80211_iface_limit
807 wlan_hdd_p2p_p2p_iface_limit[] = {
808 	{
809 	   /* The p2p interface in P2P+P2P can be GO/CLI.
810 	    * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
811 	    */
812 	   .max = 2,
813 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
814 	},
815 };
816 #elif defined(WLAN_FEATURE_STA_SAP_P2P_CONCURRENCY)
817 /* STA + AP + P2P combination */
818 static const struct ieee80211_iface_limit
819 wlan_hdd_sta_ap_p2p_iface_limit[] = {
820 	{
821 	   .max = 1,
822 	   .types = BIT(NL80211_IFTYPE_STATION)
823 	},
824 	{
825 	   .max = 1,
826 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
827 	},
828 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
829 	{
830 	   .max = 1,
831 	   .types = BIT(NL80211_IFTYPE_AP)
832 	},
833 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
834 };
835 #endif
836 
837 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
838 /* STA + AP combination */
839 static const struct ieee80211_iface_limit
840 wlan_hdd_sta_ap_iface_limit[] = {
841 	{
842 	   .max = 1,
843 	   .types = BIT(NL80211_IFTYPE_STATION)
844 	},
845 	{
846 	   .max = 1,
847 	   .types = BIT(NL80211_IFTYPE_AP)
848 	},
849 };
850 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
851 
852 /* STA + P2P combination */
853 static const struct ieee80211_iface_limit
854 	wlan_hdd_sta_p2p_iface_limit[] = {
855 	{
856 		.max = 1,
857 		.types = BIT(NL80211_IFTYPE_STATION)
858 	},
859 	{
860 		/* Support for either (GO or CLI) */
861 		.max = 1,
862 		.types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
863 	},
864 };
865 
866 /* Monitor interface */
867 static const struct ieee80211_iface_limit
868 	wlan_hdd_mon_iface_limit[] = {
869 	{
870 		.max = 2,
871 		.types = BIT(NL80211_IFTYPE_MONITOR),
872 	},
873 };
874 
875 #if defined(WLAN_FEATURE_NAN) && \
876 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
877 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
878 /* STA + NAN disc combination */
879 static const struct ieee80211_iface_limit
880 	wlan_hdd_sta_nan_iface_limit[] = {
881 	{
882 		/* STA */
883 		.max = 1,
884 		.types = BIT(NL80211_IFTYPE_STATION)
885 	},
886 	{
887 		/* NAN */
888 		.max = 1,
889 		.types = BIT(NL80211_IFTYPE_NAN),
890 	},
891 };
892 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
893 
894 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
895 /* SAP + NAN disc combination */
896 static const struct ieee80211_iface_limit
897 	wlan_hdd_sap_nan_iface_limit[] = {
898 	{
899 		/* SAP */
900 		.max = 1,
901 		.types = BIT(NL80211_IFTYPE_AP)
902 	},
903 	{
904 		/* NAN */
905 		.max = 1,
906 		.types = BIT(NL80211_IFTYPE_NAN),
907 	},
908 };
909 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
910 #endif /* WLAN_FEATURE_NAN */
911 
912 static struct ieee80211_iface_combination
913 	wlan_hdd_iface_combination[] = {
914 	/* STA */
915 	{
916 		.limits = wlan_hdd_sta_iface_limit,
917 		.num_different_channels = 2,
918 		.max_interfaces = 2,
919 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
920 	},
921 	/* AP */
922 	{
923 		.limits = wlan_hdd_ap_iface_limit,
924 		.num_different_channels = 2,
925 		.max_interfaces = (QDF_MAX_NO_OF_SAP_MODE),
926 		.n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
927 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
928 	defined(CFG80211_BEACON_INTERVAL_BACKPORT)
929 		.beacon_int_min_gcd = 1,
930 #endif
931 	},
932 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
933 	/* P2P */
934 	{
935 		.limits = wlan_hdd_p2p_iface_limit,
936 		.num_different_channels = 2,
937 		.max_interfaces = 2,
938 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
939 	},
940 	/* STA + P2P + P2P */
941 	{
942 		.limits = wlan_hdd_sta_p2p_p2p_iface_limit,
943 		.num_different_channels = 2,
944 		.max_interfaces = 3,
945 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_p2p_iface_limit),
946 		.beacon_int_infra_match = true,
947 	},
948 	/* STA + P2P + SAP */
949 	{
950 		.limits = wlan_hdd_sta_ap_p2p_iface_limit,
951 		/* we can allow 3 channels for three different persona
952 		 * but due to firmware limitation, allow max 2 concrnt channels.
953 		 */
954 		.num_different_channels = 2,
955 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
956 		.max_interfaces = 3,
957 #else
958 		.max_interfaces = 2,
959 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
960 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2p_iface_limit),
961 		.beacon_int_infra_match = true,
962 	},
963 	/* SAP + P2P */
964 	{
965 		.limits = wlan_hdd_sap_p2p_iface_limit,
966 		.num_different_channels = 2,
967 		/* 1-SAP + 1-P2P */
968 		.max_interfaces = 2,
969 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
970 		.beacon_int_infra_match = true,
971 	},
972 	/* P2P + P2P */
973 	{
974 		.limits = wlan_hdd_p2p_p2p_iface_limit,
975 		.num_different_channels = 2,
976 		/* 2-P2P */
977 		.max_interfaces = 2,
978 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
979 		.beacon_int_infra_match = true,
980 	},
981 #elif defined(WLAN_FEATURE_STA_SAP_P2P_CONCURRENCY)
982 	/* STA + P2P + SAP */
983 	{
984 		.limits = wlan_hdd_sta_ap_p2p_iface_limit,
985 		/* we can allow 3 channels for three different persona
986 		 * but due to firmware limitation, allow max 2 concrnt channels.
987 		 */
988 		.num_different_channels = 2,
989 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
990 		.max_interfaces = 3,
991 #else
992 		.max_interfaces = 2,
993 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
994 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2p_iface_limit),
995 		.beacon_int_infra_match = true,
996 	},
997 #endif /* WLAN_FEATURE_NO_P2P_CONCURRENCY */
998 	/* STA + P2P */
999 	{
1000 		.limits = wlan_hdd_sta_p2p_iface_limit,
1001 		.num_different_channels = 2,
1002 		.max_interfaces = 2,
1003 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
1004 		.beacon_int_infra_match = true,
1005 	},
1006 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
1007 	/* STA + SAP */
1008 	{
1009 		.limits = wlan_hdd_sta_ap_iface_limit,
1010 		.num_different_channels = 2,
1011 		.max_interfaces = 2,
1012 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
1013 		.beacon_int_infra_match = true,
1014 	},
1015 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
1016 	/* Monitor */
1017 	{
1018 		.limits = wlan_hdd_mon_iface_limit,
1019 		.max_interfaces = 2,
1020 		.num_different_channels = 2,
1021 		.n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
1022 	},
1023 #if defined(WLAN_FEATURE_NAN) && \
1024 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
1025 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
1026 	/* NAN + STA */
1027 	{
1028 		.limits = wlan_hdd_sta_nan_iface_limit,
1029 		.max_interfaces = 2,
1030 		.num_different_channels = 2,
1031 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_nan_iface_limit),
1032 	},
1033 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
1034 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
1035 	/* NAN + SAP */
1036 	{
1037 		.limits = wlan_hdd_sap_nan_iface_limit,
1038 		.num_different_channels = 2,
1039 		.max_interfaces = 2,
1040 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_nan_iface_limit),
1041 		.beacon_int_infra_match = true,
1042 	},
1043 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
1044 #endif /* WLAN_FEATURE_NAN */
1045 };
1046 
1047 /* 1 and 2 port concurrencies */
1048 static struct ieee80211_iface_combination
1049 	wlan_hdd_derived_combination[] = {
1050 	/* STA */
1051 	{
1052 		.limits = wlan_hdd_sta_iface_limit,
1053 		.num_different_channels = 2,
1054 		.max_interfaces = 2,
1055 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
1056 	},
1057 	/* AP */
1058 	{
1059 		.limits = wlan_hdd_ap_iface_limit,
1060 		.num_different_channels = 2,
1061 		.max_interfaces = (QDF_MAX_NO_OF_SAP_MODE),
1062 		.n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
1063 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
1064 	defined(CFG80211_BEACON_INTERVAL_BACKPORT)
1065 		.beacon_int_min_gcd = 1,
1066 #endif
1067 	},
1068 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
1069 	/* P2P */
1070 	{
1071 		.limits = wlan_hdd_p2p_iface_limit,
1072 		.num_different_channels = 2,
1073 		.max_interfaces = 2,
1074 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
1075 	},
1076 
1077 	/* SAP + P2P */
1078 	{
1079 		.limits = wlan_hdd_sap_p2p_iface_limit,
1080 		.num_different_channels = 2,
1081 		/* 1-SAP + 1-P2P */
1082 		.max_interfaces = 2,
1083 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
1084 		.beacon_int_infra_match = true,
1085 	},
1086 	/* P2P + P2P */
1087 	{
1088 		.limits = wlan_hdd_p2p_p2p_iface_limit,
1089 		.num_different_channels = 2,
1090 		/* 2-P2P */
1091 		.max_interfaces = 2,
1092 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
1093 		.beacon_int_infra_match = true,
1094 	},
1095 #endif
1096 	/* STA + P2P */
1097 	{
1098 		.limits = wlan_hdd_sta_p2p_iface_limit,
1099 		.num_different_channels = 2,
1100 		.max_interfaces = 2,
1101 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
1102 		.beacon_int_infra_match = true,
1103 	},
1104 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
1105 	/* STA + SAP */
1106 	{
1107 		.limits = wlan_hdd_sta_ap_iface_limit,
1108 		.num_different_channels = 2,
1109 		.max_interfaces = 2,
1110 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
1111 		.beacon_int_infra_match = true,
1112 	},
1113 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
1114 	/* Monitor */
1115 	{
1116 		.limits = wlan_hdd_mon_iface_limit,
1117 		.max_interfaces = 2,
1118 		.num_different_channels = 2,
1119 		.n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
1120 	},
1121 #if defined(WLAN_FEATURE_NAN) && \
1122 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
1123 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
1124 	/* NAN + STA */
1125 	{
1126 		.limits = wlan_hdd_sta_nan_iface_limit,
1127 		.max_interfaces = 2,
1128 		.num_different_channels = 2,
1129 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_nan_iface_limit),
1130 	},
1131 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
1132 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
1133 	/* NAN + SAP */
1134 	{
1135 		.limits = wlan_hdd_sap_nan_iface_limit,
1136 		.num_different_channels = 2,
1137 		.max_interfaces = 2,
1138 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_nan_iface_limit),
1139 		.beacon_int_infra_match = true,
1140 	},
1141 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
1142 #endif /* WLAN_FEATURE_NAN */
1143 };
1144 
1145 static struct ieee80211_iface_combination
1146 	wlan_hdd_non_dbs_iface_combination[] = {
1147 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
1148 	/* P2P */
1149 	{
1150 		.limits = wlan_hdd_p2p_iface_limit,
1151 		.num_different_channels = 2,
1152 		.max_interfaces = 2,
1153 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
1154 	},
1155 
1156 	/* SAP + P2P */
1157 	{
1158 		.limits = wlan_hdd_sap_p2p_iface_limit,
1159 		.num_different_channels = 2,
1160 		/* 1-SAP + 1-P2P */
1161 		.max_interfaces = 2,
1162 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
1163 		.beacon_int_infra_match = true,
1164 	},
1165 	/* P2P + P2P */
1166 	{
1167 		.limits = wlan_hdd_p2p_p2p_iface_limit,
1168 		.num_different_channels = 2,
1169 		/* 2-P2P */
1170 		.max_interfaces = 2,
1171 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
1172 		.beacon_int_infra_match = true,
1173 	},
1174 #endif
1175 	/* STA + P2P */
1176 	{
1177 		.limits = wlan_hdd_sta_p2p_iface_limit,
1178 		.num_different_channels = 2,
1179 		.max_interfaces = 2,
1180 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
1181 		.beacon_int_infra_match = true,
1182 	},
1183 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
1184 	/* STA + SAP */
1185 	{
1186 		.limits = wlan_hdd_sta_ap_iface_limit,
1187 		.num_different_channels = 2,
1188 		.max_interfaces = 2,
1189 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
1190 		.beacon_int_infra_match = true,
1191 	},
1192 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
1193 	/* Monitor */
1194 	{
1195 		.limits = wlan_hdd_mon_iface_limit,
1196 		.max_interfaces = 2,
1197 		.num_different_channels = 2,
1198 		.n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
1199 	},
1200 #if defined(WLAN_FEATURE_NAN) && \
1201 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
1202 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
1203 	/* NAN + STA */
1204 	{
1205 		.limits = wlan_hdd_sta_nan_iface_limit,
1206 		.max_interfaces = 2,
1207 		.num_different_channels = 2,
1208 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_nan_iface_limit),
1209 	},
1210 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
1211 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
1212 	/* NAN + SAP */
1213 	{
1214 		.limits = wlan_hdd_sap_nan_iface_limit,
1215 		.num_different_channels = 2,
1216 		.max_interfaces = 2,
1217 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_nan_iface_limit),
1218 		.beacon_int_infra_match = true,
1219 	},
1220 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
1221 #endif /* WLAN_FEATURE_NAN */
1222 };
1223 static struct cfg80211_ops wlan_hdd_cfg80211_ops;
1224 
1225 #ifdef WLAN_NL80211_TESTMODE
1226 enum wlan_hdd_tm_attr {
1227 	WLAN_HDD_TM_ATTR_INVALID = 0,
1228 	WLAN_HDD_TM_ATTR_CMD = 1,
1229 	WLAN_HDD_TM_ATTR_DATA = 2,
1230 	WLAN_HDD_TM_ATTR_STREAM_ID = 3,
1231 	WLAN_HDD_TM_ATTR_TYPE = 4,
1232 	/* keep last */
1233 	WLAN_HDD_TM_ATTR_AFTER_LAST,
1234 	WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
1235 };
1236 
1237 enum wlan_hdd_tm_cmd {
1238 	WLAN_HDD_TM_CMD_WLAN_FTM = 0,
1239 	WLAN_HDD_TM_CMD_WLAN_HB = 1,
1240 };
1241 
1242 #define WLAN_HDD_TM_DATA_MAX_LEN    5000
1243 
1244 static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
1245 	[WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
1246 	[WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
1247 				   .len = WLAN_HDD_TM_DATA_MAX_LEN},
1248 };
1249 #endif /* WLAN_NL80211_TESTMODE */
1250 
1251 enum wlan_hdd_vendor_ie_access_policy {
1252 	WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
1253 	WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
1254 };
1255 
1256 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
1257 static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
1258 	.flags = WIPHY_WOWLAN_MAGIC_PKT,
1259 	.n_patterns = WOWL_MAX_PTRNS_ALLOWED,
1260 	.pattern_min_len = 1,
1261 	.pattern_max_len = WOWL_PTRN_MAX_SIZE,
1262 };
1263 #endif
1264 
1265 /**
1266  * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
1267  * @flags: Pointer to the flags to Add channel switch flag.
1268  *
1269  * This Function adds Channel Switch support flag, if channel switch is
1270  * supported by kernel.
1271  * Return: void.
1272  */
1273 #ifdef CHANNEL_SWITCH_SUPPORTED
hdd_add_channel_switch_support(uint32_t * flags)1274 static inline void hdd_add_channel_switch_support(uint32_t *flags)
1275 {
1276 	*flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
1277 }
1278 #else
hdd_add_channel_switch_support(uint32_t * flags)1279 static inline void hdd_add_channel_switch_support(uint32_t *flags)
1280 {
1281 }
1282 #endif
1283 
1284 #ifdef FEATURE_WLAN_TDLS
1285 
1286 /* TDLS capabilities params */
1287 #define PARAM_MAX_TDLS_SESSION \
1288 		QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
1289 #define PARAM_TDLS_FEATURE_SUPPORT \
1290 		QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
1291 
1292 /**
1293  * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
1294  * @wiphy:    WIPHY structure pointer
1295  * @wdev:     Wireless device structure pointer
1296  * @data:     Pointer to the data received
1297  * @data_len: Length of the data received
1298  *
1299  * This function provides TDLS capabilities
1300  *
1301  * Return: 0 on success and errno on failure
1302  */
__wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1303 static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
1304 						     struct wireless_dev *wdev,
1305 						     const void *data,
1306 						     int data_len)
1307 {
1308 	int status;
1309 	struct net_device *dev = wdev->netdev;
1310 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1311 	struct wlan_objmgr_vdev *vdev;
1312 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1313 	struct sk_buff *skb;
1314 	uint32_t set = 0;
1315 	uint32_t max_num_tdls_sta = 0;
1316 	bool tdls_support;
1317 	bool tdls_external_control;
1318 	bool tdls_sleep_sta_enable;
1319 	bool tdls_buffer_sta;
1320 	bool tdls_off_channel;
1321 	bool tdls_fw_wideband_cap;
1322 
1323 	hdd_enter_dev(wdev->netdev);
1324 
1325 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1326 		hdd_err("Command not allowed in FTM mode");
1327 		return -EPERM;
1328 	}
1329 
1330 	if (hdd_validate_adapter(adapter))
1331 		return -EINVAL;
1332 
1333 	status = wlan_hdd_validate_context(hdd_ctx);
1334 	if (status)
1335 		return status;
1336 
1337 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1338 						       (2 * sizeof(u32)) +
1339 						       NLMSG_HDRLEN);
1340 	if (!skb) {
1341 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1342 		return -EINVAL;
1343 	}
1344 
1345 	if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) ==
1346 	     QDF_STATUS_SUCCESS) && !tdls_support) {
1347 		hdd_debug("TDLS feature not Enabled or Not supported in FW");
1348 		if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
1349 			nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
1350 			hdd_err("nla put fail");
1351 			goto fail;
1352 		}
1353 	} else {
1354 		cfg_tdls_get_external_control(hdd_ctx->psoc,
1355 					      &tdls_external_control);
1356 		cfg_tdls_get_sleep_sta_enable(hdd_ctx->psoc,
1357 					      &tdls_sleep_sta_enable);
1358 		cfg_tdls_get_buffer_sta_enable(hdd_ctx->psoc,
1359 					       &tdls_buffer_sta);
1360 		cfg_tdls_get_off_channel_enable(hdd_ctx->psoc,
1361 						&tdls_off_channel);
1362 		vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
1363 						   WLAN_OSIF_ID);
1364 		if (!vdev) {
1365 			hdd_err("Vdev is null return");
1366 			goto fail;
1367 		}
1368 
1369 		tdls_fw_wideband_cap =
1370 				wlan_cfg80211_tdls_is_fw_wideband_capable(vdev);
1371 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1372 
1373 		set = set | WIFI_TDLS_SUPPORT;
1374 		set = set | (tdls_external_control ?
1375 					WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
1376 		set = set | (tdls_off_channel ?
1377 					WIFI_TDLS_OFFCHANNEL_SUPPORT : 0);
1378 		set = set | (tdls_fw_wideband_cap ?
1379 					WIFI_TDLS_WIDER_BW_SUPPORT : 0);
1380 		max_num_tdls_sta = cfg_tdls_get_max_peer_count(hdd_ctx->psoc);
1381 
1382 		hdd_debug("TDLS Feature supported value %x tdls_max_peer_count:%d",
1383 			  set, max_num_tdls_sta);
1384 		if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
1385 				max_num_tdls_sta) ||
1386 		    nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
1387 			hdd_err("nla put fail");
1388 			goto fail;
1389 		}
1390 	}
1391 	return wlan_cfg80211_vendor_cmd_reply(skb);
1392 fail:
1393 	wlan_cfg80211_vendor_free_skb(skb);
1394 	return -EINVAL;
1395 }
1396 
1397 /**
1398  * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
1399  * @wiphy:    WIPHY structure pointer
1400  * @wdev:     Wireless device structure pointer
1401  * @data:     Pointer to the data received
1402  * @data_len: Length of the data received
1403  *
1404  * This function provides TDLS capabilities
1405  *
1406  * Return: 0 on success and errno on failure
1407  */
1408 static int
wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1409 wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
1410 					struct wireless_dev *wdev,
1411 					const void *data,
1412 					int data_len)
1413 {
1414 	struct osif_psoc_sync *psoc_sync;
1415 	int errno;
1416 
1417 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
1418 	if (errno)
1419 		return errno;
1420 
1421 	errno = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
1422 							  data, data_len);
1423 
1424 	osif_psoc_sync_op_stop(psoc_sync);
1425 
1426 	return errno;
1427 }
1428 
hdd_get_bw_offset(uint32_t ch_width)1429 static uint8_t hdd_get_bw_offset(uint32_t ch_width)
1430 {
1431 	uint8_t bw_offset = 0;
1432 
1433 	if (ch_width == CH_WIDTH_40MHZ)
1434 		bw_offset = 1 << BW_40_OFFSET_BIT;
1435 	else if (ch_width == CH_WIDTH_20MHZ)
1436 		bw_offset = 1 << BW_20_OFFSET_BIT;
1437 
1438 	return bw_offset;
1439 }
1440 
1441 #else /* !FEATURE_WLAN_TDLS */
1442 
hdd_get_bw_offset(uint32_t ch_width)1443 static inline uint8_t hdd_get_bw_offset(uint32_t ch_width)
1444 {
1445 	return 0;
1446 }
1447 
1448 #endif /* FEATURE_WLAN_TDLS */
1449 
1450 /**
1451  * wlan_vendor_bitmap_to_reg_wifi_band_bitmap() - Convert vendor bitmap to
1452  * reg_wifi_band bitmap
1453  * @psoc: PSOC pointer
1454  * @vendor_bitmap: vendor bitmap value coming via vendor command
1455  *
1456  * Return: reg_wifi_band bitmap
1457  */
1458 static uint32_t
wlan_vendor_bitmap_to_reg_wifi_band_bitmap(struct wlan_objmgr_psoc * psoc,uint32_t vendor_bitmap)1459 wlan_vendor_bitmap_to_reg_wifi_band_bitmap(struct wlan_objmgr_psoc *psoc,
1460 					   uint32_t vendor_bitmap)
1461 {
1462 	uint32_t reg_bitmap = 0;
1463 
1464 	if (vendor_bitmap == QCA_SETBAND_AUTO)
1465 		reg_bitmap |= REG_BAND_MASK_ALL;
1466 	if (vendor_bitmap & QCA_SETBAND_2G)
1467 		reg_bitmap |= BIT(REG_BAND_2G);
1468 	if (vendor_bitmap & QCA_SETBAND_5G)
1469 		reg_bitmap |= BIT(REG_BAND_5G);
1470 	if (vendor_bitmap & QCA_SETBAND_6G)
1471 		reg_bitmap |= BIT(REG_BAND_6G);
1472 
1473 	if (!wlan_reg_is_6ghz_supported(psoc)) {
1474 		hdd_debug("Driver doesn't support 6ghz");
1475 		reg_bitmap = (reg_bitmap & (~BIT(REG_BAND_6G)));
1476 	}
1477 
1478 	return reg_bitmap;
1479 }
1480 
wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type * destFreqList,struct ch_avoid_ind_type * srcFreqList)1481 int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
1482 		struct ch_avoid_ind_type *srcFreqList)
1483 {
1484 	int i;
1485 	uint32_t room;
1486 	struct ch_avoid_freq_type *avoid_range =
1487 	&destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
1488 
1489 	room = CH_AVOID_MAX_RANGE - destFreqList->ch_avoid_range_cnt;
1490 	if (srcFreqList->ch_avoid_range_cnt > room) {
1491 		hdd_err("avoid freq overflow");
1492 		return -EINVAL;
1493 	}
1494 	destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
1495 
1496 	for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
1497 		avoid_range->start_freq =
1498 			srcFreqList->avoid_freq_range[i].start_freq;
1499 		avoid_range->end_freq =
1500 			srcFreqList->avoid_freq_range[i].end_freq;
1501 		avoid_range++;
1502 	}
1503 	return 0;
1504 }
1505 /*
1506  * FUNCTION: wlan_hdd_send_avoid_freq_event
1507  * This is called when wlan driver needs to send vendor specific
1508  * avoid frequency range event to userspace
1509  */
wlan_hdd_send_avoid_freq_event(struct hdd_context * hdd_ctx,struct ch_avoid_ind_type * avoid_freq_list)1510 int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
1511 				   struct ch_avoid_ind_type *avoid_freq_list)
1512 {
1513 	struct sk_buff *skb;
1514 	enum qca_nl80211_vendor_subcmds_index index =
1515 		QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX;
1516 
1517 	hdd_enter();
1518 
1519 	if (!hdd_ctx) {
1520 		hdd_err("HDD context is null");
1521 		return -EINVAL;
1522 	}
1523 
1524 	if (!avoid_freq_list) {
1525 		hdd_err("avoid_freq_list is null");
1526 		return -EINVAL;
1527 	}
1528 
1529 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
1530 					       sizeof(struct ch_avoid_ind_type),
1531 					       index, GFP_KERNEL);
1532 	if (!skb) {
1533 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1534 		return -EINVAL;
1535 	}
1536 
1537 	memcpy(skb_put(skb, sizeof(struct ch_avoid_ind_type)),
1538 	       (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
1539 
1540 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
1541 
1542 	hdd_exit();
1543 	return 0;
1544 }
1545 
1546 /*
1547  * define short names for the global vendor params
1548  * used by QCA_NL80211_VENDOR_SUBCMD_HANG
1549  */
1550 #define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
1551 
1552 /**
1553  * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
1554  * hang reason
1555  * @reason: cds recovery reason
1556  *
1557  * Return: Vendor specific reason code
1558  */
1559 static enum qca_wlan_vendor_hang_reason
hdd_convert_hang_reason(enum qdf_hang_reason reason)1560 hdd_convert_hang_reason(enum qdf_hang_reason reason)
1561 {
1562 	u32 ret_val;
1563 
1564 	switch (reason) {
1565 	case QDF_RX_HASH_NO_ENTRY_FOUND:
1566 		ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
1567 		break;
1568 	case QDF_PEER_DELETION_TIMEDOUT:
1569 		ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
1570 		break;
1571 	case QDF_PEER_UNMAP_TIMEDOUT:
1572 		ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
1573 		break;
1574 	case QDF_SCAN_REQ_EXPIRED:
1575 		ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
1576 		break;
1577 	case QDF_SCAN_ATTEMPT_FAILURES:
1578 		ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
1579 		break;
1580 	case QDF_GET_MSG_BUFF_FAILURE:
1581 		ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
1582 		break;
1583 	case QDF_ACTIVE_LIST_TIMEOUT:
1584 		ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
1585 		break;
1586 	case QDF_SUSPEND_TIMEOUT:
1587 		ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
1588 		break;
1589 	case QDF_RESUME_TIMEOUT:
1590 		ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
1591 		break;
1592 	case QDF_WMI_EXCEED_MAX_PENDING_CMDS:
1593 		ret_val = QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS;
1594 		break;
1595 	case QDF_AP_STA_CONNECT_REQ_TIMEOUT:
1596 		ret_val = QCA_WLAN_HANG_AP_STA_CONNECT_REQ_TIMEOUT;
1597 		break;
1598 	case QDF_STA_AP_CONNECT_REQ_TIMEOUT:
1599 		ret_val = QCA_WLAN_HANG_STA_AP_CONNECT_REQ_TIMEOUT;
1600 		break;
1601 	case QDF_MAC_HW_MODE_CHANGE_TIMEOUT:
1602 		ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CHANGE_TIMEOUT;
1603 		break;
1604 	case QDF_MAC_HW_MODE_CONFIG_TIMEOUT:
1605 		ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CONFIG_TIMEOUT;
1606 		break;
1607 	case QDF_VDEV_START_RESPONSE_TIMED_OUT:
1608 		ret_val = QCA_WLAN_HANG_VDEV_START_RESPONSE_TIMED_OUT;
1609 		break;
1610 	case QDF_VDEV_RESTART_RESPONSE_TIMED_OUT:
1611 		ret_val = QCA_WLAN_HANG_VDEV_RESTART_RESPONSE_TIMED_OUT;
1612 		break;
1613 	case QDF_VDEV_STOP_RESPONSE_TIMED_OUT:
1614 		ret_val = QCA_WLAN_HANG_VDEV_STOP_RESPONSE_TIMED_OUT;
1615 		break;
1616 	case QDF_VDEV_DELETE_RESPONSE_TIMED_OUT:
1617 		ret_val = QCA_WLAN_HANG_VDEV_DELETE_RESPONSE_TIMED_OUT;
1618 		break;
1619 	case QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT:
1620 		ret_val = QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
1621 		break;
1622 	case QDF_WMI_BUF_SEQUENCE_MISMATCH:
1623 		ret_val = QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
1624 		break;
1625 	case QDF_HAL_REG_WRITE_FAILURE:
1626 		ret_val = QCA_WLAN_HANG_REG_WRITE_FAILURE;
1627 		break;
1628 	case QDF_SUSPEND_NO_CREDIT:
1629 		ret_val = QCA_WLAN_HANG_SUSPEND_NO_CREDIT;
1630 		break;
1631 	case QCA_HANG_BUS_FAILURE:
1632 		ret_val = QCA_WLAN_HANG_BUS_FAILURE;
1633 		break;
1634 	case QDF_TASKLET_CREDIT_LATENCY_DETECT:
1635 		ret_val = QCA_WLAN_HANG_TASKLET_CREDIT_LATENCY_DETECT;
1636 		break;
1637 	case QDF_RX_REG_PKT_ROUTE_ERR:
1638 		ret_val = QCA_WLAN_HANG_RX_MSDU_BUF_RCVD_IN_ERR_RING;
1639 		break;
1640 	case QDF_VDEV_SM_OUT_OF_SYNC:
1641 		ret_val = QCA_WLAN_HANG_VDEV_SM_OUT_OF_SYNC;
1642 		break;
1643 	case QDF_STATS_REQ_TIMEDOUT:
1644 		ret_val = QCA_WLAN_HANG_STATS_REQ_TIMEOUT;
1645 		break;
1646 	case QDF_TX_DESC_LEAK:
1647 		ret_val = QCA_WLAN_HANG_TX_DESC_LEAK;
1648 		break;
1649 	case QDF_SCHED_TIMEOUT:
1650 		ret_val = QCA_WLAN_HANG_SCHED_TIMEOUT;
1651 		break;
1652 	case QDF_SELF_PEER_DEL_FAILED:
1653 		ret_val = QCA_WLAN_HANG_SELF_PEER_DEL_FAIL;
1654 		break;
1655 	case QDF_DEL_SELF_STA_FAILED:
1656 		ret_val = QCA_WLAN_HANG_DEL_SELF_STA_FAIL;
1657 		break;
1658 	case QDF_FLUSH_LOGS:
1659 		ret_val = QCA_WLAN_HANG_FLUSH_LOGS;
1660 		break;
1661 	case QDF_HOST_WAKEUP_REASON_PAGEFAULT:
1662 		ret_val = QCA_WLAN_HANG_HOST_WAKEUP_REASON_PAGE_FAULT;
1663 		break;
1664 	case QDF_REASON_UNSPECIFIED:
1665 	default:
1666 		ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
1667 		break;
1668 	}
1669 	return ret_val;
1670 }
1671 
1672 /**
1673  * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
1674  * @hdd_ctx: Pointer to hdd context
1675  * @reason: cds recovery reason
1676  * @data: Hang Data
1677  * @data_len: length of @data
1678  *
1679  * Return: 0 on success or failure reason
1680  */
wlan_hdd_send_hang_reason_event(struct hdd_context * hdd_ctx,enum qdf_hang_reason reason,uint8_t * data,size_t data_len)1681 int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
1682 				    enum qdf_hang_reason reason, uint8_t *data,
1683 				    size_t data_len)
1684 {
1685 	struct sk_buff *vendor_event;
1686 	enum qca_wlan_vendor_hang_reason hang_reason;
1687 
1688 	hdd_enter();
1689 
1690 	if (!hdd_ctx) {
1691 		hdd_err("HDD context is null");
1692 		return -EINVAL;
1693 	}
1694 
1695 	vendor_event = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1696 							NULL,
1697 							sizeof(uint32_t) +
1698 							data_len,
1699 							HANG_REASON_INDEX,
1700 							GFP_KERNEL);
1701 	if (!vendor_event) {
1702 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1703 		return -ENOMEM;
1704 	}
1705 
1706 	hang_reason = hdd_convert_hang_reason(reason);
1707 
1708 	if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
1709 			(uint32_t)hang_reason) ||
1710 	    nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON_DATA,
1711 		    data_len, data)) {
1712 		hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
1713 		wlan_cfg80211_vendor_free_skb(vendor_event);
1714 		return -EINVAL;
1715 	}
1716 
1717 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1718 
1719 	hdd_exit();
1720 	return 0;
1721 }
1722 
1723 #undef HANG_REASON_INDEX
1724 
1725 /**
1726  * wlan_hdd_get_adjacent_chan_freq(): Gets next/previous channel
1727  * with respect to the channel passed.
1728  * @freq: Channel frequency
1729  * @upper: If "true" then next channel is returned or else
1730  * previous channel is returned.
1731  *
1732  * This function returns the next/previous adjacent-channel to
1733  * the channel passed. If "upper = true" then next channel is
1734  * returned else previous is returned.
1735  */
wlan_hdd_get_adjacent_chan_freq(qdf_freq_t freq,bool upper)1736 static qdf_freq_t wlan_hdd_get_adjacent_chan_freq(qdf_freq_t freq, bool upper)
1737 {
1738 	enum channel_enum ch_idx = wlan_reg_get_chan_enum_for_freq(freq);
1739 
1740 	if (reg_is_chan_enum_invalid(ch_idx))
1741 		return -EINVAL;
1742 
1743 	if (upper && (ch_idx < (NUM_CHANNELS - 1)))
1744 		ch_idx++;
1745 	else if (!upper && (ch_idx > CHAN_ENUM_2412))
1746 		ch_idx--;
1747 	else
1748 		return -EINVAL;
1749 
1750 	return WLAN_REG_CH_TO_FREQ(ch_idx);
1751 }
1752 
1753 /**
1754  * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
1755  * avoided when Do_Not_Break_Stream is active.
1756  * @hdd_ctx:  HDD Context
1757  * @op_freq:  AP/P2P-GO operating channel frequency
1758  *
1759  * This function sends list of frequencies to be avoided when
1760  * Do_Not_Break_Stream is active.
1761  * To clear the avoid_frequency_list in the application,
1762  * op_freq = 0 can be passed.
1763  *
1764  * Return: 0 on success and errno on failure
1765  */
wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context * hdd_ctx,qdf_freq_t op_freq)1766 int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx,
1767 				      qdf_freq_t op_freq)
1768 {
1769 	struct ch_avoid_ind_type p2p_avoid_freq_list;
1770 	qdf_freq_t min_freq, max_freq;
1771 	int ret;
1772 	qdf_freq_t freq;
1773 
1774 	hdd_enter();
1775 
1776 	if (!hdd_ctx) {
1777 		hdd_err("invalid param");
1778 		return -EINVAL;
1779 	}
1780 
1781 	qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
1782 	/*
1783 	 * If channel passed is zero, clear the avoid_freq list in application.
1784 	 */
1785 	if (!op_freq) {
1786 #ifdef FEATURE_WLAN_CH_AVOID
1787 		mutex_lock(&hdd_ctx->avoid_freq_lock);
1788 		qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
1789 				sizeof(struct ch_avoid_ind_type));
1790 		if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
1791 			memcpy(&p2p_avoid_freq_list,
1792 			       &hdd_ctx->coex_avoid_freq_list,
1793 			       sizeof(struct ch_avoid_ind_type));
1794 		mutex_unlock(&hdd_ctx->avoid_freq_lock);
1795 #endif
1796 		ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
1797 						     &p2p_avoid_freq_list);
1798 		if (ret)
1799 			hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1800 				ret);
1801 
1802 		return ret;
1803 	}
1804 
1805 	if (WLAN_REG_IS_24GHZ_CH_FREQ(op_freq)) {
1806 		min_freq = WLAN_REG_MIN_24GHZ_CHAN_FREQ;
1807 		max_freq = WLAN_REG_MAX_24GHZ_CHAN_FREQ;
1808 	} else if (WLAN_REG_IS_5GHZ_CH_FREQ(op_freq)) {
1809 		min_freq = WLAN_REG_MIN_5GHZ_CHAN_FREQ;
1810 		max_freq = WLAN_REG_MAX_5GHZ_CHAN_FREQ;
1811 	} else {
1812 		hdd_err("invalid channel freq:%d", op_freq);
1813 		return -EINVAL;
1814 	}
1815 
1816 	if (op_freq > min_freq && op_freq < max_freq) {
1817 		p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1818 		p2p_avoid_freq_list.avoid_freq_range[0].start_freq = min_freq;
1819 
1820 		/* Get channel before the op_freq */
1821 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, false);
1822 		if (freq < 0)
1823 			return -EINVAL;
1824 		p2p_avoid_freq_list.avoid_freq_range[0].end_freq = freq;
1825 
1826 		/* Get channel next to the op_freq */
1827 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, true);
1828 		if (freq < 0)
1829 			return -EINVAL;
1830 		p2p_avoid_freq_list.avoid_freq_range[1].start_freq = freq;
1831 
1832 		p2p_avoid_freq_list.avoid_freq_range[1].end_freq = max_freq;
1833 	} else if (op_freq == min_freq) {
1834 		p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1835 
1836 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, true);
1837 		if (freq < 0)
1838 			return -EINVAL;
1839 		p2p_avoid_freq_list.avoid_freq_range[0].start_freq = freq;
1840 
1841 		p2p_avoid_freq_list.avoid_freq_range[0].end_freq = max_freq;
1842 	} else {
1843 		p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1844 		p2p_avoid_freq_list.avoid_freq_range[0].start_freq = min_freq;
1845 
1846 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, false);
1847 		if (freq < 0)
1848 			return -EINVAL;
1849 		p2p_avoid_freq_list.avoid_freq_range[0].end_freq = freq;
1850 	}
1851 #ifdef FEATURE_WLAN_CH_AVOID
1852 	mutex_lock(&hdd_ctx->avoid_freq_lock);
1853 	hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1854 	if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
1855 		ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
1856 				&hdd_ctx->coex_avoid_freq_list);
1857 		if (ret) {
1858 			mutex_unlock(&hdd_ctx->avoid_freq_lock);
1859 			hdd_err("avoid freq merge failed");
1860 			return ret;
1861 		}
1862 	}
1863 	mutex_unlock(&hdd_ctx->avoid_freq_lock);
1864 #endif
1865 	ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
1866 	if (ret)
1867 		hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1868 
1869 	return ret;
1870 }
1871 
1872 /* vendor specific events */
1873 static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
1874 	[QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1875 		.vendor_id =
1876 			QCA_NL80211_VENDOR_ID,
1877 		.subcmd =
1878 			QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1879 	},
1880 
1881 	[QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1882 		.vendor_id =
1883 			QCA_NL80211_VENDOR_ID,
1884 		.subcmd =
1885 			QCA_NL80211_VENDOR_SUBCMD_NAN
1886 	},
1887 
1888 #ifdef WLAN_FEATURE_STATS_EXT
1889 	[QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1890 		.vendor_id =
1891 			QCA_NL80211_VENDOR_ID,
1892 		.subcmd =
1893 			QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1894 	},
1895 #endif /* WLAN_FEATURE_STATS_EXT */
1896 	[QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS_INDEX] = {
1897 		.vendor_id =
1898 			QCA_NL80211_VENDOR_ID,
1899 		.subcmd =
1900 			QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS
1901 	},
1902 
1903 #ifdef FEATURE_WLAN_EXTSCAN
1904 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1905 		.vendor_id =
1906 			QCA_NL80211_VENDOR_ID,
1907 		.subcmd =
1908 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1909 	},
1910 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1911 		.vendor_id =
1912 			QCA_NL80211_VENDOR_ID,
1913 		.subcmd =
1914 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1915 	},
1916 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1917 		.
1918 		vendor_id
1919 			=
1920 				QCA_NL80211_VENDOR_ID,
1921 		.subcmd =
1922 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1923 	},
1924 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1925 		.
1926 		vendor_id
1927 			=
1928 				QCA_NL80211_VENDOR_ID,
1929 		.
1930 		subcmd =
1931 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1932 	},
1933 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1934 		.
1935 		vendor_id
1936 			=
1937 				QCA_NL80211_VENDOR_ID,
1938 		.
1939 		subcmd
1940 			=
1941 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1942 	},
1943 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1944 		.
1945 		vendor_id
1946 			=
1947 				QCA_NL80211_VENDOR_ID,
1948 		.subcmd =
1949 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1950 	},
1951 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1952 		.vendor_id =
1953 			QCA_NL80211_VENDOR_ID,
1954 		.subcmd =
1955 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1956 	},
1957 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1958 		.
1959 		vendor_id
1960 			=
1961 				QCA_NL80211_VENDOR_ID,
1962 		.subcmd =
1963 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1964 	},
1965 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1966 		.
1967 		vendor_id
1968 			=
1969 				QCA_NL80211_VENDOR_ID,
1970 		.subcmd =
1971 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1972 	},
1973 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1974 		.
1975 		vendor_id
1976 			=
1977 				QCA_NL80211_VENDOR_ID,
1978 		.
1979 		subcmd
1980 			=
1981 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1982 	},
1983 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1984 		.
1985 		vendor_id
1986 			=
1987 				QCA_NL80211_VENDOR_ID,
1988 		.
1989 		subcmd =
1990 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1991 	},
1992 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1993 		.
1994 		vendor_id
1995 			=
1996 				QCA_NL80211_VENDOR_ID,
1997 		.
1998 		subcmd
1999 			=
2000 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
2001 	},
2002 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
2003 		.
2004 		vendor_id
2005 			=
2006 				QCA_NL80211_VENDOR_ID,
2007 		.
2008 		subcmd
2009 			=
2010 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
2011 	},
2012 #endif /* FEATURE_WLAN_EXTSCAN */
2013 
2014 #ifdef WLAN_FEATURE_LINK_LAYER_STATS
2015 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
2016 		.vendor_id =
2017 			QCA_NL80211_VENDOR_ID,
2018 		.subcmd =
2019 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
2020 	},
2021 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
2022 		.vendor_id =
2023 			QCA_NL80211_VENDOR_ID,
2024 		.subcmd =
2025 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
2026 	},
2027 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
2028 		.vendor_id =
2029 			QCA_NL80211_VENDOR_ID,
2030 		.subcmd =
2031 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
2032 	},
2033 	[QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
2034 		.vendor_id =
2035 			QCA_NL80211_VENDOR_ID,
2036 		.subcmd =
2037 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
2038 	},
2039 	[QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
2040 		.vendor_id =
2041 			QCA_NL80211_VENDOR_ID,
2042 		.subcmd =
2043 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
2044 	},
2045 	[QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
2046 		.vendor_id =
2047 			QCA_NL80211_VENDOR_ID,
2048 		.subcmd =
2049 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
2050 	},
2051 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
2052 		.vendor_id =
2053 			QCA_NL80211_VENDOR_ID,
2054 		.subcmd =
2055 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
2056 	},
2057 #endif /* WLAN_FEATURE_LINK_LAYER_STATS */
2058 	[QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
2059 		.vendor_id =
2060 			QCA_NL80211_VENDOR_ID,
2061 		.subcmd =
2062 			QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
2063 	},
2064 	[QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
2065 		.vendor_id = QCA_NL80211_VENDOR_ID,
2066 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
2067 	},
2068 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2069 	[QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
2070 		.vendor_id =
2071 			QCA_NL80211_VENDOR_ID,
2072 		.subcmd =
2073 			QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
2074 	},
2075 #endif
2076 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] =  {
2077 		.vendor_id =
2078 			QCA_NL80211_VENDOR_ID,
2079 		.subcmd =
2080 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
2081 	},
2082 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] =  {
2083 		.vendor_id =
2084 			QCA_NL80211_VENDOR_ID,
2085 		.subcmd =
2086 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
2087 	},
2088 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] =  {
2089 		.vendor_id =
2090 			QCA_NL80211_VENDOR_ID,
2091 		.subcmd =
2092 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
2093 	},
2094 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] =  {
2095 		.vendor_id =
2096 			QCA_NL80211_VENDOR_ID,
2097 		.subcmd =
2098 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
2099 	},
2100 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] =  {
2101 		.vendor_id =
2102 			QCA_NL80211_VENDOR_ID,
2103 		.subcmd =
2104 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
2105 	},
2106 #ifdef FEATURE_WLAN_EXTSCAN
2107 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
2108 		.vendor_id = QCA_NL80211_VENDOR_ID,
2109 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
2110 	},
2111 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
2112 		.vendor_id = QCA_NL80211_VENDOR_ID,
2113 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
2114 	},
2115 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
2116 		.vendor_id = QCA_NL80211_VENDOR_ID,
2117 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
2118 	},
2119 #endif /* FEATURE_WLAN_EXTSCAN */
2120 
2121 	FEATURE_RSSI_MONITOR_VENDOR_EVENTS
2122 
2123 #ifdef WLAN_FEATURE_TSF
2124 	[QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
2125 		.vendor_id = QCA_NL80211_VENDOR_ID,
2126 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
2127 	},
2128 #endif
2129 	[QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
2130 		.vendor_id = QCA_NL80211_VENDOR_ID,
2131 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
2132 	},
2133 	[QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
2134 		.vendor_id = QCA_NL80211_VENDOR_ID,
2135 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
2136 	},
2137 	/* OCB events */
2138 	[QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
2139 		.vendor_id = QCA_NL80211_VENDOR_ID,
2140 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
2141 	},
2142 #ifdef FEATURE_LFR_SUBNET_DETECTION
2143 	[QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
2144 		.vendor_id = QCA_NL80211_VENDOR_ID,
2145 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
2146 	},
2147 #endif /*FEATURE_LFR_SUBNET_DETECTION */
2148 
2149 	FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS_INDEX
2150 
2151 	[QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
2152 		.vendor_id = QCA_NL80211_VENDOR_ID,
2153 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
2154 	},
2155 
2156 	[QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
2157 		.vendor_id = QCA_NL80211_VENDOR_ID,
2158 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
2159 	},
2160 	[QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
2161 		.vendor_id = QCA_NL80211_VENDOR_ID,
2162 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
2163 	},
2164 	[QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
2165 		.vendor_id = QCA_NL80211_VENDOR_ID,
2166 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
2167 	},
2168 	[QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
2169 		.vendor_id = QCA_NL80211_VENDOR_ID,
2170 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
2171 	},
2172 	[QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
2173 		.vendor_id = QCA_NL80211_VENDOR_ID,
2174 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
2175 	},
2176 	[QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
2177 		.vendor_id = QCA_NL80211_VENDOR_ID,
2178 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
2179 	},
2180 	[QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
2181 		.vendor_id = QCA_NL80211_VENDOR_ID,
2182 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
2183 	},
2184 	[QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX] = {
2185 		.vendor_id = QCA_NL80211_VENDOR_ID,
2186 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT,
2187 	 },
2188 	[QCA_NL80211_VENDOR_SUBCMD_NAN_EXT_INDEX] = {
2189 		.vendor_id = QCA_NL80211_VENDOR_ID,
2190 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN_EXT
2191 	},
2192 	[QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX] = {
2193 		.vendor_id = QCA_NL80211_VENDOR_ID,
2194 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
2195 	},
2196 
2197 	BCN_RECV_FEATURE_VENDOR_EVENTS
2198 	FEATURE_MEDIUM_ASSESS_VENDOR_EVENTS
2199 	[QCA_NL80211_VENDOR_SUBCMD_ROAM_INDEX] = {
2200 		.vendor_id = QCA_NL80211_VENDOR_ID,
2201 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
2202 	},
2203 	[QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX] = {
2204 		.vendor_id = QCA_NL80211_VENDOR_ID,
2205 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_OEM_DATA,
2206 	},
2207 	[QCA_NL80211_VENDOR_SUBCMD_REQUEST_SAR_LIMITS_INDEX] = {
2208 		.vendor_id = QCA_NL80211_VENDOR_ID,
2209 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS_EVENT,
2210 	},
2211 	[QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX] = {
2212 		.vendor_id = QCA_NL80211_VENDOR_ID,
2213 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO,
2214 	},
2215 	FEATURE_THERMAL_VENDOR_EVENTS
2216 	FEATURE_DRIVER_DISCONNECT_REASON
2217 #ifdef WLAN_SUPPORT_TWT
2218 	FEATURE_TWT_VENDOR_EVENTS
2219 #endif
2220 	FEATURE_CFR_DATA_VENDOR_EVENTS
2221 #ifdef WLAN_FEATURE_CONNECTIVITY_LOGGING
2222 	FEATURE_CONNECTIVITY_LOGGING_EVENT
2223 #endif
2224 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2225 	[QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS_INDEX] = {
2226 		.vendor_id = QCA_NL80211_VENDOR_ID,
2227 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS,
2228 	},
2229 #endif
2230 	FEATURE_MCC_QUOTA_VENDOR_EVENTS
2231 	[QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY_INDEX] = {
2232 		.vendor_id = QCA_NL80211_VENDOR_ID,
2233 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY,
2234 	},
2235 	FEATURE_WIFI_POS_11AZ_AUTH_EVENTS
2236 #ifdef WLAN_FEATURE_SR
2237 	[QCA_NL80211_VENDOR_SUBCMD_SR_INDEX] = {
2238 		.vendor_id = QCA_NL80211_VENDOR_ID,
2239 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_SR,
2240 	},
2241 #endif
2242 	FEATURE_GREEN_AP_LOW_LATENCY_PWR_SAVE_EVENT
2243 	FEATURE_ROAM_STATS_EVENTS
2244 #ifdef WLAN_FEATURE_11BE_MLO
2245 	[QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP_INDEX] = {
2246 		.vendor_id = QCA_NL80211_VENDOR_ID,
2247 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP,
2248 	},
2249 	[QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG_INDEX] = {
2250 		.vendor_id = QCA_NL80211_VENDOR_ID,
2251 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG,
2252 	},
2253 #endif
2254 	FEATURE_AFC_VENDOR_EVENTS
2255 
2256 	[QCA_NL80211_VENDOR_SUBCMD_AUDIO_TRANSPORT_SWITCH_INDEX] = {
2257 		.vendor_id = QCA_NL80211_VENDOR_ID,
2258 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_AUDIO_TRANSPORT_SWITCH,
2259 	},
2260 
2261 	FEATURE_TX_LATENCY_STATS_EVENTS
2262 	[QCA_NL80211_VENDOR_SUBCMD_FW_PAGE_FAULT_REPORT_INDEX] = {
2263 		.vendor_id = QCA_NL80211_VENDOR_ID,
2264 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_FW_PAGE_FAULT_REPORT,
2265 	},
2266 };
2267 
2268 /**
2269  * __is_driver_dfs_capable() - get driver DFS capability
2270  * @wiphy:   pointer to wireless wiphy structure.
2271  * @wdev:    pointer to wireless_dev structure.
2272  * @data:    Pointer to the data to be passed via vendor interface
2273  * @data_len:Length of the data to be passed
2274  *
2275  * This function is called by userspace to indicate whether or not
2276  * the driver supports DFS offload.
2277  *
2278  * Return: 0 on success, negative errno on failure
2279  */
__is_driver_dfs_capable(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)2280 static int __is_driver_dfs_capable(struct wiphy *wiphy,
2281 				   struct wireless_dev *wdev,
2282 				   const void *data,
2283 				   int data_len)
2284 {
2285 	u32 dfs_capability = 0;
2286 	struct sk_buff *temp_skbuff;
2287 	int ret_val;
2288 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
2289 
2290 	hdd_enter_dev(wdev->netdev);
2291 
2292 	ret_val = wlan_hdd_validate_context(hdd_ctx);
2293 	if (ret_val)
2294 		return ret_val;
2295 
2296 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2297 		hdd_err("Command not allowed in FTM mode");
2298 		return -EPERM;
2299 	}
2300 
2301 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
2302 	defined(CFG80211_DFS_OFFLOAD_BACKPORT)
2303 	dfs_capability =
2304 		wiphy_ext_feature_isset(wiphy,
2305 					NL80211_EXT_FEATURE_DFS_OFFLOAD);
2306 #else
2307 	dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
2308 #endif
2309 
2310 	temp_skbuff = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2311 							       sizeof(u32) +
2312 							       NLMSG_HDRLEN);
2313 	if (temp_skbuff) {
2314 		ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
2315 				      dfs_capability);
2316 		if (ret_val) {
2317 			hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
2318 			wlan_cfg80211_vendor_free_skb(temp_skbuff);
2319 
2320 			return ret_val;
2321 		}
2322 
2323 		return wlan_cfg80211_vendor_cmd_reply(temp_skbuff);
2324 	}
2325 
2326 	hdd_err("dfs capability: buffer alloc fail");
2327 	return -ENOMEM;
2328 }
2329 
2330 /**
2331  * is_driver_dfs_capable() - get driver DFS capability
2332  * @wiphy:   pointer to wireless wiphy structure.
2333  * @wdev:    pointer to wireless_dev structure.
2334  * @data:    Pointer to the data to be passed via vendor interface
2335  * @data_len:Length of the data to be passed
2336  *
2337  * This function is called by userspace to indicate whether or not
2338  * the driver supports DFS offload.  This is an SSR-protected
2339  * wrapper function.
2340  *
2341  * Return: 0 on success, negative errno on failure
2342  */
is_driver_dfs_capable(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)2343 static int is_driver_dfs_capable(struct wiphy *wiphy,
2344 				 struct wireless_dev *wdev,
2345 				 const void *data,
2346 				 int data_len)
2347 {
2348 	struct osif_psoc_sync *psoc_sync;
2349 	int errno;
2350 
2351 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
2352 	if (errno)
2353 		return errno;
2354 
2355 	errno = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
2356 
2357 	osif_psoc_sync_op_stop(psoc_sync);
2358 
2359 	return errno;
2360 }
2361 
2362 /**
2363  * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
2364  *
2365  * @adapter: SAP adapter pointer
2366  *
2367  * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
2368  * radio. So in case of DFS MCC scenario override current SAP given config
2369  * to follow concurrent SAP DFS config
2370  *
2371  * Return: 0 - No DFS issue, 1 - Override done and negative error codes
2372  */
wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter * adapter)2373 int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
2374 {
2375 	struct hdd_adapter *con_sap_adapter;
2376 	struct sap_config *sap_config, *con_sap_config;
2377 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2378 	uint32_t con_ch_freq;
2379 
2380 	if (!hdd_ctx) {
2381 		hdd_err("hdd context is NULL");
2382 		return 0;
2383 	}
2384 
2385 	/*
2386 	 * Check if AP+AP case, once primary AP chooses a DFS
2387 	 * channel secondary AP should always follow primary APs channel
2388 	 */
2389 	if (!policy_mgr_concurrent_beaconing_sessions_running(
2390 		hdd_ctx->psoc))
2391 		return 0;
2392 
2393 	con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
2394 	if (!con_sap_adapter)
2395 		return 0;
2396 
2397 	sap_config = &adapter->deflink->session.ap.sap_config;
2398 	con_sap_config = &con_sap_adapter->deflink->session.ap.sap_config;
2399 	con_ch_freq = con_sap_adapter->deflink->session.ap.operating_chan_freq;
2400 
2401 	if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, con_ch_freq))
2402 		return 0;
2403 
2404 	hdd_debug("Only SCC AP-AP DFS Permitted (ch_freq=%d, con_ch_freq=%d)",
2405 		  sap_config->chan_freq, con_ch_freq);
2406 	hdd_debug("Overriding guest AP's channel");
2407 	sap_config->chan_freq = con_ch_freq;
2408 
2409 	if (con_sap_config->acs_cfg.acs_mode == true) {
2410 		if (con_ch_freq != con_sap_config->acs_cfg.pri_ch_freq &&
2411 		    con_ch_freq != con_sap_config->acs_cfg.ht_sec_ch_freq) {
2412 			hdd_err("Primary AP channel config error");
2413 			hdd_err("Operating ch: %d ACS ch freq: %d Sec Freq %d",
2414 				con_ch_freq,
2415 				con_sap_config->acs_cfg.pri_ch_freq,
2416 				con_sap_config->acs_cfg.ht_sec_ch_freq);
2417 			return -EINVAL;
2418 		}
2419 		/* Sec AP ACS info is overwritten with Pri AP due to DFS
2420 		 * MCC restriction. So free ch list allocated in do_acs
2421 		 * func for Sec AP and realloc for Pri AP ch list size
2422 		 */
2423 		if (sap_config->acs_cfg.freq_list) {
2424 			qdf_mem_free(sap_config->acs_cfg.freq_list);
2425 			sap_config->acs_cfg.freq_list = NULL;
2426 		}
2427 		if (sap_config->acs_cfg.master_freq_list) {
2428 			qdf_mem_free(sap_config->acs_cfg.master_freq_list);
2429 			sap_config->acs_cfg.master_freq_list = NULL;
2430 		}
2431 
2432 		qdf_mem_copy(&sap_config->acs_cfg,
2433 			     &con_sap_config->acs_cfg,
2434 			     sizeof(struct sap_acs_cfg));
2435 
2436 		sap_config->acs_cfg.freq_list =
2437 			qdf_mem_malloc(sizeof(uint32_t) *
2438 				con_sap_config->acs_cfg.ch_list_count);
2439 		if (!sap_config->acs_cfg.freq_list) {
2440 			sap_config->acs_cfg.ch_list_count = 0;
2441 			return -ENOMEM;
2442 		}
2443 		qdf_mem_copy(sap_config->acs_cfg.freq_list,
2444 			     con_sap_config->acs_cfg.freq_list,
2445 			     con_sap_config->acs_cfg.ch_list_count *
2446 				sizeof(uint32_t));
2447 
2448 		sap_config->acs_cfg.master_freq_list =
2449 			qdf_mem_malloc(sizeof(uint32_t) *
2450 				con_sap_config->acs_cfg.master_ch_list_count);
2451 		if (!sap_config->acs_cfg.master_freq_list) {
2452 			sap_config->acs_cfg.master_ch_list_count = 0;
2453 			qdf_mem_free(sap_config->acs_cfg.freq_list);
2454 			sap_config->acs_cfg.freq_list = NULL;
2455 			return -ENOMEM;
2456 		}
2457 		qdf_mem_copy(sap_config->acs_cfg.master_freq_list,
2458 			     con_sap_config->acs_cfg.master_freq_list,
2459 			     con_sap_config->acs_cfg.master_ch_list_count *
2460 				sizeof(uint32_t));
2461 	} else {
2462 		sap_config->acs_cfg.pri_ch_freq = con_ch_freq;
2463 		if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
2464 			sap_config->acs_cfg.ht_sec_ch_freq =
2465 						con_sap_config->sec_ch_freq;
2466 	}
2467 
2468 	return con_ch_freq;
2469 }
2470 
2471 /**
2472  * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
2473  * @sap_cfg: pointer to SAP config struct
2474  * @hw_mode: hw mode retrieved from vendor command buffer
2475  * @ht_enabled: whether HT phy mode is enabled
2476  * @vht_enabled: whether VHT phy mode is enabled
2477  *
2478  * This function populates the ACS hw mode based on the configuration retrieved
2479  * from the vendor command buffer; and sets ACS start and end channel for the
2480  * given band.
2481  *
2482  * Return: 0 if success; -EINVAL if ACS channel list is NULL
2483  */
wlan_hdd_set_acs_ch_range(struct sap_config * sap_cfg,enum qca_wlan_vendor_acs_hw_mode hw_mode,bool ht_enabled,bool vht_enabled)2484 static int wlan_hdd_set_acs_ch_range(
2485 	struct sap_config *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
2486 	bool ht_enabled, bool vht_enabled)
2487 {
2488 	int i;
2489 
2490 	if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
2491 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
2492 		sap_cfg->acs_cfg.start_ch_freq =
2493 				wlan_reg_ch_to_freq(CHAN_ENUM_2412);
2494 		sap_cfg->acs_cfg.end_ch_freq =
2495 				wlan_reg_ch_to_freq(CHAN_ENUM_2484);
2496 	} else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
2497 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
2498 		sap_cfg->acs_cfg.start_ch_freq =
2499 				wlan_reg_ch_to_freq(CHAN_ENUM_2412);
2500 		sap_cfg->acs_cfg.end_ch_freq =
2501 				wlan_reg_ch_to_freq(CHAN_ENUM_2472);
2502 	} else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
2503 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
2504 		sap_cfg->acs_cfg.start_ch_freq =
2505 				wlan_reg_ch_to_freq(CHAN_ENUM_5180);
2506 		sap_cfg->acs_cfg.end_ch_freq =
2507 				wlan_reg_ch_to_freq(CHAN_ENUM_5885);
2508 	} else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
2509 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
2510 		sap_cfg->acs_cfg.start_ch_freq =
2511 				wlan_reg_ch_to_freq(CHAN_ENUM_2412);
2512 		sap_cfg->acs_cfg.end_ch_freq =
2513 				wlan_reg_ch_to_freq(CHAN_ENUM_5885);
2514 	}
2515 
2516 	if (ht_enabled)
2517 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
2518 
2519 	if (vht_enabled)
2520 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2521 
2522 	/* Parse ACS Chan list from hostapd */
2523 	if (!sap_cfg->acs_cfg.freq_list)
2524 		return -EINVAL;
2525 
2526 	sap_cfg->acs_cfg.start_ch_freq = sap_cfg->acs_cfg.freq_list[0];
2527 	sap_cfg->acs_cfg.end_ch_freq =
2528 		sap_cfg->acs_cfg.freq_list[sap_cfg->acs_cfg.ch_list_count - 1];
2529 	for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
2530 		/* avoid channel as start channel */
2531 		if (sap_cfg->acs_cfg.start_ch_freq >
2532 		    sap_cfg->acs_cfg.freq_list[i] &&
2533 		    sap_cfg->acs_cfg.freq_list[i] != 0)
2534 			sap_cfg->acs_cfg.start_ch_freq =
2535 			    sap_cfg->acs_cfg.freq_list[i];
2536 		if (sap_cfg->acs_cfg.end_ch_freq <
2537 				sap_cfg->acs_cfg.freq_list[i])
2538 			sap_cfg->acs_cfg.end_ch_freq =
2539 			    sap_cfg->acs_cfg.freq_list[i];
2540 	}
2541 
2542 	return 0;
2543 }
2544 
hdd_update_acs_channel_list(struct sap_config * sap_config,enum band_info band)2545 static void hdd_update_acs_channel_list(struct sap_config *sap_config,
2546 					enum band_info band)
2547 {
2548 	int i, temp_count = 0;
2549 	int acs_list_count = sap_config->acs_cfg.ch_list_count;
2550 
2551 	for (i = 0; i < acs_list_count; i++) {
2552 		if (BAND_2G == band) {
2553 			if (WLAN_REG_IS_24GHZ_CH_FREQ(
2554 				sap_config->acs_cfg.freq_list[i])) {
2555 				sap_config->acs_cfg.freq_list[temp_count] =
2556 					sap_config->acs_cfg.freq_list[i];
2557 				temp_count++;
2558 			}
2559 		} else if (BAND_5G == band) {
2560 			if (WLAN_REG_IS_5GHZ_CH_FREQ(
2561 				sap_config->acs_cfg.freq_list[i]) ||
2562 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(
2563 				sap_config->acs_cfg.freq_list[i])) {
2564 				sap_config->acs_cfg.freq_list[temp_count] =
2565 					sap_config->acs_cfg.freq_list[i];
2566 				temp_count++;
2567 			}
2568 		}
2569 	}
2570 	sap_config->acs_cfg.ch_list_count = temp_count;
2571 }
2572 
2573 /**
2574  * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
2575  * @link_info: Link info pointer in SAP HDD adapter
2576  *
2577  * This function starts the ACS procedure if there are no
2578  * constraints like MBSSID DFS restrictions.
2579  *
2580  * Return: Status of ACS Start procedure
2581  */
wlan_hdd_cfg80211_start_acs(struct wlan_hdd_link_info * link_info)2582 int wlan_hdd_cfg80211_start_acs(struct wlan_hdd_link_info *link_info)
2583 {
2584 	struct hdd_context *hdd_ctx;
2585 	struct sap_config *sap_config;
2586 	struct sap_context *sap_ctx;
2587 	struct hdd_ap_ctx *ap_ctx;
2588 	sap_event_cb acs_event_callback;
2589 	uint8_t mcc_to_scc_switch = 0;
2590 	int status;
2591 	QDF_STATUS qdf_status;
2592 	struct hdd_adapter *adapter = link_info->adapter;
2593 
2594 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2595 	status = wlan_hdd_validate_context(hdd_ctx);
2596 	if (0 != status)
2597 		return status;
2598 
2599 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
2600 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
2601 	sap_config = &ap_ctx->sap_config;
2602 
2603 	if (hdd_ctx->acs_policy.acs_chan_freq)
2604 		sap_config->chan_freq = hdd_ctx->acs_policy.acs_chan_freq;
2605 	else
2606 		sap_config->chan_freq = AUTO_CHANNEL_SELECT;
2607 	ucfg_policy_mgr_get_mcc_scc_switch(hdd_ctx->psoc,
2608 					   &mcc_to_scc_switch);
2609 	/*
2610 	 * No DFS SCC is allowed in Auto use case. Hence not
2611 	 * calling DFS override
2612 	 */
2613 	if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
2614 	    mcc_to_scc_switch &&
2615 	    !(policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) &&
2616 	    WLAN_REG_IS_24GHZ_CH_FREQ(sap_config->acs_cfg.end_ch_freq)) &&
2617 	    !wlansap_dcs_is_wlan_interference_mitigation_enabled(sap_ctx)) {
2618 		status = wlan_hdd_sap_cfg_dfs_override(adapter);
2619 		if (status < 0)
2620 			return status;
2621 
2622 		if (status > 0) {
2623 			/*notify hostapd about channel override */
2624 			wlan_hdd_cfg80211_acs_ch_select_evt(link_info, true);
2625 			wlansap_dcs_set_wlan_interference_mitigation_on_band(sap_ctx,
2626 									     sap_config);
2627 			return 0;
2628 		}
2629 	}
2630 	/* When first 2 connections are on the same frequency band,
2631 	 * then PCL would include only channels from the other
2632 	 * frequency band on which no connections are active
2633 	 */
2634 	if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
2635 		(sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2636 		struct policy_mgr_conc_connection_info *conc_connection_info;
2637 		uint32_t i;
2638 
2639 		conc_connection_info = policy_mgr_get_conn_info(&i);
2640 		if (policy_mgr_are_2_freq_on_same_mac(hdd_ctx->psoc,
2641 			conc_connection_info[0].freq,
2642 			conc_connection_info[1].freq)) {
2643 			if (!WLAN_REG_IS_24GHZ_CH_FREQ(
2644 				sap_config->acs_cfg.pcl_chan_freq[0])) {
2645 				sap_config->acs_cfg.band =
2646 					QCA_ACS_MODE_IEEE80211A;
2647 				hdd_update_acs_channel_list(sap_config,
2648 					BAND_5G);
2649 			} else {
2650 				sap_config->acs_cfg.band =
2651 					QCA_ACS_MODE_IEEE80211G;
2652 				hdd_update_acs_channel_list(sap_config,
2653 					BAND_2G);
2654 			}
2655 		}
2656 	}
2657 	status = wlan_hdd_config_acs(hdd_ctx, adapter);
2658 	if (status) {
2659 		hdd_err("ACS config failed");
2660 		return -EINVAL;
2661 	}
2662 
2663 	acs_event_callback = hdd_hostapd_sap_event_cb;
2664 
2665 	qdf_mem_copy(sap_config->self_macaddr.bytes,
2666 		adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
2667 
2668 	qdf_status = wlansap_acs_chselect(sap_ctx, acs_event_callback,
2669 					  sap_config, adapter->dev);
2670 
2671 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
2672 		hdd_err("ACS channel select failed");
2673 		return -EINVAL;
2674 	}
2675 	if (sap_is_auto_channel_select(sap_ctx))
2676 		sap_config->acs_cfg.acs_mode = true;
2677 
2678 	/* If ACS scan is skipped then ACS request would be completed by now,
2679 	 * so no need to set acs in progress
2680 	 */
2681 	if (!sap_config->acs_cfg.skip_acs_scan)
2682 		qdf_atomic_set(&ap_ctx->acs_in_progress, 1);
2683 
2684 	return 0;
2685 }
2686 
2687 /**
2688  * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
2689  * @hdd_ctx: hdd context
2690  * @acs_chan_params: external acs channel params
2691  * @sap_config: SAP config
2692  *
2693  * This API provides unsorted pcl list.
2694  * this list is a subset of the valid channel list given by hostapd.
2695  * if channel is not present in pcl, weightage will be given as zero
2696  *
2697  * Return: Zero on success, non-zero on failure
2698  */
hdd_update_vendor_pcl_list(struct hdd_context * hdd_ctx,struct hdd_vendor_acs_chan_params * acs_chan_params,struct sap_config * sap_config)2699 static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
2700 		struct hdd_vendor_acs_chan_params *acs_chan_params,
2701 		struct sap_config *sap_config)
2702 {
2703 	int i, j;
2704 	/*
2705 	 * PCL shall contain only the preferred channels from the
2706 	 * application. If those channels are not present in the
2707 	 * driver PCL, then set the weight to zero
2708 	 */
2709 	for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
2710 		acs_chan_params->vendor_pcl_list[i] =
2711 				sap_config->acs_cfg.freq_list[i];
2712 		acs_chan_params->vendor_weight_list[i] = 0;
2713 		for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
2714 			if (sap_config->acs_cfg.freq_list[i] ==
2715 			    sap_config->acs_cfg.pcl_chan_freq[j]) {
2716 				acs_chan_params->vendor_weight_list[i] =
2717 				sap_config->acs_cfg.pcl_channels_weight_list[j];
2718 				break;
2719 			}
2720 		}
2721 	}
2722 	acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
2723 }
2724 
2725 /**
2726  * hdd_update_reg_chan_info : This API constructs channel info
2727  * for all the given channel
2728  * @adapter: pointer to SAP adapter struct
2729  * @channel_count: channel count
2730  * @freq_list: channel frequency (MHz) list
2731  *
2732  * Return: Status of of channel information updation
2733  */
2734 static int
hdd_update_reg_chan_info(struct hdd_adapter * adapter,uint32_t channel_count,uint32_t * freq_list)2735 hdd_update_reg_chan_info(struct hdd_adapter *adapter,
2736 			 uint32_t channel_count, uint32_t *freq_list)
2737 {
2738 	int i;
2739 	struct hdd_channel_info *icv;
2740 	struct ch_params ch_params = {0};
2741 	uint8_t bw_offset = 0, chan = 0;
2742 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2743 	struct sap_config *sap_config =
2744 				&adapter->deflink->session.ap.sap_config;
2745 	mac_handle_t mac_handle;
2746 	uint8_t sub_20_chan_width = 0;
2747 	QDF_STATUS status;
2748 
2749 	mac_handle = hdd_ctx->mac_handle;
2750 	sap_config->channel_info_count = channel_count;
2751 
2752 	status = ucfg_mlme_get_sub_20_chan_width(hdd_ctx->psoc,
2753 						 &sub_20_chan_width);
2754 	if (QDF_IS_STATUS_ERROR(status))
2755 		hdd_err("Failed to get sub_20_chan_width config");
2756 
2757 	for (i = 0; i < channel_count; i++) {
2758 		icv = &sap_config->channel_info[i];
2759 		chan = wlan_reg_freq_to_chan(hdd_ctx->pdev,
2760 					     freq_list[i]);
2761 		if (chan == 0)
2762 			continue;
2763 
2764 		icv->freq = freq_list[i];
2765 		icv->ieee_chan_number = chan;
2766 		icv->max_reg_power = wlan_reg_get_channel_reg_power_for_freq(
2767 				hdd_ctx->pdev, freq_list[i]);
2768 
2769 		/* filling demo values */
2770 		icv->max_radio_power = HDD_MAX_TX_POWER;
2771 		icv->min_radio_power = HDD_MIN_TX_POWER;
2772 		/* not supported in current driver */
2773 		icv->max_antenna_gain = 0;
2774 
2775 		bw_offset = hdd_get_bw_offset(sap_config->acs_cfg.ch_width);
2776 		icv->reg_class_id =
2777 			wlan_hdd_find_opclass(mac_handle, chan, bw_offset);
2778 
2779 		if (WLAN_REG_IS_5GHZ_CH_FREQ(freq_list[i])) {
2780 			if (sap_phymode_is_eht(sap_config->SapHw_mode))
2781 				wlan_reg_set_create_punc_bitmap(&ch_params,
2782 								true);
2783 			ch_params.ch_width = sap_config->acs_cfg.ch_width;
2784 			wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
2785 								icv->freq,
2786 								0, &ch_params,
2787 								REG_CURRENT_PWR_MODE);
2788 			icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
2789 			icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
2790 		}
2791 
2792 		icv->flags = 0;
2793 		icv->flags = cds_get_vendor_reg_flags(hdd_ctx->pdev,
2794 				icv->freq,
2795 				sap_config->acs_cfg.ch_width,
2796 				sap_config->acs_cfg.is_ht_enabled,
2797 				sap_config->acs_cfg.is_vht_enabled,
2798 				sub_20_chan_width);
2799 		if (icv->flags & IEEE80211_CHAN_PASSIVE)
2800 			icv->flagext |= IEEE80211_CHAN_DFS;
2801 
2802 		hdd_debug("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
2803 			icv->freq, icv->flags,
2804 			icv->flagext, icv->ieee_chan_number,
2805 			icv->max_reg_power, icv->max_radio_power,
2806 			icv->min_radio_power, icv->reg_class_id,
2807 			icv->max_antenna_gain, icv->vht_center_freq_seg0,
2808 			icv->vht_center_freq_seg1);
2809 	}
2810 	return 0;
2811 }
2812 
2813 /* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
2814 #define CHAN_INFO_ATTR_FLAGS \
2815 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
2816 #define CHAN_INFO_ATTR_FLAG_EXT \
2817 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
2818 #define CHAN_INFO_ATTR_FREQ \
2819 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
2820 #define CHAN_INFO_ATTR_MAX_REG_POWER \
2821 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
2822 #define CHAN_INFO_ATTR_MAX_POWER \
2823 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
2824 #define CHAN_INFO_ATTR_MIN_POWER \
2825 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
2826 #define CHAN_INFO_ATTR_REG_CLASS_ID \
2827 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
2828 #define CHAN_INFO_ATTR_ANTENNA_GAIN \
2829 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
2830 #define CHAN_INFO_ATTR_VHT_SEG_0 \
2831 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
2832 #define CHAN_INFO_ATTR_VHT_SEG_1 \
2833 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
2834 
2835 #define CHAN_INFO_ATTR_FREQ_VHT_SEG_0 \
2836 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2837 #define CHAN_INFO_ATTR_FREQ_VHT_SEG_1 \
2838 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2839 
2840 /**
2841  * hdd_cfg80211_update_channel_info() - add channel info attributes
2842  * @hdd_ctx: pointer to hdd context
2843  * @skb: pointer to sk buff
2844  * @sap_config: pointer to SAP configuration
2845  * @idx: attribute index
2846  *
2847  * Return: Success(0) or reason code for failure
2848  */
2849 static int32_t
hdd_cfg80211_update_channel_info(struct hdd_context * hdd_ctx,struct sk_buff * skb,struct sap_config * sap_config,int idx)2850 hdd_cfg80211_update_channel_info(struct hdd_context *hdd_ctx,
2851 				 struct sk_buff *skb,
2852 				 struct sap_config *sap_config, int idx)
2853 {
2854 	struct nlattr *nla_attr, *channel;
2855 	struct hdd_channel_info *icv;
2856 	int i;
2857 	uint32_t freq_seg_0 = 0, freq_seg_1 = 0;
2858 	enum reg_wifi_band band;
2859 	uint8_t band_mask;
2860 
2861 	nla_attr = nla_nest_start(skb, idx);
2862 	if (!nla_attr)
2863 		goto fail;
2864 
2865 	for (i = 0; i < sap_config->channel_info_count; i++) {
2866 		channel = nla_nest_start(skb, i);
2867 		if (!channel)
2868 			goto fail;
2869 
2870 		icv = &sap_config->channel_info[i];
2871 		if (!icv) {
2872 			hdd_err("channel info not found");
2873 			goto fail;
2874 		}
2875 
2876 		band = wlan_reg_freq_to_band(icv->freq);
2877 		band_mask = 1 << band;
2878 
2879 		if (icv->vht_center_freq_seg0)
2880 			freq_seg_0 = wlan_reg_chan_band_to_freq(hdd_ctx->pdev,
2881 						    icv->vht_center_freq_seg0,
2882 						    band_mask);
2883 		if (icv->vht_center_freq_seg1)
2884 			freq_seg_1 = wlan_reg_chan_band_to_freq(hdd_ctx->pdev,
2885 						    icv->vht_center_freq_seg1,
2886 						    band_mask);
2887 
2888 		if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
2889 				icv->freq) ||
2890 		    nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
2891 				icv->flags) ||
2892 		    nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
2893 				icv->flagext) ||
2894 		    nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
2895 				icv->max_reg_power) ||
2896 		    nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
2897 				icv->max_radio_power) ||
2898 		    nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
2899 				icv->min_radio_power) ||
2900 		    nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
2901 				icv->reg_class_id) ||
2902 		    nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
2903 				icv->max_antenna_gain) ||
2904 		    nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
2905 				icv->vht_center_freq_seg0) ||
2906 		    nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
2907 				icv->vht_center_freq_seg1) ||
2908 		    nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_0,
2909 				freq_seg_0) ||
2910 		    nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_1,
2911 				freq_seg_1)) {
2912 			hdd_err("put fail");
2913 			goto fail;
2914 		}
2915 		nla_nest_end(skb, channel);
2916 	}
2917 	nla_nest_end(skb, nla_attr);
2918 	return 0;
2919 fail:
2920 	hdd_err("nl channel update failed");
2921 	return -EINVAL;
2922 }
2923 #undef CHAN_INFO_ATTR_FLAGS
2924 #undef CHAN_INFO_ATTR_FLAG_EXT
2925 #undef CHAN_INFO_ATTR_FREQ
2926 #undef CHAN_INFO_ATTR_MAX_REG_POWER
2927 #undef CHAN_INFO_ATTR_MAX_POWER
2928 #undef CHAN_INFO_ATTR_MIN_POWER
2929 #undef CHAN_INFO_ATTR_REG_CLASS_ID
2930 #undef CHAN_INFO_ATTR_ANTENNA_GAIN
2931 #undef CHAN_INFO_ATTR_VHT_SEG_0
2932 #undef CHAN_INFO_ATTR_VHT_SEG_1
2933 
2934 #undef CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2935 #undef CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2936 
2937 /**
2938  * hdd_cfg80211_update_pcl() - add pcl info attributes
2939  * @hdd_ctx: pointer to hdd context
2940  * @skb: pointer to sk buff
2941  * @ch_list_count: number of channels to add
2942  * @idx: attribute index
2943  * @vendor_pcl_list: PCL list
2944  * @vendor_weight_list: PCL weights
2945  *
2946  * Return: Success(0) or reason code for failure
2947  */
2948 static int32_t
hdd_cfg80211_update_pcl(struct hdd_context * hdd_ctx,struct sk_buff * skb,uint8_t ch_list_count,int idx,uint32_t * vendor_pcl_list,uint8_t * vendor_weight_list)2949 hdd_cfg80211_update_pcl(struct hdd_context *hdd_ctx,
2950 			struct sk_buff *skb,
2951 			uint8_t ch_list_count, int idx,
2952 			uint32_t *vendor_pcl_list, uint8_t *vendor_weight_list)
2953 {
2954 	struct nlattr *nla_attr, *channel;
2955 	int i;
2956 	uint8_t chan;
2957 
2958 	nla_attr = nla_nest_start(skb, idx);
2959 	if (!nla_attr)
2960 		goto fail;
2961 
2962 	for (i = 0; i < ch_list_count; i++) {
2963 		channel = nla_nest_start(skb, i);
2964 		if (!channel)
2965 			goto fail;
2966 
2967 		chan = (uint8_t)wlan_reg_freq_to_chan(hdd_ctx->pdev,
2968 						      vendor_pcl_list[i]);
2969 
2970 		if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL, chan) ||
2971 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
2972 				vendor_pcl_list[i]) ||
2973 		    nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
2974 			       vendor_weight_list[i])) {
2975 			hdd_err("put fail");
2976 			goto fail;
2977 		}
2978 		nla_nest_end(skb, channel);
2979 	}
2980 	nla_nest_end(skb, nla_attr);
2981 
2982 	return 0;
2983 fail:
2984 	hdd_err("updating pcl list failed");
2985 	return -EINVAL;
2986 }
2987 
hdd_get_scan_band(struct hdd_context * hdd_ctx,struct sap_config * sap_config,enum band_info * band)2988 static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
2989 			      struct sap_config *sap_config,
2990 			      enum band_info *band)
2991 {
2992 	/* Get scan band */
2993 	if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2994 	   (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
2995 		*band = BAND_2G;
2996 	} else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
2997 		*band = BAND_5G;
2998 	} else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
2999 		*band = BAND_ALL;
3000 	}
3001 }
3002 
3003 /**
3004  * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
3005  * @adapter: adapter
3006  * @channel_count: valid channel count
3007  * @freq_list: valid channel frequency (MHz) list
3008  * @band: frequency band
3009  *
3010  * This API returns valid channel list for SAP after removing nol and
3011  * channel which lies outside of configuration.
3012  *
3013  * Return: Zero on success, non-zero on failure
3014  */
wlan_hdd_sap_get_valid_channellist(struct hdd_adapter * adapter,uint32_t * channel_count,uint32_t * freq_list,enum band_info band)3015 static int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
3016 					      uint32_t *channel_count,
3017 					      uint32_t *freq_list,
3018 					      enum band_info band)
3019 {
3020 	struct sap_config *sap_config;
3021 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3022 	uint32_t pcl_freqs[NUM_CHANNELS] = {0};
3023 	uint32_t chan_count;
3024 	uint32_t i;
3025 	QDF_STATUS status;
3026 	struct wlan_objmgr_pdev *pdev = hdd_ctx->pdev;
3027 
3028 	sap_config = &adapter->deflink->session.ap.sap_config;
3029 
3030 	status = policy_mgr_get_valid_chans(hdd_ctx->psoc,
3031 					    pcl_freqs,
3032 					    &chan_count);
3033 	if (QDF_IS_STATUS_ERROR(status)) {
3034 		hdd_err("Failed to get channel list");
3035 		return -EINVAL;
3036 	}
3037 
3038 	*channel_count = 0;
3039 	for (i = 0; i < chan_count; i++) {
3040 		if (*channel_count >= NUM_CHANNELS)
3041 			break;
3042 
3043 		if (band == BAND_2G &&
3044 		    WLAN_REG_IS_24GHZ_CH_FREQ(pcl_freqs[i]) &&
3045 		    !wlan_reg_is_disable_for_pwrmode(pdev, pcl_freqs[i],
3046 						     REG_CURRENT_PWR_MODE)) {
3047 			freq_list[*channel_count] = pcl_freqs[i];
3048 			*channel_count += 1;
3049 		} else if (band == BAND_5G &&
3050 			   (WLAN_REG_IS_5GHZ_CH_FREQ(pcl_freqs[i]) ||
3051 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(pcl_freqs[i])) &&
3052 			   !wlan_reg_is_disable_for_pwrmode(
3053 							pdev, pcl_freqs[i],
3054 							REG_CURRENT_PWR_MODE)) {
3055 			freq_list[*channel_count] = pcl_freqs[i];
3056 			*channel_count += 1;
3057 		}
3058 	}
3059 
3060 	if (*channel_count == 0) {
3061 		hdd_err("no valid channel found");
3062 		return -EINVAL;
3063 	}
3064 
3065 	return 0;
3066 }
3067 
3068 /**
3069  * hdd_get_external_acs_event_len() - Get event buffer length for external ACS
3070  * @channel_count: number of channels for ACS operation
3071  *
3072  * Return: External ACS event (SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG) buffer length.
3073  */
hdd_get_external_acs_event_len(uint32_t channel_count)3074 static int hdd_get_external_acs_event_len(uint32_t channel_count)
3075 {
3076 	uint32_t len = NLMSG_HDRLEN;
3077 	uint32_t i;
3078 
3079 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON */
3080 	len += nla_total_size(sizeof(u8));
3081 
3082 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED */
3083 	len += nla_total_size(sizeof(u32));
3084 
3085 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT */
3086 	len += nla_total_size(sizeof(u32));
3087 
3088 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH */
3089 	len += nla_total_size(sizeof(u8));
3090 
3091 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND */
3092 	len += nla_total_size(sizeof(u8));
3093 
3094 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE */
3095 	len += nla_total_size(sizeof(u32));
3096 
3097 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST */
3098 	len += nla_total_size(channel_count * sizeof(u32));
3099 
3100 	for (i = 0; i < channel_count; i++) {
3101 		/* QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL */
3102 		len += nla_total_size(sizeof(u8));
3103 
3104 		/* QCA_WLAN_VENDOR_ATTR_PCL_FREQ */
3105 		len += nla_total_size(sizeof(u32));
3106 
3107 		/* QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT */
3108 		len += nla_total_size(sizeof(u8));
3109 	}
3110 
3111 	for (i = 0; i < channel_count; i++) {
3112 		/* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ */
3113 		len += nla_total_size(sizeof(u16));
3114 
3115 		/* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS */
3116 		len += nla_total_size(sizeof(u32));
3117 
3118 		/* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT */
3119 		len += nla_total_size(sizeof(u32));
3120 
3121 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER */
3122 		len += nla_total_size(sizeof(u8));
3123 
3124 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER */
3125 		len += nla_total_size(sizeof(u8));
3126 
3127 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER */
3128 		len += nla_total_size(sizeof(u8));
3129 
3130 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID */
3131 		len += nla_total_size(sizeof(u8));
3132 
3133 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN */
3134 		len += nla_total_size(sizeof(u8));
3135 
3136 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 */
3137 		len += nla_total_size(sizeof(u8));
3138 
3139 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 */
3140 		len += nla_total_size(sizeof(u8));
3141 
3142 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 */
3143 		len += nla_total_size(sizeof(u32));
3144 
3145 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 */
3146 		len += nla_total_size(sizeof(u32));
3147 	}
3148 
3149 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY */
3150 	len += nla_total_size(sizeof(u32));
3151 
3152 	return len;
3153 }
3154 
hdd_cfg80211_update_acs_config(struct hdd_adapter * adapter,uint8_t reason)3155 int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
3156 				   uint8_t reason)
3157 {
3158 	struct sk_buff *skb = NULL;
3159 	struct sap_config *sap_config;
3160 	uint32_t channel_count = 0, status = -EINVAL;
3161 	uint32_t *freq_list;
3162 	uint32_t vendor_pcl_list[NUM_CHANNELS] = {0};
3163 	uint8_t vendor_weight_list[NUM_CHANNELS] = {0};
3164 	struct hdd_vendor_acs_chan_params acs_chan_params;
3165 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3166 	enum band_info band = BAND_2G;
3167 	eCsrPhyMode phy_mode;
3168 	enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
3169 	uint32_t i, id;
3170 	QDF_STATUS qdf_status;
3171 	bool is_external_acs_policy = cfg_default(CFG_EXTERNAL_ACS_POLICY);
3172 	uint32_t len;
3173 
3174 	if (!hdd_ctx) {
3175 		hdd_err("HDD context is NULL");
3176 		return -EINVAL;
3177 	}
3178 
3179 	hdd_enter();
3180 	sap_config = &adapter->deflink->session.ap.sap_config;
3181 	/* When first 2 connections are on the same frequency band,
3182 	 * then PCL would include only channels from the other
3183 	 * frequency band on which no connections are active
3184 	 */
3185 	if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
3186 	    (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
3187 		struct policy_mgr_conc_connection_info	*conc_connection_info;
3188 
3189 		conc_connection_info = policy_mgr_get_conn_info(&i);
3190 		if (policy_mgr_are_2_freq_on_same_mac(hdd_ctx->psoc,
3191 			conc_connection_info[0].freq,
3192 			conc_connection_info[1].freq)) {
3193 			if (!WLAN_REG_IS_24GHZ_CH_FREQ(
3194 				sap_config->acs_cfg.pcl_chan_freq[0])) {
3195 				sap_config->acs_cfg.band =
3196 					QCA_ACS_MODE_IEEE80211A;
3197 				hdd_update_acs_channel_list(sap_config,
3198 					BAND_5G);
3199 			} else {
3200 				sap_config->acs_cfg.band =
3201 					QCA_ACS_MODE_IEEE80211G;
3202 				hdd_update_acs_channel_list(sap_config,
3203 					BAND_2G);
3204 			}
3205 		}
3206 	}
3207 
3208 	hdd_get_scan_band(hdd_ctx, &adapter->deflink->session.ap.sap_config,
3209 			  &band);
3210 
3211 	freq_list = qdf_mem_malloc(sizeof(uint32_t) * NUM_CHANNELS);
3212 	if (!freq_list)
3213 		return -ENOMEM;
3214 
3215 	if (sap_config->acs_cfg.freq_list) {
3216 		/* Copy INI or hostapd provided ACS channel range*/
3217 		for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
3218 			freq_list[i] = sap_config->acs_cfg.freq_list[i];
3219 		channel_count = sap_config->acs_cfg.ch_list_count;
3220 	} else {
3221 		/* No channel list provided, copy all valid channels */
3222 		wlan_hdd_sap_get_valid_channellist(adapter,
3223 			&channel_count,
3224 			freq_list,
3225 			band);
3226 	}
3227 
3228 	sap_config->channel_info = qdf_mem_malloc(
3229 					sizeof(struct hdd_channel_info) *
3230 					channel_count);
3231 	if (!sap_config->channel_info) {
3232 		status = -ENOMEM;
3233 		goto fail;
3234 	}
3235 
3236 	hdd_update_reg_chan_info(adapter, channel_count, freq_list);
3237 
3238 	/* Get phymode */
3239 	phy_mode = adapter->deflink->session.ap.sap_config.acs_cfg.hw_mode;
3240 
3241 	len = hdd_get_external_acs_event_len(channel_count);
3242 	id = QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG;
3243 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, &adapter->wdev,
3244 					       len, id, GFP_KERNEL);
3245 	if (!skb) {
3246 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
3247 		status = -ENOMEM;
3248 		goto fail;
3249 	}
3250 	/*
3251 	 * Application expects pcl to be a subset of channel list
3252 	 * Remove all channels which are not in channel list from pcl
3253 	 * and add weight as zero
3254 	 */
3255 	acs_chan_params.vendor_pcl_list = vendor_pcl_list;
3256 	acs_chan_params.vendor_weight_list = vendor_weight_list;
3257 
3258 	hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
3259 				   sap_config);
3260 
3261 	if (acs_chan_params.pcl_count) {
3262 		hdd_debug("ACS PCL list: len: %d",
3263 			  acs_chan_params.pcl_count);
3264 		for (i = 0; i < acs_chan_params.pcl_count; i++)
3265 			hdd_debug("channel_frequency: %u, weight: %u",
3266 				  acs_chan_params.
3267 				  vendor_pcl_list[i],
3268 				  acs_chan_params.
3269 				  vendor_weight_list[i]);
3270 	}
3271 
3272 	qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
3273 						       &is_external_acs_policy);
3274 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3275 		hdd_err("get_external_acs_policy failed, set default");
3276 
3277 	if (is_external_acs_policy) {
3278 		acs_policy =
3279 			QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
3280 	} else {
3281 		acs_policy =
3282 			QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
3283 	}
3284 	/* Update values in NL buffer */
3285 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
3286 		       reason) ||
3287 	    nla_put_flag(skb,
3288 		QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
3289 	    nla_put_flag(skb,
3290 		QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
3291 		||
3292 	    nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
3293 		       sap_config->acs_cfg.ch_width) ||
3294 	    nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
3295 		       band) ||
3296 	    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
3297 		       phy_mode) ||
3298 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
3299 		    channel_count * sizeof(uint32_t), freq_list)) {
3300 		hdd_err("nla put fail");
3301 		goto fail;
3302 	}
3303 	status =
3304 	hdd_cfg80211_update_pcl(hdd_ctx, skb,
3305 				acs_chan_params.pcl_count,
3306 				QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
3307 				vendor_pcl_list,
3308 				vendor_weight_list);
3309 
3310 	if (status != 0)
3311 		goto fail;
3312 
3313 	id = QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO;
3314 
3315 	status = hdd_cfg80211_update_channel_info(hdd_ctx, skb, sap_config, id);
3316 	if (status != 0)
3317 		goto fail;
3318 
3319 	status = nla_put_u32(skb,
3320 			     QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
3321 			     acs_policy);
3322 
3323 	if (status != 0)
3324 		goto fail;
3325 
3326 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
3327 	qdf_mem_free(freq_list);
3328 	qdf_mem_free(sap_config->channel_info);
3329 
3330 	return 0;
3331 fail:
3332 	qdf_mem_free(freq_list);
3333 	if (sap_config->channel_info)
3334 		qdf_mem_free(sap_config->channel_info);
3335 	wlan_cfg80211_vendor_free_skb(skb);
3336 	return status;
3337 }
3338 
3339 /**
3340  * hdd_create_acs_timer(): Initialize vendor ACS timer
3341  * @adapter: pointer to SAP adapter struct
3342  *
3343  * This function initializes the vendor ACS timer.
3344  *
3345  * Return: Status of create vendor ACS timer
3346  */
hdd_create_acs_timer(struct hdd_adapter * adapter)3347 static int hdd_create_acs_timer(struct hdd_adapter *adapter)
3348 {
3349 	struct hdd_external_acs_timer_context *timer_context;
3350 	QDF_STATUS status;
3351 
3352 	if (adapter->deflink->session.ap.vendor_acs_timer_initialized)
3353 		return 0;
3354 
3355 	hdd_debug("Starting vendor app based ACS");
3356 	timer_context = qdf_mem_malloc(sizeof(*timer_context));
3357 	if (!timer_context)
3358 		return -ENOMEM;
3359 
3360 	timer_context->adapter = adapter;
3361 
3362 	set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->deflink->link_flags);
3363 	status = qdf_mc_timer_init(
3364 		  &adapter->deflink->session.ap.vendor_acs_timer,
3365 		  QDF_TIMER_TYPE_SW,
3366 		  hdd_acs_response_timeout_handler, timer_context);
3367 	if (status != QDF_STATUS_SUCCESS) {
3368 		hdd_err("Failed to initialize acs response timeout timer");
3369 		return -EFAULT;
3370 	}
3371 	adapter->deflink->session.ap.vendor_acs_timer_initialized = true;
3372 	return 0;
3373 }
3374 
3375 static const struct nla_policy
3376 wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1] = {
3377 	[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
3378 	[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
3379 	[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
3380 	[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
3381 	[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
3382 	[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_BINARY,
3383 				.len = sizeof(NLA_U8) * NUM_CHANNELS },
3384 	[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_BINARY,
3385 				.len = sizeof(NLA_U32) * NUM_CHANNELS },
3386 	[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED] = { .type = NLA_FLAG },
3387 	[QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP] = { .type = NLA_U16 },
3388 	[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED] = { .type = NLA_FLAG },
3389 	[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL] = { .type = NLA_U8 },
3390 	[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME] = { .type = NLA_U32 },
3391 };
3392 
hdd_start_vendor_acs(struct hdd_adapter * adapter)3393 int hdd_start_vendor_acs(struct hdd_adapter *adapter)
3394 {
3395 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3396 	int status;
3397 	QDF_STATUS qdf_status;
3398 	bool is_acs_support_for_dfs_ltecoex = cfg_default(CFG_USER_ACS_DFS_LTE);
3399 
3400 	status = hdd_create_acs_timer(adapter);
3401 	if (status != 0) {
3402 		hdd_err("failed to create acs timer");
3403 		return status;
3404 	}
3405 	status = hdd_update_acs_timer_reason(adapter,
3406 		QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
3407 	if (status != 0) {
3408 		hdd_err("failed to update acs timer reason");
3409 		return status;
3410 	}
3411 	qdf_status = ucfg_mlme_get_acs_support_for_dfs_ltecoex(
3412 				hdd_ctx->psoc,
3413 				&is_acs_support_for_dfs_ltecoex);
3414 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3415 		hdd_err("get_acs_support_for_dfs_ltecoex failed, set def");
3416 
3417 	if (is_acs_support_for_dfs_ltecoex)
3418 		status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
3419 				WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
3420 				true));
3421 	else
3422 		status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
3423 				WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
3424 				false));
3425 
3426 	return status;
3427 }
3428 
3429 /**
3430  * hdd_avoid_acs_channels() - Avoid acs channels
3431  * @hdd_ctx: Pointer to the hdd context
3432  * @sap_config: Sap config structure pointer
3433  *
3434  * This function avoids channels from the acs corresponding to
3435  * the frequencies configured in the ini sap_avoid_acs_freq_list
3436  *
3437  * Return: None
3438  */
3439 
3440 #ifdef SAP_AVOID_ACS_FREQ_LIST
hdd_avoid_acs_channels(struct hdd_context * hdd_ctx,struct sap_config * sap_config)3441 static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
3442 				   struct sap_config *sap_config)
3443 {
3444 	int i, j, ch_cnt = 0;
3445 	uint16_t avoid_acs_freq_list[CFG_VALID_CHANNEL_LIST_LEN];
3446 	uint8_t avoid_acs_freq_list_num;
3447 
3448 	ucfg_mlme_get_acs_avoid_freq_list(hdd_ctx->psoc,
3449 					  avoid_acs_freq_list,
3450 					  &avoid_acs_freq_list_num);
3451 
3452 	for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
3453 		for (j = 0; j < avoid_acs_freq_list_num; j++) {
3454 			if (sap_config->acs_cfg.freq_list[i] ==
3455 						avoid_acs_freq_list[j]) {
3456 				hdd_debug("skip freq %d",
3457 					  sap_config->acs_cfg.freq_list[i]);
3458 				break;
3459 			}
3460 		}
3461 		if (j == avoid_acs_freq_list_num)
3462 			sap_config->acs_cfg.freq_list[ch_cnt++] =
3463 					sap_config->acs_cfg.freq_list[i];
3464 	}
3465 	sap_config->acs_cfg.ch_list_count = ch_cnt;
3466 }
3467 #else
hdd_avoid_acs_channels(struct hdd_context * hdd_ctx,struct sap_config * sap_config)3468 static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
3469 				   struct sap_config *sap_config)
3470 {
3471 }
3472 #endif
3473 
wlan_hdd_trim_acs_channel_list(uint32_t * pcl,uint8_t pcl_count,uint32_t * org_freq_list,uint8_t * org_ch_list_count)3474 void wlan_hdd_trim_acs_channel_list(uint32_t *pcl, uint8_t pcl_count,
3475 				    uint32_t *org_freq_list,
3476 				    uint8_t *org_ch_list_count)
3477 {
3478 	uint16_t i, j, ch_list_count = 0;
3479 
3480 	if (*org_ch_list_count >= NUM_CHANNELS) {
3481 		hdd_err("org_ch_list_count too big %d",
3482 			*org_ch_list_count);
3483 		return;
3484 	}
3485 
3486 	if (pcl_count >= NUM_CHANNELS) {
3487 		hdd_err("pcl_count is too big %d", pcl_count);
3488 		return;
3489 	}
3490 
3491 	hdd_debug("Update ACS chan freq with PCL");
3492 	for (j = 0; j < *org_ch_list_count; j++)
3493 		for (i = 0; i < pcl_count; i++)
3494 			if (pcl[i] == org_freq_list[j]) {
3495 				org_freq_list[ch_list_count++] = pcl[i];
3496 				break;
3497 			}
3498 
3499 	*org_ch_list_count = ch_list_count;
3500 }
3501 
3502 /* wlan_hdd_dump_freq_list() - Dump the ACS master frequency list
3503  *
3504  * @freq_list: Frequency list
3505  * @num_freq: num of frequencies in list
3506  *
3507  * Dump the ACS master frequency list.
3508  */
3509 static inline
wlan_hdd_dump_freq_list(uint32_t * freq_list,uint8_t num_freq)3510 void wlan_hdd_dump_freq_list(uint32_t *freq_list, uint8_t num_freq)
3511 {
3512 	uint32_t buf_len = 0;
3513 	uint32_t i = 0, j = 0;
3514 	uint8_t *master_chlist;
3515 
3516 	if (num_freq >= NUM_CHANNELS)
3517 		return;
3518 
3519 	buf_len = NUM_CHANNELS * 4;
3520 	master_chlist = qdf_mem_malloc(buf_len);
3521 
3522 	if (!master_chlist)
3523 		return;
3524 
3525 	for (i = 0; i < num_freq && j < buf_len; i++) {
3526 		j += qdf_scnprintf(master_chlist + j, buf_len - j,
3527 				   "%d ", freq_list[i]);
3528 	}
3529 
3530 	hdd_debug("Master channel list: %s", master_chlist);
3531 	qdf_mem_free(master_chlist);
3532 }
3533 
wlan_hdd_handle_zero_acs_list(struct hdd_context * hdd_ctx,uint32_t * acs_freq_list,uint8_t * acs_ch_list_count,uint32_t * org_freq_list,uint8_t org_ch_list_count)3534 void wlan_hdd_handle_zero_acs_list(struct hdd_context *hdd_ctx,
3535 				   uint32_t *acs_freq_list,
3536 				   uint8_t *acs_ch_list_count,
3537 				   uint32_t *org_freq_list,
3538 				   uint8_t org_ch_list_count)
3539 {
3540 	uint16_t i, sta_count;
3541 	uint32_t acs_chan_default = 0, acs_dfs_chan = 0;
3542 	bool force_sap_allowed = false;
3543 	enum channel_state state;
3544 
3545 	if (!acs_ch_list_count || *acs_ch_list_count > 0 ||
3546 	    !acs_freq_list) {
3547 		return;
3548 	}
3549 	if (!org_ch_list_count || !org_freq_list)
3550 		return;
3551 
3552 	if (!policy_mgr_is_force_scc(hdd_ctx->psoc))
3553 		return;
3554 	sta_count = policy_mgr_mode_specific_connection_count
3555 			(hdd_ctx->psoc, PM_STA_MODE, NULL);
3556 	sta_count += policy_mgr_mode_specific_connection_count
3557 			(hdd_ctx->psoc, PM_P2P_CLIENT_MODE, NULL);
3558 
3559 	ucfg_mlme_get_force_sap_enabled(hdd_ctx->psoc, &force_sap_allowed);
3560 	if (!sta_count && !force_sap_allowed)
3561 		return;
3562 
3563 	wlan_hdd_dump_freq_list(org_freq_list, org_ch_list_count);
3564 
3565 	for (i = 0; i < org_ch_list_count; i++) {
3566 		state = wlan_reg_get_channel_state_for_pwrmode(
3567 				hdd_ctx->pdev, org_freq_list[i],
3568 				REG_CURRENT_PWR_MODE);
3569 		if (state == CHANNEL_STATE_DISABLE ||
3570 		    state == CHANNEL_STATE_INVALID)
3571 			continue;
3572 
3573 		if (wlan_reg_is_6ghz_chan_freq(org_freq_list[i]) &&
3574 		    !wlan_reg_is_6ghz_psc_chan_freq(org_freq_list[i]))
3575 			continue;
3576 
3577 		if (!policy_mgr_is_safe_channel(hdd_ctx->psoc,
3578 						org_freq_list[i]))
3579 			continue;
3580 		/* Make dfs channel as last choice */
3581 		if (state == CHANNEL_STATE_DFS ||
3582 		    state == CHANNEL_STATE_PASSIVE) {
3583 			acs_dfs_chan = org_freq_list[i];
3584 			continue;
3585 		}
3586 		acs_chan_default = org_freq_list[i];
3587 		break;
3588 	}
3589 	if (!acs_chan_default) {
3590 		if (acs_dfs_chan)
3591 			acs_chan_default = acs_dfs_chan;
3592 		else
3593 			acs_chan_default = org_freq_list[0];
3594 	}
3595 
3596 	acs_freq_list[0] = acs_chan_default;
3597 	*acs_ch_list_count = 1;
3598 	hdd_debug("restore acs chan list to single freq %d", acs_chan_default);
3599 }
3600 
3601 /**
3602  * wlan_hdd_handle_single_ch_in_acs_list() - Handle acs list with single channel
3603  * @link_info: Link info pointer in HDD adapter
3604  *
3605  * If only one acs channel is left after filter, driver will return the channel
3606  * to hostapd without ACS scan.
3607  *
3608  * Return: None
3609  */
3610 static void
wlan_hdd_handle_single_ch_in_acs_list(struct wlan_hdd_link_info * link_info)3611 wlan_hdd_handle_single_ch_in_acs_list(struct wlan_hdd_link_info *link_info)
3612 {
3613 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
3614 	uint32_t channel_bonding_mode_2g;
3615 	struct sap_config *sap_config;
3616 
3617 	sap_config = &link_info->session.ap.sap_config;
3618 	ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
3619 					    &channel_bonding_mode_2g);
3620 	sap_config->acs_cfg.start_ch_freq =
3621 		sap_config->acs_cfg.freq_list[0];
3622 	sap_config->acs_cfg.end_ch_freq =
3623 		sap_config->acs_cfg.freq_list[0];
3624 	sap_config->acs_cfg.pri_ch_freq =
3625 			      sap_config->acs_cfg.freq_list[0];
3626 	if (sap_config->acs_cfg.pri_ch_freq <=
3627 	    WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484) &&
3628 	    sap_config->acs_cfg.ch_width >=
3629 				CH_WIDTH_40MHZ &&
3630 	    !channel_bonding_mode_2g) {
3631 		sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
3632 		hdd_debug("2.4ghz channel resetting BW to %d 2.4 cbmode %d",
3633 			  sap_config->acs_cfg.ch_width,
3634 			  channel_bonding_mode_2g);
3635 	}
3636 
3637 	wlan_sap_set_sap_ctx_acs_cfg(
3638 		WLAN_HDD_GET_SAP_CTX_PTR(link_info), sap_config);
3639 	sap_config_acs_result(hdd_ctx->mac_handle,
3640 			      WLAN_HDD_GET_SAP_CTX_PTR(link_info),
3641 			    sap_config->acs_cfg.ht_sec_ch_freq);
3642 	sap_config->ch_params.ch_width =
3643 			sap_config->acs_cfg.ch_width;
3644 	sap_config->ch_params.sec_ch_offset =
3645 			wlan_reg_freq_to_chan(
3646 			hdd_ctx->pdev,
3647 			sap_config->acs_cfg.ht_sec_ch_freq);
3648 	sap_config->ch_params.center_freq_seg0 =
3649 	wlan_reg_freq_to_chan(
3650 		hdd_ctx->pdev,
3651 		sap_config->acs_cfg.vht_seg0_center_ch_freq);
3652 	sap_config->ch_params.center_freq_seg1 =
3653 	wlan_reg_freq_to_chan(
3654 		hdd_ctx->pdev,
3655 		sap_config->acs_cfg.vht_seg1_center_ch_freq);
3656 	sap_config->ch_params.mhz_freq_seg0 =
3657 		sap_config->acs_cfg.vht_seg0_center_ch_freq;
3658 	sap_config->ch_params.mhz_freq_seg1 =
3659 		sap_config->acs_cfg.vht_seg1_center_ch_freq;
3660 	/*notify hostapd about channel override */
3661 	wlan_hdd_cfg80211_acs_ch_select_evt(link_info, true);
3662 	wlansap_dcs_set_wlan_interference_mitigation_on_band(
3663 		WLAN_HDD_GET_SAP_CTX_PTR(link_info),
3664 		sap_config);
3665 }
3666 
3667 #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC)
wlan_hdd_set_sap_acs_ch_width_320(struct sap_config * sap_config)3668 static void wlan_hdd_set_sap_acs_ch_width_320(struct sap_config *sap_config)
3669 {
3670 	sap_config->acs_cfg.ch_width = CH_WIDTH_320MHZ;
3671 }
3672 
wlan_hdd_is_sap_acs_ch_width_320(struct sap_config * sap_config)3673 static bool wlan_hdd_is_sap_acs_ch_width_320(struct sap_config *sap_config)
3674 {
3675 	return sap_config->acs_cfg.ch_width == CH_WIDTH_320MHZ;
3676 }
3677 
wlan_hdd_set_chandef_for_11be(struct cfg80211_chan_def * chandef,struct wlan_channel * chan_info)3678 static void wlan_hdd_set_chandef_for_11be(struct cfg80211_chan_def *chandef,
3679 					  struct wlan_channel *chan_info)
3680 {
3681 	if (chan_info->ch_width != CH_WIDTH_320MHZ)
3682 		return;
3683 
3684 	chandef->width = NL80211_CHAN_WIDTH_320;
3685 	/* Set center_freq1 to center frequency of complete 320MHz */
3686 	chandef->center_freq1 = chan_info->ch_cfreq2;
3687 }
3688 
3689 #else /* !WLAN_FEATURE_11BE */
3690 static inline
wlan_hdd_set_sap_acs_ch_width_320(struct sap_config * sap_config)3691 void wlan_hdd_set_sap_acs_ch_width_320(struct sap_config *sap_config)
3692 {
3693 }
3694 
3695 static inline
wlan_hdd_is_sap_acs_ch_width_320(struct sap_config * sap_config)3696 bool wlan_hdd_is_sap_acs_ch_width_320(struct sap_config *sap_config)
3697 {
3698 	return false;
3699 }
3700 
3701 static inline void
wlan_hdd_set_chandef_for_11be(struct cfg80211_chan_def * chandef,struct wlan_channel * chan_info)3702 wlan_hdd_set_chandef_for_11be(struct cfg80211_chan_def *chandef,
3703 			      struct wlan_channel *chan_info)
3704 {
3705 }
3706 #endif /* WLAN_FEATURE_11BE */
3707 
3708 #ifdef WLAN_FEATURE_11BE
3709 /**
3710  * wlan_hdd_acs_set_eht_enabled() - set is_eht_enabled of acs config
3711  * @sap_config: pointer to sap_config
3712  * @eht_enabled: eht is enabled
3713  *
3714  * Return: void
3715  */
wlan_hdd_acs_set_eht_enabled(struct sap_config * sap_config,bool eht_enabled)3716 static void wlan_hdd_acs_set_eht_enabled(struct sap_config *sap_config,
3717 					 bool eht_enabled)
3718 {
3719 	if (!sap_config) {
3720 		hdd_err("Invalid sap_config");
3721 		return;
3722 	}
3723 
3724 	sap_config->acs_cfg.is_eht_enabled = eht_enabled;
3725 }
3726 #else
wlan_hdd_acs_set_eht_enabled(struct sap_config * sap_config,bool eht_enabled)3727 static void wlan_hdd_acs_set_eht_enabled(struct sap_config *sap_config,
3728 					 bool eht_enabled)
3729 {
3730 }
3731 #endif /* WLAN_FEATURE_11BE */
3732 
wlan_hdd_update_bw_from_mlme(struct hdd_context * hdd_ctx,struct sap_config * sap_config)3733 static uint16_t wlan_hdd_update_bw_from_mlme(struct hdd_context *hdd_ctx,
3734 					     struct sap_config *sap_config)
3735 {
3736 	uint16_t ch_width, temp_ch_width = 0;
3737 	QDF_STATUS status;
3738 	uint8_t hw_mode = HW_MODE_DBS;
3739 	struct wma_caps_per_phy caps_per_phy = {0};
3740 
3741 	ch_width = sap_config->acs_cfg.ch_width;
3742 
3743 	if (ch_width > CH_WIDTH_80P80MHZ)
3744 		return ch_width;
3745 
3746 	/* 2.4ghz is already handled for acs */
3747 	if (sap_config->acs_cfg.end_ch_freq <=
3748 	    WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484))
3749 		return ch_width;
3750 
3751 	if (!policy_mgr_is_dbs_enable(hdd_ctx->psoc))
3752 		hw_mode = HW_MODE_DBS_NONE;
3753 
3754 	status = wma_get_caps_for_phyidx_hwmode(&caps_per_phy, hw_mode,
3755 						CDS_BAND_5GHZ);
3756 	if (!QDF_IS_STATUS_SUCCESS(status))
3757 		return ch_width;
3758 
3759 	switch (ch_width) {
3760 	case CH_WIDTH_80P80MHZ:
3761 		if (!(caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ))
3762 		{
3763 			if (caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_160MHZ)
3764 				temp_ch_width = CH_WIDTH_160MHZ;
3765 			else
3766 				temp_ch_width = CH_WIDTH_80MHZ;
3767 		}
3768 		break;
3769 	case CH_WIDTH_160MHZ:
3770 		if (!((caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
3771 		      || (caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_160MHZ)))
3772 				temp_ch_width = CH_WIDTH_80MHZ;
3773 		break;
3774 	default:
3775 		break;
3776 	}
3777 
3778 	if (!temp_ch_width)
3779 		return ch_width;
3780 
3781 	hdd_debug("ch_width updated from %d to %d vht_5g: %x", ch_width,
3782 		  temp_ch_width, caps_per_phy.vht_5g);
3783 	return temp_ch_width;
3784 }
3785 
3786 /**
3787  *  wlan_hdd_check_is_acs_request_same() - API to compare ongoing ACS and
3788  *					current received ACS request
3789  * @adapter: hdd adapter
3790  * @data: ACS data
3791  * @data_len: ACS data length
3792  *
3793  * This function is used to compare ongoing ACS params with current received
3794  * ACS request on same interface.
3795  *
3796  * Return: true only if ACS request received is same as ongoing ACS
3797  */
wlan_hdd_check_is_acs_request_same(struct hdd_adapter * adapter,const void * data,int data_len)3798 static bool wlan_hdd_check_is_acs_request_same(struct hdd_adapter *adapter,
3799 					       const void *data, int data_len)
3800 {
3801 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
3802 	uint8_t hw_mode, ht_enabled, ht40_enabled, vht_enabled, eht_enabled;
3803 	struct sap_config *sap_config;
3804 	uint32_t last_scan_ageout_time = 0;
3805 	uint8_t ch_list_count;
3806 	uint16_t ch_width;
3807 	int ret, i, j;
3808 	struct wlan_objmgr_psoc *psoc;
3809 
3810 	ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
3811 				      data_len,
3812 				      wlan_hdd_cfg80211_do_acs_policy);
3813 	if (ret) {
3814 		hdd_err("Invalid ATTR");
3815 		return false;
3816 	}
3817 
3818 	if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE])
3819 		return false;
3820 
3821 	sap_config = &adapter->deflink->session.ap.sap_config;
3822 
3823 	hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
3824 	if (sap_config->acs_cfg.master_acs_cfg.hw_mode != hw_mode)
3825 		return false;
3826 
3827 	ht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
3828 	if (sap_config->acs_cfg.master_acs_cfg.ht != ht_enabled)
3829 		return false;
3830 
3831 	ht40_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
3832 	if (sap_config->acs_cfg.master_acs_cfg.ht40 != ht40_enabled)
3833 		return false;
3834 
3835 	vht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
3836 	if (sap_config->acs_cfg.master_acs_cfg.vht != vht_enabled)
3837 		return false;
3838 
3839 	eht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED]);
3840 	if (sap_config->acs_cfg.master_acs_cfg.eht != eht_enabled)
3841 		return false;
3842 
3843 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH])
3844 		ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
3845 	else
3846 		ch_width = 0;
3847 	if (sap_config->acs_cfg.master_acs_cfg.ch_width != ch_width)
3848 		return false;
3849 
3850 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME]) {
3851 		last_scan_ageout_time =
3852 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME]);
3853 	} else {
3854 		psoc = wlan_vdev_get_psoc(adapter->deflink->vdev);
3855 		if (psoc)
3856 			wlan_scan_get_last_scan_ageout_time(
3857 							psoc,
3858 							&last_scan_ageout_time);
3859 	}
3860 	if (sap_config->acs_cfg.last_scan_ageout_time != last_scan_ageout_time)
3861 		return false;
3862 
3863 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
3864 		uint32_t *freq =
3865 			nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
3866 
3867 		ch_list_count = nla_len(
3868 				tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
3869 				sizeof(uint32_t);
3870 		if (sap_config->acs_cfg.master_ch_list_count != ch_list_count)
3871 			return false;
3872 		for (i = 0; i < ch_list_count; i++) {
3873 			j = 0;
3874 			while (j < ch_list_count && freq[i] !=
3875 			       sap_config->acs_cfg.master_freq_list[j])
3876 				j++;
3877 			if (j == ch_list_count)
3878 				return false;
3879 		}
3880 	} else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
3881 		uint8_t *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3882 
3883 		ch_list_count = nla_len(
3884 					tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3885 		if (sap_config->acs_cfg.master_ch_list_count != ch_list_count)
3886 			return false;
3887 		for (i = 0; i < ch_list_count; i++) {
3888 			j = 0;
3889 			while (j < ch_list_count &&
3890 			       wlan_reg_legacy_chan_to_freq(
3891 			       adapter->hdd_ctx->pdev, tmp[i]) !=
3892 			       sap_config->acs_cfg.master_freq_list[j])
3893 				j++;
3894 			if (j == ch_list_count)
3895 				return false;
3896 		}
3897 	}
3898 
3899 	return true;
3900 }
3901 
3902 #ifndef WLAN_FEATURE_LL_LT_SAP
3903 /**
3904  * hdd_remove_passive_dfs_acs_channel_for_ll_sap(): Remove passive/dfs channel
3905  * for LL SAP
3906  * @sap_config: Pointer to sap_config
3907  * @psoc: Pointer to psoc
3908  * @pdev: Pointer to pdev
3909  * @vdev_id: Vdev Id
3910  *
3911  * This function will remove passive/dfs acs channel for low latency SAP
3912  * which are configured through userspace.
3913  *
3914  * Return: void
3915  */
hdd_remove_passive_dfs_acs_channel_for_ll_sap(struct sap_config * sap_config,struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev,uint8_t vdev_id)3916 static void hdd_remove_passive_dfs_acs_channel_for_ll_sap(
3917 					struct sap_config *sap_config,
3918 					struct wlan_objmgr_psoc *psoc,
3919 					struct wlan_objmgr_pdev *pdev,
3920 					uint8_t vdev_id)
3921 {
3922 	uint32_t i, ch_cnt = 0;
3923 	uint32_t freq = 0;
3924 
3925 	if (!policy_mgr_is_vdev_ll_sap(psoc, vdev_id))
3926 		return;
3927 
3928 	for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
3929 		freq = sap_config->acs_cfg.freq_list[i];
3930 
3931 		/* Remove passive/dfs channel for LL SAP */
3932 		if (wlan_reg_is_passive_for_freq(pdev, freq) ||
3933 		    wlan_reg_is_dfs_for_freq(pdev, freq))
3934 			continue;
3935 
3936 		sap_config->acs_cfg.freq_list[ch_cnt++] = freq;
3937 	}
3938 
3939 	if (ch_cnt != sap_config->acs_cfg.ch_list_count) {
3940 		hdd_debug("New count after modification %d", ch_cnt);
3941 		sap_config->acs_cfg.ch_list_count = ch_cnt;
3942 		sap_dump_acs_channel(&sap_config->acs_cfg);
3943 	}
3944 }
3945 #else
3946 static inline void
hdd_remove_passive_dfs_acs_channel_for_ll_sap(struct sap_config * sap_config,struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev,uint8_t vdev_id)3947 hdd_remove_passive_dfs_acs_channel_for_ll_sap(struct sap_config *sap_config,
3948 					      struct wlan_objmgr_psoc *psoc,
3949 					      struct wlan_objmgr_pdev *pdev,
3950 					      uint8_t vdev_id)
3951 {
3952 }
3953 #endif
3954 
3955 /* Stored ACS Frequency timeout in msec */
3956 #define STORED_ACS_FREQ_TIMEOUT 5000
3957 static bool
wlan_hdd_is_prev_acs_freq_present_in_acs_config(struct sap_config * sap_cfg)3958 wlan_hdd_is_prev_acs_freq_present_in_acs_config(struct sap_config *sap_cfg)
3959 {
3960 	uint32_t i = 0;
3961 	bool prev_acs_freq_found = false;
3962 
3963 	if (!qdf_system_time_before(
3964 		qdf_get_time_of_the_day_ms(),
3965 		sap_cfg->last_acs_complete_time + STORED_ACS_FREQ_TIMEOUT))
3966 		return prev_acs_freq_found;
3967 
3968 	for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
3969 		if (sap_cfg->acs_cfg.freq_list[i] == sap_cfg->last_acs_freq) {
3970 			prev_acs_freq_found = true;
3971 			break;
3972 		}
3973 	}
3974 
3975 	return prev_acs_freq_found;
3976 }
3977 
3978 static bool
wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(struct hdd_adapter * adapter)3979 wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(struct hdd_adapter *adapter)
3980 {
3981 	struct hdd_context *hdd_ctx;
3982 	struct sap_config *sap_config;
3983 	int status;
3984 	bool prev_acs_freq_valid = false;
3985 	struct sap_context *sap_ctx;
3986 
3987 	if (!adapter) {
3988 		hdd_err("adapter is NULL");
3989 		return prev_acs_freq_valid;
3990 	}
3991 
3992 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3993 	status = wlan_hdd_validate_context(hdd_ctx);
3994 	if (0 != status) {
3995 		hdd_err("Invalid HDD context");
3996 		return prev_acs_freq_valid;
3997 	}
3998 
3999 	sap_config = &adapter->deflink->session.ap.sap_config;
4000 	if (!sap_config) {
4001 		hdd_err("SAP config is NULL");
4002 		return prev_acs_freq_valid;
4003 	}
4004 
4005 	if (!sap_config->last_acs_freq || !sap_config->last_acs_complete_time)
4006 		return prev_acs_freq_valid;
4007 
4008 	if (!policy_mgr_is_vdev_ll_lt_sap(
4009 				hdd_ctx->psoc,
4010 				adapter->deflink->vdev_id))
4011 		return prev_acs_freq_valid;
4012 
4013 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink);
4014 	if (wlan_hdd_is_prev_acs_freq_present_in_acs_config(sap_config)) {
4015 		wlansap_update_ll_lt_sap_acs_result(sap_ctx,
4016 						    sap_config->last_acs_freq);
4017 
4018 		hdd_debug("vdev %d, return prev ACS freq %d stored at %lu, current time %lu",
4019 			  adapter->deflink->vdev_id, sap_config->last_acs_freq,
4020 			  sap_config->last_acs_complete_time,
4021 			  qdf_get_time_of_the_day_ms());
4022 
4023 		/* Notify to hostapd without storing the last acs frequency.
4024 		 * Reason for not storing the last acs frequency is to avoid
4025 		 * storing the same freq again and again
4026 		 */
4027 		wlan_hdd_cfg80211_acs_ch_select_evt(adapter->deflink, false);
4028 		wlansap_dcs_set_wlan_interference_mitigation_on_band(sap_ctx,
4029 								    sap_config);
4030 
4031 		prev_acs_freq_valid = true;
4032 	}
4033 
4034 	return prev_acs_freq_valid;
4035 }
4036 
4037 /**
4038  * hdd_remove_6ghz_freq_from_acs_list(): Removed 6 GHz frequecies from ACS list
4039  * @org_freq_list: ACS frequecny list
4040  * @org_ch_list_count: Number of frequencies in ACS list
4041  *
4042  * Return: None
4043  */
hdd_remove_6ghz_freq_from_acs_list(uint32_t * org_freq_list,uint8_t * org_ch_list_count)4044 static void hdd_remove_6ghz_freq_from_acs_list(uint32_t *org_freq_list,
4045 					       uint8_t *org_ch_list_count)
4046 {
4047 	uint16_t i, ch_list_count = 0;
4048 
4049 	hdd_debug("Remove 6 GHz channels from ACS list");
4050 	for (i = 0; i < *org_ch_list_count; i++) {
4051 		if (wlan_reg_is_6ghz_chan_freq(org_freq_list[i]))
4052 			continue;
4053 		org_freq_list[ch_list_count++] = org_freq_list[i];
4054 	}
4055 	*org_ch_list_count = ch_list_count;
4056 }
4057 
4058 /**
4059  * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
4060  * @wiphy:  Linux wiphy struct pointer
4061  * @wdev:   Linux wireless device struct pointer
4062  * @data:   ACS information from hostapd
4063  * @data_len: ACS information length
4064  *
4065  * This function handle DO_ACS Vendor command from hostapd, parses ACS config
4066  * and starts ACS procedure.
4067  *
4068  * Return: ACS procedure start status
4069  */
__wlan_hdd_cfg80211_do_acs(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)4070 static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
4071 					struct wireless_dev *wdev,
4072 					const void *data, int data_len)
4073 {
4074 	struct net_device *ndev = wdev->netdev;
4075 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
4076 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
4077 	struct sap_config *sap_config;
4078 	struct sap_context *sap_ctx;
4079 	struct hdd_ap_ctx *ap_ctx;
4080 	struct sk_buff *temp_skbuff;
4081 	int ret, i;
4082 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
4083 	bool ht_enabled, ht40_enabled, vht_enabled, eht_enabled;
4084 	uint16_t ch_width;
4085 	enum qca_wlan_vendor_acs_hw_mode hw_mode;
4086 	enum policy_mgr_con_mode pm_mode;
4087 	QDF_STATUS qdf_status;
4088 	bool is_vendor_acs_support = false;
4089 	bool is_external_acs_policy = false;
4090 	bool is_vendor_unsafe_ch_present = false;
4091 	bool sap_force_11n_for_11ac = 0;
4092 	bool go_force_11n_for_11ac = 0;
4093 	bool is_ll_lt_sap = false;
4094 	bool sap_force_11n = false;
4095 	bool go_11ac_override = 0;
4096 	bool sap_11ac_override = 0;
4097 	uint8_t vht_ch_width;
4098 	uint32_t channel_bonding_mode_2g;
4099 	uint32_t last_scan_ageout_time;
4100 	struct wlan_hdd_link_info *link_info = adapter->deflink;
4101 
4102 	/* ***Note*** Donot set SME config related to ACS operation here because
4103 	 * ACS operation is not synchronouse and ACS for Second AP may come when
4104 	 * ACS operation for first AP is going on. So only do_acs is split to
4105 	 * separate start_acs routine. Also SME-PMAC struct that is used to
4106 	 * pass parameters from HDD to SAP is global. Thus All ACS related SME
4107 	 * config shall be set only from start_acs.
4108 	 */
4109 
4110 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4111 		hdd_err("Command not allowed in FTM mode");
4112 		return -EPERM;
4113 	}
4114 
4115 	ret = wlan_hdd_validate_context(hdd_ctx);
4116 	if (ret)
4117 		return ret;
4118 
4119 	ucfg_mlme_get_sap_force_11n_for_11ac(hdd_ctx->psoc,
4120 					     &sap_force_11n_for_11ac);
4121 	ucfg_mlme_get_go_force_11n_for_11ac(hdd_ctx->psoc,
4122 					    &go_force_11n_for_11ac);
4123 	ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
4124 					    &channel_bonding_mode_2g);
4125 
4126 	if (policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc, link_info->vdev_id)) {
4127 		is_ll_lt_sap = true;
4128 		policy_mgr_ll_lt_sap_restart_concurrent_sap(hdd_ctx->psoc,
4129 							    true);
4130 	}
4131 
4132 	if (is_ll_lt_sap || sap_force_11n_for_11ac)
4133 		sap_force_11n = true;
4134 
4135 	if (!((adapter->device_mode == QDF_SAP_MODE) ||
4136 	      (adapter->device_mode == QDF_P2P_GO_MODE))) {
4137 		hdd_err("Invalid device mode %d", adapter->device_mode);
4138 		return -EINVAL;
4139 	}
4140 
4141 	if (cds_is_sub_20_mhz_enabled()) {
4142 		hdd_err("ACS not supported in sub 20 MHz ch wd.");
4143 		return -EINVAL;
4144 	}
4145 
4146 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
4147 
4148 	if (qdf_atomic_read(&ap_ctx->acs_in_progress) > 0) {
4149 		if (wlan_hdd_check_is_acs_request_same(adapter,
4150 						       data, data_len)) {
4151 			hdd_debug("Same ACS req as ongoing is received, return success");
4152 			ret = 0;
4153 			goto out;
4154 		}
4155 		hdd_err("ACS rejected as previous ACS req already in progress");
4156 		return -EINVAL;
4157 	} else {
4158 		qdf_atomic_set(&ap_ctx->acs_in_progress, 1);
4159 		qdf_event_reset(&link_info->acs_complete_event);
4160 	}
4161 
4162 	hdd_reg_wait_for_country_change(hdd_ctx);
4163 
4164 	ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
4165 					 data_len,
4166 					 wlan_hdd_cfg80211_do_acs_policy);
4167 	if (ret) {
4168 		hdd_err("Invalid ATTR");
4169 		goto out;
4170 	}
4171 
4172 	if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
4173 		hdd_err("Attr hw_mode failed");
4174 		ret = -EINVAL;
4175 		goto out;
4176 	}
4177 
4178 	sap_config = &ap_ctx->sap_config;
4179 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
4180 
4181 	/* Check and free if memory is already allocated for acs channel list */
4182 	wlan_hdd_undo_acs(link_info);
4183 
4184 	qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
4185 
4186 	hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
4187 	hdd_nofl_info("ACS request vid %d hw mode %d",
4188 		      link_info->vdev_id, hw_mode);
4189 	ht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
4190 	ht40_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
4191 	vht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
4192 	eht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED]);
4193 
4194 	sap_config->acs_cfg.master_acs_cfg.hw_mode = hw_mode;
4195 	sap_config->acs_cfg.master_acs_cfg.ht = ht_enabled;
4196 	sap_config->acs_cfg.master_acs_cfg.ht40 = ht40_enabled;
4197 	sap_config->acs_cfg.master_acs_cfg.vht = vht_enabled;
4198 	sap_config->acs_cfg.master_acs_cfg.eht = eht_enabled;
4199 
4200 	if (((adapter->device_mode == QDF_SAP_MODE) &&
4201 	      sap_force_11n) ||
4202 	    ((adapter->device_mode == QDF_P2P_GO_MODE) &&
4203 	      go_force_11n_for_11ac)) {
4204 		vht_enabled = 0;
4205 		hdd_info("VHT is Disabled in ACS");
4206 	}
4207 
4208 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
4209 		ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
4210 		sap_config->acs_cfg.master_acs_cfg.ch_width = ch_width;
4211 	} else {
4212 		if (ht_enabled && ht40_enabled)
4213 			ch_width = 40;
4214 		else
4215 			ch_width = 20;
4216 		sap_config->acs_cfg.master_acs_cfg.ch_width = 0;
4217 	}
4218 
4219 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED])
4220 		eht_enabled =
4221 			nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED]);
4222 	else
4223 		eht_enabled = 0;
4224 
4225 	if (ch_width == 320 && !eht_enabled)
4226 		ch_width = 160;
4227 
4228 	/* this may be possible, when sap_force_11n_for_11ac or
4229 	 * go_force_11n_for_11ac is set
4230 	 */
4231 	if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
4232 		if (ht_enabled && ht40_enabled)
4233 			ch_width = 40;
4234 		else
4235 			ch_width = 20;
4236 	}
4237 	if (is_ll_lt_sap)
4238 		ch_width = 20;
4239 
4240 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME])
4241 		last_scan_ageout_time =
4242 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME]);
4243 	else
4244 		wlan_scan_get_last_scan_ageout_time(hdd_ctx->psoc,
4245 						    &last_scan_ageout_time);
4246 
4247 	if (ch_width == 320)
4248 		wlan_hdd_set_sap_acs_ch_width_320(sap_config);
4249 	else if (ch_width == 160)
4250 		sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
4251 	else if (ch_width == 80)
4252 		sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
4253 	else if (ch_width == 40)
4254 		sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
4255 	else
4256 		sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
4257 
4258 	/* Firstly try to get channel frequencies */
4259 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
4260 		uint32_t *freq =
4261 			nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
4262 		sap_config->acs_cfg.ch_list_count = nla_len(
4263 			tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
4264 				sizeof(uint32_t);
4265 		if (sap_config->acs_cfg.ch_list_count) {
4266 			sap_config->acs_cfg.freq_list = qdf_mem_malloc(
4267 				sap_config->acs_cfg.ch_list_count *
4268 				sizeof(uint32_t));
4269 			sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
4270 				sap_config->acs_cfg.ch_list_count *
4271 				sizeof(uint32_t));
4272 			if (!sap_config->acs_cfg.freq_list ||
4273 			    !sap_config->acs_cfg.master_freq_list) {
4274 				ret = -ENOMEM;
4275 				goto out;
4276 			}
4277 
4278 			for (i = 0; i < sap_config->acs_cfg.ch_list_count;
4279 			     i++) {
4280 				sap_config->acs_cfg.master_freq_list[i] =
4281 									freq[i];
4282 				sap_config->acs_cfg.freq_list[i] = freq[i];
4283 			}
4284 			sap_config->acs_cfg.master_ch_list_count =
4285 					sap_config->acs_cfg.ch_list_count;
4286 		}
4287 	} else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
4288 		uint8_t *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
4289 
4290 		sap_config->acs_cfg.ch_list_count = nla_len(
4291 					tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
4292 		if (sap_config->acs_cfg.ch_list_count) {
4293 			sap_config->acs_cfg.freq_list = qdf_mem_malloc(
4294 					sap_config->acs_cfg.ch_list_count *
4295 					sizeof(uint32_t));
4296 			sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
4297 					sap_config->acs_cfg.ch_list_count *
4298 					sizeof(uint32_t));
4299 			if (!sap_config->acs_cfg.freq_list ||
4300 			    !sap_config->acs_cfg.master_freq_list) {
4301 				ret = -ENOMEM;
4302 				goto out;
4303 			}
4304 
4305 			/* convert channel to frequency */
4306 			for (i = 0; i < sap_config->acs_cfg.ch_list_count;
4307 			     i++) {
4308 				sap_config->acs_cfg.freq_list[i] =
4309 					wlan_reg_legacy_chan_to_freq(
4310 								hdd_ctx->pdev,
4311 								tmp[i]);
4312 				sap_config->acs_cfg.master_freq_list[i] =
4313 					sap_config->acs_cfg.freq_list[i];
4314 			}
4315 			sap_config->acs_cfg.master_ch_list_count =
4316 					sap_config->acs_cfg.ch_list_count;
4317 		}
4318 	}
4319 
4320 	if (!sap_config->acs_cfg.ch_list_count) {
4321 		hdd_err("acs config chan count 0");
4322 		ret = -EINVAL;
4323 		goto out;
4324 	} else {
4325 		hdd_nofl_debug("Dump raw ACS chanlist - ");
4326 		sap_dump_acs_channel(&sap_config->acs_cfg);
4327 	}
4328 
4329 	hdd_handle_acs_2g_preferred_sap_conc(hdd_ctx->psoc, adapter,
4330 					     sap_config);
4331 	hdd_avoid_acs_channels(hdd_ctx, sap_config);
4332 
4333 	pm_mode =
4334 		policy_mgr_qdf_opmode_to_pm_con_mode(hdd_ctx->psoc,
4335 						     adapter->device_mode,
4336 						     adapter->deflink->vdev_id);
4337 
4338 	/* Remove passive/dfs acs channel for ll sap */
4339 	hdd_remove_passive_dfs_acs_channel_for_ll_sap(
4340 						sap_config, hdd_ctx->psoc,
4341 						hdd_ctx->pdev,
4342 						link_info->vdev_id);
4343 
4344 	/* consult policy manager to get PCL */
4345 	qdf_status = policy_mgr_get_pcl(hdd_ctx->psoc, pm_mode,
4346 					sap_config->acs_cfg.pcl_chan_freq,
4347 					&sap_config->acs_cfg.pcl_ch_count,
4348 					sap_config->acs_cfg.
4349 					pcl_channels_weight_list,
4350 					NUM_CHANNELS,
4351 					link_info->vdev_id);
4352 
4353 	policy_mgr_get_pcl_channel_for_ll_sap_concurrency(
4354 				hdd_ctx->psoc,
4355 				link_info->vdev_id,
4356 				sap_config->acs_cfg.pcl_chan_freq,
4357 				sap_config->acs_cfg.pcl_channels_weight_list,
4358 				&sap_config->acs_cfg.pcl_ch_count);
4359 
4360 	sap_config->acs_cfg.band = hw_mode;
4361 
4362 	qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
4363 						       &is_external_acs_policy);
4364 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
4365 		hdd_err("get_external_acs_policy failed");
4366 
4367 	sap_config->acs_cfg.acs_mode = true;
4368 
4369 	if (wlan_reg_get_keep_6ghz_sta_cli_connection(hdd_ctx->pdev))
4370 		hdd_remove_6ghz_freq_from_acs_list(
4371 					sap_config->acs_cfg.freq_list,
4372 					&sap_config->acs_cfg.ch_list_count);
4373 
4374 	if ((is_external_acs_policy &&
4375 	    policy_mgr_is_force_scc(hdd_ctx->psoc) &&
4376 	    policy_mgr_get_connection_count(hdd_ctx->psoc)) || is_ll_lt_sap) {
4377 		if (adapter->device_mode == QDF_SAP_MODE)
4378 			is_vendor_unsafe_ch_present =
4379 				wlansap_filter_vendor_unsafe_ch_freq(sap_ctx,
4380 								     sap_config);
4381 		wlan_hdd_trim_acs_channel_list(
4382 					sap_config->acs_cfg.pcl_chan_freq,
4383 					sap_config->acs_cfg.pcl_ch_count,
4384 					sap_config->acs_cfg.freq_list,
4385 					&sap_config->acs_cfg.ch_list_count);
4386 		if (!sap_config->acs_cfg.ch_list_count &&
4387 		    sap_config->acs_cfg.master_ch_list_count &&
4388 		    !is_vendor_unsafe_ch_present &&
4389 		    !is_ll_lt_sap)
4390 			wlan_hdd_handle_zero_acs_list(
4391 				hdd_ctx,
4392 				sap_config->acs_cfg.freq_list,
4393 				&sap_config->acs_cfg.ch_list_count,
4394 				sap_config->acs_cfg.master_freq_list,
4395 				sap_config->acs_cfg.master_ch_list_count);
4396 		/* if it is only one channel, send ACS event to upper layer */
4397 		if (sap_config->acs_cfg.ch_list_count == 1) {
4398 			wlan_hdd_handle_single_ch_in_acs_list(link_info);
4399 			ret = 0;
4400 			goto out;
4401 		} else if (!sap_config->acs_cfg.ch_list_count) {
4402 			hdd_err("channel list count 0");
4403 			ret = -EINVAL;
4404 			goto out;
4405 		}
4406 	} else if (adapter->device_mode == QDF_SAP_MODE) {
4407 		wlansap_filter_vendor_unsafe_ch_freq(sap_ctx, sap_config);
4408 		if (sap_config->acs_cfg.ch_list_count == 1) {
4409 			wlan_hdd_handle_single_ch_in_acs_list(link_info);
4410 			ret = 0;
4411 			goto out;
4412 		} else if (!sap_config->acs_cfg.ch_list_count) {
4413 			hdd_err("channel count 0 after vendor unsafe filter");
4414 			ret = -EINVAL;
4415 			goto out;
4416 		}
4417 	}
4418 
4419 	ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
4420 					ht_enabled, vht_enabled);
4421 	if (ret) {
4422 		hdd_err("set acs channel range failed");
4423 		goto out;
4424 	}
4425 
4426 	ucfg_mlme_is_go_11ac_override(hdd_ctx->psoc, &go_11ac_override);
4427 	ucfg_mlme_is_sap_11ac_override(hdd_ctx->psoc, &sap_11ac_override);
4428 	/* ACS override for android */
4429 	if (ht_enabled &&
4430 	    sap_config->acs_cfg.end_ch_freq >=
4431 		WLAN_REG_CH_TO_FREQ(CHAN_ENUM_5180) &&
4432 	    ((adapter->device_mode == QDF_SAP_MODE &&
4433 	      !sap_force_11n &&
4434 	      sap_11ac_override) ||
4435 	      (adapter->device_mode == QDF_P2P_GO_MODE &&
4436 	      !go_force_11n_for_11ac &&
4437 	      go_11ac_override))) {
4438 		vht_enabled = 1;
4439 		sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
4440 		qdf_status =
4441 			ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
4442 							&vht_ch_width);
4443 		ch_width = vht_ch_width;
4444 		sap_config->acs_cfg.ch_width = ch_width;
4445 	}
4446 
4447 	/* Check 2.4ghz cbmode and update BW if only 2.4 channels are present */
4448 	if (sap_config->acs_cfg.end_ch_freq <=
4449 	    WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484) &&
4450 	    sap_config->acs_cfg.ch_width >= eHT_CHANNEL_WIDTH_40MHZ) {
4451 
4452 		sap_config->acs_cfg.ch_width = channel_bonding_mode_2g ?
4453 			eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ;
4454 
4455 		hdd_debug("Only 2.4ghz channels, resetting BW to %d 2.4 cbmode %d",
4456 			  sap_config->acs_cfg.ch_width,
4457 			  channel_bonding_mode_2g);
4458 	}
4459 
4460 	sap_config->acs_cfg.ch_width = wlan_hdd_update_bw_from_mlme(hdd_ctx,
4461 								    sap_config);
4462 
4463 	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",
4464 		       hdd_ctx->reg.alpha2, ch_width,
4465 		       sap_config->acs_cfg.hw_mode, sap_config->acs_cfg.ch_width,
4466 		       ht_enabled, vht_enabled, eht_enabled,
4467 		       sap_config->acs_cfg.start_ch_freq,
4468 		       sap_config->acs_cfg.end_ch_freq,
4469 		       sap_config->acs_cfg.band, last_scan_ageout_time);
4470 	host_log_acs_req_event(adapter->dev->name,
4471 			  csr_phy_mode_str(sap_config->acs_cfg.hw_mode),
4472 			  ch_width, ht_enabled, vht_enabled,
4473 			  sap_config->acs_cfg.start_ch_freq,
4474 			  sap_config->acs_cfg.end_ch_freq);
4475 
4476 	sap_config->acs_cfg.is_ht_enabled = ht_enabled;
4477 	sap_config->acs_cfg.is_vht_enabled = vht_enabled;
4478 	wlan_hdd_acs_set_eht_enabled(sap_config, eht_enabled);
4479 	sap_config->acs_cfg.last_scan_ageout_time = last_scan_ageout_time;
4480 
4481 	sap_dump_acs_channel(&sap_config->acs_cfg);
4482 
4483 	if (wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(adapter)) {
4484 		ret = 0;
4485 		goto out;
4486 	}
4487 
4488 	qdf_status = ucfg_mlme_get_vendor_acs_support(hdd_ctx->psoc,
4489 						      &is_vendor_acs_support);
4490 	if (QDF_IS_STATUS_ERROR(qdf_status))
4491 		hdd_err("get_vendor_acs_support failed, set default");
4492 
4493 	/* Check if vendor specific acs is enabled */
4494 	if (is_vendor_acs_support)
4495 		ret = hdd_start_vendor_acs(adapter);
4496 	else
4497 		ret = wlan_hdd_cfg80211_start_acs(link_info);
4498 
4499 out:
4500 	if (ret == 0) {
4501 		temp_skbuff =
4502 			wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4503 								 NLMSG_HDRLEN);
4504 		if (temp_skbuff)
4505 			return wlan_cfg80211_vendor_cmd_reply(temp_skbuff);
4506 	}
4507 	qdf_atomic_set(&ap_ctx->acs_in_progress, 0);
4508 
4509 	return ret;
4510 }
4511 
4512 /**
4513  * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
4514  * @wiphy:  Linux wiphy struct pointer
4515  * @wdev:   Linux wireless device struct pointer
4516  * @data:   ACS information from hostapd
4517  * @data_len: ACS information len
4518  *
4519  * This function handle DO_ACS Vendor command from hostapd, parses ACS config
4520  * and starts ACS procedure.
4521  *
4522  * Return: ACS procedure start status
4523  */
4524 
wlan_hdd_cfg80211_do_acs(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)4525 static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
4526 				    struct wireless_dev *wdev,
4527 				    const void *data, int data_len)
4528 {
4529 	int errno;
4530 	struct osif_vdev_sync *vdev_sync;
4531 
4532 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
4533 	if (errno)
4534 		return errno;
4535 
4536 	errno = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
4537 
4538 	osif_vdev_sync_op_stop(vdev_sync);
4539 
4540 	return errno;
4541 }
4542 
wlan_hdd_undo_acs(struct wlan_hdd_link_info * link_info)4543 void wlan_hdd_undo_acs(struct wlan_hdd_link_info *link_info)
4544 {
4545 	sap_undo_acs(WLAN_HDD_GET_SAP_CTX_PTR(link_info),
4546 		     &link_info->session.ap.sap_config);
4547 }
4548 
4549 /**
4550  * hdd_fill_acs_chan_freq() - Populate channel frequencies (MHz) selected in ACS
4551  * @hdd_ctx: pointer to hdd context
4552  * @sap_cfg: sap acs configuration
4553  * @vendor_event: output pointer to populate channel frequencies (MHz)
4554  *
4555  * Return: If populated successfully return 0 else negative value.
4556  */
hdd_fill_acs_chan_freq(struct hdd_context * hdd_ctx,struct sap_config * sap_cfg,struct sk_buff * vendor_event)4557 static int hdd_fill_acs_chan_freq(struct hdd_context *hdd_ctx,
4558 				  struct sap_config *sap_cfg,
4559 				  struct sk_buff *vendor_event)
4560 {
4561 	uint32_t id;
4562 	int errno;
4563 
4564 	id = QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY;
4565 	errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.pri_ch_freq);
4566 	if (errno) {
4567 		hdd_err("VENDOR_ATTR_ACS_PRIMARY_FREQUENCY put fail");
4568 		return errno;
4569 	}
4570 
4571 	id = QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY;
4572 	errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.ht_sec_ch_freq);
4573 	if (errno) {
4574 		hdd_err("VENDOR_ATTR_ACS_SECONDARY_FREQUENCY put fail");
4575 		return errno;
4576 	}
4577 
4578 	id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY;
4579 	errno = nla_put_u32(vendor_event, id,
4580 			    sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
4581 	if (errno) {
4582 		hdd_err("VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY put fail");
4583 		return errno;
4584 	}
4585 
4586 	id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY;
4587 	errno = nla_put_u32(vendor_event, id,
4588 			    sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
4589 	if (errno) {
4590 		hdd_err("VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY put fail");
4591 		return errno;
4592 	}
4593 
4594 	return 0;
4595 }
4596 
hdd_get_acs_evt_data_len(struct sap_config * sap_cfg)4597 static int hdd_get_acs_evt_data_len(struct sap_config *sap_cfg)
4598 {
4599 	uint32_t len = NLMSG_HDRLEN;
4600 
4601 	/* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL */
4602 	len += nla_total_size(sizeof(u8));
4603 
4604 	/* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL */
4605 	len += nla_total_size(sizeof(u8));
4606 
4607 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL */
4608 	len += nla_total_size(sizeof(u8));
4609 
4610 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL */
4611 	len += nla_total_size(sizeof(u8));
4612 
4613 	/* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY */
4614 	len += nla_total_size(sizeof(u32));
4615 
4616 	/* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY */
4617 	len += nla_total_size(sizeof(u32));
4618 
4619 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY */
4620 	len += nla_total_size(sizeof(u32));
4621 
4622 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY */
4623 	len += nla_total_size(sizeof(u32));
4624 
4625 	/* QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH */
4626 	len += nla_total_size(sizeof(u16));
4627 
4628 	/* QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE */
4629 	len += nla_total_size(sizeof(u8));
4630 
4631 	/* QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP */
4632 	if (sap_acs_is_puncture_applicable(&sap_cfg->acs_cfg))
4633 		len += nla_total_size(sizeof(u16));
4634 
4635 	return len;
4636 }
4637 
4638 #ifdef WLAN_FEATURE_11BE
4639 /**
4640  * wlan_hdd_acs_get_puncture_bitmap() - get puncture_bitmap for acs result
4641  * @acs_cfg: pointer to struct sap_acs_cfg
4642  *
4643  * Return: acs puncture bitmap
4644  */
wlan_hdd_acs_get_puncture_bitmap(struct sap_acs_cfg * acs_cfg)4645 static uint16_t wlan_hdd_acs_get_puncture_bitmap(struct sap_acs_cfg *acs_cfg)
4646 {
4647 	if (sap_acs_is_puncture_applicable(acs_cfg))
4648 		return acs_cfg->acs_puncture_bitmap;
4649 
4650 	return 0;
4651 }
4652 #else
wlan_hdd_acs_get_puncture_bitmap(struct sap_acs_cfg * acs_cfg)4653 static uint16_t wlan_hdd_acs_get_puncture_bitmap(struct sap_acs_cfg *acs_cfg)
4654 {
4655 	return 0;
4656 }
4657 #endif /* WLAN_FEATURE_11BE */
4658 
wlan_hdd_cfg80211_acs_ch_select_evt(struct wlan_hdd_link_info * link_info,bool store_acs_freq)4659 void wlan_hdd_cfg80211_acs_ch_select_evt(struct wlan_hdd_link_info *link_info,
4660 					 bool store_acs_freq)
4661 {
4662 	struct hdd_adapter *adapter = link_info->adapter;
4663 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4664 	struct sap_config *sap_cfg;
4665 	struct sk_buff *vendor_event;
4666 	int ret_val;
4667 	uint16_t ch_width;
4668 	uint8_t pri_channel;
4669 	uint8_t ht_sec_channel;
4670 	uint8_t vht_seg0_center_ch, vht_seg1_center_ch;
4671 	uint32_t id = QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX;
4672 	uint32_t len;
4673 	uint16_t puncture_bitmap;
4674 
4675 	qdf_atomic_set(&link_info->session.ap.acs_in_progress, 0);
4676 	qdf_event_set(&link_info->acs_complete_event);
4677 
4678 	sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(link_info))->sap_config;
4679 	len = hdd_get_acs_evt_data_len(sap_cfg);
4680 
4681 	if (store_acs_freq &&
4682 	    policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc,
4683 					 link_info->vdev_id)) {
4684 		sap_cfg->last_acs_freq = sap_cfg->acs_cfg.pri_ch_freq;
4685 		sap_cfg->last_acs_complete_time = qdf_get_time_of_the_day_ms();
4686 	}
4687 
4688 	vendor_event = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4689 							&adapter->wdev, len, id,
4690 							GFP_KERNEL);
4691 
4692 	if (!vendor_event) {
4693 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
4694 		return;
4695 	}
4696 
4697 	ret_val = hdd_fill_acs_chan_freq(hdd_ctx, sap_cfg, vendor_event);
4698 	if (ret_val) {
4699 		hdd_err("failed to put frequencies");
4700 		wlan_cfg80211_vendor_free_skb(vendor_event);
4701 		return;
4702 	}
4703 
4704 	pri_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
4705 					    sap_cfg->acs_cfg.pri_ch_freq);
4706 
4707 	ht_sec_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
4708 					       sap_cfg->acs_cfg.ht_sec_ch_freq);
4709 
4710 	ret_val = nla_put_u8(vendor_event,
4711 				QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
4712 				pri_channel);
4713 	if (ret_val) {
4714 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
4715 		wlan_cfg80211_vendor_free_skb(vendor_event);
4716 		return;
4717 	}
4718 
4719 	ret_val = nla_put_u8(vendor_event,
4720 			     QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
4721 			     ht_sec_channel);
4722 	if (ret_val) {
4723 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
4724 		wlan_cfg80211_vendor_free_skb(vendor_event);
4725 		return;
4726 	}
4727 	vht_seg0_center_ch = wlan_reg_freq_to_chan(
4728 				hdd_ctx->pdev,
4729 				sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
4730 	ret_val = nla_put_u8(vendor_event,
4731 			QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
4732 			vht_seg0_center_ch);
4733 	if (ret_val) {
4734 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
4735 		wlan_cfg80211_vendor_free_skb(vendor_event);
4736 		return;
4737 	}
4738 	vht_seg1_center_ch = wlan_reg_freq_to_chan(
4739 				hdd_ctx->pdev,
4740 				sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
4741 	ret_val = nla_put_u8(vendor_event,
4742 			QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
4743 			vht_seg1_center_ch);
4744 	if (ret_val) {
4745 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
4746 		wlan_cfg80211_vendor_free_skb(vendor_event);
4747 		return;
4748 	}
4749 
4750 	if (wlan_hdd_is_sap_acs_ch_width_320(sap_cfg))
4751 		ch_width = 320;
4752 	else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
4753 		ch_width = 160;
4754 	else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
4755 		ch_width = 80;
4756 	else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
4757 		ch_width = 40;
4758 	else
4759 		ch_width = 20;
4760 
4761 	ret_val = nla_put_u16(vendor_event,
4762 				QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
4763 				ch_width);
4764 	if (ret_val) {
4765 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
4766 		wlan_cfg80211_vendor_free_skb(vendor_event);
4767 		return;
4768 	}
4769 	if (WLAN_REG_IS_24GHZ_CH_FREQ(sap_cfg->acs_cfg.pri_ch_freq))
4770 		ret_val = nla_put_u8(vendor_event,
4771 					QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
4772 					QCA_ACS_MODE_IEEE80211G);
4773 	else
4774 		ret_val = nla_put_u8(vendor_event,
4775 					QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
4776 					QCA_ACS_MODE_IEEE80211A);
4777 
4778 	if (ret_val) {
4779 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
4780 		wlan_cfg80211_vendor_free_skb(vendor_event);
4781 		return;
4782 	}
4783 
4784 	puncture_bitmap = wlan_hdd_acs_get_puncture_bitmap(&sap_cfg->acs_cfg);
4785 	if (sap_acs_is_puncture_applicable(&sap_cfg->acs_cfg)) {
4786 		ret_val = nla_put_u16(vendor_event,
4787 				      QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP,
4788 				      puncture_bitmap);
4789 		if (ret_val) {
4790 			hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP put fail");
4791 			wlan_cfg80211_vendor_free_skb(vendor_event);
4792 			return;
4793 		}
4794 	}
4795 
4796 	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",
4797 		  adapter->dev->name, sap_cfg->acs_cfg.pri_ch_freq,
4798 		  sap_cfg->acs_cfg.ht_sec_ch_freq,
4799 		  sap_cfg->acs_cfg.vht_seg0_center_ch_freq,
4800 		  sap_cfg->acs_cfg.vht_seg1_center_ch_freq, ch_width,
4801 		  sap_acs_is_puncture_applicable(&sap_cfg->acs_cfg),
4802 		  puncture_bitmap);
4803 
4804 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
4805 }
4806 
4807 /**
4808  * hdd_is_wlm_latency_manager_supported - Checks if WLM Latency manager is
4809  *                                        supported
4810  * @hdd_ctx: The HDD context
4811  *
4812  * Return: True if supported, false otherwise
4813  */
4814 static inline
hdd_is_wlm_latency_manager_supported(struct hdd_context * hdd_ctx)4815 bool hdd_is_wlm_latency_manager_supported(struct hdd_context *hdd_ctx)
4816 {
4817 	bool latency_enable;
4818 
4819 	if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_latency_enable
4820 				(hdd_ctx->psoc, &latency_enable)))
4821 		return false;
4822 
4823 	if (latency_enable &&
4824 	    sme_is_feature_supported_by_fw(VDEV_LATENCY_CONFIG))
4825 		return true;
4826 	else
4827 		return false;
4828 }
4829 
4830 static int
__wlan_hdd_cfg80211_get_supported_features(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)4831 __wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
4832 					 struct wireless_dev *wdev,
4833 					 const void *data,
4834 					 int data_len)
4835 {
4836 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
4837 	struct sk_buff *skb = NULL;
4838 	uint32_t fset = 0;
4839 	int ret;
4840 #ifdef FEATURE_WLAN_TDLS
4841 	bool bvalue;
4842 #endif
4843 	uint32_t fine_time_meas_cap;
4844 
4845 	/* ENTER_DEV() intentionally not used in a frequently invoked API */
4846 
4847 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4848 		hdd_err("Command not allowed in FTM mode");
4849 		return -EPERM;
4850 	}
4851 
4852 	ret = wlan_hdd_validate_context(hdd_ctx);
4853 	if (ret)
4854 		return ret;
4855 
4856 	if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
4857 		hdd_debug("Infra Station mode is supported by driver");
4858 		fset |= WIFI_FEATURE_INFRA;
4859 	}
4860 	if (true == hdd_is_5g_supported(hdd_ctx)) {
4861 		hdd_debug("INFRA_5G is supported by firmware");
4862 		fset |= WIFI_FEATURE_INFRA_5G;
4863 	}
4864 #ifdef WLAN_FEATURE_P2P
4865 	if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
4866 	    (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
4867 		hdd_debug("WiFi-Direct is supported by driver");
4868 		fset |= WIFI_FEATURE_P2P;
4869 	}
4870 #endif
4871 	fset |= WIFI_FEATURE_SOFT_AP;
4872 
4873 	/* HOTSPOT is a supplicant feature, enable it by default */
4874 	fset |= WIFI_FEATURE_HOTSPOT;
4875 
4876 	if (ucfg_extscan_get_enable(hdd_ctx->psoc) &&
4877 	    sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
4878 		hdd_debug("EXTScan is supported by firmware");
4879 		fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
4880 	}
4881 	if (wlan_hdd_nan_is_supported(hdd_ctx)) {
4882 		hdd_debug("NAN is supported by firmware");
4883 		fset |= WIFI_FEATURE_NAN;
4884 	}
4885 
4886 	ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, &fine_time_meas_cap);
4887 
4888 	if (sme_is_feature_supported_by_fw(RTT) &&
4889 	    rtt_is_enabled(fine_time_meas_cap)) {
4890 		hdd_debug("RTT is supported by firmware and driver: %x",
4891 			  fine_time_meas_cap);
4892 		fset |= WIFI_FEATURE_D2D_RTT;
4893 		fset |= WIFI_FEATURE_D2AP_RTT;
4894 	}
4895 #ifdef FEATURE_WLAN_SCAN_PNO
4896 	if (ucfg_scan_get_pno_scan_support(hdd_ctx->psoc) &&
4897 	    sme_is_feature_supported_by_fw(PNO)) {
4898 		hdd_debug("PNO is supported by firmware");
4899 		fset |= WIFI_FEATURE_PNO;
4900 	}
4901 #endif
4902 	if (ucfg_policy_mgr_get_dual_sta_feature(hdd_ctx->psoc))
4903 		fset |= WIFI_FEATURE_ADDITIONAL_STA;
4904 
4905 #ifdef FEATURE_WLAN_TDLS
4906 	cfg_tdls_get_support_enable(hdd_ctx->psoc, &bvalue);
4907 	if ((bvalue) && sme_is_feature_supported_by_fw(TDLS)) {
4908 		hdd_debug("TDLS is supported by firmware");
4909 		fset |= WIFI_FEATURE_TDLS;
4910 	}
4911 
4912 	cfg_tdls_get_off_channel_enable(hdd_ctx->psoc, &bvalue);
4913 	if (sme_is_feature_supported_by_fw(TDLS) &&
4914 	    bvalue && sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
4915 		hdd_debug("TDLS off-channel is supported by firmware");
4916 		fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
4917 	}
4918 #endif
4919 	fset |= WIFI_FEATURE_AP_STA;
4920 	fset |= WIFI_FEATURE_RSSI_MONITOR;
4921 	fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
4922 	fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
4923 	fset |= WIFI_FEATURE_CONFIG_NDO;
4924 
4925 	if (hdd_link_layer_stats_supported())
4926 		fset |= WIFI_FEATURE_LINK_LAYER_STATS;
4927 
4928 	if (hdd_roaming_supported(hdd_ctx))
4929 		fset |= WIFI_FEATURE_CONTROL_ROAMING;
4930 
4931 	if (hdd_scan_random_mac_addr_supported())
4932 		fset |= WIFI_FEATURE_SCAN_RAND;
4933 
4934 	if (hdd_is_wlm_latency_manager_supported(hdd_ctx))
4935 		fset |= WIFI_FEATURE_SET_LATENCY_MODE;
4936 
4937 	if (hdd_dynamic_mac_addr_supported(hdd_ctx))
4938 		fset |= WIFI_FEATURE_DYNAMIC_SET_MAC;
4939 
4940 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
4941 						       NLMSG_HDRLEN);
4942 	if (!skb) {
4943 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
4944 		return -EINVAL;
4945 	}
4946 	hdd_debug("Supported Features : 0x%x", fset);
4947 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
4948 		hdd_err("nla put fail");
4949 		goto nla_put_failure;
4950 	}
4951 	ret = wlan_cfg80211_vendor_cmd_reply(skb);
4952 	return ret;
4953 nla_put_failure:
4954 	wlan_cfg80211_vendor_free_skb(skb);
4955 	return -EINVAL;
4956 }
4957 
4958 /**
4959  * wlan_hdd_cfg80211_get_supported_features() - get supported features
4960  * @wiphy:   pointer to wireless wiphy structure.
4961  * @wdev:    pointer to wireless_dev structure.
4962  * @data:    Pointer to the data to be passed via vendor interface
4963  * @data_len:Length of the data to be passed
4964  *
4965  * Return:   Return the Success or Failure code.
4966  */
4967 static int
wlan_hdd_cfg80211_get_supported_features(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)4968 wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
4969 					struct wireless_dev *wdev,
4970 					const void *data, int data_len)
4971 {
4972 	struct osif_psoc_sync *psoc_sync;
4973 	int errno;
4974 
4975 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
4976 	if (errno)
4977 		return errno;
4978 
4979 	errno = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
4980 							   data, data_len);
4981 
4982 	osif_psoc_sync_op_stop(psoc_sync);
4983 
4984 	return errno;
4985 }
4986 
4987 /**
4988  * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
4989  * @wiphy:   pointer to wireless wiphy structure.
4990  * @wdev:    pointer to wireless_dev structure.
4991  * @data:    Pointer to the data to be passed via vendor interface
4992  * @data_len:Length of the data to be passed
4993  *
4994  * Set the MAC address that is to be used for scanning.
4995  *
4996  * Return:   Return the Success or Failure code.
4997  */
4998 static int
__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)4999 __wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
5000 					 struct wireless_dev *wdev,
5001 					 const void *data,
5002 					 int data_len)
5003 {
5004 	struct scan_mac_oui scan_mac_oui = { {0} };
5005 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
5006 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
5007 	QDF_STATUS status;
5008 	int ret, len;
5009 	struct net_device *ndev = wdev->netdev;
5010 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
5011 	mac_handle_t mac_handle;
5012 	bool mac_spoofing_enabled;
5013 
5014 	hdd_enter_dev(wdev->netdev);
5015 
5016 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5017 		hdd_err("Command not allowed in FTM mode");
5018 		return -EPERM;
5019 	}
5020 
5021 	ret = wlan_hdd_validate_context(hdd_ctx);
5022 	if (ret)
5023 		return ret;
5024 
5025 	mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
5026 	if (!mac_spoofing_enabled) {
5027 		hdd_debug("MAC address spoofing is not enabled");
5028 		return -ENOTSUPP;
5029 	}
5030 
5031 	/*
5032 	 * audit note: it is ok to pass a NULL policy here since only
5033 	 * one attribute is parsed and it is explicitly validated
5034 	 */
5035 	if (wlan_cfg80211_nla_parse(tb,
5036 				  QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
5037 				  data, data_len, NULL)) {
5038 		hdd_err("Invalid ATTR");
5039 		return -EINVAL;
5040 	}
5041 
5042 	if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
5043 		hdd_err("attr mac oui failed");
5044 		return -EINVAL;
5045 	}
5046 
5047 	len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
5048 	if (len != sizeof(scan_mac_oui.oui)) {
5049 		hdd_err("attr mac oui invalid size %d expected %zu",
5050 			len, sizeof(scan_mac_oui.oui));
5051 		return -EINVAL;
5052 	}
5053 
5054 	nla_memcpy(scan_mac_oui.oui,
5055 		   tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
5056 		   sizeof(scan_mac_oui.oui));
5057 
5058 	/* populate rest of scan_mac_oui for mac addr randomization */
5059 	scan_mac_oui.vdev_id = adapter->deflink->vdev_id;
5060 	scan_mac_oui.enb_probe_req_sno_randomization = true;
5061 
5062 	hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d",
5063 		  scan_mac_oui.oui[0], scan_mac_oui.oui[1],
5064 		  scan_mac_oui.oui[2], scan_mac_oui.vdev_id);
5065 
5066 	hdd_update_ie_allowlist_attr(&scan_mac_oui.ie_allowlist, hdd_ctx);
5067 
5068 	mac_handle = hdd_ctx->mac_handle;
5069 	status = sme_set_scanning_mac_oui(mac_handle, &scan_mac_oui);
5070 	if (!QDF_IS_STATUS_SUCCESS(status))
5071 		hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
5072 
5073 	return qdf_status_to_os_return(status);
5074 }
5075 
5076 /**
5077  * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
5078  * @wiphy:   pointer to wireless wiphy structure.
5079  * @wdev:    pointer to wireless_dev structure.
5080  * @data:    Pointer to the data to be passed via vendor interface
5081  * @data_len:Length of the data to be passed
5082  *
5083  * Set the MAC address that is to be used for scanning.  This is an
5084  * SSR-protecting wrapper function.
5085  *
5086  * Return:   Return the Success or Failure code.
5087  */
5088 static int
wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)5089 wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
5090 				       struct wireless_dev *wdev,
5091 				       const void *data,
5092 				       int data_len)
5093 {
5094 	int errno;
5095 	struct osif_vdev_sync *vdev_sync;
5096 
5097 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5098 	if (errno)
5099 		return errno;
5100 
5101 	errno = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
5102 							 data, data_len);
5103 
5104 	osif_vdev_sync_op_stop(vdev_sync);
5105 
5106 	return errno;
5107 }
5108 
5109 #define NUM_BITS_IN_BYTE       8
5110 
5111 /**
5112  * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
5113  * @feature_flags: pointer to the byte array of features.
5114  * @feature: Feature to be turned ON in the byte array.
5115  *
5116  * Return: None
5117  *
5118  * This is called to turn ON or SET the feature flag for the requested feature.
5119  **/
wlan_hdd_cfg80211_set_feature(uint8_t * feature_flags,uint8_t feature)5120 static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
5121 					  uint8_t feature)
5122 {
5123 	uint32_t index;
5124 	uint8_t bit_mask;
5125 
5126 	index = feature / NUM_BITS_IN_BYTE;
5127 	bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
5128 	feature_flags[index] |= bit_mask;
5129 }
5130 
5131 /**
5132  * wlan_hdd_set_ndi_feature() - Set NDI related features
5133  * @feature_flags: pointer to the byte array of features.
5134  *
5135  * Return: None
5136  **/
5137 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0))
wlan_hdd_set_ndi_feature(uint8_t * feature_flags)5138 static void wlan_hdd_set_ndi_feature(uint8_t *feature_flags)
5139 {
5140 	wlan_hdd_cfg80211_set_feature(feature_flags,
5141 				      QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI);
5142 }
5143 #else
wlan_hdd_set_ndi_feature(uint8_t * feature_flags)5144 static inline void wlan_hdd_set_ndi_feature(uint8_t *feature_flags)
5145 {
5146 }
5147 #endif
5148 
wlan_hdd_set_ll_lt_sap_feature(struct wlan_objmgr_psoc * psoc,uint8_t * feature_flags)5149 static inline void wlan_hdd_set_ll_lt_sap_feature(struct wlan_objmgr_psoc *psoc,
5150 						  uint8_t *feature_flags)
5151 {
5152 	/* To Do: Once FW feature capability changes for ll_lt_sap feature are
5153 	 * merged, then this feature will be set based on that feature set
5154 	 * capability
5155 	 */
5156 	if (!ucfg_is_ll_lt_sap_supported(psoc)) {
5157 		hdd_debug("ll_lt_sap feature is disabled in FW");
5158 		return;
5159 	}
5160 	wlan_hdd_cfg80211_set_feature(feature_flags,
5161 				      QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN);
5162 }
5163 
5164 #define MAX_CONCURRENT_CHAN_ON_24G    2
5165 #define MAX_CONCURRENT_CHAN_ON_5G     2
5166 
5167 /**
5168  * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
5169  * @wiphy: pointer to wireless wiphy structure.
5170  * @wdev: pointer to wireless_dev structure.
5171  * @data: Pointer to the data to be passed via vendor interface
5172  * @data_len:Length of the data to be passed
5173  *
5174  * This is called when wlan driver needs to send supported feature set to
5175  * supplicant upon a request/query from the supplicant.
5176  *
5177  * Return: Return the Success or Failure code.
5178  **/
5179 static int
__wlan_hdd_cfg80211_get_features(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)5180 __wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
5181 				 struct wireless_dev *wdev,
5182 				 const void *data, int data_len)
5183 {
5184 	struct sk_buff *skb = NULL;
5185 	uint32_t dbs_capability = 0;
5186 	bool one_by_one_dbs, two_by_two_dbs;
5187 	bool value, twt_req, twt_res;
5188 	QDF_STATUS ret = QDF_STATUS_E_FAILURE;
5189 	QDF_STATUS status;
5190 	int ret_val;
5191 	uint8_t max_assoc_cnt = 0;
5192 	uint8_t max_str_link_count = 0;
5193 
5194 	uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
5195 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
5196 
5197 	hdd_enter_dev(wdev->netdev);
5198 
5199 	ret_val = wlan_hdd_validate_context(hdd_ctx);
5200 	if (ret_val)
5201 		return ret_val;
5202 
5203 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5204 		hdd_err("Command not allowed in FTM mode");
5205 		return -EPERM;
5206 	}
5207 
5208 	if (roaming_offload_enabled(hdd_ctx)) {
5209 		hdd_debug("Key Mgmt Offload is supported");
5210 		wlan_hdd_cfg80211_set_feature(feature_flags,
5211 				QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
5212 	}
5213 
5214 	wlan_hdd_cfg80211_set_feature(feature_flags,
5215 				QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
5216 	if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx->psoc))
5217 		wlan_hdd_cfg80211_set_feature(feature_flags,
5218 			QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
5219 
5220 	if (policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc))
5221 		wlan_hdd_cfg80211_set_feature(feature_flags,
5222 			QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS);
5223 
5224 	if (wma_is_p2p_lo_capable())
5225 		wlan_hdd_cfg80211_set_feature(feature_flags,
5226 			QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
5227 
5228 	value = false;
5229 	status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc, &value);
5230 	if (QDF_IS_STATUS_ERROR(status))
5231 		hdd_err("could not get OCE STA enable info");
5232 	if (value)
5233 		wlan_hdd_cfg80211_set_feature(feature_flags,
5234 					      QCA_WLAN_VENDOR_FEATURE_OCE_STA);
5235 
5236 	value = false;
5237 	status = ucfg_mlme_get_oce_sap_enabled_info(hdd_ctx->psoc, &value);
5238 	if (QDF_IS_STATUS_ERROR(status))
5239 		hdd_err("could not get OCE SAP enable info");
5240 	if (value)
5241 		wlan_hdd_cfg80211_set_feature(feature_flags,
5242 					  QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
5243 
5244 	value = false;
5245 	status = ucfg_mlme_get_adaptive11r_enabled(hdd_ctx->psoc, &value);
5246 	if (QDF_IS_STATUS_ERROR(status))
5247 		hdd_err("could not get FT-Adaptive 11R info");
5248 	if (value) {
5249 		hdd_debug("FT-Adaptive 11R is Enabled");
5250 		wlan_hdd_cfg80211_set_feature(feature_flags,
5251 					  QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R);
5252 	}
5253 
5254 	hdd_get_twt_requestor(hdd_ctx->psoc, &twt_req);
5255 	hdd_get_twt_responder(hdd_ctx->psoc, &twt_res);
5256 	hdd_debug("twt_req:%d twt_res:%d", twt_req, twt_res);
5257 
5258 	if (twt_req || twt_res) {
5259 		wlan_hdd_cfg80211_set_feature(feature_flags,
5260 					      QCA_WLAN_VENDOR_FEATURE_TWT);
5261 
5262 		wlan_hdd_cfg80211_set_feature(
5263 				feature_flags,
5264 				QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT);
5265 	}
5266 
5267 	/* Check the kernel version for upstream commit aced43ce780dc5 that
5268 	 * has support for processing user cell_base hints when wiphy is
5269 	 * self managed or check the backport flag for the same.
5270 	 */
5271 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
5272 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
5273 	wlan_hdd_cfg80211_set_feature(feature_flags,
5274 			QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY);
5275 #endif
5276 
5277 	if (wlan_hdd_thermal_config_support())
5278 		wlan_hdd_cfg80211_set_feature(feature_flags,
5279 					QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG);
5280 
5281 	wlan_hdd_set_ndi_feature(feature_flags);
5282 	wlan_hdd_cfg80211_set_feature(
5283 				feature_flags,
5284 				QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST);
5285 	wlan_wifi_pos_cfg80211_set_features(hdd_ctx->psoc, feature_flags);
5286 	wlan_hdd_set_ll_lt_sap_feature(hdd_ctx->psoc, feature_flags);
5287 
5288 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5289 						       sizeof(feature_flags) +
5290 						       NLMSG_HDRLEN);
5291 
5292 	if (!skb) {
5293 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
5294 		return -ENOMEM;
5295 	}
5296 
5297 	if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
5298 			sizeof(feature_flags), feature_flags))
5299 		goto nla_put_failure;
5300 
5301 	ret = policy_mgr_get_dbs_hw_modes(hdd_ctx->psoc,
5302 					  &one_by_one_dbs, &two_by_two_dbs);
5303 	if (QDF_STATUS_SUCCESS == ret) {
5304 		if (one_by_one_dbs)
5305 			dbs_capability = DRV_DBS_CAPABILITY_1X1;
5306 
5307 		if (two_by_two_dbs)
5308 			dbs_capability = DRV_DBS_CAPABILITY_2X2;
5309 
5310 		if (!one_by_one_dbs && !two_by_two_dbs)
5311 			dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
5312 	} else {
5313 		hdd_err("wma_get_dbs_hw_mode failed");
5314 		dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
5315 	}
5316 
5317 	hdd_debug("dbs_capability is %d", dbs_capability);
5318 
5319 	if (nla_put_u32(skb,
5320 			QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
5321 			dbs_capability))
5322 		goto nla_put_failure;
5323 
5324 
5325 	if (nla_put_u32(skb,
5326 			QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
5327 			MAX_CONCURRENT_CHAN_ON_24G))
5328 		goto nla_put_failure;
5329 
5330 	if (nla_put_u32(skb,
5331 			QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
5332 			MAX_CONCURRENT_CHAN_ON_5G))
5333 		goto nla_put_failure;
5334 
5335 	max_assoc_cnt = wlan_mlme_get_sta_mlo_conn_max_num(hdd_ctx->psoc);
5336 	if (max_assoc_cnt) {
5337 		if (nla_put_u8(
5338 			skb,
5339 			QCA_WLAN_VENDOR_ATTR_MLO_CAPABILITY_MAX_ASSOCIATION_COUNT,
5340 			max_assoc_cnt))
5341 			goto nla_put_failure;
5342 
5343 		max_str_link_count = DEFAULT_MAX_STR_LINK_COUNT;
5344 
5345 		if (policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) ||
5346 		    policy_mgr_is_hw_sbs_capable(hdd_ctx->psoc))
5347 			max_str_link_count = MAX_STR_LINK_COUNT;
5348 
5349 		if (nla_put_u8(skb,
5350 			       QCA_WLAN_VENDOR_ATTR_MLO_CAPABILITY_MAX_STR_LINK_COUNT,
5351 			       max_str_link_count))
5352 			goto nla_put_failure;
5353 	}
5354 
5355 	hdd_debug("max_assoc_cnt %d max_str_link_count %d",
5356 		  max_assoc_cnt, max_str_link_count);
5357 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
5358 			   feature_flags, sizeof(feature_flags));
5359 
5360 	return wlan_cfg80211_vendor_cmd_reply(skb);
5361 
5362 nla_put_failure:
5363 	wlan_cfg80211_vendor_free_skb(skb);
5364 	return -EINVAL;
5365 }
5366 
5367 /**
5368  * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
5369  * @wiphy:   pointer to wireless wiphy structure.
5370  * @wdev:    pointer to wireless_dev structure.
5371  * @data:    Pointer to the data to be passed via vendor interface
5372  * @data_len:Length of the data to be passed
5373  *
5374  * This is called when wlan driver needs to send supported feature set to
5375  * supplicant upon a request/query from the supplicant.
5376  *
5377  * Return:   Return the Success or Failure code.
5378  */
5379 static int
wlan_hdd_cfg80211_get_features(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)5380 wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
5381 		struct wireless_dev *wdev,
5382 		const void *data, int data_len)
5383 {
5384 	struct osif_psoc_sync *psoc_sync;
5385 	int errno;
5386 
5387 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
5388 	if (errno)
5389 		return errno;
5390 
5391 	errno = __wlan_hdd_cfg80211_get_features(wiphy, wdev, data, data_len);
5392 
5393 	osif_psoc_sync_op_stop(psoc_sync);
5394 
5395 	return errno;
5396 }
5397 
5398 #define PARAM_NUM_NW \
5399 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
5400 #define PARAM_SET_BSSID \
5401 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
5402 #define PARAM_SET_BSSID_HINT \
5403 		QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT
5404 #define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
5405 #define PARAM_LIST_SSID  QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
5406 #define MAX_ROAMING_PARAM \
5407 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
5408 #define PARAM_NUM_BSSID \
5409 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
5410 #define PARAM_BSSID_PREFS \
5411 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
5412 #define PARAM_ROAM_BSSID \
5413 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
5414 #define PARAM_RSSI_MODIFIER \
5415 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
5416 #define PARAMS_NUM_BSSID \
5417 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
5418 #define PARAM_BSSID_PARAMS \
5419 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
5420 #define PARAM_A_BAND_BOOST_THLD \
5421 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
5422 #define PARAM_A_BAND_PELT_THLD \
5423 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
5424 #define PARAM_A_BAND_BOOST_FACTOR \
5425 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
5426 #define PARAM_A_BAND_PELT_FACTOR \
5427 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
5428 #define PARAM_A_BAND_MAX_BOOST \
5429 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
5430 #define PARAM_ROAM_HISTERESYS \
5431 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
5432 #define PARAM_RSSI_TRIGGER \
5433 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
5434 #define PARAM_ROAM_ENABLE \
5435 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
5436 #define PARAM_ROAM_CONTROL_CONFIG \
5437 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL
5438 #define PARAM_FREQ_LIST_SCHEME \
5439 	QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME
5440 #define PARAM_FREQ_LIST_SCHEME_MAX \
5441 	QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_MAX
5442 #define PARAM_SCAN_FREQ_LIST \
5443 	QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
5444 #define PARAM_SCAN_FREQ_LIST_TYPE \
5445 	QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE
5446 #define PARAM_CAND_SEL_CRITERIA_MAX \
5447 	QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_MAX
5448 #define PARAM_CAND_SEL_SCORE_RSSI \
5449 	QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_RSSI
5450 
5451 const struct nla_policy wlan_hdd_set_roam_param_policy[
5452 			MAX_ROAMING_PARAM + 1] = {
5453 	[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
5454 	[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
5455 	[PARAM_NUM_NW] = {.type = NLA_U32},
5456 	[PARAM_SSID_LIST] = { .type = NLA_NESTED },
5457 	[PARAM_LIST_SSID] = { .type = NLA_BINARY },
5458 	[PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
5459 	[PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
5460 	[PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
5461 	[PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
5462 	[PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
5463 	[PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
5464 	[PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
5465 	[PARAM_ROAM_ENABLE] = {	.type = NLA_S32},
5466 	[PARAM_BSSID_PREFS] = { .type = NLA_NESTED },
5467 	[PARAM_NUM_BSSID] = {.type = NLA_U32},
5468 	[PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
5469 	[PARAM_BSSID_PARAMS] = {.type = NLA_NESTED},
5470 	[PARAMS_NUM_BSSID] = {.type = NLA_U32},
5471 	[PARAM_ROAM_BSSID] = VENDOR_NLA_POLICY_MAC_ADDR,
5472 	[PARAM_SET_BSSID] = VENDOR_NLA_POLICY_MAC_ADDR,
5473 	[PARAM_SET_BSSID_HINT] = {.type = NLA_FLAG},
5474 	[PARAM_ROAM_CONTROL_CONFIG] = {.type = NLA_NESTED},
5475 };
5476 
5477 /**
5478  * hdd_set_allow_list() - parse allow list
5479  * @hdd_ctx: HDD context
5480  * @rso_config: rso config
5481  * @tb: list of attributes
5482  * @vdev_id: vdev id
5483  * @rso_usr_cfg: roam userspace params
5484  *
5485  * Return: 0 on success; error number on failure
5486  */
hdd_set_allow_list(struct hdd_context * hdd_ctx,struct rso_config_params * rso_config,struct nlattr ** tb,uint8_t vdev_id,struct rso_user_config * rso_usr_cfg)5487 static int hdd_set_allow_list(struct hdd_context *hdd_ctx,
5488 			      struct rso_config_params *rso_config,
5489 			      struct nlattr **tb, uint8_t vdev_id,
5490 			      struct rso_user_config *rso_usr_cfg)
5491 {
5492 	int rem, i;
5493 	uint32_t buf_len = 0, count;
5494 	struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
5495 	struct nlattr *curr_attr = NULL;
5496 	mac_handle_t mac_handle;
5497 	struct wlan_ssid *ssid;
5498 
5499 	i = 0;
5500 	if (tb[PARAM_NUM_NW]) {
5501 		count = nla_get_u32(tb[PARAM_NUM_NW]);
5502 	} else {
5503 		hdd_err("Number of networks is not provided");
5504 		goto fail;
5505 	}
5506 
5507 	if (count && tb[PARAM_SSID_LIST]) {
5508 		nla_for_each_nested(curr_attr,
5509 				    tb[PARAM_SSID_LIST], rem) {
5510 			if (i == MAX_SSID_ALLOWED_LIST) {
5511 				hdd_err("Excess MAX_SSID_ALLOWED_LIST");
5512 				goto fail;
5513 			}
5514 			if (wlan_cfg80211_nla_parse(tb2,
5515 					QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
5516 					nla_data(curr_attr),
5517 					nla_len(curr_attr),
5518 					wlan_hdd_set_roam_param_policy)) {
5519 				hdd_err("nla_parse failed");
5520 				goto fail;
5521 			}
5522 			/* Parse and Fetch allowed SSID list*/
5523 			if (!tb2[PARAM_LIST_SSID]) {
5524 				hdd_err("attr allowed ssid failed");
5525 				goto fail;
5526 			}
5527 			buf_len = nla_len(tb2[PARAM_LIST_SSID]);
5528 			/*
5529 			 * Upper Layers include a null termination
5530 			 * character. Check for the actual permissible
5531 			 * length of SSID and also ensure not to copy
5532 			 * the NULL termination character to the driver
5533 			 * buffer.
5534 			 */
5535 			if (buf_len <= 1 || (buf_len - 1) > WLAN_SSID_MAX_LEN) {
5536 				hdd_err("Invalid buffer length");
5537 				continue;
5538 			}
5539 
5540 			ssid = &rso_usr_cfg->ssid_allowed_list[i];
5541 			nla_memcpy(ssid->ssid,
5542 				   tb2[PARAM_LIST_SSID], buf_len - 1);
5543 			ssid->length = buf_len - 1;
5544 			hdd_debug("SSID[%d]: " QDF_SSID_FMT ",length = %d", i,
5545 				  QDF_SSID_REF(ssid->length, ssid->ssid),
5546 				  rso_usr_cfg->ssid_allowed_list[i].length);
5547 			i++;
5548 		}
5549 	}
5550 
5551 	if (i != count) {
5552 		hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
5553 		goto fail;
5554 	}
5555 
5556 	rso_usr_cfg->num_ssid_allowed_list = i;
5557 	hdd_debug("Num of Allowed SSID %d", rso_usr_cfg->num_ssid_allowed_list);
5558 	mac_handle = hdd_ctx->mac_handle;
5559 	sme_update_roam_params(mac_handle, vdev_id, rso_config, rso_usr_cfg,
5560 			       REASON_ROAM_SET_SSID_ALLOWED);
5561 	return 0;
5562 
5563 fail:
5564 	return -EINVAL;
5565 }
5566 
5567 /**
5568  * hdd_set_bssid_prefs() - parse set bssid prefs
5569  * @hdd_ctx:        HDD context
5570  * @rso_config: rso config
5571  * @tb:            list of attributes
5572  * @vdev_id:    vdev id
5573  *
5574  * Return: 0 on success; error number on failure
5575  */
hdd_set_bssid_prefs(struct hdd_context * hdd_ctx,struct rso_config_params * rso_config,struct nlattr ** tb,uint8_t vdev_id)5576 static int hdd_set_bssid_prefs(struct hdd_context *hdd_ctx,
5577 			       struct rso_config_params *rso_config,
5578 			       struct nlattr **tb, uint8_t vdev_id)
5579 {
5580 	int rem, i;
5581 	uint32_t count;
5582 	struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
5583 	struct nlattr *curr_attr = NULL;
5584 	mac_handle_t mac_handle;
5585 
5586 	/* Parse and fetch number of preferred BSSID */
5587 	if (!tb[PARAM_NUM_BSSID]) {
5588 		hdd_err("attr num of preferred bssid failed");
5589 		goto fail;
5590 	}
5591 	count = nla_get_u32(tb[PARAM_NUM_BSSID]);
5592 	if (count > MAX_BSSID_FAVORED) {
5593 		hdd_err("Preferred BSSID count %u exceeds max %u",
5594 			count, MAX_BSSID_FAVORED);
5595 		goto fail;
5596 	}
5597 	hdd_debug("Num of Preferred BSSID (%d)", count);
5598 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
5599 		hdd_err("attr Preferred BSSID failed");
5600 		goto fail;
5601 	}
5602 
5603 	i = 0;
5604 	nla_for_each_nested(curr_attr,
5605 		tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
5606 		rem) {
5607 		if (i == count) {
5608 			hdd_warn("Ignoring excess Preferred BSSID");
5609 			break;
5610 		}
5611 
5612 		if (wlan_cfg80211_nla_parse(tb2,
5613 					 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
5614 					 nla_data(curr_attr),
5615 					 nla_len(curr_attr),
5616 					 wlan_hdd_set_roam_param_policy)) {
5617 			hdd_err("nla_parse failed");
5618 			goto fail;
5619 		}
5620 		/* Parse and fetch MAC address */
5621 		if (!tb2[PARAM_ROAM_BSSID]) {
5622 			hdd_err("attr mac address failed");
5623 			goto fail;
5624 		}
5625 		nla_memcpy(rso_config->bssid_favored[i].bytes,
5626 			  tb2[PARAM_ROAM_BSSID],
5627 			  QDF_MAC_ADDR_SIZE);
5628 		hdd_debug(QDF_MAC_ADDR_FMT,
5629 			  QDF_MAC_ADDR_REF(rso_config->bssid_favored[i].bytes));
5630 		/* Parse and fetch preference factor*/
5631 		if (!tb2[PARAM_RSSI_MODIFIER]) {
5632 			hdd_err("BSSID Preference score failed");
5633 			goto fail;
5634 		}
5635 		rso_config->bssid_favored_factor[i] = nla_get_u32(
5636 			tb2[PARAM_RSSI_MODIFIER]);
5637 		hdd_debug("BSSID Preference score (%d)",
5638 			  rso_config->bssid_favored_factor[i]);
5639 		i++;
5640 	}
5641 	if (i < count)
5642 		hdd_warn("Num Preferred BSSID %u less than expected %u",
5643 				 i, count);
5644 
5645 	rso_config->num_bssid_favored = i;
5646 	mac_handle = hdd_ctx->mac_handle;
5647 	sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
5648 			       REASON_ROAM_SET_FAVORED_BSSID);
5649 
5650 	return 0;
5651 
5652 fail:
5653 	return -EINVAL;
5654 }
5655 
5656 /**
5657  * hdd_set_denylist_bssid() - parse set denylist bssid
5658  * @hdd_ctx:        HDD context
5659  * @rso_config:   roam params
5660  * @tb:            list of attributes
5661  * @vdev_id:    vdev id
5662  *
5663  * Return: 0 on success; error number on failure
5664  */
hdd_set_denylist_bssid(struct hdd_context * hdd_ctx,struct rso_config_params * rso_config,struct nlattr ** tb,uint8_t vdev_id)5665 static int hdd_set_denylist_bssid(struct hdd_context *hdd_ctx,
5666 				  struct rso_config_params *rso_config,
5667 				  struct nlattr **tb,
5668 				  uint8_t vdev_id)
5669 {
5670 	int rem, i;
5671 	uint32_t count;
5672 	uint8_t j = 0;
5673 	struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
5674 	struct nlattr *curr_attr = NULL;
5675 	struct qdf_mac_addr *deny_list_bssid;
5676 	mac_handle_t mac_handle;
5677 
5678 	/* Parse and fetch number of denylist BSSID */
5679 	if (!tb[PARAMS_NUM_BSSID]) {
5680 		hdd_err("attr num of denylist bssid failed");
5681 		goto fail;
5682 	}
5683 	count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
5684 	if (count > MAX_BSSID_AVOID_LIST) {
5685 		hdd_err("Denylist BSSID count %u exceeds max %u",
5686 			count, MAX_BSSID_AVOID_LIST);
5687 		goto fail;
5688 	}
5689 	hdd_debug("Num of denylist BSSID (%d)", count);
5690 	deny_list_bssid = qdf_mem_malloc(sizeof(*deny_list_bssid) *
5691 					  MAX_BSSID_AVOID_LIST);
5692 	if (!deny_list_bssid)
5693 		goto fail;
5694 
5695 	i = 0;
5696 	if (count && tb[PARAM_BSSID_PARAMS]) {
5697 		nla_for_each_nested(curr_attr,
5698 			tb[PARAM_BSSID_PARAMS],
5699 			rem) {
5700 			if (i == count) {
5701 				hdd_warn("Ignoring excess Denylist BSSID");
5702 				break;
5703 			}
5704 
5705 			if (wlan_cfg80211_nla_parse(tb2,
5706 					 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
5707 					 nla_data(curr_attr),
5708 					 nla_len(curr_attr),
5709 					 wlan_hdd_set_roam_param_policy)) {
5710 				hdd_err("nla_parse failed");
5711 				qdf_mem_free(deny_list_bssid);
5712 				goto fail;
5713 			}
5714 			/* Parse and fetch MAC address */
5715 			if (!tb2[PARAM_SET_BSSID]) {
5716 				hdd_err("attr denylist addr failed");
5717 				qdf_mem_free(deny_list_bssid);
5718 				goto fail;
5719 			}
5720 			if (tb2[PARAM_SET_BSSID_HINT]) {
5721 				struct reject_ap_info ap_info;
5722 
5723 				qdf_mem_zero(&ap_info,
5724 					     sizeof(struct reject_ap_info));
5725 				nla_memcpy(ap_info.bssid.bytes,
5726 					   tb2[PARAM_SET_BSSID],
5727 					   QDF_MAC_ADDR_SIZE);
5728 				ap_info.reject_ap_type = USERSPACE_AVOID_TYPE;
5729 				ap_info.reject_reason =
5730 						REASON_USERSPACE_AVOID_LIST;
5731 				ap_info.source = ADDED_BY_DRIVER;
5732 
5733 				/* This BSSID is avoided and not denylisted */
5734 				ucfg_dlm_add_bssid_to_reject_list(hdd_ctx->pdev,
5735 								  &ap_info);
5736 				i++;
5737 				continue;
5738 			}
5739 			nla_memcpy(deny_list_bssid[j].bytes,
5740 				   tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
5741 			hdd_debug(QDF_MAC_ADDR_FMT,
5742 				  QDF_MAC_ADDR_REF(deny_list_bssid[j].bytes));
5743 			i++;
5744 			j++;
5745 		}
5746 	}
5747 
5748 	if (i < count)
5749 		hdd_warn("Num Denylist BSSID %u less than expected %u",
5750 			 i, count);
5751 
5752 	/* Send the denylist to the denylist mgr component */
5753 	ucfg_dlm_add_userspace_deny_list(hdd_ctx->pdev, deny_list_bssid, j);
5754 	qdf_mem_free(deny_list_bssid);
5755 	mac_handle = hdd_ctx->mac_handle;
5756 	sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
5757 			       REASON_ROAM_SET_DENYLIST_BSSID);
5758 
5759 	return 0;
5760 fail:
5761 	return -EINVAL;
5762 }
5763 
5764 static const struct nla_policy
5765 roam_scan_freq_list_scheme_policy[PARAM_FREQ_LIST_SCHEME_MAX + 1] = {
5766 	[PARAM_SCAN_FREQ_LIST_TYPE] = {.type = NLA_U32},
5767 	[PARAM_SCAN_FREQ_LIST] = {.type = NLA_NESTED},
5768 };
5769 
5770 /**
5771  * hdd_send_roam_scan_channel_freq_list_to_sme() - Send control roam scan freqs
5772  * @hdd_ctx: HDD context
5773  * @vdev_id: vdev id
5774  * @tb: Nested attribute carrying frequency list scheme
5775  *
5776  * Extracts the frequency list and frequency list type from the frequency
5777  * list scheme and send the frequencies to SME.
5778  *
5779  * Return: QDF_STATUS
5780  */
5781 static QDF_STATUS
hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context * hdd_ctx,uint8_t vdev_id,struct nlattr * tb)5782 hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context *hdd_ctx,
5783 					    uint8_t vdev_id, struct nlattr *tb)
5784 {
5785 	QDF_STATUS status;
5786 	struct nlattr *tb2[PARAM_FREQ_LIST_SCHEME_MAX + 1], *curr_attr;
5787 	uint8_t num_chan = 0;
5788 	uint32_t freq_list[SIR_MAX_SUPPORTED_CHANNEL_LIST] = {0};
5789 	uint32_t list_type;
5790 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
5791 	int rem;
5792 
5793 	if (wlan_cfg80211_nla_parse_nested(tb2, PARAM_FREQ_LIST_SCHEME_MAX,
5794 					   tb,
5795 					   roam_scan_freq_list_scheme_policy)) {
5796 		hdd_err("nla_parse failed");
5797 		return QDF_STATUS_E_INVAL;
5798 	}
5799 
5800 	if (!tb2[PARAM_SCAN_FREQ_LIST] || !tb2[PARAM_SCAN_FREQ_LIST_TYPE]) {
5801 		hdd_err("ROAM_CONTROL_SCAN_FREQ_LIST or type are not present");
5802 		return QDF_STATUS_E_INVAL;
5803 	}
5804 
5805 	list_type = nla_get_u32(tb2[PARAM_SCAN_FREQ_LIST_TYPE]);
5806 	if (list_type != QCA_PREFERRED_SCAN_FREQ_LIST &&
5807 	    list_type != QCA_SPECIFIC_SCAN_FREQ_LIST) {
5808 		hdd_err("Invalid freq list type received: %u", list_type);
5809 		return QDF_STATUS_E_INVAL;
5810 	}
5811 
5812 	nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
5813 		if (num_chan >= SIR_MAX_SUPPORTED_CHANNEL_LIST) {
5814 			hdd_err("number of channels (%d) supported exceeded max (%d)",
5815 				num_chan, SIR_MAX_SUPPORTED_CHANNEL_LIST);
5816 			return QDF_STATUS_E_INVAL;
5817 		}
5818 		num_chan++;
5819 	}
5820 	num_chan = 0;
5821 
5822 	nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
5823 		if (nla_len(curr_attr) != sizeof(uint32_t)) {
5824 			hdd_err("len is not correct for frequency %d",
5825 				num_chan);
5826 			return QDF_STATUS_E_INVAL;
5827 		}
5828 		freq_list[num_chan++] = nla_get_u32(curr_attr);
5829 	}
5830 
5831 	status = sme_update_roam_scan_freq_list(mac_handle, vdev_id, freq_list,
5832 						num_chan, list_type);
5833 	if (QDF_IS_STATUS_ERROR(status))
5834 		hdd_err("Failed to update channel list information");
5835 
5836 	return status;
5837 }
5838 
5839 static const struct nla_policy
5840 roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = {
5841 	[QCA_ATTR_ROAM_CONTROL_ENABLE] = {.type = NLA_U8},
5842 	[QCA_ATTR_ROAM_CONTROL_STATUS] = {.type = NLA_U8},
5843 	[PARAM_FREQ_LIST_SCHEME] = {.type = NLA_NESTED},
5844 	[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD] = {.type = NLA_U32},
5845 	[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL] = {.type = NLA_FLAG},
5846 	[QCA_ATTR_ROAM_CONTROL_TRIGGERS] = {.type = NLA_U32},
5847 	[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA] = {.type = NLA_NESTED},
5848 	[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD] = {.type = NLA_U32},
5849 	[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME] = {.type = NLA_U32},
5850 	[QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD] = {.type = NLA_U32},
5851 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD] = {.type = NLA_U32},
5852 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ] = {
5853 			.type = NLA_U32},
5854 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ] = {
5855 			.type = NLA_U32},
5856 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ] = {
5857 			.type = NLA_U32},
5858 	[QCA_ATTR_ROAM_CONTROL_USER_REASON] = {.type = NLA_U32},
5859 	[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS] = {.type = NLA_U32},
5860 	[QCA_ATTR_ROAM_CONTROL_BAND_MASK] = {.type = NLA_U32},
5861 	[QCA_ATTR_ROAM_CONTROL_RX_LINKSPEED_THRESHOLD] = {.type = NLA_U16},
5862 	[QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX] = {.type = NLA_U16},
5863 	[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_NO_REUSE_PARTIAL_SCAN_FREQ] = {
5864 			.type = NLA_U8},
5865 	[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_6GHZ_ONLY_ON_PRIOR_DISCOVERY] = {
5866 			.type = NLA_U8},
5867 	[QCA_ATTR_ROAM_CONTROL_CONNECTED_HIGH_RSSI_OFFSET] = {.type = NLA_U8},
5868 };
5869 
5870 /**
5871  * hdd_send_roam_full_scan_period_to_sme() - Send full roam scan period to SME
5872  * @hdd_ctx: HDD context
5873  * @vdev_id: vdev id
5874  * @full_roam_scan_period: Idle period in seconds between two successive
5875  *			   full channel roam scans
5876  * @check_and_update: If this is true/set, update the value only if the current
5877  *		      configured value is not same as global value read from
5878  *		      ini param. This is to give priority to the user configured
5879  *		      values and retain the value, if updated already.
5880  *		      If this is not set, update the value without any check.
5881  *
5882  * Validate the full roam scan period and send it to firmware
5883  *
5884  * Return: QDF_STATUS
5885  */
5886 static QDF_STATUS
hdd_send_roam_full_scan_period_to_sme(struct hdd_context * hdd_ctx,uint8_t vdev_id,uint32_t full_roam_scan_period,bool check_and_update)5887 hdd_send_roam_full_scan_period_to_sme(struct hdd_context *hdd_ctx,
5888 				      uint8_t vdev_id,
5889 				      uint32_t full_roam_scan_period,
5890 				      bool check_and_update)
5891 {
5892 	QDF_STATUS status;
5893 	uint32_t full_roam_scan_period_current, full_roam_scan_period_global;
5894 
5895 	if (!ucfg_mlme_validate_full_roam_scan_period(full_roam_scan_period))
5896 		return QDF_STATUS_E_INVAL;
5897 
5898 	hdd_debug("Received Command to Set full roam scan period = %u",
5899 		  full_roam_scan_period);
5900 
5901 	status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
5902 					       &full_roam_scan_period_current);
5903 	if (QDF_IS_STATUS_ERROR(status))
5904 		return status;
5905 
5906 	full_roam_scan_period_global =
5907 		sme_get_full_roam_scan_period_global(hdd_ctx->mac_handle);
5908 	if (check_and_update &&
5909 	    full_roam_scan_period_current != full_roam_scan_period_global) {
5910 		hdd_debug("Full roam scan period is already updated, value: %u",
5911 			  full_roam_scan_period_current);
5912 		return QDF_STATUS_SUCCESS;
5913 	}
5914 	status = sme_update_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
5915 						  full_roam_scan_period);
5916 	if (QDF_IS_STATUS_ERROR(status))
5917 		hdd_err("Failed to set full scan period");
5918 
5919 	return status;
5920 }
5921 
5922 /**
5923  * wlan_hdd_convert_control_roam_trigger_bitmap  - Convert the
5924  * vendor specific reason code to internal reason code.
5925  * @trigger_reason_bitmap: Vendor specific roam trigger bitmap
5926  *
5927  * Return: Internal roam trigger bitmap
5928  */
5929 static uint32_t
wlan_hdd_convert_control_roam_trigger_bitmap(uint32_t trigger_reason_bitmap)5930 wlan_hdd_convert_control_roam_trigger_bitmap(uint32_t trigger_reason_bitmap)
5931 {
5932 	uint32_t drv_trigger_bitmap = 0, all_bitmap;
5933 
5934 	/* Enable the complete trigger bitmap when all bits are set in
5935 	 * the control config bitmap
5936 	 */
5937 	all_bitmap = (QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN << 1) - 1;
5938 	if (trigger_reason_bitmap == all_bitmap)
5939 		return BIT(ROAM_TRIGGER_REASON_MAX) - 1;
5940 
5941 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PER)
5942 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PER);
5943 
5944 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BEACON_MISS)
5945 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BMISS);
5946 
5947 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_POOR_RSSI)
5948 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_LOW_RSSI);
5949 
5950 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BETTER_RSSI)
5951 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_HIGH_RSSI);
5952 
5953 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PERIODIC)
5954 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PERIODIC);
5955 
5956 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DENSE)
5957 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_DENSE);
5958 
5959 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BTM)
5960 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BTM);
5961 
5962 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
5963 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BSS_LOAD);
5964 
5965 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_USER_TRIGGER)
5966 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_FORCED);
5967 
5968 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DEAUTH)
5969 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_DEAUTH);
5970 
5971 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_IDLE)
5972 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_IDLE);
5973 
5974 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_TX_FAILURES)
5975 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_STA_KICKOUT);
5976 
5977 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN)
5978 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BACKGROUND);
5979 
5980 	return drv_trigger_bitmap;
5981 }
5982 
5983 /**
5984  * wlan_hdd_convert_control_roam_scan_scheme_bitmap()  - Convert the
5985  * vendor specific roam scan scheme for roam triggers to internal roam trigger
5986  * bitmap for partial scan.
5987  * @trigger_reason_bitmap: Vendor specific roam trigger bitmap
5988  *
5989  * Return: Internal roam scan scheme bitmap
5990  */
5991 static uint32_t
wlan_hdd_convert_control_roam_scan_scheme_bitmap(uint32_t trigger_reason_bitmap)5992 wlan_hdd_convert_control_roam_scan_scheme_bitmap(uint32_t trigger_reason_bitmap)
5993 {
5994 	uint32_t drv_scan_scheme_bitmap = 0;
5995 
5996 	/*
5997 	 * Partial scan scheme override over default scan scheme only for
5998 	 * the PER, BMISS, Low RSSI, BTM, BSS_LOAD Triggers
5999 	 */
6000 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PER)
6001 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_PER);
6002 
6003 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BEACON_MISS)
6004 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BMISS);
6005 
6006 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_POOR_RSSI)
6007 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_LOW_RSSI);
6008 
6009 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BTM)
6010 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BTM);
6011 
6012 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
6013 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BSS_LOAD);
6014 
6015 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_USER_TRIGGER)
6016 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_FORCED);
6017 
6018 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DEAUTH)
6019 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_DEAUTH);
6020 
6021 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_IDLE)
6022 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_IDLE);
6023 
6024 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_TX_FAILURES)
6025 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_STA_KICKOUT);
6026 
6027 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN)
6028 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BACKGROUND);
6029 
6030 	return drv_scan_scheme_bitmap;
6031 }
6032 
6033 /**
6034  * hdd_send_roam_triggers_to_sme() - Send roam trigger bitmap to SME
6035  * @hdd_ctx: HDD context
6036  * @vdev_id: vdev id
6037  * @roam_trigger_bitmap: Vendor configured roam trigger bitmap to be configured
6038  *			 to firmware
6039  *
6040  * Send the roam trigger bitmap received to SME
6041  *
6042  * Return: QDF_STATUS
6043  */
6044 static QDF_STATUS
hdd_send_roam_triggers_to_sme(struct hdd_context * hdd_ctx,uint8_t vdev_id,uint32_t roam_trigger_bitmap)6045 hdd_send_roam_triggers_to_sme(struct hdd_context *hdd_ctx,
6046 			      uint8_t vdev_id,
6047 			      uint32_t roam_trigger_bitmap)
6048 {
6049 	QDF_STATUS status;
6050 	struct wlan_roam_triggers triggers;
6051 	struct wlan_hdd_link_info *link_info;
6052 
6053 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6054 	if (!link_info) {
6055 		hdd_err("Invalid vdev");
6056 		return QDF_STATUS_E_FAILURE;
6057 	}
6058 
6059 	if (link_info->adapter->device_mode != QDF_STA_MODE) {
6060 		hdd_err("Roam trigger bitmap supported only in STA mode");
6061 		return QDF_STATUS_E_FAILURE;
6062 	}
6063 
6064 	triggers.vdev_id = vdev_id;
6065 	triggers.trigger_bitmap =
6066 	    wlan_hdd_convert_control_roam_trigger_bitmap(roam_trigger_bitmap);
6067 	hdd_debug("trigger bitmap: 0x%x converted trigger_bitmap: 0x%x",
6068 		  roam_trigger_bitmap, triggers.trigger_bitmap);
6069 	/*
6070 	 * In standalone STA, if this vendor command is received between
6071 	 * ROAM_START and roam synch indication, it is better to reject
6072 	 * roam disable since driver would send vdev_params command to
6073 	 * de-initialize roaming structures in fw.
6074 	 * In STA+STA mode, if this vendor command to enable roaming is
6075 	 * received for one STA vdev and ROAM_START was received for other
6076 	 * STA vdev, then also driver would be send vdev_params command to
6077 	 * de-initialize roaming structures in fw on the roaming enabled
6078 	 * vdev.
6079 	 */
6080 	if (hdd_is_roaming_in_progress(hdd_ctx)) {
6081 		mlme_set_roam_trigger_bitmap(hdd_ctx->psoc,
6082 					     link_info->vdev_id,
6083 					     triggers.trigger_bitmap);
6084 		hdd_err("Reject set roam trigger as roaming is in progress");
6085 
6086 		return QDF_STATUS_E_BUSY;
6087 	}
6088 
6089 	/*
6090 	 * roam trigger bitmap is > 0 - Roam triggers are set.
6091 	 * roam trigger bitmap is 0 - Disable roaming
6092 	 *
6093 	 * For both the above modes, reset the roam scan scheme bitmap to
6094 	 * 0.
6095 	 */
6096 	status = ucfg_cm_update_roam_scan_scheme_bitmap(hdd_ctx->psoc,
6097 							vdev_id, 0);
6098 
6099 	status = ucfg_cm_rso_set_roam_trigger(hdd_ctx->pdev, vdev_id,
6100 					      &triggers);
6101 	if (QDF_IS_STATUS_ERROR(status))
6102 		hdd_err("Failed to set roam control trigger bitmap");
6103 
6104 	return status;
6105 }
6106 
6107 /*
6108  * Disable default scoring algorithm. This is intended to set all bits of the
6109  * disable_bitmap in struct scoring_param.
6110  */
6111 #define DISABLE_SCORING 0
6112 
6113 /*
6114  * Enable scoring algorithm. This is intended to clear all bits of the
6115  * disable_bitmap in struct scoring_param.
6116  */
6117 #define ENABLE_SCORING 1
6118 
6119 /*
6120  * Controlled roam candidate selection is enabled from userspace.
6121  * Driver/firmware should honor the selection criteria
6122  */
6123 #define CONTROL_ROAM_CAND_SEL_ENABLE 1
6124 
6125 /*
6126  * Controlled roam candidate selection is disabled from userspace.
6127  * Driver/firmware can use its internal candidate selection criteria
6128  */
6129 #define CONTROL_ROAM_CAND_SEL_DISABLE 0
6130 
6131 static const struct nla_policy
6132 roam_scan_cand_sel_policy[PARAM_CAND_SEL_CRITERIA_MAX + 1] = {
6133 	[PARAM_CAND_SEL_SCORE_RSSI] = {.type = NLA_U8},
6134 };
6135 
6136 /**
6137  * hdd_send_roam_cand_sel_criteria_to_sme() - Send candidate sel criteria to SME
6138  * @hdd_ctx: HDD context
6139  * @vdev_id: vdev id
6140  * @attr: Nested attribute carrying candidate selection criteria
6141  *
6142  * Extract different candidate sel criteria mentioned and convert it to
6143  * driver/firmware understable format.
6144  *
6145  * Return: QDF_STATUS
6146  */
6147 static QDF_STATUS
hdd_send_roam_cand_sel_criteria_to_sme(struct hdd_context * hdd_ctx,uint8_t vdev_id,struct nlattr * attr)6148 hdd_send_roam_cand_sel_criteria_to_sme(struct hdd_context *hdd_ctx,
6149 				       uint8_t vdev_id,
6150 				       struct nlattr *attr)
6151 {
6152 	QDF_STATUS status;
6153 	struct nlattr *tb2[PARAM_CAND_SEL_CRITERIA_MAX + 1];
6154 	struct nlattr *curr_attr;
6155 	uint8_t sel_criteria = 0, rssi_score = 0, scoring;
6156 	int rem;
6157 
6158 	hdd_debug("Received Command to Set candidate selection criteria ");
6159 	nla_for_each_nested(curr_attr, attr, rem) {
6160 		sel_criteria++;
6161 		break;
6162 	}
6163 
6164 	if (sel_criteria &&
6165 	    wlan_cfg80211_nla_parse_nested(tb2, PARAM_CAND_SEL_CRITERIA_MAX,
6166 					   attr, roam_scan_cand_sel_policy)) {
6167 		hdd_err("nla_parse failed");
6168 		return QDF_STATUS_E_INVAL;
6169 	}
6170 
6171 	/*
6172 	 * Firmware supports the below configurations currently,
6173 	 * 1. Default selection criteria where all scoring params
6174 	 *    are enabled and different weightages/scores are given to
6175 	 *    different parameters.
6176 	 *    When userspace doesn't specify any candidate selection criteria,
6177 	 *    this will be enabled.
6178 	 * 2. Legacy candidate selection criteria where scoring
6179 	 *    algorithm is disabled and only RSSI is considered for
6180 	 *    roam candidate selection.
6181 	 *    When userspace specify 100% weightage for RSSI, this will
6182 	 *    be enabled.
6183 	 * Rest of the combinations are not supported for now.
6184 	 */
6185 	if (sel_criteria == CONTROL_ROAM_CAND_SEL_ENABLE) {
6186 		/* Legacy selection criteria: 100% weightage to RSSI */
6187 		if (tb2[PARAM_CAND_SEL_SCORE_RSSI])
6188 			rssi_score = nla_get_u8(tb2[PARAM_CAND_SEL_SCORE_RSSI]);
6189 
6190 		if (rssi_score != 100) {
6191 			hdd_debug("Ignore the candidate selection criteria");
6192 			return QDF_STATUS_E_INVAL;
6193 		}
6194 		scoring = DISABLE_SCORING;
6195 	} else {
6196 		/* Default selection criteria */
6197 		scoring = ENABLE_SCORING;
6198 	}
6199 
6200 	status = sme_modify_roam_cand_sel_criteria(hdd_ctx->mac_handle, vdev_id,
6201 						   !!scoring);
6202 	if (QDF_IS_STATUS_ERROR(status))
6203 		hdd_err("Failed to disable scoring");
6204 
6205 	return status;
6206 }
6207 
6208 /**
6209  * hdd_send_roam_scan_period_to_sme() - Send roam scan period to SME
6210  * @hdd_ctx: HDD context
6211  * @vdev_id: vdev id
6212  * @roam_scan_period: Roam scan period in seconds
6213  * @check_and_update: If this is true/set, update the value only if the current
6214  *		      configured value is not same as global value read from
6215  *		      ini param. This is to give priority to the user configured
6216  *		      values and retain the value, if updated already.
6217  *		      If this is not set, update the value without any check.
6218  *
6219  * Validate the roam scan period and send it to firmware if valid.
6220  *
6221  * Return: QDF_STATUS
6222  */
6223 static QDF_STATUS
hdd_send_roam_scan_period_to_sme(struct hdd_context * hdd_ctx,uint8_t vdev_id,uint32_t roam_scan_period,bool check_and_update)6224 hdd_send_roam_scan_period_to_sme(struct hdd_context *hdd_ctx,
6225 				 uint8_t vdev_id,
6226 				 uint32_t roam_scan_period,
6227 				 bool check_and_update)
6228 {
6229 	QDF_STATUS status;
6230 	uint16_t roam_scan_period_current, roam_scan_period_global = 0;
6231 
6232 	if (!ucfg_mlme_validate_scan_period(hdd_ctx->psoc,
6233 					    roam_scan_period * 1000))
6234 		return QDF_STATUS_E_INVAL;
6235 
6236 	hdd_debug("Received Command to Set roam scan period (Empty Scan refresh period) = %d",
6237 		  roam_scan_period);
6238 
6239 	status = ucfg_cm_get_empty_scan_refresh_period(
6240 						hdd_ctx->psoc, vdev_id,
6241 						&roam_scan_period_current);
6242 	if (QDF_IS_STATUS_ERROR(status))
6243 		return status;
6244 
6245 	ucfg_cm_get_empty_scan_refresh_period_global(hdd_ctx->psoc,
6246 						     &roam_scan_period_global);
6247 	if (check_and_update &&
6248 	    roam_scan_period_current != roam_scan_period_global) {
6249 		hdd_debug("roam scan period is already updated, value: %u",
6250 			  roam_scan_period_current / 1000);
6251 		return QDF_STATUS_SUCCESS;
6252 	}
6253 	status = sme_update_empty_scan_refresh_period(hdd_ctx->mac_handle,
6254 						      vdev_id,
6255 						      roam_scan_period * 1000);
6256 	if (QDF_IS_STATUS_ERROR(status))
6257 		hdd_err("Failed to set scan period");
6258 
6259 	return status;
6260 }
6261 
6262 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && \
6263 defined(FEATURE_RX_LINKSPEED_ROAM_TRIGGER)
6264 /**
6265  * hdd_set_roam_rx_linkspeed_threshold() - Set rx link speed threshold
6266  * @psoc: Pointer to psoc
6267  * @vdev: vdev
6268  * @linkspeed_threshold: threshold value to set
6269  *
6270  * Return: none
6271  */
6272 static QDF_STATUS
hdd_set_roam_rx_linkspeed_threshold(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint32_t linkspeed_threshold)6273 hdd_set_roam_rx_linkspeed_threshold(struct wlan_objmgr_psoc *psoc,
6274 				    struct wlan_objmgr_vdev *vdev,
6275 				    uint32_t linkspeed_threshold)
6276 {
6277 	if (!ucfg_cm_is_linkspeed_roam_trigger_supported(psoc))
6278 		return QDF_STATUS_E_NOSUPPORT;
6279 
6280 	if (linkspeed_threshold) {
6281 		dp_ucfg_enable_link_monitoring(psoc, vdev,
6282 					       linkspeed_threshold);
6283 	} else {
6284 		dp_ucfg_disable_link_monitoring(psoc, vdev);
6285 		wlan_hdd_link_speed_update(psoc, wlan_vdev_get_id(vdev),
6286 					   false);
6287 	}
6288 
6289 	return QDF_STATUS_SUCCESS;
6290 }
6291 #else
6292 static inline QDF_STATUS
hdd_set_roam_rx_linkspeed_threshold(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint32_t linkspeed_threshold)6293 hdd_set_roam_rx_linkspeed_threshold(struct wlan_objmgr_psoc *psoc,
6294 				    struct wlan_objmgr_vdev *vdev,
6295 				    uint32_t linkspeed_threshold)
6296 {
6297 	return QDF_STATUS_E_NOSUPPORT;
6298 }
6299 #endif
6300 
6301 /* Roam Hand-off delay range is 20 to 1000 msec */
6302 #define MIN_ROAM_HO_DELAY 20
6303 #define MAX_ROAM_HO_DELAY 1000
6304 
6305 /* Include/Exclude roam partial scan channels in full scan */
6306 #define INCLUDE_ROAM_PARTIAL_SCAN_FREQ 0
6307 #define EXCLUDE_ROAM_PARTIAL_SCAN_FREQ 1
6308 
6309 /* Include the supported 6 GHz PSC channels in full scan by default */
6310 #define INCLUDE_6GHZ_IN_FULL_SCAN_BY_DEF	0
6311 /* Include the 6 GHz channels in roam full scan only on prior discovery */
6312 #define INCLUDE_6GHZ_IN_FULL_SCAN_IF_DISC	1
6313 
6314 #ifdef WLAN_VENDOR_HANDOFF_CONTROL
6315 /**
6316  * hdd_get_handoff_param() - get vendor handoff parameters
6317  * @hdd_ctx: HDD context
6318  * @vdev_id: vdev id
6319  *
6320  * Wrapper function for hdd_cm_get_handoff_param
6321  *
6322  * Return: QDF_STATUS
6323  */
hdd_get_handoff_param(struct hdd_context * hdd_ctx,uint8_t vdev_id)6324 static QDF_STATUS hdd_get_handoff_param(struct hdd_context *hdd_ctx,
6325 					uint8_t vdev_id)
6326 {
6327 	return hdd_cm_get_handoff_param(hdd_ctx->psoc, vdev_id,
6328 					VENDOR_CONTROL_PARAM_ROAM_ALL);
6329 }
6330 #else
6331 static inline QDF_STATUS
hdd_get_handoff_param(struct hdd_context * hdd_ctx,uint8_t vdev_id)6332 hdd_get_handoff_param(struct hdd_context *hdd_ctx, uint8_t vdev_id)
6333 {
6334 	return QDF_STATUS_SUCCESS;
6335 }
6336 #endif
6337 
6338 /**
6339  * hdd_set_roam_with_control_config() - Set roam control configuration
6340  * @hdd_ctx: HDD context
6341  * @tb: List of attributes carrying roam subcmd data
6342  * @vdev_id: vdev id
6343  *
6344  * Extracts the attribute PARAM_ROAM_CONTROL_CONFIG from the attributes list tb
6345  * and sends the corresponding roam control configuration to driver/firmware.
6346  *
6347  * Return: 0 on success; error number on failure
6348  */
6349 static int
hdd_set_roam_with_control_config(struct hdd_context * hdd_ctx,struct nlattr ** tb,uint8_t vdev_id)6350 hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx,
6351 				 struct nlattr **tb,
6352 				 uint8_t vdev_id)
6353 {
6354 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6355 	struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1], *attr;
6356 	uint32_t value;
6357 	struct wlan_cm_roam_vendor_btm_params param = {0};
6358 	bool is_wtc_param_updated = false;
6359 	uint32_t band_mask;
6360 	uint16_t threshold;
6361 	struct wlan_hdd_link_info *link_info;
6362 	uint8_t roam_control_enable = false;
6363 
6364 	hdd_enter();
6365 
6366 	/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
6367 	if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
6368 		hdd_err("Attribute CONTROL_CONFIG is not present");
6369 		return -EINVAL;
6370 	}
6371 
6372 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6373 	if (!link_info || hdd_validate_adapter(link_info->adapter))
6374 		return QDF_STATUS_E_FAILURE;
6375 
6376 	if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
6377 					   tb[PARAM_ROAM_CONTROL_CONFIG],
6378 					   roam_control_policy)) {
6379 		hdd_err("nla_parse failed");
6380 		return -EINVAL;
6381 	}
6382 
6383 	attr = tb2[PARAM_FREQ_LIST_SCHEME];
6384 	if (attr) {
6385 		status = hdd_send_roam_scan_channel_freq_list_to_sme(hdd_ctx,
6386 								     vdev_id,
6387 								     attr);
6388 		if (QDF_IS_STATUS_ERROR(status))
6389 			hdd_err("failed to config roam control");
6390 	}
6391 
6392 	if (tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]) {
6393 		value = nla_get_u32(tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]);
6394 		hdd_debug("Received roam trigger bitmap: 0x%x", value);
6395 		status = hdd_send_roam_triggers_to_sme(hdd_ctx,
6396 						       vdev_id,
6397 						       value);
6398 		if (status)
6399 			hdd_err("failed to config roam triggers");
6400 	}
6401 
6402 	attr = tb2[QCA_ATTR_ROAM_CONTROL_ENABLE];
6403 	if (attr) {
6404 		roam_control_enable = nla_get_u8(attr);
6405 		if (roam_control_enable &&
6406 		    ucfg_cm_roam_is_vendor_handoff_control_enable(
6407 			hdd_ctx->psoc)) {
6408 			status = hdd_get_handoff_param(hdd_ctx, vdev_id);
6409 			if (QDF_IS_STATUS_ERROR(status)) {
6410 				hdd_err("failed to get vendor handoff params");
6411 				return qdf_status_to_os_return(status);
6412 			}
6413 		}
6414 
6415 		hdd_debug("Parse and send roam control to FW: %s",
6416 			  roam_control_enable ? "Enable" : "Disable");
6417 
6418 		status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
6419 						    vdev_id,
6420 						    roam_control_enable);
6421 		if (QDF_IS_STATUS_ERROR(status))
6422 			hdd_err("failed to enable/disable roam control config");
6423 
6424 		attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
6425 		if (attr) {
6426 			/* Default value received as part of Roam control enable
6427 			 * Set this only if user hasn't configured any value so
6428 			 * far.
6429 			 */
6430 			value = nla_get_u32(attr);
6431 			status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
6432 								  vdev_id,
6433 								  value, true);
6434 			if (QDF_IS_STATUS_ERROR(status))
6435 				hdd_err("failed to send scan period to firmware");
6436 		}
6437 
6438 		attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
6439 		if (attr) {
6440 			value = nla_get_u32(attr);
6441 			/* Default value received as part of Roam control enable
6442 			 * Set this only if user hasn't configured any value so
6443 			 * far.
6444 			 */
6445 			status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
6446 								       vdev_id,
6447 								       value,
6448 								       true);
6449 			if (status)
6450 				hdd_err("failed to config full scan period");
6451 		}
6452 	} else {
6453 		attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
6454 		if (attr) {
6455 			/* User configured value, cache the value directly */
6456 			value = nla_get_u32(attr);
6457 			status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
6458 								  vdev_id,
6459 								  value, false);
6460 			if (QDF_IS_STATUS_ERROR(status))
6461 				hdd_err("failed to send scan period to firmware");
6462 		}
6463 
6464 		attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
6465 		if (attr) {
6466 			value = nla_get_u32(attr);
6467 			/* User configured value, cache the value directly */
6468 			status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
6469 								       vdev_id,
6470 								       value,
6471 								       false);
6472 			if (status)
6473 				hdd_err("failed to config full scan period");
6474 		}
6475 	}
6476 
6477 	attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS];
6478 	if (attr) {
6479 		value = wlan_hdd_convert_control_roam_scan_scheme_bitmap(
6480 							nla_get_u32(attr));
6481 		status = ucfg_cm_update_roam_scan_scheme_bitmap(hdd_ctx->psoc,
6482 								vdev_id,
6483 								value);
6484 	}
6485 
6486 	/* Scoring and roam candidate selection criteria */
6487 	attr = tb2[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA];
6488 	if (attr) {
6489 		status = hdd_send_roam_cand_sel_criteria_to_sme(hdd_ctx,
6490 								vdev_id, attr);
6491 		if (QDF_IS_STATUS_ERROR(status))
6492 			hdd_err("failed to set candidate selection criteria");
6493 	}
6494 
6495 	attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME];
6496 	if (attr) {
6497 		param.scan_freq_scheme = nla_get_u32(attr);
6498 		is_wtc_param_updated = true;
6499 	}
6500 
6501 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD];
6502 	if (attr) {
6503 		param.connected_rssi_threshold = nla_get_u32(attr);
6504 		is_wtc_param_updated = true;
6505 	}
6506 
6507 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD];
6508 	if (attr) {
6509 		param.candidate_rssi_threshold_2g = nla_get_u32(attr);
6510 		is_wtc_param_updated = true;
6511 	}
6512 
6513 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ];
6514 	if (attr) {
6515 		param.candidate_rssi_threshold_2g = nla_get_u32(attr);
6516 		is_wtc_param_updated = true;
6517 	}
6518 
6519 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ];
6520 	if (attr) {
6521 		param.candidate_rssi_threshold_5g = nla_get_u32(attr);
6522 		is_wtc_param_updated = true;
6523 	} else {
6524 		param.candidate_rssi_threshold_5g =
6525 					param.candidate_rssi_threshold_2g;
6526 	}
6527 
6528 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ];
6529 	if (attr) {
6530 		param.candidate_rssi_threshold_6g = nla_get_u32(attr);
6531 		is_wtc_param_updated = true;
6532 	} else {
6533 		param.candidate_rssi_threshold_6g =
6534 					param.candidate_rssi_threshold_2g;
6535 	}
6536 
6537 	attr = tb2[QCA_ATTR_ROAM_CONTROL_USER_REASON];
6538 	if (attr) {
6539 		param.user_roam_reason = nla_get_u32(attr);
6540 		is_wtc_param_updated = true;
6541 	} else {
6542 		param.user_roam_reason = DISABLE_VENDOR_BTM_CONFIG;
6543 	}
6544 
6545 	if (tb2[QCA_ATTR_ROAM_CONTROL_BAND_MASK]) {
6546 		band_mask =
6547 			nla_get_u32(tb2[QCA_ATTR_ROAM_CONTROL_BAND_MASK]);
6548 		band_mask =
6549 			wlan_vendor_bitmap_to_reg_wifi_band_bitmap(hdd_ctx->psoc,
6550 								   band_mask);
6551 		hdd_debug("[ROAM BAND] set roam band mask:%d", band_mask);
6552 		if (band_mask) {
6553 			ucfg_cm_set_roam_band_mask(hdd_ctx->psoc, vdev_id,
6554 						   band_mask);
6555 		} else {
6556 			hdd_debug("Invalid roam BAND_MASK");
6557 			return -EINVAL;
6558 		}
6559 
6560 		if (ucfg_cm_is_change_in_band_allowed(hdd_ctx->psoc, vdev_id,
6561 						      band_mask)) {
6562 
6563 			/* Disable roaming on Vdev before setting PCL */
6564 			sme_stop_roaming(hdd_ctx->mac_handle, vdev_id,
6565 					 REASON_DRIVER_DISABLED, RSO_SET_PCL);
6566 
6567 			policy_mgr_set_pcl_for_existing_combo(hdd_ctx->psoc,
6568 							      PM_STA_MODE,
6569 							      vdev_id);
6570 
6571 			/* Enable roaming once SET pcl is done */
6572 			sme_start_roaming(hdd_ctx->mac_handle, vdev_id,
6573 					  REASON_DRIVER_ENABLED, RSO_SET_PCL);
6574 		}
6575 	}
6576 
6577 	attr = tb2[QCA_ATTR_ROAM_CONTROL_RX_LINKSPEED_THRESHOLD];
6578 	if (attr) {
6579 		threshold = nla_get_u16(attr);
6580 		status = hdd_set_roam_rx_linkspeed_threshold(hdd_ctx->psoc,
6581 							     link_info->vdev,
6582 							     threshold);
6583 	}
6584 
6585 	if (is_wtc_param_updated) {
6586 		wlan_cm_roam_set_vendor_btm_params(hdd_ctx->psoc, &param);
6587 		/* Sends RSO update */
6588 		sme_send_vendor_btm_params(hdd_ctx->mac_handle, vdev_id);
6589 	}
6590 
6591 	attr = tb2[QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX];
6592 	if (attr) {
6593 		value = nla_get_u16(attr);
6594 		if (value < MIN_ROAM_HO_DELAY || value > MAX_ROAM_HO_DELAY) {
6595 			hdd_err("Invalid roam HO delay value: %d", value);
6596 			return -EINVAL;
6597 		}
6598 
6599 		hdd_debug("Received roam HO delay value: %d", value);
6600 
6601 		status = ucfg_cm_roam_send_ho_delay_config(hdd_ctx->pdev,
6602 							   vdev_id, value);
6603 		if (QDF_IS_STATUS_ERROR(status))
6604 			hdd_err("failed to set hand-off delay");
6605 	}
6606 
6607 	attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_NO_REUSE_PARTIAL_SCAN_FREQ];
6608 	if (attr) {
6609 		value = nla_get_u8(attr);
6610 		if (value < INCLUDE_ROAM_PARTIAL_SCAN_FREQ ||
6611 		    value > EXCLUDE_ROAM_PARTIAL_SCAN_FREQ) {
6612 			hdd_err("Invalid value %d to exclude partial scan freq",
6613 				value);
6614 			return -EINVAL;
6615 		}
6616 
6617 		hdd_debug("%s partial scan channels in roam full scan",
6618 			  value ? "Exclude" : "Include");
6619 
6620 		status = ucfg_cm_exclude_rm_partial_scan_freq(hdd_ctx->pdev,
6621 							      vdev_id, value);
6622 		if (QDF_IS_STATUS_ERROR(status))
6623 			hdd_err("Fail to exclude roam partial scan channels");
6624 	}
6625 
6626 	attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_6GHZ_ONLY_ON_PRIOR_DISCOVERY];
6627 	if (attr) {
6628 		value = nla_get_u8(attr);
6629 		if (value < INCLUDE_6GHZ_IN_FULL_SCAN_BY_DEF ||
6630 		    value > INCLUDE_6GHZ_IN_FULL_SCAN_IF_DISC) {
6631 			hdd_err("Invalid value %d to decide inclusion of 6 GHz channels",
6632 				value);
6633 			return -EINVAL;
6634 		}
6635 
6636 		hdd_debug("Include 6 GHz channels in roam full scan by %s",
6637 			  value ? "prior discovery" : "default");
6638 
6639 		status = ucfg_cm_roam_full_scan_6ghz_on_disc(hdd_ctx->pdev,
6640 							     vdev_id, value);
6641 		if (QDF_IS_STATUS_ERROR(status))
6642 			hdd_err("Fail to decide inclusion of 6 GHz channels");
6643 	}
6644 
6645 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CONNECTED_HIGH_RSSI_OFFSET];
6646 	if (attr) {
6647 		value = nla_get_u8(attr);
6648 		if (!cfg_in_range(CFG_LFR_ROAM_SCAN_HI_RSSI_DELTA, value)) {
6649 			hdd_err("High RSSI offset value %d is out of range",
6650 				value);
6651 			return -EINVAL;
6652 		}
6653 
6654 		hdd_debug("%s roam scan high RSSI with offset: %d for vdev %d",
6655 			  value ? "Enable" : "Disable", value, vdev_id);
6656 
6657 		if (!value &&
6658 		    !wlan_cm_get_roam_scan_high_rssi_offset(hdd_ctx->psoc)) {
6659 			hdd_debug("Roam scan high RSSI is already disabled");
6660 			return -EINVAL;
6661 		}
6662 
6663 		status = ucfg_cm_set_roam_scan_high_rssi_offset(hdd_ctx->psoc,
6664 								vdev_id, value);
6665 		if (QDF_IS_STATUS_ERROR(status))
6666 			hdd_err("Fail to set roam scan high RSSI offset for vdev %d",
6667 				vdev_id);
6668 	}
6669 
6670 	return qdf_status_to_os_return(status);
6671 }
6672 
6673 #define ENABLE_ROAM_TRIGGERS_ALL (QCA_ROAM_TRIGGER_REASON_PER | \
6674 				  QCA_ROAM_TRIGGER_REASON_BEACON_MISS | \
6675 				  QCA_ROAM_TRIGGER_REASON_POOR_RSSI | \
6676 				  QCA_ROAM_TRIGGER_REASON_BETTER_RSSI | \
6677 				  QCA_ROAM_TRIGGER_REASON_PERIODIC | \
6678 				  QCA_ROAM_TRIGGER_REASON_DENSE | \
6679 				  QCA_ROAM_TRIGGER_REASON_BTM | \
6680 				  QCA_ROAM_TRIGGER_REASON_BSS_LOAD | \
6681 				  QCA_ROAM_TRIGGER_REASON_USER_TRIGGER | \
6682 				  QCA_ROAM_TRIGGER_REASON_DEAUTH | \
6683 				  QCA_ROAM_TRIGGER_REASON_IDLE | \
6684 				  QCA_ROAM_TRIGGER_REASON_TX_FAILURES | \
6685 				  QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN)
6686 
6687 static int
hdd_clear_roam_control_config(struct hdd_context * hdd_ctx,struct nlattr ** tb,uint8_t vdev_id)6688 hdd_clear_roam_control_config(struct hdd_context *hdd_ctx,
6689 			      struct nlattr **tb,
6690 			      uint8_t vdev_id)
6691 {
6692 	QDF_STATUS status;
6693 	struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
6694 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
6695 	uint32_t value;
6696 
6697 	/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
6698 	if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
6699 		hdd_err("Attribute CONTROL_CONFIG is not present");
6700 		return -EINVAL;
6701 	}
6702 
6703 	if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
6704 					   tb[PARAM_ROAM_CONTROL_CONFIG],
6705 					   roam_control_policy)) {
6706 		hdd_err("nla_parse failed");
6707 		return -EINVAL;
6708 	}
6709 
6710 	hdd_debug("Clear the control config done through SET");
6711 	if (tb2[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL]) {
6712 		hdd_debug("Disable roam control config done through SET");
6713 		status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
6714 						    vdev_id, 0);
6715 		if (QDF_IS_STATUS_ERROR(status)) {
6716 			hdd_err("failed to enable/disable roam control config");
6717 			return qdf_status_to_os_return(status);
6718 		}
6719 
6720 		value = ENABLE_ROAM_TRIGGERS_ALL;
6721 		hdd_debug("Reset roam trigger bitmap to 0x%x", value);
6722 		status = hdd_send_roam_triggers_to_sme(hdd_ctx, vdev_id, value);
6723 		if (QDF_IS_STATUS_ERROR(status)) {
6724 			hdd_err("failed to restore roam trigger bitmap");
6725 			return qdf_status_to_os_return(status);
6726 		}
6727 
6728 		status = sme_roam_control_restore_default_config(mac_handle,
6729 								 vdev_id);
6730 		if (QDF_IS_STATUS_ERROR(status)) {
6731 			hdd_err("failed to config roam control");
6732 			return qdf_status_to_os_return(status);
6733 		}
6734 	}
6735 
6736 	return 0;
6737 }
6738 
6739 /**
6740  * hdd_roam_control_config_buf_size() - Calculate the skb size to be allocated
6741  * @hdd_ctx: HDD context
6742  * @tb: List of attributes to be populated
6743  *
6744  * Calculate the buffer size to be allocated based on the attributes
6745  * mentioned in tb.
6746  *
6747  * Return: buffer size to be allocated
6748  */
6749 static uint16_t
hdd_roam_control_config_buf_size(struct hdd_context * hdd_ctx,struct nlattr ** tb)6750 hdd_roam_control_config_buf_size(struct hdd_context *hdd_ctx,
6751 				 struct nlattr **tb)
6752 {
6753 	uint16_t skb_len = 0;
6754 
6755 	if (tb[QCA_ATTR_ROAM_CONTROL_STATUS])
6756 		skb_len += NLA_HDRLEN + sizeof(uint8_t);
6757 
6758 	if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD])
6759 		skb_len += NLA_HDRLEN + sizeof(uint32_t);
6760 
6761 	if (tb[QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME])
6762 		/*
6763 		 * Response has 3 nests, 1 atrribure value and a
6764 		 * attribute list of frequencies.
6765 		 */
6766 		skb_len += 3 * nla_total_size(0) +
6767 			nla_total_size(sizeof(uint32_t)) +
6768 			(nla_total_size(sizeof(uint32_t)) *
6769 			NUM_CHANNELS);
6770 
6771 	if (tb[QCA_ATTR_ROAM_CONTROL_BAND_MASK])
6772 		skb_len += NLA_HDRLEN + sizeof(uint32_t);
6773 
6774 	return skb_len;
6775 }
6776 
6777 /**
6778  * wlan_reg_wifi_band_bitmap_to_vendor_bitmap() - Convert enum reg_wifi_band
6779  * to enum qca_set_band
6780  * @reg_wifi_band_bitmap: enum reg_wifi_band
6781  *
6782  * Return: qca_set_band value
6783  */
6784 static uint32_t
wlan_reg_wifi_band_bitmap_to_vendor_bitmap(uint32_t reg_wifi_band_bitmap)6785 wlan_reg_wifi_band_bitmap_to_vendor_bitmap(uint32_t reg_wifi_band_bitmap)
6786 {
6787 	uint32_t vendor_mask = 0;
6788 
6789 	if (reg_wifi_band_bitmap & BIT(REG_BAND_2G))
6790 		vendor_mask |= QCA_SETBAND_2G;
6791 	if (reg_wifi_band_bitmap & BIT(REG_BAND_5G))
6792 		vendor_mask |= QCA_SETBAND_5G;
6793 	if (reg_wifi_band_bitmap & BIT(REG_BAND_6G))
6794 		vendor_mask |= QCA_SETBAND_6G;
6795 
6796 	return vendor_mask;
6797 }
6798 
6799 /**
6800  * hdd_roam_control_config_fill_data() - Fill the data requested by userspace
6801  * @hdd_ctx: HDD context
6802  * @vdev_id: vdev id
6803  * @skb: SK buffer
6804  * @tb: List of attributes
6805  *
6806  * Get the data corresponding to the attribute list specified in tb and
6807  * update the same to skb by populating the same attributes.
6808  *
6809  * Return: 0 on success; error number on failure
6810  */
6811 static int
hdd_roam_control_config_fill_data(struct hdd_context * hdd_ctx,uint8_t vdev_id,struct sk_buff * skb,struct nlattr ** tb)6812 hdd_roam_control_config_fill_data(struct hdd_context *hdd_ctx, uint8_t vdev_id,
6813 				  struct sk_buff *skb, struct nlattr **tb)
6814 {
6815 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6816 	uint8_t roam_control;
6817 	struct nlattr *config, *get_freq_scheme, *get_freq;
6818 	uint32_t full_roam_scan_period, roam_band, vendor_band_mask;
6819 	uint8_t num_channels = 0;
6820 	uint32_t i = 0, freq_list[NUM_CHANNELS] = { 0 };
6821 	struct wlan_hdd_link_info *link_info;
6822 
6823 	config = nla_nest_start(skb, PARAM_ROAM_CONTROL_CONFIG);
6824 	if (!config) {
6825 		hdd_err("nla nest start failure");
6826 		return -EINVAL;
6827 	}
6828 
6829 	if (tb[QCA_ATTR_ROAM_CONTROL_STATUS]) {
6830 		status = sme_get_roam_config_status(hdd_ctx->mac_handle,
6831 						    vdev_id,
6832 						    &roam_control);
6833 		if (QDF_IS_STATUS_ERROR(status))
6834 			goto out;
6835 		hdd_debug("Roam control: %s",
6836 			  roam_control ? "Enabled" : "Disabled");
6837 		if (nla_put_u8(skb, QCA_ATTR_ROAM_CONTROL_STATUS,
6838 			       roam_control)) {
6839 			hdd_info("failed to put vendor_roam_control");
6840 			return -ENOMEM;
6841 		}
6842 	}
6843 
6844 	if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD]) {
6845 		status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle,
6846 						       vdev_id,
6847 						       &full_roam_scan_period);
6848 		if (QDF_IS_STATUS_ERROR(status))
6849 			goto out;
6850 		hdd_debug("full_roam_scan_period: %u", full_roam_scan_period);
6851 
6852 		if (nla_put_u32(skb, QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD,
6853 				full_roam_scan_period)) {
6854 			hdd_info("failed to put full_roam_scan_period");
6855 			return -EINVAL;
6856 		}
6857 	}
6858 
6859 	if (tb[QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME]) {
6860 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6861 		if (!link_info) {
6862 			hdd_info("Invalid vdev");
6863 			return -EINVAL;
6864 		}
6865 
6866 		hdd_debug("Get roam scan frequencies req received");
6867 		status = hdd_get_roam_scan_freq(link_info->adapter,
6868 						hdd_ctx->mac_handle,
6869 						freq_list, &num_channels);
6870 		if (QDF_IS_STATUS_ERROR(status)) {
6871 			hdd_info("failed to get roam scan freq");
6872 			goto out;
6873 		}
6874 
6875 		hdd_debug("num_channels %d", num_channels);
6876 		get_freq_scheme = nla_nest_start(
6877 				skb, QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME);
6878 		if (!get_freq_scheme) {
6879 			hdd_info("failed to nest start for roam scan freq");
6880 			return -EINVAL;
6881 		}
6882 
6883 		if (nla_put_u32(skb, PARAM_SCAN_FREQ_LIST_TYPE, 0)) {
6884 			hdd_info("failed to put list type");
6885 			return -EINVAL;
6886 		}
6887 
6888 		get_freq = nla_nest_start(
6889 				skb, QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST);
6890 		if (!get_freq) {
6891 			hdd_info("failed to nest start for roam scan freq");
6892 			return -EINVAL;
6893 		}
6894 
6895 		for (i = 0; i < num_channels; i++) {
6896 			if (nla_put_u32(skb, PARAM_SCAN_FREQ_LIST,
6897 					freq_list[i])) {
6898 				hdd_info("failed to put freq at index %d", i);
6899 				return -EINVAL;
6900 			}
6901 		}
6902 		nla_nest_end(skb, get_freq);
6903 		nla_nest_end(skb, get_freq_scheme);
6904 	}
6905 
6906 	if (tb[QCA_ATTR_ROAM_CONTROL_BAND_MASK]) {
6907 		status = ucfg_cm_get_roam_band(hdd_ctx->psoc, vdev_id,
6908 					       &roam_band);
6909 		if (QDF_IS_STATUS_ERROR(status))
6910 			goto out;
6911 		vendor_band_mask =
6912 			wlan_reg_wifi_band_bitmap_to_vendor_bitmap(roam_band);
6913 		if (nla_put_u32(skb, QCA_ATTR_ROAM_CONTROL_BAND_MASK,
6914 				vendor_band_mask)) {
6915 			hdd_info("failed to put roam_band");
6916 			return -EINVAL;
6917 		}
6918 		hdd_debug("sending vendor_band_mask: %d reg band:%d",
6919 			  vendor_band_mask, roam_band);
6920 	}
6921 
6922 	nla_nest_end(skb, config);
6923 
6924 out:
6925 	return qdf_status_to_os_return(status);
6926 }
6927 
6928 /**
6929  * hdd_send_roam_control_config() - Send the roam config as vendor cmd reply
6930  * @hdd_ctx: HDD context
6931  * @vdev_id: vdev id
6932  * @tb: List of attributes
6933  *
6934  * Parse the attributes list tb and  get the data corresponding to the
6935  * attributes specified in tb. Send them as a vendor response.
6936  *
6937  * Return: 0 on success; error number on failure
6938  */
6939 static int
hdd_send_roam_control_config(struct hdd_context * hdd_ctx,uint8_t vdev_id,struct nlattr ** tb)6940 hdd_send_roam_control_config(struct hdd_context *hdd_ctx,
6941 			     uint8_t vdev_id,
6942 			     struct nlattr **tb)
6943 {
6944 	struct sk_buff *skb;
6945 	uint16_t skb_len;
6946 	int status;
6947 
6948 	skb_len = hdd_roam_control_config_buf_size(hdd_ctx, tb);
6949 	if (!skb_len) {
6950 		hdd_err("No data requested");
6951 		return -EINVAL;
6952 	}
6953 
6954 	skb_len += NLMSG_HDRLEN;
6955 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
6956 	if (!skb) {
6957 		hdd_info("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
6958 		return -ENOMEM;
6959 	}
6960 
6961 	status = hdd_roam_control_config_fill_data(hdd_ctx, vdev_id, skb, tb);
6962 	if (status)
6963 		goto fail;
6964 
6965 	return wlan_cfg80211_vendor_cmd_reply(skb);
6966 
6967 fail:
6968 	hdd_err("nla put fail");
6969 	wlan_cfg80211_vendor_free_skb(skb);
6970 	return status;
6971 }
6972 
6973 /**
6974  * hdd_get_roam_control_config() - Send requested roam config to userspace
6975  * @hdd_ctx: HDD context
6976  * @tb: list of attributes
6977  * @vdev_id: vdev id
6978  *
6979  * Return: 0 on success; error number on failure
6980  */
hdd_get_roam_control_config(struct hdd_context * hdd_ctx,struct nlattr ** tb,uint8_t vdev_id)6981 static int hdd_get_roam_control_config(struct hdd_context *hdd_ctx,
6982 				       struct nlattr **tb,
6983 				       uint8_t vdev_id)
6984 {
6985 	QDF_STATUS status;
6986 	struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
6987 
6988 	/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
6989 	if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
6990 		hdd_err("Attribute CONTROL_CONFIG is not present");
6991 		return -EINVAL;
6992 	}
6993 
6994 	if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
6995 					   tb[PARAM_ROAM_CONTROL_CONFIG],
6996 					   roam_control_policy)) {
6997 		hdd_err("nla_parse failed");
6998 		return -EINVAL;
6999 	}
7000 
7001 	status = hdd_send_roam_control_config(hdd_ctx, vdev_id, tb2);
7002 	if (status) {
7003 		hdd_err("failed to enable/disable roam control");
7004 		return status;
7005 	}
7006 
7007 	return qdf_status_to_os_return(status);
7008 }
7009 
7010 #undef PARAM_ROAM_CONTROL_CONFIG
7011 #undef PARAM_FREQ_LIST_SCHEME_MAX
7012 #undef PARAM_FREQ_LIST_SCHEME
7013 #undef PARAM_SCAN_FREQ_LIST
7014 #undef PARAM_SCAN_FREQ_LIST_TYPE
7015 #undef PARAM_CAND_SEL_CRITERIA_MAX
7016 #undef PARAM_CAND_SEL_SCORE_RSSI
7017 
7018 /**
7019  * hdd_set_ext_roam_params() - parse ext roam params
7020  * @hdd_ctx: HDD context
7021  * @data: ext roam params attribute payload
7022  * @data_len: length of @data
7023  * @vdev_id: vdev id
7024  * @rso_config: roam params
7025  * @rso_usr_cfg: roam userspace params
7026  *
7027  * Return: 0 on success; error number on failure
7028  */
hdd_set_ext_roam_params(struct hdd_context * hdd_ctx,const void * data,int data_len,uint8_t vdev_id,struct rso_config_params * rso_config,struct rso_user_config * rso_usr_cfg)7029 static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
7030 				   const void *data, int data_len,
7031 				   uint8_t vdev_id,
7032 				   struct rso_config_params *rso_config,
7033 				   struct rso_user_config *rso_usr_cfg)
7034 {
7035 	uint32_t cmd_type, req_id;
7036 	struct nlattr *tb[MAX_ROAMING_PARAM + 1];
7037 	int ret;
7038 	mac_handle_t mac_handle;
7039 
7040 	if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
7041 				    wlan_hdd_set_roam_param_policy)) {
7042 		hdd_err("Invalid ATTR");
7043 		return -EINVAL;
7044 	}
7045 	/* Parse and fetch Command Type */
7046 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
7047 		hdd_err("roam cmd type failed");
7048 		goto fail;
7049 	}
7050 
7051 	cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
7052 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
7053 		hdd_err("attr request id failed");
7054 		goto fail;
7055 	}
7056 	mac_handle = hdd_ctx->mac_handle;
7057 	req_id = nla_get_u32(
7058 		tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
7059 	hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
7060 	switch (cmd_type) {
7061 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST:
7062 		ret = hdd_set_allow_list(hdd_ctx, rso_config, tb, vdev_id,
7063 					 rso_usr_cfg);
7064 		if (ret)
7065 			goto fail;
7066 		break;
7067 
7068 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
7069 		/* Parse and fetch 5G Boost Threshold */
7070 		if (!tb[PARAM_A_BAND_BOOST_THLD]) {
7071 			hdd_err("5G boost threshold failed");
7072 			goto fail;
7073 		}
7074 		rso_config->raise_rssi_thresh_5g = nla_get_s32(
7075 			tb[PARAM_A_BAND_BOOST_THLD]);
7076 		hdd_debug("5G Boost Threshold (%d)",
7077 			rso_config->raise_rssi_thresh_5g);
7078 		/* Parse and fetch 5G Penalty Threshold */
7079 		if (!tb[PARAM_A_BAND_PELT_THLD]) {
7080 			hdd_err("5G penalty threshold failed");
7081 			goto fail;
7082 		}
7083 		rso_config->drop_rssi_thresh_5g = nla_get_s32(
7084 			tb[PARAM_A_BAND_PELT_THLD]);
7085 		hdd_debug("5G Penalty Threshold (%d)",
7086 			rso_config->drop_rssi_thresh_5g);
7087 		/* Parse and fetch 5G Boost Factor */
7088 		if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
7089 			hdd_err("5G boost Factor failed");
7090 			goto fail;
7091 		}
7092 		rso_config->raise_factor_5g = nla_get_u32(
7093 			tb[PARAM_A_BAND_BOOST_FACTOR]);
7094 		hdd_debug("5G Boost Factor (%d)",
7095 			rso_config->raise_factor_5g);
7096 		/* Parse and fetch 5G Penalty factor */
7097 		if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
7098 			hdd_err("5G Penalty Factor failed");
7099 			goto fail;
7100 		}
7101 		rso_config->drop_factor_5g = nla_get_u32(
7102 			tb[PARAM_A_BAND_PELT_FACTOR]);
7103 		hdd_debug("5G Penalty factor (%d)",
7104 			rso_config->drop_factor_5g);
7105 		/* Parse and fetch 5G Max Boost */
7106 		if (!tb[PARAM_A_BAND_MAX_BOOST]) {
7107 			hdd_err("5G Max Boost failed");
7108 			goto fail;
7109 		}
7110 		rso_config->max_raise_rssi_5g = nla_get_u32(
7111 			tb[PARAM_A_BAND_MAX_BOOST]);
7112 		hdd_debug("5G Max Boost (%d)",
7113 			rso_config->max_raise_rssi_5g);
7114 		/* Parse and fetch Rssi Diff */
7115 		if (!tb[PARAM_ROAM_HISTERESYS]) {
7116 			hdd_err("Rssi Diff failed");
7117 			goto fail;
7118 		}
7119 		rso_config->rssi_diff = nla_get_s32(
7120 			tb[PARAM_ROAM_HISTERESYS]);
7121 		hdd_debug("RSSI Diff (%d)",
7122 			rso_config->rssi_diff);
7123 		/* Parse and fetch Alert Rssi Threshold */
7124 		if (!tb[PARAM_RSSI_TRIGGER]) {
7125 			hdd_err("Alert Rssi Threshold failed");
7126 			goto fail;
7127 		}
7128 		rso_config->alert_rssi_threshold = nla_get_u32(
7129 			tb[PARAM_RSSI_TRIGGER]);
7130 		hdd_debug("Alert RSSI Threshold (%d)",
7131 			rso_config->alert_rssi_threshold);
7132 		sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
7133 				       REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
7134 		break;
7135 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM:
7136 		/* Parse and fetch Activate Good Rssi Roam */
7137 		if (!tb[PARAM_ROAM_ENABLE]) {
7138 			hdd_err("Activate Good Rssi Roam failed");
7139 			goto fail;
7140 		}
7141 		rso_config->good_rssi_roam = nla_get_s32(
7142 			tb[PARAM_ROAM_ENABLE]);
7143 		hdd_debug("Activate Good Rssi Roam (%d)",
7144 			  rso_config->good_rssi_roam);
7145 		sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
7146 				       REASON_ROAM_GOOD_RSSI_CHANGED);
7147 		break;
7148 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS:
7149 		ret = hdd_set_bssid_prefs(hdd_ctx, rso_config, tb, vdev_id);
7150 		if (ret)
7151 			goto fail;
7152 		break;
7153 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID:
7154 		ret = hdd_set_denylist_bssid(hdd_ctx, rso_config, tb, vdev_id);
7155 		if (ret)
7156 			goto fail;
7157 		break;
7158 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET:
7159 		ret = hdd_set_roam_with_control_config(hdd_ctx, tb, vdev_id);
7160 		if (ret)
7161 			goto fail;
7162 		break;
7163 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR:
7164 		ret = hdd_clear_roam_control_config(hdd_ctx, tb, vdev_id);
7165 		if (ret)
7166 			goto fail;
7167 		break;
7168 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET:
7169 		ret = hdd_get_roam_control_config(hdd_ctx, tb, vdev_id);
7170 		if (ret)
7171 			goto fail;
7172 		break;
7173 	}
7174 
7175 	return 0;
7176 
7177 fail:
7178 	return -EINVAL;
7179 }
7180 
7181 /**
7182  * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
7183  * @wiphy:                 The wiphy structure
7184  * @wdev:                  The wireless device
7185  * @data:                  Data passed by framework
7186  * @data_len:              Parameters to be configured passed as data
7187  *
7188  * The roaming related parameters are configured by the framework
7189  * using this interface.
7190  *
7191  * Return: Return either success or failure code.
7192  */
7193 static int
__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)7194 __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
7195 	struct wireless_dev *wdev, const void *data, int data_len)
7196 {
7197 	struct net_device *dev = wdev->netdev;
7198 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7199 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7200 	struct rso_config_params *rso_config;
7201 	struct rso_user_config *rso_usr_cfg = NULL;
7202 
7203 	int ret;
7204 
7205 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7206 		hdd_err("Command not allowed in FTM mode");
7207 		return -EPERM;
7208 	}
7209 
7210 	ret = wlan_hdd_validate_context(hdd_ctx);
7211 	if (ret)
7212 		return ret;
7213 
7214 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7215 		hdd_err("Driver Modules are closed");
7216 		return -EINVAL;
7217 	}
7218 
7219 	rso_config = qdf_mem_malloc(sizeof(*rso_config));
7220 	if (!rso_config)
7221 		return -ENOMEM;
7222 
7223 	rso_usr_cfg = qdf_mem_malloc(sizeof(*rso_usr_cfg));
7224 	if (!rso_usr_cfg)
7225 		return -ENOMEM;
7226 
7227 	ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
7228 				      adapter->deflink->vdev_id, rso_config,
7229 				      rso_usr_cfg);
7230 	qdf_mem_free(rso_config);
7231 	qdf_mem_free(rso_usr_cfg);
7232 
7233 	if (ret)
7234 		goto fail;
7235 
7236 	return 0;
7237 fail:
7238 	return ret;
7239 }
7240 #undef PARAM_NUM_NW
7241 #undef PARAM_SET_BSSID
7242 #undef PARAM_SET_BSSID_HINT
7243 #undef PARAM_SSID_LIST
7244 #undef PARAM_LIST_SSID
7245 #undef MAX_ROAMING_PARAM
7246 #undef PARAM_NUM_BSSID
7247 #undef PARAM_BSSID_PREFS
7248 #undef PARAM_ROAM_BSSID
7249 #undef PARAM_RSSI_MODIFIER
7250 #undef PARAMS_NUM_BSSID
7251 #undef PARAM_BSSID_PARAMS
7252 #undef PARAM_A_BAND_BOOST_THLD
7253 #undef PARAM_A_BAND_PELT_THLD
7254 #undef PARAM_A_BAND_BOOST_FACTOR
7255 #undef PARAM_A_BAND_PELT_FACTOR
7256 #undef PARAM_A_BAND_MAX_BOOST
7257 #undef PARAM_ROAM_HISTERESYS
7258 #undef PARAM_RSSI_TRIGGER
7259 #undef PARAM_ROAM_ENABLE
7260 
7261 
7262 /**
7263  * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
7264  * @wiphy:   pointer to wireless wiphy structure.
7265  * @wdev:    pointer to wireless_dev structure.
7266  * @data:    Pointer to the data to be passed via vendor interface
7267  * @data_len:Length of the data to be passed
7268  *
7269  * Return:   Return the Success or Failure code.
7270  */
7271 static int
wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)7272 wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
7273 				struct wireless_dev *wdev,
7274 				const void *data,
7275 				int data_len)
7276 {
7277 	int errno;
7278 	struct osif_vdev_sync *vdev_sync;
7279 
7280 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7281 	if (errno)
7282 		return errno;
7283 
7284 	errno = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
7285 							data, data_len);
7286 
7287 	osif_vdev_sync_op_stop(vdev_sync);
7288 
7289 	return errno;
7290 }
7291 
7292 #define RATEMASK_PARAMS_TYPE_MAX 4
7293 #define RATEMASK_PARAMS_BITMAP_MAX 16
7294 #define RATEMASK_PARAMS_MAX QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX
7295 const struct nla_policy wlan_hdd_set_ratemask_param_policy[
7296 			RATEMASK_PARAMS_MAX + 1] = {
7297 	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST] = {.type = NLA_NESTED},
7298 	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE] = {.type = NLA_U8},
7299 	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP] = {.type = NLA_BINARY,
7300 					.len = RATEMASK_PARAMS_BITMAP_MAX},
7301 };
7302 
7303 /**
7304  * hdd_set_ratemask_params() - parse ratemask params
7305  * @hdd_ctx: HDD context
7306  * @data: ratemask attribute payload
7307  * @data_len: length of @data
7308  * @vdev: vdev to modify
7309  *
7310  * Return: 0 on success; error number on failure
7311  */
hdd_set_ratemask_params(struct hdd_context * hdd_ctx,const void * data,int data_len,struct wlan_objmgr_vdev * vdev)7312 static int hdd_set_ratemask_params(struct hdd_context *hdd_ctx,
7313 				   const void *data, int data_len,
7314 				   struct wlan_objmgr_vdev *vdev)
7315 {
7316 	struct nlattr *tb[RATEMASK_PARAMS_MAX + 1];
7317 	struct nlattr *tb2[RATEMASK_PARAMS_MAX + 1];
7318 	struct nlattr *curr_attr;
7319 	int ret, rem;
7320 	struct config_ratemask_params rate_params[RATEMASK_PARAMS_TYPE_MAX];
7321 	uint8_t ratemask_type, num_ratemask = 0, len;
7322 	uint32_t bitmap[RATEMASK_PARAMS_BITMAP_MAX / 4];
7323 
7324 	ret = wlan_cfg80211_nla_parse(tb,
7325 				      RATEMASK_PARAMS_MAX,
7326 				      data, data_len,
7327 				      wlan_hdd_set_ratemask_param_policy);
7328 	if (ret) {
7329 		hdd_err("Invalid ATTR");
7330 		return -EINVAL;
7331 	}
7332 
7333 	if (!tb[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST]) {
7334 		hdd_err("ratemask array attribute not present");
7335 		return -EINVAL;
7336 	}
7337 
7338 	memset(rate_params, 0, (RATEMASK_PARAMS_TYPE_MAX *
7339 				sizeof(struct config_ratemask_params)));
7340 
7341 	nla_for_each_nested(curr_attr,
7342 			    tb[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST],
7343 			    rem) {
7344 		if (num_ratemask >= RATEMASK_PARAMS_TYPE_MAX) {
7345 			hdd_err("Exceeding ratemask_list_param_num value");
7346 			return -EINVAL;
7347 		}
7348 
7349 		if (wlan_cfg80211_nla_parse(
7350 				tb2, RATEMASK_PARAMS_MAX,
7351 				nla_data(curr_attr), nla_len(curr_attr),
7352 				wlan_hdd_set_ratemask_param_policy)) {
7353 			hdd_err("nla_parse failed");
7354 			return -EINVAL;
7355 		}
7356 
7357 		if (!tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE]) {
7358 			hdd_err("type attribute not present");
7359 			return -EINVAL;
7360 		}
7361 
7362 		if (!tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP]) {
7363 			hdd_err("bitmap attribute not present");
7364 			return -EINVAL;
7365 		}
7366 
7367 		ratemask_type =
7368 		 nla_get_u8(tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE]);
7369 		if (ratemask_type >= RATEMASK_PARAMS_TYPE_MAX) {
7370 			hdd_err("invalid ratemask type");
7371 			return -EINVAL;
7372 		}
7373 
7374 		len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP]);
7375 		qdf_mem_zero(bitmap, sizeof(bitmap));
7376 		nla_memcpy(bitmap,
7377 			   tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP],
7378 			   len);
7379 
7380 		hdd_debug("rate_type:%d, lower32 0x%x, lower32_2 0x%x, higher32 0x%x, higher32_2 0x%x",
7381 			  ratemask_type, bitmap[0], bitmap[1],
7382 			  bitmap[2], bitmap[3]);
7383 
7384 		rate_params[num_ratemask].type = ratemask_type;
7385 		rate_params[num_ratemask].lower32 = bitmap[0];
7386 		rate_params[num_ratemask].lower32_2 = bitmap[1];
7387 		rate_params[num_ratemask].higher32 = bitmap[2];
7388 		rate_params[num_ratemask].higher32_2 = bitmap[3];
7389 
7390 		num_ratemask += 1;
7391 	}
7392 
7393 	ret = ucfg_set_ratemask_params(vdev, num_ratemask, rate_params);
7394 	if (ret)
7395 		hdd_err("ucfg_set_ratemask_params failed");
7396 	return ret;
7397 }
7398 
7399 /**
7400  * __wlan_hdd_cfg80211_set_ratemask_config() - Ratemask parameters
7401  * @wiphy:                 The wiphy structure
7402  * @wdev:                  The wireless device
7403  * @data:                  Data passed by framework
7404  * @data_len:              Parameters to be configured passed as data
7405  *
7406  * The ratemask parameters are configured by the framework
7407  * using this interface.
7408  *
7409  * Return: Return either success or failure code.
7410  */
7411 static int
__wlan_hdd_cfg80211_set_ratemask_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)7412 __wlan_hdd_cfg80211_set_ratemask_config(struct wiphy *wiphy,
7413 					struct wireless_dev *wdev,
7414 					const void *data, int data_len)
7415 {
7416 	struct net_device *dev = wdev->netdev;
7417 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7418 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7419 	struct wlan_objmgr_vdev *vdev;
7420 	int ret;
7421 
7422 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7423 		hdd_err("Command not allowed in FTM mode");
7424 		return -EPERM;
7425 	}
7426 
7427 	ret = wlan_hdd_validate_context(hdd_ctx);
7428 	if (ret)
7429 		return ret;
7430 
7431 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7432 		hdd_err("Driver Modules are closed");
7433 		return -EINVAL;
7434 	}
7435 
7436 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
7437 					   WLAN_OSIF_POWER_ID);
7438 	if (!vdev) {
7439 		hdd_err("vdev not present");
7440 		return -EINVAL;
7441 	}
7442 
7443 	ret = hdd_set_ratemask_params(hdd_ctx, data, data_len, vdev);
7444 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
7445 	if (ret)
7446 		goto fail;
7447 
7448 	return 0;
7449 fail:
7450 	return ret;
7451 }
7452 
7453 /**
7454  * wlan_hdd_cfg80211_set_ratemask_config() - set ratemask config
7455  * @wiphy:   pointer to wireless wiphy structure.
7456  * @wdev:    pointer to wireless_dev structure.
7457  * @data:    Pointer to the data to be passed via vendor interface
7458  * @data_len:Length of the data to be passed
7459  *
7460  * Return:   Return the Success or Failure code.
7461  */
7462 static int
wlan_hdd_cfg80211_set_ratemask_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)7463 wlan_hdd_cfg80211_set_ratemask_config(struct wiphy *wiphy,
7464 				      struct wireless_dev *wdev,
7465 				      const void *data,
7466 				      int data_len)
7467 {
7468 	int errno;
7469 	struct osif_vdev_sync *vdev_sync;
7470 
7471 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7472 	if (errno)
7473 		return errno;
7474 
7475 	errno = __wlan_hdd_cfg80211_set_ratemask_config(wiphy, wdev,
7476 							data, data_len);
7477 
7478 	osif_vdev_sync_op_stop(vdev_sync);
7479 
7480 	return errno;
7481 }
7482 
7483 #define PWR_SAVE_FAIL_CMD_INDEX \
7484 	QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
7485 
hdd_chip_pwr_save_fail_detected_cb(hdd_handle_t hdd_handle,struct chip_pwr_save_fail_detected_params * data)7486 void hdd_chip_pwr_save_fail_detected_cb(hdd_handle_t hdd_handle,
7487 			struct chip_pwr_save_fail_detected_params
7488 			*data)
7489 {
7490 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
7491 	struct sk_buff *skb;
7492 	int flags = cds_get_gfp_flags();
7493 
7494 	hdd_enter();
7495 
7496 	if (wlan_hdd_validate_context(hdd_ctx))
7497 		return;
7498 
7499 	if (!data) {
7500 		hdd_debug("data is null");
7501 		return;
7502 	}
7503 
7504 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
7505 					       NLMSG_HDRLEN +
7506 					       sizeof(uint32_t) +
7507 					       NLMSG_HDRLEN,
7508 					       PWR_SAVE_FAIL_CMD_INDEX, flags);
7509 	if (!skb) {
7510 		hdd_info("wlan_cfg80211_vendor_event_alloc failed");
7511 		return;
7512 	}
7513 
7514 	hdd_debug("failure reason code: %u", data->failure_reason_code);
7515 
7516 	if (nla_put_u32(skb,
7517 		QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
7518 		data->failure_reason_code))
7519 		goto fail;
7520 
7521 	wlan_cfg80211_vendor_event(skb, flags);
7522 	hdd_exit();
7523 	return;
7524 
7525 fail:
7526 	wlan_cfg80211_vendor_free_skb(skb);
7527 }
7528 #undef PWR_SAVE_FAIL_CMD_INDEX
7529 
7530 const struct nla_policy
7531 wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
7532 				       +1] = {
7533 	[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
7534 };
7535 
7536 /**
7537  *  wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
7538  *  @hdd_ctx:      HDD context
7539  *  @device_mode:    device mode
7540  *  Return:         bool
7541  */
wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context * hdd_ctx,enum QDF_OPMODE device_mode)7542 static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
7543 						   enum QDF_OPMODE device_mode)
7544 {
7545 	struct hdd_adapter *adapter, *next_adapter = NULL;
7546 	struct hdd_ap_ctx *ap_ctx;
7547 	struct hdd_station_ctx *sta_ctx;
7548 	wlan_net_dev_ref_dbgid dbgid =
7549 				NET_DEV_HOLD_CHECK_DFS_CHANNEL_FOR_ADAPTER;
7550 	struct wlan_hdd_link_info *link_info;
7551 
7552 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
7553 					   dbgid) {
7554 		if (adapter->device_mode != device_mode)
7555 			goto next_adapter;
7556 
7557 		hdd_adapter_for_each_active_link_info(adapter, link_info) {
7558 			if (device_mode == QDF_SAP_MODE) {
7559 				ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
7560 				/*
7561 				 *  if there is SAP already running on
7562 				 *  DFS channel, do not disable scan on
7563 				 *  dfs channels. Note that with SAP on DFS,
7564 				 *  there cannot be conurrency on single radio.
7565 				 *  But then we can have multiple radios !!
7566 				 *
7567 				 *  Indoor channels are also marked DFS,
7568 				 *  therefore check if the channel has
7569 				 *  REGULATORY_CHAN_RADAR channel flag to
7570 				 *  identify if the channel is DFS
7571 				 */
7572 				if (wlan_reg_is_dfs_for_freq(
7573 						hdd_ctx->pdev,
7574 						ap_ctx->operating_chan_freq)) {
7575 					hdd_err("SAP running on DFS channel");
7576 					hdd_adapter_dev_put_debug(adapter,
7577 								  dbgid);
7578 					if (next_adapter)
7579 						hdd_adapter_dev_put_debug(
7580 								next_adapter,
7581 								dbgid);
7582 					return true;
7583 				}
7584 			}
7585 
7586 			if (device_mode == QDF_STA_MODE) {
7587 				sta_ctx =
7588 					WLAN_HDD_GET_STATION_CTX_PTR(link_info);
7589 				/*
7590 				 *  if STA is already connected on DFS channel,
7591 				 *  do not disable scan on dfs channels.
7592 				 *
7593 				 *  Indoor channels are also marked DFS,
7594 				 *  therefore check if the channel has
7595 				 *  REGULATORY_CHAN_RADAR channel flag to
7596 				 *  identify if the channel is DFS
7597 				 */
7598 				if (hdd_cm_is_vdev_associated(link_info) &&
7599 				    wlan_reg_is_dfs_for_freq(
7600 					    hdd_ctx->pdev,
7601 					    sta_ctx->conn_info.chan_freq)) {
7602 					hdd_err("client connected on DFS channel");
7603 					hdd_adapter_dev_put_debug(adapter,
7604 								  dbgid);
7605 					if (next_adapter)
7606 						hdd_adapter_dev_put_debug(
7607 								next_adapter,
7608 								dbgid);
7609 					return true;
7610 				}
7611 			}
7612 		}
7613 next_adapter:
7614 		hdd_adapter_dev_put_debug(adapter, dbgid);
7615 	}
7616 
7617 	return false;
7618 }
7619 
7620 /**
7621  * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
7622  * @hdd_ctx: HDD context within host driver
7623  * @enable_dfs_channels: If true, DFS channels can be used for scanning
7624  *
7625  * Loops through devices to see who is operating on DFS channels
7626  * and then disables/enables DFS channels.
7627  * Fails the disable request if any device is active on a DFS channel.
7628  *
7629  * Return: 0 or other error codes.
7630  */
7631 
wlan_hdd_enable_dfs_chan_scan(struct hdd_context * hdd_ctx,bool enable_dfs_channels)7632 int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
7633 				  bool enable_dfs_channels)
7634 {
7635 	QDF_STATUS status;
7636 	bool err;
7637 	mac_handle_t mac_handle;
7638 	bool enable_dfs_scan = true;
7639 
7640 	ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
7641 						&enable_dfs_scan);
7642 
7643 	if (enable_dfs_channels == enable_dfs_scan) {
7644 		hdd_debug("DFS channels are already %s",
7645 			  enable_dfs_channels ? "enabled" : "disabled");
7646 		return 0;
7647 	}
7648 
7649 	if (!enable_dfs_channels) {
7650 		err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
7651 							     QDF_STA_MODE);
7652 		if (err)
7653 			return -EOPNOTSUPP;
7654 
7655 		err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
7656 							     QDF_SAP_MODE);
7657 		if (err)
7658 			return -EOPNOTSUPP;
7659 	}
7660 
7661 	ucfg_scan_cfg_set_dfs_chan_scan_allowed(hdd_ctx->psoc,
7662 						enable_dfs_channels);
7663 
7664 	mac_handle = hdd_ctx->mac_handle;
7665 	status = sme_enable_dfs_chan_scan(mac_handle, enable_dfs_channels);
7666 	if (QDF_IS_STATUS_ERROR(status)) {
7667 		hdd_err("Failed to set DFS channel scan flag to %d",
7668 			enable_dfs_channels);
7669 		return qdf_status_to_os_return(status);
7670 	}
7671 
7672 	hdd_abort_mac_scan_all_adapters(hdd_ctx);
7673 
7674 	/* pass dfs channel status to regulatory component */
7675 	status = ucfg_reg_enable_dfs_channels(hdd_ctx->pdev,
7676 					      enable_dfs_channels);
7677 
7678 	if (QDF_IS_STATUS_ERROR(status))
7679 		hdd_err("Failed to %s DFS channels",
7680 			enable_dfs_channels ? "enable" : "disable");
7681 
7682 	return qdf_status_to_os_return(status);
7683 }
7684 
7685 /**
7686  *  __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
7687  *  @wiphy:          corestack handler
7688  *  @wdev:           wireless device
7689  *  @data:           data
7690  *  @data_len:       data length
7691  *  Return:         success(0) or reason code for failure
7692  */
__wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)7693 static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
7694 						     struct wireless_dev *wdev,
7695 						     const void *data,
7696 						     int data_len)
7697 {
7698 	struct net_device *dev = wdev->netdev;
7699 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
7700 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
7701 	int ret_val;
7702 	uint32_t no_dfs_flag = 0;
7703 	bool enable_dfs_scan = true;
7704 	hdd_enter_dev(dev);
7705 
7706 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7707 		hdd_err("Command not allowed in FTM mode");
7708 		return -EPERM;
7709 	}
7710 
7711 	ret_val = wlan_hdd_validate_context(hdd_ctx);
7712 	if (ret_val)
7713 		return ret_val;
7714 
7715 	if (wlan_cfg80211_nla_parse(tb,
7716 				    QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
7717 				    data, data_len,
7718 				    wlan_hdd_set_no_dfs_flag_config_policy)) {
7719 		hdd_err("invalid attr");
7720 		return -EINVAL;
7721 	}
7722 
7723 	if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
7724 		hdd_err("attr dfs flag failed");
7725 		return -EINVAL;
7726 	}
7727 
7728 	no_dfs_flag = nla_get_u32(
7729 		tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
7730 
7731 	hdd_debug("DFS flag: %d", no_dfs_flag);
7732 
7733 	if (no_dfs_flag > 1) {
7734 		hdd_err("invalid value of dfs flag");
7735 		return -EINVAL;
7736 	}
7737 	ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
7738 						&enable_dfs_scan);
7739 
7740 	if (enable_dfs_scan) {
7741 		ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
7742 	} else {
7743 		if ((!no_dfs_flag) != enable_dfs_scan) {
7744 			hdd_err("DFS chan ini configured %d, no dfs flag: %d",
7745 				enable_dfs_scan,
7746 				no_dfs_flag);
7747 			return -EINVAL;
7748 		}
7749 	}
7750 
7751 	return ret_val;
7752 }
7753 
7754 /**
7755  * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
7756  *
7757  * @wiphy: wiphy device pointer
7758  * @wdev: wireless device pointer
7759  * @data: Vendor command data buffer
7760  * @data_len: Buffer length
7761  *
7762  * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
7763  * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
7764  *
7765  * Return: EOK or other error codes.
7766  */
7767 
wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)7768 static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
7769 						   struct wireless_dev *wdev,
7770 						   const void *data,
7771 						   int data_len)
7772 {
7773 	struct osif_psoc_sync *psoc_sync;
7774 	int errno;
7775 
7776 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
7777 	if (errno)
7778 		return errno;
7779 
7780 	errno = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
7781 							  data, data_len);
7782 
7783 	osif_psoc_sync_op_stop(psoc_sync);
7784 
7785 	return errno;
7786 }
7787 
7788 const struct nla_policy
7789 wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
7790 	[QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
7791 };
7792 
7793 /**
7794  * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
7795  * @wiphy: wiphy device pointer
7796  * @wdev: wireless device pointer
7797  * @data: Vendor command data buffer
7798  * @data_len: Buffer length
7799  *
7800  * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
7801  * setup WISA Mode features.
7802  *
7803  * Return: Success(0) or reason code for failure
7804  */
__wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)7805 static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
7806 		struct wireless_dev *wdev, const void *data, int data_len)
7807 {
7808 	struct net_device *dev = wdev->netdev;
7809 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7810 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
7811 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
7812 	struct sir_wisa_params wisa;
7813 	int ret_val;
7814 	QDF_STATUS status;
7815 	bool wisa_mode;
7816 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
7817 	mac_handle_t mac_handle;
7818 
7819 	hdd_enter_dev(dev);
7820 	ret_val = wlan_hdd_validate_context(hdd_ctx);
7821 	if (ret_val)
7822 		goto err;
7823 
7824 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7825 		hdd_err("Command not allowed in FTM mode");
7826 		return -EPERM;
7827 	}
7828 
7829 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
7830 				    data_len, wlan_hdd_wisa_cmd_policy)) {
7831 		hdd_err("Invalid WISA cmd attributes");
7832 		ret_val = -EINVAL;
7833 		goto err;
7834 	}
7835 	if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
7836 		hdd_err("Invalid WISA mode");
7837 		ret_val = -EINVAL;
7838 		goto err;
7839 	}
7840 
7841 	wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
7842 	hdd_debug("WISA Mode: %d", wisa_mode);
7843 	wisa.mode = wisa_mode;
7844 	wisa.vdev_id = adapter->deflink->vdev_id;
7845 	mac_handle = hdd_ctx->mac_handle;
7846 	status = sme_set_wisa_params(mac_handle, &wisa);
7847 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7848 		hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
7849 		ret_val = -EINVAL;
7850 	}
7851 	if (QDF_IS_STATUS_SUCCESS(status) || !wisa_mode)
7852 		cdp_set_wisa_mode(soc, adapter->deflink->vdev_id, wisa_mode);
7853 err:
7854 	hdd_exit();
7855 	return ret_val;
7856 }
7857 
7858 /**
7859  * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
7860  * @wiphy:          corestack handler
7861  * @wdev:           wireless device
7862  * @data:           data
7863  * @data_len:       data length
7864  *
7865  * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
7866  * setup WISA mode features.
7867  *
7868  * Return: Success(0) or reason code for failure
7869  */
wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)7870 static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
7871 						   struct wireless_dev *wdev,
7872 						   const void *data,
7873 						   int data_len)
7874 {
7875 	int errno;
7876 	struct osif_vdev_sync *vdev_sync;
7877 
7878 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7879 	if (errno)
7880 		return errno;
7881 
7882 	errno = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev,
7883 						    data, data_len);
7884 
7885 	osif_vdev_sync_op_stop(vdev_sync);
7886 
7887 	return errno;
7888 }
7889 
hdd_get_stainfo(struct hdd_station_info * astainfo,struct qdf_mac_addr mac_addr)7890 struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
7891 					 struct qdf_mac_addr mac_addr)
7892 {
7893 	struct hdd_station_info *stainfo = NULL;
7894 	int i;
7895 
7896 	for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
7897 		if (!qdf_mem_cmp(&astainfo[i].sta_mac,
7898 				 &mac_addr,
7899 				 QDF_MAC_ADDR_SIZE)) {
7900 			stainfo = &astainfo[i];
7901 			break;
7902 		}
7903 	}
7904 
7905 	return stainfo;
7906 }
7907 
7908 /*
7909  * undef short names defined for get station command
7910  * used by __wlan_hdd_cfg80211_get_station_cmd()
7911  */
7912 #undef STATION_INVALID
7913 #undef STATION_INFO
7914 #undef STATION_ASSOC_FAIL_REASON
7915 #undef STATION_REMOTE
7916 #undef STATION_MAX
7917 #undef LINK_INFO_STANDARD_NL80211_ATTR
7918 #undef AP_INFO_STANDARD_NL80211_ATTR
7919 #undef INFO_ROAM_COUNT
7920 #undef INFO_AKM
7921 #undef WLAN802_11_MODE
7922 #undef AP_INFO_HS20_INDICATION
7923 #undef HT_OPERATION
7924 #undef VHT_OPERATION
7925 #undef INFO_ASSOC_FAIL_REASON
7926 #undef REMOTE_MAX_PHY_RATE
7927 #undef REMOTE_TX_PACKETS
7928 #undef REMOTE_TX_BYTES
7929 #undef REMOTE_RX_PACKETS
7930 #undef REMOTE_RX_BYTES
7931 #undef REMOTE_LAST_TX_RATE
7932 #undef REMOTE_LAST_RX_RATE
7933 #undef REMOTE_WMM
7934 #undef REMOTE_SUPPORTED_MODE
7935 #undef REMOTE_AMPDU
7936 #undef REMOTE_TX_STBC
7937 #undef REMOTE_RX_STBC
7938 #undef REMOTE_CH_WIDTH
7939 #undef REMOTE_SGI_ENABLE
7940 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
7941 #undef REMOTE_PAD
7942 #endif
7943 
7944 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
7945 /**
7946  * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
7947  * @wiphy: pointer to wireless wiphy structure.
7948  * @wdev: pointer to wireless_dev structure.
7949  * @data: Pointer to the Key data
7950  * @data_len:Length of the data passed
7951  *
7952  * This is called when wlan driver needs to save the keys received via
7953  * vendor specific command.
7954  *
7955  * Return: Return the Success or Failure code.
7956  */
__wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)7957 static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
7958 					       struct wireless_dev *wdev,
7959 					       const void *data, int data_len)
7960 {
7961 	struct net_device *dev = wdev->netdev;
7962 	struct hdd_adapter *hdd_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7963 	struct hdd_context *hdd_ctx;
7964 	struct hdd_station_ctx *sta_ctx =
7965 			WLAN_HDD_GET_STATION_CTX_PTR(hdd_adapter->deflink);
7966 	struct wlan_crypto_pmksa pmksa;
7967 	int status;
7968 	mac_handle_t mac_handle;
7969 
7970 	hdd_enter_dev(dev);
7971 
7972 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7973 		hdd_err("Command not allowed in FTM mode");
7974 		return -EPERM;
7975 	}
7976 
7977 	if ((!data) || (data_len <= 0) ||
7978 	    (data_len > MAX_PMK_LEN)) {
7979 		hdd_err("Invalid data");
7980 		return -EINVAL;
7981 	}
7982 
7983 	hdd_ctx = WLAN_HDD_GET_CTX(hdd_adapter);
7984 	if (!hdd_ctx) {
7985 		hdd_err("HDD context is null");
7986 		return -EINVAL;
7987 	}
7988 
7989 	status = wlan_hdd_validate_context(hdd_ctx);
7990 	if (status)
7991 		return status;
7992 
7993 	mac_handle = hdd_ctx->mac_handle;
7994 	qdf_mem_zero(&pmksa, sizeof(pmksa));
7995 	pmksa.pmk_len = data_len;
7996 	qdf_mem_copy(pmksa.pmk, data, data_len);
7997 
7998 	qdf_mem_copy(&pmksa.bssid, &sta_ctx->conn_info.bssid,
7999 		     QDF_MAC_ADDR_SIZE);
8000 
8001 	sme_roam_set_psk_pmk(mac_handle, &pmksa,
8002 			     hdd_adapter->deflink->vdev_id, true);
8003 	qdf_mem_zero(&pmksa, sizeof(pmksa));
8004 	return 0;
8005 }
8006 
8007 /**
8008  * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
8009  * @wiphy:   pointer to wireless wiphy structure.
8010  * @wdev:    pointer to wireless_dev structure.
8011  * @data:    Pointer to the Key data
8012  * @data_len:Length of the data passed
8013  *
8014  * This is called when wlan driver needs to save the keys received via
8015  * vendor specific command.
8016  *
8017  * Return:   Return the Success or Failure code.
8018  */
wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)8019 static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
8020 					     struct wireless_dev *wdev,
8021 					     const void *data, int data_len)
8022 {
8023 	int errno;
8024 	struct osif_vdev_sync *vdev_sync;
8025 
8026 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
8027 	if (errno)
8028 		return errno;
8029 
8030 	errno = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev,
8031 						    data, data_len);
8032 
8033 	osif_vdev_sync_op_stop(vdev_sync);
8034 
8035 	return errno;
8036 }
8037 #endif
8038 
8039 const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
8040 			QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
8041 	[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
8042 	[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
8043 	[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
8044 };
8045 
8046 /**
8047  * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
8048  * @wiphy:   pointer to wireless wiphy structure.
8049  * @wdev:    pointer to wireless_dev structure.
8050  * @data:    Pointer to the data to be passed via vendor interface
8051  * @data_len:Length of the data to be passed
8052  *
8053  * This is called when wlan driver needs to send wifi driver related info
8054  * (driver/fw version) to the user space application upon request.
8055  *
8056  * Return:   Return the Success or Failure code.
8057  */
8058 static int
__wlan_hdd_cfg80211_get_wifi_info(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)8059 __wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
8060 				  struct wireless_dev *wdev,
8061 				  const void *data, int data_len)
8062 {
8063 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
8064 	struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
8065 	uint8_t *firmware_version = NULL;
8066 	int status;
8067 	struct sk_buff *reply_skb;
8068 	uint32_t skb_len = 0;
8069 	struct pld_soc_info info;
8070 	bool stt_flag = false;
8071 
8072 	hdd_enter_dev(wdev->netdev);
8073 
8074 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8075 		hdd_err("Command not allowed in FTM mode");
8076 		return -EPERM;
8077 	}
8078 
8079 	status = wlan_hdd_validate_context(hdd_ctx);
8080 	if (status)
8081 		return status;
8082 
8083 	if (wlan_cfg80211_nla_parse(tb_vendor,
8084 				    QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
8085 				    data, data_len,
8086 				    qca_wlan_vendor_get_wifi_info_policy)) {
8087 		hdd_err("WIFI_INFO_GET NL CMD parsing failed");
8088 		return -EINVAL;
8089 	}
8090 
8091 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
8092 		hdd_debug("Rcvd req for Driver version");
8093 		skb_len += nla_total_size(strlen(QWLAN_VERSIONSTR) + 1);
8094 	}
8095 
8096 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
8097 		hdd_debug("Rcvd req for FW version");
8098 		if (!pld_get_soc_info(hdd_ctx->parent_dev, &info))
8099 			stt_flag = true;
8100 
8101 		firmware_version = qdf_mem_malloc(SIR_VERSION_STRING_LEN);
8102 		if (!firmware_version)
8103 			return -ENOMEM;
8104 
8105 		snprintf(firmware_version, SIR_VERSION_STRING_LEN,
8106 			 "FW:%d.%d.%d.%d.%d.%d HW:%s STT:%s",
8107 			 hdd_ctx->fw_version_info.major_spid,
8108 			 hdd_ctx->fw_version_info.minor_spid,
8109 			 hdd_ctx->fw_version_info.siid,
8110 			 hdd_ctx->fw_version_info.rel_id,
8111 			 hdd_ctx->fw_version_info.crmid,
8112 			 hdd_ctx->fw_version_info.sub_id,
8113 			 hdd_ctx->target_hw_name,
8114 			 (stt_flag ? info.fw_build_id : " "));
8115 		skb_len += nla_total_size(strlen(firmware_version) + 1);
8116 	}
8117 
8118 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
8119 		hdd_debug("Rcvd req for Radio index");
8120 		skb_len += nla_total_size(sizeof(uint32_t));
8121 	}
8122 
8123 	if (!skb_len) {
8124 		hdd_err("unknown attribute in get_wifi_info request");
8125 		qdf_mem_free(firmware_version);
8126 		return -EINVAL;
8127 	}
8128 
8129 	skb_len += NLMSG_HDRLEN;
8130 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
8131 	if (!reply_skb) {
8132 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
8133 		qdf_mem_free(firmware_version);
8134 		return -ENOMEM;
8135 	}
8136 
8137 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
8138 		if (nla_put_string(reply_skb,
8139 			    QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
8140 			    QWLAN_VERSIONSTR))
8141 			goto error_nla_fail;
8142 	}
8143 
8144 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
8145 		if (nla_put_string(reply_skb,
8146 			    QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
8147 			    firmware_version))
8148 			goto error_nla_fail;
8149 	}
8150 
8151 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
8152 		if (nla_put_u32(reply_skb,
8153 				QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
8154 				hdd_ctx->radio_index))
8155 			goto error_nla_fail;
8156 	}
8157 
8158 	qdf_mem_free(firmware_version);
8159 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
8160 
8161 error_nla_fail:
8162 	hdd_err("nla put fail");
8163 	qdf_mem_free(firmware_version);
8164 	wlan_cfg80211_vendor_free_skb(reply_skb);
8165 	return -EINVAL;
8166 }
8167 
8168 /**
8169  * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
8170  * @wiphy:   pointer to wireless wiphy structure.
8171  * @wdev:    pointer to wireless_dev structure.
8172  * @data:    Pointer to the data to be passed via vendor interface
8173  * @data_len:Length of the data to be passed
8174  *
8175  * This is called when wlan driver needs to send wifi driver related info
8176  * (driver/fw version) to the user space application upon request.
8177  *
8178  * Return:   Return the Success or Failure code.
8179  */
8180 static int
wlan_hdd_cfg80211_get_wifi_info(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)8181 wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
8182 		struct wireless_dev *wdev,
8183 		const void *data, int data_len)
8184 {
8185 	struct osif_psoc_sync *psoc_sync;
8186 	int errno;
8187 
8188 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
8189 	if (errno)
8190 		return errno;
8191 
8192 	errno = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
8193 
8194 	osif_psoc_sync_op_stop(psoc_sync);
8195 
8196 	return errno;
8197 }
8198 
8199 const struct nla_policy get_logger_set_policy[
8200 			QCA_WLAN_VENDOR_ATTR_LOGGER_MAX + 1] = {
8201 	[QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED] = {.type = NLA_U32},
8202 };
8203 
8204 /**
8205  * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
8206  * @wiphy:   pointer to wireless wiphy structure.
8207  * @wdev:    pointer to wireless_dev structure.
8208  * @data:    Pointer to the data to be passed via vendor interface
8209  * @data_len:Length of the data to be passed
8210  *
8211  * This is called by userspace to know the supported logger features
8212  *
8213  * Return:   Return the Success or Failure code.
8214  */
8215 static int
__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)8216 __wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
8217 		struct wireless_dev *wdev,
8218 		const void *data, int data_len)
8219 {
8220 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
8221 	int status;
8222 	uint32_t features;
8223 	struct sk_buff *reply_skb = NULL;
8224 	bool enable_ring_buffer;
8225 
8226 	hdd_enter_dev(wdev->netdev);
8227 
8228 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8229 		hdd_err("Command not allowed in FTM mode");
8230 		return -EPERM;
8231 	}
8232 
8233 	status = wlan_hdd_validate_context(hdd_ctx);
8234 	if (status)
8235 		return status;
8236 
8237 	features = 0;
8238 	wlan_mlme_get_status_ring_buffer(hdd_ctx->psoc, &enable_ring_buffer);
8239 	if (enable_ring_buffer) {
8240 		features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
8241 		features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
8242 		features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
8243 		features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
8244 		features |= WIFI_LOGGER_PACKET_FATE_SUPPORTED;
8245 		hdd_debug("Supported logger features: 0x%0x", features);
8246 	} else {
8247 		hdd_info("Ring buffer disable");
8248 	}
8249 
8250 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
8251 							     sizeof(uint32_t) +
8252 							     NLA_HDRLEN +
8253 							     NLMSG_HDRLEN);
8254 	if (!reply_skb) {
8255 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
8256 		return -ENOMEM;
8257 	}
8258 
8259 	if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
8260 				   features)) {
8261 		hdd_err("nla put fail");
8262 		wlan_cfg80211_vendor_free_skb(reply_skb);
8263 		return -EINVAL;
8264 	}
8265 
8266 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
8267 }
8268 
8269 /**
8270  * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
8271  * @wiphy:   pointer to wireless wiphy structure.
8272  * @wdev:    pointer to wireless_dev structure.
8273  * @data:    Pointer to the data to be passed via vendor interface
8274  * @data_len:Length of the data to be passed
8275  *
8276  * This is called by userspace to know the supported logger features
8277  *
8278  * Return:   Return the Success or Failure code.
8279  */
8280 static int
wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)8281 wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
8282 		struct wireless_dev *wdev,
8283 		const void *data, int data_len)
8284 {
8285 	struct osif_psoc_sync *psoc_sync;
8286 	int errno;
8287 
8288 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
8289 	if (errno)
8290 		return errno;
8291 
8292 	errno = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
8293 							    data, data_len);
8294 
8295 	osif_psoc_sync_op_stop(psoc_sync);
8296 
8297 	return errno;
8298 }
8299 
8300 #ifdef WLAN_FEATURE_GTK_OFFLOAD
wlan_hdd_save_gtk_offload_params(struct hdd_adapter * adapter,uint8_t * kck_ptr,uint8_t kck_len,uint8_t * kek_ptr,uint32_t kek_len,uint8_t * replay_ctr,bool big_endian)8301 void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
8302 				      uint8_t *kck_ptr, uint8_t kck_len,
8303 				      uint8_t *kek_ptr, uint32_t kek_len,
8304 				      uint8_t *replay_ctr, bool big_endian)
8305 {
8306 	struct hdd_station_ctx *hdd_sta_ctx;
8307 	uint8_t *buf;
8308 	int i;
8309 	struct pmo_gtk_req *gtk_req = NULL;
8310 	struct wlan_objmgr_vdev *vdev;
8311 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
8312 	struct hdd_context *hdd_ctx =  WLAN_HDD_GET_CTX(adapter);
8313 
8314 	gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
8315 	if (!gtk_req)
8316 		return;
8317 
8318 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
8319 	if (kck_ptr) {
8320 		if (kck_len > sizeof(gtk_req->kck)) {
8321 			kck_len = sizeof(gtk_req->kck);
8322 			QDF_ASSERT(0);
8323 		}
8324 		qdf_mem_copy(gtk_req->kck, kck_ptr, kck_len);
8325 		gtk_req->kck_len = kck_len;
8326 	}
8327 
8328 	if (kek_ptr) {
8329 		/* paranoia */
8330 		if (kek_len > sizeof(gtk_req->kek)) {
8331 			kek_len = sizeof(gtk_req->kek);
8332 			QDF_ASSERT(0);
8333 		}
8334 		qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
8335 	}
8336 
8337 	qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssid);
8338 
8339 	gtk_req->kek_len = kek_len;
8340 	gtk_req->is_fils_connection = hdd_is_fils_connection(hdd_ctx, adapter);
8341 
8342 	/* convert big to little endian since driver work on little endian */
8343 	buf = (uint8_t *)&gtk_req->replay_counter;
8344 	for (i = 0; i < 8; i++)
8345 		buf[7 - i] = replay_ctr[i];
8346 
8347 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
8348 					   WLAN_OSIF_POWER_ID);
8349 	if (!vdev)
8350 		goto end;
8351 	status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
8352 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
8353 	if (status != QDF_STATUS_SUCCESS)
8354 		hdd_err("Failed to cache GTK Offload");
8355 
8356 end:
8357 	qdf_mem_free(gtk_req);
8358 }
8359 #endif
8360 
8361 #ifdef WLAN_CFR_ENABLE
hdd_cfr_data_send_nl_event(uint8_t vdev_id,uint32_t pid,const void * data,uint32_t data_len)8362 void hdd_cfr_data_send_nl_event(uint8_t vdev_id, uint32_t pid,
8363 				const void *data, uint32_t data_len)
8364 {
8365 	uint32_t len, ret;
8366 	struct sk_buff *vendor_event;
8367 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8368 	struct wlan_hdd_link_info *link_info;
8369 	struct nlmsghdr *nlhdr;
8370 
8371 	if (!hdd_ctx) {
8372 		hdd_err("HDD context is NULL");
8373 		return;
8374 	}
8375 
8376 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
8377 	if (!link_info) {
8378 		hdd_err("adapter NULL for vdev id %d", vdev_id);
8379 		return;
8380 	}
8381 
8382 	hdd_debug("vdev id %d pid %d data len %d", vdev_id, pid, data_len);
8383 	len = nla_total_size(data_len) + NLMSG_HDRLEN;
8384 	vendor_event = wlan_cfg80211_vendor_event_alloc(
8385 			hdd_ctx->wiphy, &link_info->adapter->wdev, len,
8386 			QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG_INDEX,
8387 			qdf_mem_malloc_flags());
8388 
8389 	if (!vendor_event) {
8390 		hdd_err("wlan_cfg80211_vendor_event_alloc failed vdev id %d, data len %d",
8391 			vdev_id, data_len);
8392 		return;
8393 	}
8394 
8395 	ret = nla_put(vendor_event,
8396 		      QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA,
8397 		      data_len, data);
8398 	if (ret) {
8399 		hdd_err("CFR event put fails status %d", ret);
8400 		wlan_cfg80211_vendor_free_skb(vendor_event);
8401 		return;
8402 	}
8403 
8404 	if (pid) {
8405 		nlhdr = nlmsg_hdr(vendor_event);
8406 		if (nlhdr)
8407 			nlhdr->nlmsg_pid = pid;
8408 		else
8409 			hdd_err_rl("nlhdr is null");
8410 	}
8411 
8412 	wlan_cfg80211_vendor_event(vendor_event, qdf_mem_malloc_flags());
8413 }
8414 #endif
8415 
8416 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
hdd_send_roam_scan_ch_list_event(struct hdd_context * hdd_ctx,uint8_t vdev_id,uint16_t buf_len,uint8_t * buf)8417 void hdd_send_roam_scan_ch_list_event(struct hdd_context *hdd_ctx,
8418 				      uint8_t vdev_id, uint16_t buf_len,
8419 				      uint8_t *buf)
8420 {
8421 	struct sk_buff *vendor_event;
8422 	uint32_t len, ret;
8423 	struct wlan_hdd_link_info *link_info;
8424 
8425 	if (!hdd_ctx) {
8426 		hdd_err_rl("hdd context is null");
8427 		return;
8428 	}
8429 
8430 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
8431 	if (!link_info)
8432 		return;
8433 
8434 	len = nla_total_size(buf_len) + NLMSG_HDRLEN;
8435 	vendor_event =
8436 		wlan_cfg80211_vendor_event_alloc(
8437 			hdd_ctx->wiphy, &link_info->adapter->wdev, len,
8438 			QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX,
8439 			GFP_KERNEL);
8440 
8441 	if (!vendor_event) {
8442 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
8443 		return;
8444 	}
8445 
8446 	ret = nla_put(vendor_event,
8447 		      QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_CONNECT_CHANNELS,
8448 		      buf_len, buf);
8449 	if (ret) {
8450 		hdd_err("OEM event put fails status %d", ret);
8451 		wlan_cfg80211_vendor_free_skb(vendor_event);
8452 		return;
8453 	}
8454 
8455 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8456 }
8457 #endif
8458 
8459 #define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
8460 	((1 << 26) | \
8461 	 (((probe_period) & 0x1fff) << 13) | \
8462 	 ((stay_period) & 0x1fff))
8463 
8464 #define ANT_DIV_SET_SNR_DIFF(snr_diff) \
8465 	((1 << 27) | \
8466 	 ((snr_diff) & 0x1fff))
8467 
8468 #define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
8469 	((1 << 28) | \
8470 	 ((probe_dwell_time) & 0x1fff))
8471 
8472 #define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
8473 	((1 << 29) | \
8474 	 (((mgmt_snr_weight) & 0xff) << 16) | \
8475 	 (((data_snr_weight) & 0xff) << 8) | \
8476 	 ((ack_snr_weight) & 0xff))
8477 
8478 #define RX_REORDER_TIMEOUT_VOICE \
8479 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
8480 #define RX_REORDER_TIMEOUT_VIDEO \
8481 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
8482 #define RX_REORDER_TIMEOUT_BESTEFFORT \
8483 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
8484 #define RX_REORDER_TIMEOUT_BACKGROUND \
8485 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
8486 #define RX_BLOCKSIZE_PEER_MAC \
8487 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
8488 #define RX_BLOCKSIZE_WINLIMIT \
8489 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
8490 
8491 #define CONFIG_CHANNEL_WIDTH \
8492 	QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH
8493 #define CONFIG_MLO_LINK_ID \
8494 	QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID
8495 #define CONFIG_MLO_LINKS \
8496 	QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS
8497 
8498 const struct nla_policy wlan_hdd_wifi_config_policy[
8499 			QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
8500 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS] = {
8501 							.type = NLA_U32},
8502 	[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES] = {.type = NLA_BINARY},
8503 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND] = {.type = NLA_U32},
8504 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_VALUE] = {.type = NLA_U32},
8505 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA] = {.type = NLA_BINARY,
8506 						      .len = 5000 },
8507 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH] = {.type = NLA_U32},
8508 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS] = {.type = NLA_U32},
8509 	[QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX] = {.type = NLA_U32},
8510 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE] = {
8511 		.type = NLA_U32},
8512 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO] = {
8513 		.type = NLA_U32},
8514 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT] = {
8515 		.type = NLA_U32},
8516 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND] = {
8517 		.type = NLA_U32},
8518 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC] =
8519 		VENDOR_NLA_POLICY_MAC_ADDR,
8520 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT] = {
8521 		.type = NLA_U32},
8522 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24] = {
8523 		.type = NLA_U8},
8524 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5] = {
8525 		.type = NLA_U8},
8526 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {
8527 		.type = NLA_U8},
8528 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL] = {.type = NLA_U8},
8529 	[QCA_WLAN_VENDOR_ATTR_CONF_TX_RATE] = {.type = NLA_U16},
8530 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM] = {.type = NLA_U32 },
8531 	[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED] = {
8532 		.type = NLA_U8},
8533 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS] = {.type = NLA_U8 },
8534 	[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
8535 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
8536 	[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
8537 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
8538 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
8539 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
8540 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
8541 	[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
8542 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
8543 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
8544 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
8545 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY] = {
8546 		.type = NLA_U32 },
8547 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
8548 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
8549 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
8550 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
8551 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME] = {
8552 		.type = NLA_U32},
8553 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT] = {
8554 		.type = NLA_U32},
8555 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT] = {
8556 		.type = NLA_U32},
8557 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT] = {
8558 		.type = NLA_U32},
8559 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
8560 	[RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
8561 	[RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
8562 	[RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
8563 	[RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
8564 	[RX_BLOCKSIZE_PEER_MAC] = VENDOR_NLA_POLICY_MAC_ADDR,
8565 	[RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
8566 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
8567 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
8568 	[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER] = {.type = NLA_U8 },
8569 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
8570 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
8571 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
8572 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {
8573 						.type = NLA_U32 },
8574 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
8575 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {
8576 						.type = NLA_U8},
8577 	[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
8578 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
8579 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_U8},
8580 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS] = {.type = NLA_U8},
8581 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY] = {.type = NLA_U32 },
8582 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST] = {
8583 		.type = NLA_BINARY,
8584 		.len = WLAN_MAX_IE_LEN + 2},
8585 	[QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES] = {
8586 		.type = NLA_BINARY,
8587 		.len = SIR_MAC_MAX_ADD_IE_LENGTH + 2},
8588 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON] = {.type = NLA_U8 },
8589 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION] = {.type = NLA_U8 },
8590 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION] = {.type = NLA_U8 },
8591 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC] = {.type = NLA_U8 },
8592 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC] = {.type = NLA_U8 },
8593 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC] = {.type = NLA_U8 },
8594 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE] = {.type = NLA_U32 },
8595 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH] = {.type = NLA_U8 },
8596 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW] = {.type = NLA_U8 },
8597 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NSS] = {.type = NLA_U8 },
8598 	[QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT] = {
8599 		.type = NLA_U8 },
8600 	[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_ITO] = {.type = NLA_U16 },
8601 	[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_SPEC_WAKE_INTERVAL] = {
8602 		.type = NLA_U16 },
8603 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE] = {
8604 		.type = NLA_U8 },
8605 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS] = {.type = NLA_U8 },
8606 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS] = {.type = NLA_U8 },
8607 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING] = {.type = NLA_U8 },
8608 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL] = {.type = NLA_S32 },
8609 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS] = {.type = NLA_U8 },
8610 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS] = {.type = NLA_U8 },
8611 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY] = {
8612 							.type = NLA_U8 },
8613 	[QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS] = {.type = NLA_U8 },
8614 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD] = {.type = NLA_U8 },
8615 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DBAM] = {.type = NLA_U8 },
8616 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE_FOR_BE_BK] = {
8617 		.type = NLA_U8 },
8618 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEAMFORMER_PERIODIC_SOUNDING] = {
8619 		.type = NLA_U8 },
8620 	[QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE] = {
8621 		.type = NLA_U8 },
8622 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_EML_CAPABILITY] = {
8623 		.type = NLA_U8},
8624 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_SIMULTANEOUS_LINKS] = {
8625 		.type = NLA_U8},
8626 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_CAPABILITY] = {
8627 		.type = NLA_U8},
8628 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_FUNCTION] = {
8629 		.type = NLA_U8},
8630 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_NUM_LINKS] = {
8631 		.type = NLA_U8},
8632 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MODE] = {
8633 		.type = NLA_U8},
8634 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_ACTIVE_LINKS] = {
8635 		.type = NLA_NESTED},
8636 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EMLSR_MODE_SWITCH] = {
8637 		.type = NLA_U8},
8638 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UL_MU_CONFIG] = {.type = NLA_U8},
8639 	[QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST] = {
8640 		.type = NLA_NESTED},
8641 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS] = {
8642 		.type = NLA_NESTED },
8643 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PEER_AMPDU_CNT] = {.type = NLA_U16},
8644 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TTLM_NEGOTIATION_SUPPORT] = {
8645 		.type = NLA_U8},
8646 	[QCA_WLAN_VENDOR_ATTR_CONFIG_COEX_TRAFFIC_SHAPING_MODE] = {
8647 		.type = NLA_U8},
8648 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BTM_SUPPORT] = {.type = NLA_U8},
8649 	[QCA_WLAN_VENDOR_ATTR_CONFIG_KEEP_ALIVE_INTERVAL] = {
8650 		.type = NLA_U16},
8651 };
8652 
8653 #define WLAN_MAX_LINK_ID 15
8654 
8655 static const struct nla_policy bandwidth_mlo_policy[
8656 			QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
8657 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH] = {
8658 		.type = NLA_U8 },
8659 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID] = {
8660 		.type = NLA_U8 },
8661 };
8662 
8663 static const struct nla_policy
8664 qca_wlan_vendor_attr_omi_tx_policy [QCA_WLAN_VENDOR_ATTR_OMI_MAX + 1] = {
8665 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS] =       {.type = NLA_U8 },
8666 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW] =        {.type = NLA_U8 },
8667 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE] = {.type = NLA_U8 },
8668 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS] =      {.type = NLA_U8 },
8669 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE] = {.type = NLA_U8 },
8670 	[QCA_WLAN_VENDOR_ATTR_EHT_OMI_RX_NSS_EXTN] = {.type = NLA_U8 },
8671 	[QCA_WLAN_VENDOR_ATTR_EHT_OMI_CH_BW_EXTN] =  {.type = NLA_U8 },
8672 	[QCA_WLAN_VENDOR_ATTR_EHT_OMI_TX_NSS_EXTN] = {.type = NLA_U8 },
8673 };
8674 
8675 static const struct nla_policy
8676 wlan_oci_override_policy [QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX + 1] = {
8677 	[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE] = {.type = NLA_U8 },
8678 	[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY] = {.type = NLA_U32 },
8679 };
8680 
8681 const struct nla_policy
8682 wlan_hdd_wifi_test_config_policy[
8683 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
8684 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
8685 			.type = NLA_U8},
8686 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
8687 			.type = NLA_U8},
8688 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
8689 			.type = NLA_U8},
8690 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
8691 			.type = NLA_U8},
8692 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
8693 			.type = NLA_U8},
8694 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
8695 			.type = NLA_U8},
8696 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
8697 			.type = NLA_U8},
8698 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE] = {
8699 			.type = NLA_U8},
8700 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
8701 			.type = NLA_U8},
8702 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
8703 			.type = NLA_U16},
8704 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
8705 			.type = NLA_U8},
8706 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
8707 			.type = NLA_U8},
8708 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF] = {
8709 			.type = NLA_U8},
8710 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE] = {
8711 			.type = NLA_U8},
8712 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS] = {
8713 			.type = NLA_U8},
8714 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT] = {
8715 			.type = NLA_U8},
8716 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS] = {
8717 			.type = NLA_U8},
8718 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR] = {
8719 			.type = NLA_U8},
8720 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC] = {
8721 			.type = NLA_U8},
8722 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA] = {
8723 			.type = NLA_U8},
8724 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP] = {
8725 			.type = NLA_U8},
8726 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW] = {
8727 			.type = NLA_U8},
8728 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS] = {
8729 			.type = NLA_U8},
8730 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG] = {
8731 			.type = NLA_FLAG},
8732 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU] = {
8733 			.type = NLA_U8},
8734 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA] = {
8735 			.type = NLA_U8},
8736 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP] = {
8737 			.type = NLA_U8},
8738 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX] = {
8739 			.type = NLA_NESTED},
8740 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU] = {
8741 			.type = NLA_U8},
8742 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS]
8743 			= {.type = NLA_U8},
8744 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT] = {
8745 			.type = NLA_U8},
8746 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP] = {
8747 			.type = NLA_NESTED},
8748 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE] = {
8749 			.type = NLA_NESTED},
8750 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT] = {
8751 			.type = NLA_U8},
8752 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE] = {
8753 			.type = NLA_U8},
8754 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION] = {
8755 			.type = NLA_U8},
8756 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX]
8757 			= {.type = NLA_U8},
8758 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD] = {
8759 			.type = NLA_U16},
8760 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE] = {
8761 			.type = NLA_U8},
8762 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX] = {
8763 			.type = NLA_U8},
8764 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX] = {
8765 			.type = NLA_FLAG},
8766 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED] = {
8767 			.type = NLA_U8},
8768 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA] = {
8769 			.type = NLA_U8},
8770 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE] = {
8771 			.type = NLA_NESTED},
8772 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT] = {
8773 			.type = NLA_U8},
8774 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX] = {
8775 			.type = NLA_U8},
8776 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO] = {
8777 			.type = NLA_U8},
8778 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX] = {
8779 			.type = NLA_U8},
8780 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE]
8781 			= {.type = NLA_U8},
8782 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE]
8783 			= {.type = NLA_U8},
8784 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_11BE_EMLSR_MODE] = {
8785 			.type = NLA_U8},
8786 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BEAMFORMER_PERIODIC_SOUNDING] = {
8787 			.type = NLA_U8},
8788 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_80MHZ] = {
8789 			.type = NLA_U8},
8790 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_160MHZ] = {
8791 			.type = NLA_U8},
8792 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_320MHZ] = {
8793 			.type = NLA_U8},
8794 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EXCLUDE_STA_PROF_IN_PROBE_REQ] = {
8795 			.type = NLA_U8},
8796 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_EHT_TESTBED_DEFAULTS] = {
8797 			.type = NLA_U8},
8798 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MCS] = {
8799 			.type = NLA_U8},
8800 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_TB_SOUNDING_FB_RL] = {
8801 			.type = NLA_U8},
8802 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_OM_CTRL_SUPPORT] = {
8803 			.type = NLA_U8},
8804 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EMLSR_PADDING_DELAY] = {
8805 			.type = NLA_U8},
8806 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FORCE_MLO_POWER_SAVE_BCN_PERIOD] = {
8807 			.type = NLA_U8},
8808 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_STR_TX] = {
8809 			.type = NLA_U8},
8810 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_LINK_POWER_SAVE] = {
8811 			.type = NLA_NESTED},
8812 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MLD_ID_ML_PROBE_REQ] = {
8813 			.type = NLA_U8},
8814 };
8815 
8816 /**
8817  * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
8818  * @hdd_ctx: HDD context
8819  * @adapter: Pointer to HDD adapter
8820  * @ie_data: Pointer to Scan IEs buffer
8821  * @ie_len: Length of Scan IEs
8822  *
8823  * This API is used to store the default scan ies received from
8824  * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
8825  *
8826  * Return: 0 on success; error number otherwise
8827  */
wlan_hdd_save_default_scan_ies(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,uint8_t * ie_data,uint16_t ie_len)8828 static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
8829 					  struct hdd_adapter *adapter,
8830 					  uint8_t *ie_data, uint16_t ie_len)
8831 {
8832 	struct hdd_scan_info *scan_info = &adapter->scan_info;
8833 	bool add_qcn_ie;
8834 
8835 	if (!scan_info)
8836 		return -EINVAL;
8837 
8838 	if (scan_info->default_scan_ies) {
8839 		qdf_mem_free(scan_info->default_scan_ies);
8840 		scan_info->default_scan_ies = NULL;
8841 	}
8842 
8843 	scan_info->default_scan_ies_len = ie_len;
8844 	ucfg_mlme_get_qcn_ie_support(hdd_ctx->psoc, &add_qcn_ie);
8845 	if (add_qcn_ie)
8846 		ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
8847 
8848 	scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
8849 	if (!scan_info->default_scan_ies) {
8850 		scan_info->default_scan_ies_len = 0;
8851 		return -ENOMEM;
8852 	}
8853 
8854 	qdf_mem_copy(scan_info->default_scan_ies, ie_data,
8855 			  scan_info->default_scan_ies_len);
8856 
8857 	/* Add QCN IE if g_qcn_ie_support INI is enabled */
8858 	if (add_qcn_ie)
8859 		sme_add_qcn_ie(hdd_ctx->mac_handle,
8860 			       scan_info->default_scan_ies,
8861 			       &scan_info->default_scan_ies_len);
8862 
8863 	hdd_debug("Saved default scan IE:len %d",
8864 		  scan_info->default_scan_ies_len);
8865 	qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
8866 				(uint8_t *) scan_info->default_scan_ies,
8867 				scan_info->default_scan_ies_len);
8868 
8869 	return 0;
8870 }
8871 
8872 /**
8873  * wlan_hdd_handle_restrict_offchan_config() -
8874  * Handle wifi configuration attribute :
8875  * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
8876  * @adapter: Pointer to HDD adapter
8877  * @restrict_offchan: Restrict offchannel setting done by
8878  * application
8879  *
8880  * Return: 0 on success; error number otherwise
8881  */
wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter * adapter,u8 restrict_offchan)8882 static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
8883 						   u8 restrict_offchan)
8884 {
8885 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8886 	enum QDF_OPMODE dev_mode = adapter->device_mode;
8887 	struct wlan_objmgr_vdev *vdev;
8888 	int ret_val = 0;
8889 
8890 	if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
8891 		hdd_err("Invalid interface type:%d", dev_mode);
8892 		return -EINVAL;
8893 	}
8894 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
8895 	if (!vdev)
8896 		return -EINVAL;
8897 	if (restrict_offchan == 1) {
8898 		u32 vdev_id = wlan_vdev_get_id(vdev);
8899 		enum policy_mgr_con_mode pmode =
8900 		policy_mgr_qdf_opmode_to_pm_con_mode(hdd_ctx->psoc, dev_mode,
8901 						     vdev_id);
8902 		uint32_t freq;
8903 
8904 		wlan_vdev_obj_lock(vdev);
8905 		wlan_vdev_mlme_cap_set(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
8906 		wlan_vdev_obj_unlock(vdev);
8907 		freq = policy_mgr_get_channel(hdd_ctx->psoc, pmode, &vdev_id);
8908 		if (!freq ||
8909 		    wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, freq)) {
8910 			hdd_err("unable to send avoid_freq");
8911 			ret_val = -EINVAL;
8912 		}
8913 		hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
8914 	} else if (restrict_offchan == 0) {
8915 		wlan_vdev_obj_lock(vdev);
8916 		wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
8917 		wlan_vdev_obj_unlock(vdev);
8918 		if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
8919 			hdd_err("unable to clear avoid_freq");
8920 			ret_val = -EINVAL;
8921 		}
8922 		hdd_info("vdev mode %d dnbs disabled", dev_mode);
8923 	} else {
8924 		ret_val = -EINVAL;
8925 		hdd_err("Invalid RESTRICT_OFFCHAN setting");
8926 	}
8927 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
8928 	return ret_val;
8929 }
8930 
8931 /**
8932  * wlan_hdd_cfg80211_wifi_set_reorder_timeout() - set reorder timeout
8933  * @link_info: link info pointer in HDD adapter
8934  * @tb: array of pointer to struct nlattr
8935  *
8936  * Return: 0 on success; error number otherwise
8937  */
8938 static int
wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])8939 wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct wlan_hdd_link_info *link_info,
8940 					   struct nlattr *tb[])
8941 {
8942 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
8943 	int ret_val = 0;
8944 	QDF_STATUS qdf_status;
8945 	struct sir_set_rx_reorder_timeout_val reorder_timeout;
8946 	mac_handle_t mac_handle;
8947 
8948 #define RX_TIMEOUT_VAL_MIN 10
8949 #define RX_TIMEOUT_VAL_MAX 1000
8950 
8951 	if (tb[RX_REORDER_TIMEOUT_VOICE] ||
8952 	    tb[RX_REORDER_TIMEOUT_VIDEO] ||
8953 	    tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
8954 	    tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
8955 
8956 		/* if one is specified, all must be specified */
8957 		if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
8958 		    !tb[RX_REORDER_TIMEOUT_VIDEO] ||
8959 		    !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
8960 		    !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
8961 			hdd_err("four AC timeout val are required MAC");
8962 			return -EINVAL;
8963 		}
8964 
8965 		reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
8966 			tb[RX_REORDER_TIMEOUT_VOICE]);
8967 		reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
8968 			tb[RX_REORDER_TIMEOUT_VIDEO]);
8969 		reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
8970 			tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
8971 		reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
8972 			tb[RX_REORDER_TIMEOUT_BACKGROUND]);
8973 		/* timeout value is required to be in the rang 10 to 1000ms */
8974 		if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
8975 		    reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
8976 		    reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
8977 		    reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
8978 		    reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
8979 		    reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
8980 		    reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
8981 		    reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
8982 			mac_handle = hdd_ctx->mac_handle;
8983 			qdf_status = sme_set_reorder_timeout(mac_handle,
8984 							     &reorder_timeout);
8985 			if (qdf_status != QDF_STATUS_SUCCESS) {
8986 				hdd_err("failed to set reorder timeout err %d",
8987 					qdf_status);
8988 				ret_val = -EPERM;
8989 			}
8990 		} else {
8991 			hdd_err("one of the timeout value is not in range");
8992 			ret_val = -EINVAL;
8993 		}
8994 	}
8995 
8996 	return ret_val;
8997 }
8998 
8999 /**
9000  * wlan_hdd_cfg80211_wifi_set_rx_blocksize() - set rx blocksize
9001  * @link_info: Link info pointer in HDD adapter
9002  * @tb: array of pointer to struct nlattr
9003  *
9004  * Return: 0 on success; error number otherwise
9005  */
9006 static int
wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9007 wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct wlan_hdd_link_info *link_info,
9008 					struct nlattr *tb[])
9009 {
9010 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9011 	int ret_val = 0;
9012 	uint32_t set_value;
9013 	QDF_STATUS qdf_status;
9014 	struct sir_peer_set_rx_blocksize rx_blocksize;
9015 	mac_handle_t mac_handle;
9016 
9017 #define WINDOW_SIZE_VAL_MIN 1
9018 #define WINDOW_SIZE_VAL_MAX 64
9019 
9020 	if (tb[RX_BLOCKSIZE_WINLIMIT]) {
9021 
9022 		/* if one is specified, both must be specified */
9023 		if (!tb[RX_BLOCKSIZE_PEER_MAC]) {
9024 			hdd_err("Both Peer MAC and windows limit required");
9025 			return -EINVAL;
9026 		}
9027 
9028 		memcpy(&rx_blocksize.peer_macaddr,
9029 		       nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
9030 		       sizeof(rx_blocksize.peer_macaddr)),
9031 
9032 		rx_blocksize.vdev_id = link_info->vdev_id;
9033 		set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
9034 		/* maximum window size is 64 */
9035 		if (set_value >= WINDOW_SIZE_VAL_MIN &&
9036 		    set_value <= WINDOW_SIZE_VAL_MAX) {
9037 			rx_blocksize.rx_block_ack_win_limit = set_value;
9038 			mac_handle = hdd_ctx->mac_handle;
9039 			qdf_status = sme_set_rx_set_blocksize(mac_handle,
9040 							      &rx_blocksize);
9041 			if (qdf_status != QDF_STATUS_SUCCESS) {
9042 				hdd_err("failed to set aggr sizes err %d",
9043 					qdf_status);
9044 				ret_val = -EPERM;
9045 			}
9046 		} else {
9047 			hdd_err("window size val is not in range");
9048 			ret_val = -EINVAL;
9049 		}
9050 	}
9051 
9052 	return ret_val;
9053 }
9054 
hdd_set_vdev_phy_mode(struct hdd_adapter * adapter,enum qca_wlan_vendor_phy_mode vendor_phy_mode)9055 int hdd_set_vdev_phy_mode(struct hdd_adapter *adapter,
9056 			  enum qca_wlan_vendor_phy_mode vendor_phy_mode)
9057 {
9058 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9059 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
9060 	struct wlan_hdd_link_info *link_info = adapter->deflink;
9061 	eCsrPhyMode csr_req_phymode, csr_max_phymode;
9062 	enum reg_phymode reg_req_phymode, reg_max_phymode;
9063 	enum qca_wlan_vendor_phy_mode max_vendor_phy_mode;
9064 	WMI_HOST_WIFI_STANDARD std;
9065 	enum hdd_dot11_mode dot11_mode;
9066 	uint8_t supported_band;
9067 	int ret;
9068 
9069 	if (hdd_cm_is_vdev_connected(link_info)) {
9070 		hdd_err("Station is connected, command is not supported");
9071 		return -EINVAL;
9072 	}
9073 	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &csr_req_phymode);
9074 	if (ret < 0)
9075 		return ret;
9076 
9077 	reg_req_phymode = csr_convert_to_reg_phy_mode(csr_req_phymode, 0);
9078 	reg_max_phymode = wlan_reg_get_max_phymode(hdd_ctx->pdev,
9079 						   reg_req_phymode, 0);
9080 	if (reg_req_phymode != reg_max_phymode) {
9081 		hdd_debug("reg_max_phymode %d, req_req_phymode %d",
9082 			  reg_max_phymode, reg_req_phymode);
9083 		csr_max_phymode =
9084 			csr_convert_from_reg_phy_mode(reg_max_phymode);
9085 		ret = hdd_phymode_to_vendor_mode(csr_max_phymode,
9086 						 &max_vendor_phy_mode);
9087 		if (ret)
9088 			return ret;
9089 	} else {
9090 		csr_max_phymode = csr_req_phymode;
9091 		max_vendor_phy_mode = vendor_phy_mode;
9092 	}
9093 
9094 	adapter->user_phy_mode = max_vendor_phy_mode;
9095 
9096 	ret = hdd_phymode_to_dot11_mode(csr_max_phymode, &dot11_mode);
9097 	if (ret)
9098 		return ret;
9099 
9100 	ret = hdd_vendor_mode_to_band(max_vendor_phy_mode, &supported_band,
9101 				      wlan_reg_is_6ghz_supported(psoc));
9102 	if (ret)
9103 		return ret;
9104 
9105 	std = hdd_get_wifi_standard(hdd_ctx, dot11_mode, supported_band);
9106 	hdd_debug("wifi_standard %d, vendor_phy_mode %d",
9107 		  std, max_vendor_phy_mode);
9108 
9109 	ret = sme_cli_set_command(link_info->vdev_id,
9110 				  wmi_vdev_param_wifi_standard_version,
9111 				  std, VDEV_CMD);
9112 	if (ret) {
9113 		hdd_err("Failed to set standard version to fw");
9114 		return ret;
9115 	}
9116 
9117 	ucfg_mlme_set_vdev_wifi_std(hdd_ctx->psoc, link_info->vdev_id, std);
9118 
9119 	return 0;
9120 }
9121 
hdd_set_phy_mode(struct hdd_adapter * adapter,enum qca_wlan_vendor_phy_mode vendor_phy_mode)9122 int hdd_set_phy_mode(struct hdd_adapter *adapter,
9123 		     enum qca_wlan_vendor_phy_mode vendor_phy_mode)
9124 {
9125 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9126 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
9127 	eCsrPhyMode csr_req_phymode, csr_max_phymode;
9128 	enum reg_phymode reg_req_phymode, reg_max_phymode;
9129 	enum qca_wlan_vendor_phy_mode max_vendor_phy_mode = vendor_phy_mode;
9130 	uint8_t supported_band;
9131 	uint32_t bonding_mode;
9132 	int ret = 0;
9133 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_VDEV;
9134 	struct hdd_adapter *curr_adapter, *next_adapter;
9135 
9136 	if (!psoc) {
9137 		hdd_err("psoc is NULL");
9138 		return -EINVAL;
9139 	}
9140 
9141 	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &csr_req_phymode);
9142 	if (ret < 0)
9143 		return ret;
9144 
9145 	reg_req_phymode = csr_convert_to_reg_phy_mode(csr_req_phymode, 0);
9146 	reg_max_phymode = wlan_reg_get_max_phymode(hdd_ctx->pdev,
9147 						   reg_req_phymode, 0);
9148 
9149 	if (reg_req_phymode != reg_max_phymode) {
9150 		hdd_debug("reg_max_phymode %d, req_req_phymode %d",
9151 			  reg_max_phymode, reg_req_phymode);
9152 		csr_max_phymode =
9153 			csr_convert_from_reg_phy_mode(reg_max_phymode);
9154 		ret = hdd_phymode_to_vendor_mode(csr_max_phymode,
9155 						 &max_vendor_phy_mode);
9156 		if (ret)
9157 			return ret;
9158 	} else {
9159 		csr_max_phymode = csr_req_phymode;
9160 		max_vendor_phy_mode = vendor_phy_mode;
9161 	}
9162 
9163 	ret = hdd_vendor_mode_to_band(max_vendor_phy_mode, &supported_band,
9164 				      wlan_reg_is_6ghz_supported(psoc));
9165 	if (ret < 0)
9166 		return ret;
9167 
9168 	ret = hdd_vendor_mode_to_bonding_mode(max_vendor_phy_mode,
9169 					      &bonding_mode);
9170 	if (ret < 0)
9171 		return ret;
9172 
9173 	ret = hdd_update_phymode(adapter, csr_max_phymode, supported_band,
9174 				 bonding_mode);
9175 	if (ret)
9176 		return ret;
9177 
9178 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, curr_adapter, next_adapter,
9179 					   dbgid) {
9180 		if (curr_adapter->device_mode == QDF_STA_MODE &&
9181 		    !hdd_cm_is_vdev_connected(curr_adapter->deflink)) {
9182 			hdd_set_vdev_phy_mode(curr_adapter,
9183 					      max_vendor_phy_mode);
9184 		}
9185 		hdd_adapter_dev_put_debug(curr_adapter, dbgid);
9186 	}
9187 
9188 	return 0;
9189 }
9190 
9191 /**
9192  * hdd_config_phy_mode() - set PHY mode
9193  * @link_info: Link info pointer in HDD adapter
9194  * @tb: nla attr sent from userspace
9195  *
9196  * Return: 0 on success; error number otherwise
9197  */
hdd_config_phy_mode(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9198 static int hdd_config_phy_mode(struct wlan_hdd_link_info *link_info,
9199 			       struct nlattr *tb[])
9200 {
9201 	enum qca_wlan_vendor_phy_mode vendor_phy_mode;
9202 	uint32_t ifindex;
9203 	struct nlattr *phy_mode_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE];
9204 	struct nlattr *ifindex_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX];
9205 
9206 	if (!phy_mode_attr)
9207 		return 0;
9208 
9209 	vendor_phy_mode = nla_get_u32(phy_mode_attr);
9210 	if (!ifindex_attr)
9211 		return hdd_set_phy_mode(link_info->adapter, vendor_phy_mode);
9212 
9213 	ifindex = nla_get_u32(ifindex_attr);
9214 	if (ifindex == link_info->adapter->dev->ifindex)
9215 		return hdd_set_vdev_phy_mode(link_info->adapter,
9216 					     vendor_phy_mode);
9217 
9218 	hdd_err_rl("ifindex %d, expected ifindex %d", ifindex,
9219 		   link_info->adapter->dev->ifindex);
9220 	return -EINVAL;
9221 }
9222 
9223 /**
9224  * hdd_config_peer_ampdu() - Configure peer A-MPDU count
9225  * @link_info: Link info pointer in HDD adapter
9226  * @tb: nla attr sent from userspace
9227  *
9228  * Return: 0 on success; error number otherwise
9229  */
hdd_config_peer_ampdu(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9230 static int hdd_config_peer_ampdu(struct wlan_hdd_link_info *link_info,
9231 				 struct nlattr *tb[])
9232 {
9233 	struct hdd_adapter *adapter = link_info->adapter;
9234 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9235 	struct nlattr *ampdu_cnt_attr =
9236 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PEER_AMPDU_CNT];
9237 	struct nlattr *ampdu_mac_attr =
9238 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PEER_MAC];
9239 	struct qdf_mac_addr peer_macaddr;
9240 	struct wlan_objmgr_vdev *vdev;
9241 	QDF_STATUS status;
9242 	bool is_sap;
9243 	uint16_t cfg_val;
9244 
9245 	if (!ampdu_cnt_attr)
9246 		return 0;
9247 
9248 	if (adapter->device_mode == QDF_SAP_MODE ||
9249 	    adapter->device_mode == QDF_P2P_GO_MODE)
9250 		is_sap = true;
9251 	else if (adapter->device_mode == QDF_STA_MODE ||
9252 		 adapter->device_mode == QDF_P2P_CLIENT_MODE)
9253 		is_sap = false;
9254 	else {
9255 		hdd_debug("mode not support");
9256 		return -EINVAL;
9257 	}
9258 
9259 	if (is_sap) {
9260 		if (!ampdu_mac_attr) {
9261 			hdd_debug("sap must provide peer mac attr");
9262 			return -EINVAL;
9263 		}
9264 		nla_memcpy(&peer_macaddr, ampdu_mac_attr, QDF_MAC_ADDR_SIZE);
9265 	} else {
9266 		vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
9267 		if (!vdev) {
9268 			hdd_debug("vdev is null");
9269 			return -EINVAL;
9270 		}
9271 		status = wlan_vdev_get_bss_peer_mac(vdev, &peer_macaddr);
9272 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9273 		if (QDF_IS_STATUS_ERROR(status)) {
9274 			hdd_debug("fail to get bss peer mac");
9275 			return -EINVAL;
9276 		}
9277 	}
9278 	cfg_val = nla_get_u16(ampdu_cnt_attr);
9279 	return sme_set_peer_ampdu(hdd_ctx->mac_handle,
9280 				  link_info->vdev_id,
9281 				  &peer_macaddr,
9282 				  cfg_val);
9283 }
9284 
9285 /**
9286  * hdd_set_roam_reason_vsie_status() - enable/disable inclusion of
9287  * roam reason vsie in Reassoc
9288  * @link_info: Link info pointer in adapter
9289  * @attr: nla attr sent by supplicant
9290  *
9291  * Return: 0 on success, negative errno on failure
9292  */
9293 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
hdd_set_roam_reason_vsie_status(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9294 static int hdd_set_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
9295 					   const struct nlattr *attr)
9296 {
9297 	uint8_t roam_reason_vsie_enabled;
9298 	int errno;
9299 	QDF_STATUS status = QDF_STATUS_SUCCESS;
9300 	struct hdd_adapter *adapter = link_info->adapter;
9301 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9302 
9303 	if (!hdd_ctx) {
9304 		hdd_err("hdd_ctx failure");
9305 		return -EINVAL;
9306 	}
9307 
9308 	roam_reason_vsie_enabled = nla_get_u8(attr);
9309 	if (roam_reason_vsie_enabled > 1)
9310 		roam_reason_vsie_enabled = 1;
9311 
9312 	status =
9313 		ucfg_mlme_set_roam_reason_vsie_status(hdd_ctx->psoc,
9314 						      roam_reason_vsie_enabled);
9315 	if (QDF_IS_STATUS_ERROR(status)) {
9316 		hdd_err("set roam reason vsie failed");
9317 		return -EINVAL;
9318 	}
9319 
9320 	errno = sme_cli_set_command
9321 			(link_info->vdev_id,
9322 			 wmi_vdev_param_enable_disable_roam_reason_vsie,
9323 			 roam_reason_vsie_enabled, VDEV_CMD);
9324 	if (errno) {
9325 		hdd_err("Failed to set beacon report error vsie");
9326 		status = QDF_STATUS_E_FAILURE;
9327 	}
9328 
9329 	return qdf_status_to_os_return(status);
9330 }
9331 #else
9332 static inline int
hdd_set_roam_reason_vsie_status(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9333 hdd_set_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
9334 				const struct nlattr *attr)
9335 {
9336 	return -ENOTSUPP;
9337 }
9338 #endif
9339 
hdd_set_ft_over_ds(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9340 static int hdd_set_ft_over_ds(struct wlan_hdd_link_info *link_info,
9341 			      const struct nlattr *attr)
9342 {
9343 	uint8_t ft_over_ds_enable;
9344 	QDF_STATUS status = QDF_STATUS_SUCCESS;
9345 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9346 
9347 	if (!hdd_ctx) {
9348 		hdd_err("hdd_ctx failure");
9349 		return -EINVAL;
9350 	}
9351 
9352 	ft_over_ds_enable = nla_get_u8(attr);
9353 
9354 	if (ft_over_ds_enable != 0 && ft_over_ds_enable != 1) {
9355 		hdd_err_rl("Invalid ft_over_ds_enable: %d", ft_over_ds_enable);
9356 		return -EINVAL;
9357 	}
9358 
9359 	status = ucfg_mlme_set_ft_over_ds(hdd_ctx->psoc, ft_over_ds_enable);
9360 	if (QDF_IS_STATUS_ERROR(status)) {
9361 		hdd_err("set ft_over_ds failed");
9362 		return -EINVAL;
9363 	}
9364 
9365 	return status;
9366 }
9367 
hdd_config_ldpc(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9368 static int hdd_config_ldpc(struct wlan_hdd_link_info *link_info,
9369 			   const struct nlattr *attr)
9370 {
9371 	uint8_t ldpc;
9372 	int ret;
9373 
9374 	ldpc = nla_get_u8(attr);
9375 
9376 	ret = hdd_set_ldpc(link_info, ldpc);
9377 
9378 	return ret;
9379 }
9380 
hdd_config_tx_stbc(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9381 static int hdd_config_tx_stbc(struct wlan_hdd_link_info *link_info,
9382 			      const struct nlattr *attr)
9383 {
9384 	uint8_t tx_stbc;
9385 	int ret;
9386 
9387 	tx_stbc = nla_get_u8(attr);
9388 
9389 	ret = hdd_set_tx_stbc(link_info, tx_stbc);
9390 
9391 	return ret;
9392 }
9393 
hdd_config_rx_stbc(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9394 static int hdd_config_rx_stbc(struct wlan_hdd_link_info *link_info,
9395 			      const struct nlattr *attr)
9396 {
9397 	uint8_t rx_stbc;
9398 	int ret;
9399 
9400 	rx_stbc = nla_get_u8(attr);
9401 
9402 	ret = hdd_set_rx_stbc(link_info, rx_stbc);
9403 
9404 	return ret;
9405 }
9406 
hdd_config_access_policy(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9407 static int hdd_config_access_policy(struct wlan_hdd_link_info *link_info,
9408 				    struct nlattr *tb[])
9409 {
9410 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9411 	struct nlattr *policy_attr =
9412 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY];
9413 	struct nlattr *ielist_attr =
9414 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST];
9415 	uint32_t access_policy;
9416 	uint8_t ie[WLAN_MAX_IE_LEN + 2];
9417 	QDF_STATUS status;
9418 
9419 	/* nothing to do if neither attribute is present */
9420 	if (!ielist_attr && !policy_attr)
9421 		return 0;
9422 
9423 	/* if one is present, both must be present */
9424 	if (!ielist_attr || !policy_attr) {
9425 		hdd_err("Missing attribute for %s",
9426 			policy_attr ?
9427 				"ACCESS_POLICY_IE_LIST" : "ACCESS_POLICY");
9428 		return -EINVAL;
9429 	}
9430 
9431 	/* validate the access policy */
9432 	access_policy = nla_get_u32(policy_attr);
9433 	switch (access_policy) {
9434 	case QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED:
9435 	case QCA_ACCESS_POLICY_DENY_UNLESS_LISTED:
9436 		/* valid */
9437 		break;
9438 	default:
9439 		hdd_err("Invalid value. access_policy %u", access_policy);
9440 		return -EINVAL;
9441 	}
9442 
9443 	/*
9444 	 * ie length is validated by the nla_policy.  need to make a
9445 	 * copy since SME will always read WLAN_MAX_IE_LEN+2 bytes
9446 	 */
9447 	nla_memcpy(ie, ielist_attr, sizeof(ie));
9448 
9449 	hdd_debug("calling sme_update_access_policy_vendor_ie");
9450 	status = sme_update_access_policy_vendor_ie(hdd_ctx->mac_handle,
9451 						    link_info->vdev_id,
9452 						    ie, access_policy);
9453 	if (QDF_IS_STATUS_ERROR(status))
9454 		hdd_err("Failed to set vendor ie and access policy, %d",
9455 			status);
9456 
9457 	return qdf_status_to_os_return(status);
9458 }
9459 
hdd_config_mpdu_aggregation(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9460 static int hdd_config_mpdu_aggregation(struct wlan_hdd_link_info *link_info,
9461 				       struct nlattr *tb[])
9462 {
9463 	struct nlattr *tx_attr =
9464 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION];
9465 	struct nlattr *rx_attr =
9466 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION];
9467 	uint8_t tx_size, rx_size;
9468 	QDF_STATUS status;
9469 
9470 	/* nothing to do if neither attribute is present */
9471 	if (!tx_attr && !rx_attr)
9472 		return 0;
9473 
9474 	/* if one is present, both must be present */
9475 	if (!tx_attr || !rx_attr) {
9476 		hdd_err("Missing attribute for %s",
9477 			tx_attr ? "RX" : "TX");
9478 		return -EINVAL;
9479 	}
9480 
9481 	tx_size = nla_get_u8(tx_attr);
9482 	rx_size = nla_get_u8(rx_attr);
9483 	if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
9484 	    !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
9485 		hdd_err("TX %d RX %d MPDU aggr size not in range",
9486 			tx_size, rx_size);
9487 
9488 		return -EINVAL;
9489 	}
9490 
9491 	status = wma_set_tx_rx_aggr_size(link_info->vdev_id,
9492 					 tx_size, rx_size,
9493 					 WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU);
9494 
9495 	return qdf_status_to_os_return(status);
9496 }
9497 
hdd_config_msdu_aggregation(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9498 static int hdd_config_msdu_aggregation(struct wlan_hdd_link_info *link_info,
9499 				       struct nlattr *tb[])
9500 {
9501 	struct nlattr *tx_attr =
9502 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION];
9503 	struct nlattr *rx_attr =
9504 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION];
9505 	uint8_t tx_size, rx_size;
9506 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9507 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
9508 	QDF_STATUS status;
9509 
9510 	if (!mac_handle) {
9511 		hdd_err("NULL Mac handle");
9512 		return -EINVAL;
9513 	}
9514 
9515 	/* nothing to do if neither attribute is present */
9516 	if (!tx_attr && !rx_attr)
9517 		return 0;
9518 
9519 	/* if one is present, both must be present */
9520 	if (!tx_attr || !rx_attr) {
9521 		hdd_err("Missing attribute for %s",
9522 			tx_attr ? "RX" : "TX");
9523 		return -EINVAL;
9524 	}
9525 
9526 	tx_size = nla_get_u8(tx_attr);
9527 	rx_size = nla_get_u8(rx_attr);
9528 	if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
9529 	    !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
9530 		hdd_err("TX %d RX %d MSDU aggr size not in range",
9531 			tx_size, rx_size);
9532 
9533 		return -EINVAL;
9534 	}
9535 
9536 	if (tx_size > 1)
9537 		sme_set_amsdu(mac_handle, true);
9538 	else
9539 		sme_set_amsdu(mac_handle, false);
9540 
9541 	hdd_debug("tx size: %d", tx_size);
9542 	status = wma_cli_set_command(link_info->vdev_id,
9543 				     GEN_VDEV_PARAM_AMSDU,
9544 				     tx_size, GEN_CMD);
9545 	if (status) {
9546 		hdd_err("Failed to set AMSDU param to FW, status %d", status);
9547 		return qdf_status_to_os_return(status);
9548 	}
9549 
9550 	return qdf_status_to_os_return(status);
9551 }
9552 
9553 static QDF_STATUS
hdd_populate_vdev_chains(struct wlan_mlme_nss_chains * nss_chains_cfg,uint8_t tx_chains,uint8_t rx_chains,enum nss_chains_band_info band,struct wlan_objmgr_vdev * vdev)9554 hdd_populate_vdev_chains(struct wlan_mlme_nss_chains *nss_chains_cfg,
9555 			 uint8_t tx_chains,
9556 			 uint8_t rx_chains,
9557 			 enum nss_chains_band_info band,
9558 			 struct wlan_objmgr_vdev *vdev)
9559 {
9560 	struct wlan_mlme_nss_chains *dynamic_cfg;
9561 
9562 	nss_chains_cfg->num_rx_chains[band] = rx_chains;
9563 	nss_chains_cfg->num_tx_chains[band] = tx_chains;
9564 
9565 	dynamic_cfg = ucfg_mlme_get_dynamic_vdev_config(vdev);
9566 	if (!dynamic_cfg) {
9567 		hdd_err("nss chain dynamic config NULL");
9568 		return QDF_STATUS_E_FAILURE;
9569 	}
9570 	/*
9571 	 * If user gives any nss value, then chains will be adjusted based on
9572 	 * nss (in SME func sme_validate_user_nss_chain_params).
9573 	 * If Chains are not suitable as per current NSS then, we need to
9574 	 * return, and the below logic is added for the same.
9575 	 */
9576 
9577 	if ((dynamic_cfg->rx_nss[band] > rx_chains) ||
9578 	    (dynamic_cfg->tx_nss[band] > tx_chains)) {
9579 		hdd_err("Chains less than nss, configure correct nss first.");
9580 		return QDF_STATUS_E_FAILURE;
9581 	}
9582 
9583 	return QDF_STATUS_SUCCESS;
9584 }
9585 
9586 int
hdd_set_dynamic_antenna_mode(struct wlan_hdd_link_info * link_info,uint8_t num_rx_chains,uint8_t num_tx_chains)9587 hdd_set_dynamic_antenna_mode(struct wlan_hdd_link_info *link_info,
9588 			     uint8_t num_rx_chains, uint8_t num_tx_chains)
9589 {
9590 	enum nss_chains_band_info band;
9591 	struct wlan_mlme_nss_chains user_cfg;
9592 	QDF_STATUS status;
9593 	mac_handle_t mac_handle;
9594 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9595 	struct wlan_objmgr_vdev *vdev;
9596 	int ret;
9597 
9598 	ret = wlan_hdd_validate_context(hdd_ctx);
9599 	if (0 != ret)
9600 		return ret;
9601 
9602 	mac_handle = hdd_ctx->mac_handle;
9603 	if (!mac_handle) {
9604 		hdd_err("NULL MAC handle");
9605 		return -EINVAL;
9606 	}
9607 
9608 	if (!hdd_is_vdev_in_conn_state(link_info)) {
9609 		hdd_debug("Vdev (id %d) not in connected/started state, cannot accept command",
9610 			  link_info->vdev_id);
9611 		return -EINVAL;
9612 	}
9613 
9614 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
9615 	if (!vdev) {
9616 		hdd_err("vdev is NULL");
9617 		return -EINVAL;
9618 	}
9619 
9620 	qdf_mem_zero(&user_cfg, sizeof(user_cfg));
9621 	for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++) {
9622 		status = hdd_populate_vdev_chains(&user_cfg,
9623 						  num_tx_chains,
9624 						  num_rx_chains, band, vdev);
9625 		if (QDF_IS_STATUS_ERROR(status)) {
9626 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9627 			return -EINVAL;
9628 		}
9629 	}
9630 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9631 
9632 	status = sme_nss_chains_update(mac_handle,
9633 				       &user_cfg,
9634 				       link_info->vdev_id);
9635 	if (QDF_IS_STATUS_ERROR(status))
9636 		return -EINVAL;
9637 
9638 	return 0;
9639 }
9640 
hdd_config_vdev_chains(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9641 static int hdd_config_vdev_chains(struct wlan_hdd_link_info *link_info,
9642 				  struct nlattr *tb[])
9643 {
9644 	struct hdd_adapter *adapter = link_info->adapter;
9645 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9646 	uint8_t tx_chains, rx_chains;
9647 	struct nlattr *tx_attr =
9648 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS];
9649 	struct nlattr *rx_attr =
9650 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS];
9651 
9652 	if (!tx_attr && !rx_attr)
9653 		return 0;
9654 
9655 	/* if one is present, both must be present */
9656 	if (!tx_attr || !rx_attr) {
9657 		hdd_err("Missing attribute for %s",
9658 			tx_attr ? "RX" : "TX");
9659 		return -EINVAL;
9660 	}
9661 
9662 	tx_chains = nla_get_u8(tx_attr);
9663 	rx_chains = nla_get_u8(rx_attr);
9664 
9665 	hdd_debug("tx_chains %d rx_chains %d", tx_chains, rx_chains);
9666 	if (hdd_ctx->dynamic_nss_chains_support)
9667 		return hdd_set_dynamic_antenna_mode(link_info,
9668 						    rx_chains, tx_chains);
9669 	return 0;
9670 }
9671 
hdd_config_tx_rx_nss(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9672 static int hdd_config_tx_rx_nss(struct wlan_hdd_link_info *link_info,
9673 				struct nlattr *tb[])
9674 {
9675 	uint8_t tx_nss, rx_nss;
9676 	QDF_STATUS status;
9677 
9678 	struct nlattr *tx_attr =
9679 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS];
9680 	struct nlattr *rx_attr =
9681 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS];
9682 
9683 	if (!tx_attr && !rx_attr)
9684 		return 0;
9685 
9686 	/* if one is present, both must be present */
9687 	if (!tx_attr || !rx_attr) {
9688 		hdd_err("Missing attribute for %s",
9689 			tx_attr ? "RX" : "TX");
9690 		return -EINVAL;
9691 	}
9692 
9693 	tx_nss = nla_get_u8(tx_attr);
9694 	rx_nss = nla_get_u8(rx_attr);
9695 	hdd_debug("tx_nss %d rx_nss %d", tx_nss, rx_nss);
9696 	/* Only allow NSS for tx_rx_nss for 1x1, 1x2, 2x2 */
9697 	if (!((tx_nss == 1 && rx_nss == 2) || (tx_nss == 1 && rx_nss == 1) ||
9698 	      (tx_nss == 2 && rx_nss == 2))) {
9699 		hdd_err("Setting tx_nss %d rx_nss %d not allowed", tx_nss,
9700 			rx_nss);
9701 		return -EINVAL;
9702 	}
9703 	status = hdd_update_nss(link_info, tx_nss, rx_nss);
9704 	if (status != QDF_STATUS_SUCCESS) {
9705 		hdd_debug("Can't set tx_nss %d rx_nss %d", tx_nss, rx_nss);
9706 		return -EINVAL;
9707 	}
9708 
9709 	return 0;
9710 }
9711 
9712 #ifdef WLAN_FEATURE_SON
hdd_process_generic_set_cmd(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9713 static int hdd_process_generic_set_cmd(struct wlan_hdd_link_info *link_info,
9714 				       struct nlattr *tb[])
9715 {
9716 	struct wireless_dev *wdev;
9717 	struct wiphy *wiphy;
9718 	struct hdd_adapter *adapter = link_info->adapter;
9719 
9720 	if (!adapter)
9721 		return 0;
9722 
9723 	wdev = &adapter->wdev;
9724 	if (!wdev || !wdev->wiphy)
9725 		return 0;
9726 	wiphy = wdev->wiphy;
9727 
9728 	/* Generic command is used by EasyMesh,
9729 	 * route the command to SON module if it is Generic
9730 	 */
9731 	if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND])
9732 		return hdd_son_send_set_wifi_generic_command(wiphy, wdev, tb);
9733 
9734 	return 0;
9735 }
9736 #else
9737 static inline int
hdd_process_generic_set_cmd(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9738 hdd_process_generic_set_cmd(struct wlan_hdd_link_info *link_info,
9739 			    struct nlattr *tb[])
9740 {
9741 	return 0;
9742 }
9743 #endif
9744 
hdd_config_ani(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9745 static int hdd_config_ani(struct wlan_hdd_link_info *link_info,
9746 			  struct nlattr *tb[])
9747 {
9748 	int errno;
9749 	uint8_t ani_setting_type;
9750 	int32_t ani_level = 0, enable_ani;
9751 	struct nlattr *ani_setting_attr =
9752 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING];
9753 	struct nlattr *ani_level_attr =
9754 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL];
9755 
9756 	if (!ani_setting_attr)
9757 		return 0;
9758 
9759 	ani_setting_type = nla_get_u8(ani_setting_attr);
9760 	if (ani_setting_type != QCA_WLAN_ANI_SETTING_AUTO &&
9761 	    ani_setting_type != QCA_WLAN_ANI_SETTING_FIXED) {
9762 		hdd_err("invalid ani_setting_type %d", ani_setting_type);
9763 		return -EINVAL;
9764 	}
9765 
9766 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_AUTO &&
9767 	    ani_level_attr) {
9768 		hdd_err("Not support to set ani level in QCA_WLAN_ANI_SETTING_AUTO");
9769 		return -EINVAL;
9770 	}
9771 
9772 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_FIXED) {
9773 		if (!ani_level_attr) {
9774 			hdd_err("invalid ani_level_attr");
9775 			return -EINVAL;
9776 		}
9777 		ani_level = nla_get_s32(ani_level_attr);
9778 	}
9779 	hdd_debug("ani_setting_type %u, ani_level %d",
9780 		  ani_setting_type, ani_level);
9781 
9782 	/* ANI (Adaptive noise immunity) */
9783 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_AUTO)
9784 		enable_ani = 1;
9785 	else
9786 		enable_ani = 0;
9787 
9788 	errno = wma_cli_set_command(link_info->vdev_id,
9789 				    wmi_pdev_param_ani_enable,
9790 				    enable_ani, PDEV_CMD);
9791 	if (errno) {
9792 		hdd_err("Failed to set ani enable, errno %d", errno);
9793 		return errno;
9794 	}
9795 
9796 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_FIXED) {
9797 		errno = wma_cli_set_command(link_info->vdev_id,
9798 					    wmi_pdev_param_ani_ofdm_level,
9799 					    ani_level, PDEV_CMD);
9800 		if (errno) {
9801 			hdd_err("Failed to set ani level, errno %d", errno);
9802 			return errno;
9803 		}
9804 	}
9805 
9806 	return 0;
9807 }
9808 
hdd_config_ant_div_period(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9809 static int hdd_config_ant_div_period(struct wlan_hdd_link_info *link_info,
9810 				     struct nlattr *tb[])
9811 {
9812 	struct nlattr *probe_attr =
9813 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD];
9814 	struct nlattr *stay_attr =
9815 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD];
9816 	uint32_t probe_period, stay_period, ant_div_usrcfg;
9817 	int errno;
9818 
9819 	/* nothing to do if neither attribute is present */
9820 	if (!probe_attr && !stay_attr)
9821 		return 0;
9822 
9823 	/* if one is present, both must be present */
9824 	if (!probe_attr || !stay_attr) {
9825 		hdd_err("Missing attribute for %s",
9826 			probe_attr ? "STAY" : "PROBE");
9827 		return -EINVAL;
9828 	}
9829 
9830 	probe_period = nla_get_u32(probe_attr);
9831 	stay_period = nla_get_u32(stay_attr);
9832 	ant_div_usrcfg = ANT_DIV_SET_PERIOD(probe_period, stay_period);
9833 	hdd_debug("ant div set period: %x", ant_div_usrcfg);
9834 	errno = wma_cli_set_command(link_info->vdev_id,
9835 				    wmi_pdev_param_ant_div_usrcfg,
9836 				    ant_div_usrcfg, PDEV_CMD);
9837 	if (errno)
9838 		hdd_err("Failed to set ant div period, %d", errno);
9839 
9840 	return errno;
9841 }
9842 
hdd_config_ant_div_snr_weight(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])9843 static int hdd_config_ant_div_snr_weight(struct wlan_hdd_link_info *link_info,
9844 					 struct nlattr *tb[])
9845 {
9846 	struct nlattr *mgmt_attr =
9847 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT];
9848 	struct nlattr *data_attr =
9849 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT];
9850 	struct nlattr *ack_attr =
9851 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT];
9852 	uint32_t mgmt_snr, data_snr, ack_snr, ant_div_usrcfg;
9853 	int errno;
9854 
9855 	/* nothing to do if none of the attributes are present */
9856 	if (!mgmt_attr && !data_attr && !ack_attr)
9857 		return 0;
9858 
9859 	/* if one is present, all must be present */
9860 	if (!mgmt_attr || !data_attr || !ack_attr) {
9861 		hdd_err("Missing attribute");
9862 		return -EINVAL;
9863 	}
9864 
9865 	mgmt_snr = nla_get_u32(mgmt_attr);
9866 	data_snr = nla_get_u32(data_attr);
9867 	ack_snr = nla_get_u32(ack_attr);
9868 	ant_div_usrcfg = ANT_DIV_SET_WEIGHT(mgmt_snr, data_snr, ack_snr);
9869 	hdd_debug("ant div set weight: %x", ant_div_usrcfg);
9870 	errno = wma_cli_set_command(link_info->vdev_id,
9871 				    wmi_pdev_param_ant_div_usrcfg,
9872 				    ant_div_usrcfg, PDEV_CMD);
9873 	if (errno)
9874 		hdd_err("Failed to set ant div weight, %d", errno);
9875 
9876 	return errno;
9877 }
9878 
9879 static int
hdd_config_fine_time_measurement(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9880 hdd_config_fine_time_measurement(struct wlan_hdd_link_info *link_info,
9881 				 const struct nlattr *attr)
9882 {
9883 	struct hdd_adapter *adapter = link_info->adapter;
9884 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9885 	uint32_t user_capability;
9886 	uint32_t target_capability;
9887 	uint32_t final_capability;
9888 	QDF_STATUS status;
9889 
9890 	user_capability = nla_get_u32(attr);
9891 	target_capability = hdd_ctx->fine_time_meas_cap_target;
9892 	final_capability = user_capability & target_capability;
9893 
9894 	status = ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
9895 						  final_capability);
9896 	if (QDF_IS_STATUS_ERROR(status)) {
9897 		hdd_err("Unable to set value, status %d", status);
9898 		return -EINVAL;
9899 	}
9900 
9901 	sme_update_fine_time_measurement_capab(hdd_ctx->mac_handle,
9902 					       link_info->vdev_id,
9903 					       final_capability);
9904 	ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, final_capability);
9905 
9906 	hdd_debug("user: 0x%x, target: 0x%x, final: 0x%x",
9907 		  user_capability, target_capability, final_capability);
9908 
9909 	return 0;
9910 }
9911 
hdd_config_dynamic_dtim(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9912 static int hdd_config_dynamic_dtim(struct wlan_hdd_link_info *link_info,
9913 				   const struct nlattr *attr)
9914 {
9915 	struct wlan_objmgr_vdev *vdev;
9916 	uint32_t modulated_dtim;
9917 	QDF_STATUS status;
9918 
9919 	modulated_dtim = nla_get_u32(attr);
9920 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
9921 	if (!vdev)
9922 		return -EINVAL;
9923 
9924 	status = ucfg_pmo_config_modulated_dtim(vdev, modulated_dtim);
9925 
9926 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9927 
9928 	return qdf_status_to_os_return(status);
9929 }
9930 
hdd_config_listen_interval(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9931 static int hdd_config_listen_interval(struct wlan_hdd_link_info *link_info,
9932 				      const struct nlattr *attr)
9933 {
9934 	struct wlan_objmgr_vdev *vdev;
9935 	uint32_t listen_interval;
9936 	QDF_STATUS status;
9937 
9938 	listen_interval = nla_get_u32(attr);
9939 	if (listen_interval > cfg_max(CFG_PMO_ENABLE_DYNAMIC_DTIM)) {
9940 		hdd_err_rl("Invalid value for listen interval - %d",
9941 			   listen_interval);
9942 		return -EINVAL;
9943 	}
9944 
9945 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_PMO_ID);
9946 	if (!vdev)
9947 		return -EINVAL;
9948 
9949 	status = ucfg_pmo_config_listen_interval(vdev, listen_interval);
9950 
9951 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_PMO_ID);
9952 
9953 	return qdf_status_to_os_return(status);
9954 }
9955 
hdd_config_lro(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9956 static int hdd_config_lro(struct wlan_hdd_link_info *link_info,
9957 			  const struct nlattr *attr)
9958 {
9959 	struct wlan_objmgr_vdev *vdev;
9960 	uint8_t enable_flag;
9961 	QDF_STATUS status = QDF_STATUS_E_FAULT;
9962 
9963 	enable_flag = nla_get_u8(attr);
9964 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_DP_ID);
9965 	if (vdev) {
9966 		status = osif_dp_lro_set_reset(vdev, enable_flag);
9967 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
9968 	}
9969 
9970 	return qdf_status_to_os_return(status);
9971 }
9972 
hdd_config_scan_enable(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9973 static int hdd_config_scan_enable(struct wlan_hdd_link_info *link_info,
9974 				  const struct nlattr *attr)
9975 {
9976 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9977 	uint8_t enable_flag;
9978 
9979 	enable_flag = nla_get_u8(attr);
9980 	if (enable_flag)
9981 		ucfg_scan_psoc_set_enable(hdd_ctx->psoc, REASON_USER_SPACE);
9982 	else
9983 		ucfg_scan_psoc_set_disable(hdd_ctx->psoc, REASON_USER_SPACE);
9984 
9985 	return 0;
9986 }
9987 
9988 /**
9989  * hdd_config_udp_qos_upgrade_be_bk() - Set UDP QoS threshold for BE/BK AC.
9990  * @link_info: Link info pointer in HDD adapter
9991  * @attr: NL attribute
9992  *
9993  * Returns: 0 on success, -EINVAL on failure
9994  */
9995 static int
hdd_config_udp_qos_upgrade_be_bk(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)9996 hdd_config_udp_qos_upgrade_be_bk(struct wlan_hdd_link_info *link_info,
9997 				 const struct nlattr *attr)
9998 {
9999 	struct hdd_adapter *adapter = link_info->adapter;
10000 	uint8_t priority = nla_get_u8(attr);
10001 
10002 	adapter->udp_qos_upgrade_type = UDP_QOS_UPGRADE_BK_BE;
10003 	return hdd_set_udp_qos_upgrade_config(adapter, priority);
10004 }
10005 
10006 /**
10007  * hdd_config_udp_qos_upgrade_threshold() - NL attribute handler to parse
10008  *					    priority upgrade threshold value.
10009  * @link_info: Link info pointer in adapter
10010  * @attr: NL attribute
10011  *
10012  * Returns: 0 on success, -EINVAL on failure
10013  */
10014 static int
hdd_config_udp_qos_upgrade_threshold(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10015 hdd_config_udp_qos_upgrade_threshold(struct wlan_hdd_link_info *link_info,
10016 				     const struct nlattr *attr)
10017 {
10018 	struct hdd_adapter *adapter = link_info->adapter;
10019 	uint8_t priority = nla_get_u8(attr);
10020 
10021 	adapter->udp_qos_upgrade_type = UDP_QOS_UPGRADE_ALL;
10022 	return hdd_set_udp_qos_upgrade_config(adapter, priority);
10023 }
10024 
10025 static enum powersave_mode
hdd_vendor_opm_to_pmo_opm(enum qca_wlan_vendor_opm_mode opm_mode)10026 hdd_vendor_opm_to_pmo_opm(enum qca_wlan_vendor_opm_mode opm_mode)
10027 {
10028 	switch (opm_mode) {
10029 	case QCA_WLAN_VENDOR_OPM_MODE_DISABLE:
10030 		return PMO_PS_ADVANCED_POWER_SAVE_DISABLE;
10031 	case QCA_WLAN_VENDOR_OPM_MODE_ENABLE:
10032 		return PMO_PS_ADVANCED_POWER_SAVE_ENABLE;
10033 	case QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED:
10034 		return PMO_PS_ADVANCED_POWER_SAVE_USER_DEFINED;
10035 	default:
10036 		hdd_debug("Invalid opm_mode: %d", opm_mode);
10037 		return PMO_PS_ADVANCED_POWER_SAVE_DISABLE;
10038 	}
10039 }
10040 
hdd_config_power(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])10041 static int hdd_config_power(struct wlan_hdd_link_info *link_info,
10042 			    struct nlattr *tb[])
10043 {
10044 	struct hdd_adapter *adapter = link_info->adapter;
10045 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10046 	struct wlan_objmgr_vdev *vdev;
10047 	enum qca_wlan_vendor_opm_mode opm_mode;
10048 	struct pmo_ps_params ps_params = {0};
10049 	struct nlattr *power_attr =
10050 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER];
10051 	struct nlattr *opm_attr =
10052 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT];
10053 	struct nlattr *ps_ito_attr =
10054 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_ITO];
10055 	struct nlattr *spec_wake_attr =
10056 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_SPEC_WAKE_INTERVAL];
10057 	int ret;
10058 
10059 	hdd_enter_dev(adapter->dev);
10060 
10061 	if (!power_attr && !opm_attr) {
10062 		hdd_err_rl("power attr and opm attr is null");
10063 		return 0;
10064 	}
10065 
10066 
10067 	if (power_attr && opm_attr) {
10068 		hdd_err_rl("Invalid OPM set attribute");
10069 		return -EINVAL;
10070 	}
10071 
10072 	if (!ucfg_pmo_get_default_power_save_mode(hdd_ctx->psoc)) {
10073 		hdd_err_rl("OPM power save is disabled in ini");
10074 		return -EINVAL;
10075 	}
10076 
10077 	opm_mode = power_attr ? nla_get_u8(power_attr) : nla_get_u8(opm_attr);
10078 	hdd_debug("opm_mode %d", opm_mode);
10079 
10080 	if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) {
10081 		if (!ps_ito_attr || !spec_wake_attr) {
10082 			hdd_err_rl("Invalid User defined OPM attributes");
10083 			return -EINVAL;
10084 		}
10085 	}
10086 
10087 	ret = hdd_set_power_config(hdd_ctx, adapter, &opm_mode);
10088 	if (ret)
10089 		return ret;
10090 
10091 	ps_params.opm_mode = hdd_vendor_opm_to_pmo_opm(opm_mode);
10092 	if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) {
10093 		ps_params.ps_ito = nla_get_u16(ps_ito_attr);
10094 		ps_params.spec_wake = nla_get_u16(spec_wake_attr);
10095 
10096 		if (!ps_params.ps_ito)
10097 			return -EINVAL;
10098 
10099 		hdd_debug("ps_ito %d spec_wake %d opm_mode %d",
10100 			  ps_params.ps_ito, ps_params.spec_wake,
10101 			  ps_params.opm_mode);
10102 
10103 		ret = hdd_set_power_config_params(hdd_ctx, adapter,
10104 						  ps_params.ps_ito,
10105 						  ps_params.spec_wake);
10106 
10107 		if (ret)
10108 			return ret;
10109 	}
10110 
10111 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_POWER_ID);
10112 	if (!vdev) {
10113 		hdd_err("vdev is null");
10114 		return 0;
10115 	}
10116 
10117 	if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED)
10118 		ucfg_pmo_set_ps_params(vdev, &ps_params);
10119 	else
10120 		ucfg_pmo_core_vdev_set_ps_opm_mode(vdev, ps_params.opm_mode);
10121 
10122 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
10123 	return 0;
10124 }
10125 
hdd_config_stats_avg_factor(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10126 static int hdd_config_stats_avg_factor(struct wlan_hdd_link_info *link_info,
10127 				       const struct nlattr *attr)
10128 {
10129 	struct hdd_adapter *adapter = link_info->adapter;
10130 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10131 	uint16_t stats_avg_factor;
10132 	QDF_STATUS status;
10133 
10134 	stats_avg_factor = nla_get_u16(attr);
10135 	status = sme_configure_stats_avg_factor(hdd_ctx->mac_handle,
10136 						link_info->vdev_id,
10137 						stats_avg_factor);
10138 
10139 	return qdf_status_to_os_return(status);
10140 }
10141 
hdd_config_non_agg_retry(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10142 static int hdd_config_non_agg_retry(struct wlan_hdd_link_info *link_info,
10143 				    const struct nlattr *attr)
10144 {
10145 	uint8_t retry;
10146 
10147 	retry = nla_get_u8(attr);
10148 	/* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
10149 	retry = (retry > CFG_NON_AGG_RETRY_MAX) ? CFG_NON_AGG_RETRY_MAX :
10150 		((retry < CFG_NON_AGG_RETRY_MIN) ? CFG_NON_AGG_RETRY_MIN :
10151 		  retry);
10152 	hdd_debug("sending Non-Agg Retry Th: %d", retry);
10153 
10154 	return sme_set_vdev_sw_retry(link_info->vdev_id, retry,
10155 				     WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR);
10156 }
10157 
hdd_config_agg_retry(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10158 static int hdd_config_agg_retry(struct wlan_hdd_link_info *link_info,
10159 				const struct nlattr *attr)
10160 {
10161 	uint8_t retry;
10162 
10163 	retry = nla_get_u8(attr);
10164 	/* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
10165 	retry = (retry > CFG_AGG_RETRY_MAX) ? CFG_AGG_RETRY_MAX :
10166 		((retry < CFG_AGG_RETRY_MIN) ? CFG_AGG_RETRY_MIN :
10167 		  retry);
10168 	hdd_debug("sending Agg Retry Th: %d", retry);
10169 
10170 	return sme_set_vdev_sw_retry(link_info->vdev_id, retry,
10171 				     WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR);
10172 }
10173 
hdd_config_mgmt_retry(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10174 static int hdd_config_mgmt_retry(struct wlan_hdd_link_info *link_info,
10175 				 const struct nlattr *attr)
10176 {
10177 	uint8_t retry;
10178 	int param_id;
10179 	uint8_t max_mgmt_retry;
10180 
10181 	retry = nla_get_u8(attr);
10182 	max_mgmt_retry = (cfg_max(CFG_MGMT_RETRY_MAX));
10183 	retry = retry > max_mgmt_retry ?
10184 		max_mgmt_retry : retry;
10185 	param_id = wmi_pdev_param_mgmt_retry_limit;
10186 
10187 	return wma_cli_set_command(link_info->vdev_id, param_id,
10188 				   retry, PDEV_CMD);
10189 }
10190 
hdd_config_ctrl_retry(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10191 static int hdd_config_ctrl_retry(struct wlan_hdd_link_info *link_info,
10192 				 const struct nlattr *attr)
10193 {
10194 	uint8_t retry;
10195 	int param_id;
10196 
10197 	retry = nla_get_u8(attr);
10198 	retry = retry > CFG_CTRL_RETRY_MAX ?
10199 		CFG_CTRL_RETRY_MAX : retry;
10200 	param_id = wmi_pdev_param_ctrl_retry_limit;
10201 
10202 	return wma_cli_set_command(link_info->vdev_id, param_id,
10203 				   retry, PDEV_CMD);
10204 }
10205 
hdd_config_propagation_delay(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10206 static int hdd_config_propagation_delay(struct wlan_hdd_link_info *link_info,
10207 					const struct nlattr *attr)
10208 {
10209 	uint8_t delay;
10210 	uint32_t abs_delay;
10211 	int param_id;
10212 
10213 	delay = nla_get_u8(attr);
10214 	delay = delay > CFG_PROPAGATION_DELAY_MAX ?
10215 				CFG_PROPAGATION_DELAY_MAX : delay;
10216 	abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
10217 	param_id = wmi_pdev_param_propagation_delay;
10218 
10219 	return  wma_cli_set_command(link_info->vdev_id, param_id,
10220 				    abs_delay, PDEV_CMD);
10221 }
10222 
10223 static int
hdd_config_propagation_abs_delay(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10224 hdd_config_propagation_abs_delay(struct wlan_hdd_link_info *link_info,
10225 				 const struct nlattr *attr)
10226 {
10227 	uint32_t abs_delay;
10228 	int param_id;
10229 
10230 	abs_delay = nla_get_u32(attr);
10231 	param_id = wmi_pdev_param_propagation_delay;
10232 
10233 	return wma_cli_set_command(link_info->vdev_id, param_id,
10234 				   abs_delay, PDEV_CMD);
10235 }
10236 
hdd_config_tx_fail_count(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10237 static int hdd_config_tx_fail_count(struct wlan_hdd_link_info *link_info,
10238 				    const struct nlattr *attr)
10239 {
10240 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
10241 	uint32_t tx_fail_count;
10242 	QDF_STATUS status;
10243 
10244 	tx_fail_count = nla_get_u32(attr);
10245 	if (!tx_fail_count)
10246 		return 0;
10247 
10248 	status = sme_update_tx_fail_cnt_threshold(hdd_ctx->mac_handle,
10249 						  link_info->vdev_id,
10250 						  tx_fail_count);
10251 	if (QDF_IS_STATUS_ERROR(status))
10252 		hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
10253 			status);
10254 
10255 	return qdf_status_to_os_return(status);
10256 }
10257 
10258 static int
hdd_config_channel_avoidance_ind(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10259 hdd_config_channel_avoidance_ind(struct wlan_hdd_link_info *link_info,
10260 				 const struct nlattr *attr)
10261 {
10262 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
10263 	uint8_t set_value;
10264 
10265 	set_value = nla_get_u8(attr);
10266 	hdd_debug("set_value: %d", set_value);
10267 
10268 	return hdd_enable_disable_ca_event(hdd_ctx, set_value);
10269 }
10270 
hdd_config_guard_time(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10271 static int hdd_config_guard_time(struct wlan_hdd_link_info *link_info,
10272 				 const struct nlattr *attr)
10273 {
10274 	struct hdd_adapter *adapter = link_info->adapter;
10275 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10276 	uint32_t guard_time;
10277 	QDF_STATUS status;
10278 
10279 	guard_time = nla_get_u32(attr);
10280 	status = sme_configure_guard_time(hdd_ctx->mac_handle,
10281 					  link_info->vdev_id, guard_time);
10282 
10283 	return qdf_status_to_os_return(status);
10284 }
10285 
10286 static int
hdd_config_scan_default_ies(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10287 hdd_config_scan_default_ies(struct wlan_hdd_link_info *link_info,
10288 			    const struct nlattr *attr)
10289 {
10290 	struct hdd_adapter *adapter = link_info->adapter;
10291 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10292 	uint8_t *scan_ie;
10293 	uint16_t scan_ie_len;
10294 	QDF_STATUS status;
10295 	mac_handle_t mac_handle;
10296 
10297 	scan_ie_len = nla_len(attr);
10298 	hdd_debug("IE len %d session %d device mode %d",
10299 		  scan_ie_len, link_info->vdev_id, adapter->device_mode);
10300 
10301 	if (!scan_ie_len) {
10302 		hdd_err("zero-length IE prohibited");
10303 		return -EINVAL;
10304 	}
10305 
10306 	if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
10307 		hdd_err("IE length %d exceeds max of %d",
10308 			scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
10309 		return -EINVAL;
10310 	}
10311 
10312 	scan_ie = nla_data(attr);
10313 	if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
10314 		hdd_err("Invalid default scan IEs");
10315 		return -EINVAL;
10316 	}
10317 
10318 	if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
10319 					   scan_ie, scan_ie_len))
10320 		hdd_err("Failed to save default scan IEs");
10321 
10322 	if (adapter->device_mode == QDF_STA_MODE) {
10323 		mac_handle = hdd_ctx->mac_handle;
10324 		status = sme_set_default_scan_ie(mac_handle,
10325 						 link_info->vdev_id,
10326 						 scan_ie, scan_ie_len);
10327 		if (QDF_STATUS_SUCCESS != status) {
10328 			hdd_err("failed to set default scan IEs in sme: %d",
10329 				status);
10330 			return -EPERM;
10331 		}
10332 	}
10333 
10334 	return 0;
10335 }
10336 
hdd_config_ant_div_ena(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10337 static int hdd_config_ant_div_ena(struct wlan_hdd_link_info *link_info,
10338 				  const struct nlattr *attr)
10339 {
10340 	uint32_t antdiv_enable;
10341 	int errno;
10342 
10343 	antdiv_enable = nla_get_u32(attr);
10344 	hdd_debug("antdiv_enable: %d", antdiv_enable);
10345 	errno = wma_cli_set_command(link_info->vdev_id,
10346 				    wmi_pdev_param_ena_ant_div,
10347 				    antdiv_enable, PDEV_CMD);
10348 	if (errno)
10349 		hdd_err("Failed to set antdiv_enable, %d", errno);
10350 
10351 	return errno;
10352 }
10353 
hdd_config_ant_div_snr_diff(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10354 static int hdd_config_ant_div_snr_diff(struct wlan_hdd_link_info *link_info,
10355 				       const struct nlattr *attr)
10356 {
10357 	uint32_t ant_div_snr_diff;
10358 	uint32_t ant_div_usrcfg;
10359 	int errno;
10360 
10361 	ant_div_snr_diff = nla_get_u32(attr);
10362 	hdd_debug("snr diff: %x", ant_div_snr_diff);
10363 
10364 	ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(ant_div_snr_diff);
10365 	hdd_debug("usrcfg: %x", ant_div_usrcfg);
10366 
10367 	errno = wma_cli_set_command(link_info->vdev_id,
10368 				    wmi_pdev_param_ant_div_usrcfg,
10369 				    ant_div_usrcfg, PDEV_CMD);
10370 	if (errno)
10371 		hdd_err("Failed to set snr diff, %d", errno);
10372 
10373 	return errno;
10374 }
10375 
10376 static int
hdd_config_ant_div_probe_dwell_time(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10377 hdd_config_ant_div_probe_dwell_time(struct wlan_hdd_link_info *link_info,
10378 				    const struct nlattr *attr)
10379 {
10380 	uint32_t dwell_time;
10381 	uint32_t ant_div_usrcfg;
10382 	int errno;
10383 
10384 	dwell_time = nla_get_u32(attr);
10385 	hdd_debug("dwell time: %x", dwell_time);
10386 
10387 	ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(dwell_time);
10388 	hdd_debug("usrcfg: %x", ant_div_usrcfg);
10389 
10390 	errno = wma_cli_set_command(link_info->vdev_id,
10391 				    wmi_pdev_param_ant_div_usrcfg,
10392 				    ant_div_usrcfg, PDEV_CMD);
10393 	if (errno)
10394 		hdd_err("Failed to set probe dwell time, %d", errno);
10395 
10396 	return errno;
10397 }
10398 
hdd_config_ant_div_chain(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10399 static int hdd_config_ant_div_chain(struct wlan_hdd_link_info *link_info,
10400 				    const struct nlattr *attr)
10401 {
10402 	uint32_t antdiv_chain;
10403 	int errno;
10404 
10405 	antdiv_chain = nla_get_u32(attr);
10406 	hdd_debug("antdiv_chain: %d", antdiv_chain);
10407 
10408 	errno = wma_cli_set_command(link_info->vdev_id,
10409 				    wmi_pdev_param_force_chain_ant,
10410 				    antdiv_chain, PDEV_CMD);
10411 	if (errno)
10412 		hdd_err("Failed to set chain, %d", errno);
10413 
10414 	return errno;
10415 }
10416 
hdd_config_ant_div_selftest(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10417 static int hdd_config_ant_div_selftest(struct wlan_hdd_link_info *link_info,
10418 				       const struct nlattr *attr)
10419 {
10420 	uint32_t antdiv_selftest;
10421 	int errno;
10422 
10423 	antdiv_selftest = nla_get_u32(attr);
10424 	hdd_debug("antdiv_selftest: %d", antdiv_selftest);
10425 	errno = wma_cli_set_command(link_info->vdev_id,
10426 				    wmi_pdev_param_ant_div_selftest,
10427 				    antdiv_selftest, PDEV_CMD);
10428 	if (errno)
10429 		hdd_err("Failed to set selftest, %d", errno);
10430 
10431 	return errno;
10432 }
10433 
10434 static int
hdd_config_ant_div_selftest_intvl(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10435 hdd_config_ant_div_selftest_intvl(struct wlan_hdd_link_info *link_info,
10436 				  const struct nlattr *attr)
10437 {
10438 	uint32_t antdiv_selftest_intvl;
10439 	int errno;
10440 
10441 	antdiv_selftest_intvl = nla_get_u32(attr);
10442 	hdd_debug("antdiv_selftest_intvl: %d", antdiv_selftest_intvl);
10443 	errno = wma_cli_set_command(link_info->vdev_id,
10444 				    wmi_pdev_param_ant_div_selftest_intvl,
10445 				    antdiv_selftest_intvl, PDEV_CMD);
10446 	if (errno)
10447 		hdd_err("Failed to set selftest interval, %d", errno);
10448 
10449 	return errno;
10450 }
10451 
10452 static int
hdd_config_ignore_assoc_disallowed(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10453 hdd_config_ignore_assoc_disallowed(struct wlan_hdd_link_info *link_info,
10454 				   const struct nlattr *attr)
10455 {
10456 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
10457 	uint8_t ignore_assoc_disallowed;
10458 
10459 	ignore_assoc_disallowed = nla_get_u8(attr);
10460 	hdd_debug("%u", ignore_assoc_disallowed);
10461 	if ((ignore_assoc_disallowed < QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
10462 	    (ignore_assoc_disallowed > QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
10463 		return -EINVAL;
10464 
10465 	sme_set_check_assoc_disallowed(hdd_ctx->mac_handle,
10466 				       !ignore_assoc_disallowed);
10467 
10468 	return 0;
10469 }
10470 
hdd_config_restrict_offchannel(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10471 static int hdd_config_restrict_offchannel(struct wlan_hdd_link_info *link_info,
10472 					  const struct nlattr *attr)
10473 {
10474 	uint8_t restrict_offchan;
10475 
10476 	restrict_offchan = nla_get_u8(attr);
10477 	hdd_debug("%u", restrict_offchan);
10478 
10479 	if (restrict_offchan > 1) {
10480 		hdd_err("Invalid value %u", restrict_offchan);
10481 		return -EINVAL;
10482 	}
10483 
10484 	return wlan_hdd_handle_restrict_offchan_config(link_info->adapter,
10485 						       restrict_offchan);
10486 }
10487 
10488 static int
hdd_config_total_beacon_miss_count(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10489 hdd_config_total_beacon_miss_count(struct wlan_hdd_link_info *link_info,
10490 				   const struct nlattr *attr)
10491 {
10492 	struct hdd_adapter *adapter = link_info->adapter;
10493 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10494 	uint8_t first_miss_count;
10495 	uint8_t final_miss_count;
10496 	uint8_t total_miss_count;
10497 	QDF_STATUS status;
10498 
10499 	if (adapter->device_mode != QDF_STA_MODE) {
10500 		hdd_err("Only supported in sta mode");
10501 		return -EINVAL;
10502 	}
10503 
10504 	total_miss_count = nla_get_u8(attr);
10505 	ucfg_mlme_get_roam_bmiss_first_bcnt(hdd_ctx->psoc,
10506 					    &first_miss_count);
10507 	if (total_miss_count <= first_miss_count) {
10508 		hdd_err("Total %u needs to exceed first %u",
10509 			total_miss_count, first_miss_count);
10510 		return -EINVAL;
10511 	}
10512 
10513 	final_miss_count = total_miss_count - first_miss_count;
10514 
10515 	if (!ucfg_mlme_validate_roam_bmiss_final_bcnt(final_miss_count))
10516 		return -EINVAL;
10517 
10518 	hdd_debug("First count %u, final count %u",
10519 		  first_miss_count, final_miss_count);
10520 
10521 	status = sme_set_roam_bmiss_final_bcnt(hdd_ctx->mac_handle,
10522 					       link_info->vdev_id,
10523 					       final_miss_count);
10524 	if (QDF_IS_STATUS_ERROR(status)) {
10525 		hdd_err("Failed to set final count, status %u", status);
10526 		return qdf_status_to_os_return(status);
10527 	}
10528 
10529 	status = sme_set_bmiss_bcnt(link_info->vdev_id,
10530 				    first_miss_count,
10531 				    final_miss_count);
10532 	if (QDF_IS_STATUS_ERROR(status))
10533 		hdd_err("Failed to set count, status %u", status);
10534 
10535 	return qdf_status_to_os_return(status);
10536 }
10537 
10538 #ifdef WLAN_FEATURE_LL_MODE
10539 static inline
wlan_hdd_set_wlm_mode(struct hdd_context * hdd_ctx,uint16_t latency_level)10540 void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level)
10541 {
10542 	if (latency_level ==
10543 		QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW)
10544 		wlan_hdd_set_pm_qos_request(hdd_ctx, true);
10545 	else
10546 		wlan_hdd_set_pm_qos_request(hdd_ctx, false);
10547 }
10548 #else
10549 static inline
wlan_hdd_set_wlm_mode(struct hdd_context * hdd_ctx,uint16_t latency_level)10550 void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level)
10551 {
10552 }
10553 #endif
10554 
10555 /**
10556  * hdd_set_wlm_host_latency_level() - set latency flags based on latency flags
10557  * @hdd_ctx: hdd context
10558  * @adapter: adapter context
10559  * @latency_host_flags: host latency flags
10560  *
10561  * Return: none
10562  */
hdd_set_wlm_host_latency_level(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,uint32_t latency_host_flags)10563 static void hdd_set_wlm_host_latency_level(struct hdd_context *hdd_ctx,
10564 					   struct hdd_adapter *adapter,
10565 					   uint32_t latency_host_flags)
10566 {
10567 	ol_txrx_soc_handle soc_hdl = cds_get_context(QDF_MODULE_ID_SOC);
10568 	struct wlan_objmgr_vdev *vdev;
10569 
10570 	if (!soc_hdl)
10571 		return;
10572 
10573 	if (latency_host_flags & WLM_HOST_PM_QOS_FLAG) {
10574 		hdd_ctx->pm_qos_request_flags |=
10575 					(1 << adapter->deflink->vdev_id);
10576 	} else {
10577 		hdd_ctx->pm_qos_request_flags &=
10578 					~(1 << adapter->deflink->vdev_id);
10579 	}
10580 
10581 	if (hdd_ctx->pm_qos_request_flags)
10582 		wlan_hdd_set_pm_qos_request(hdd_ctx, true);
10583 	else
10584 		wlan_hdd_set_pm_qos_request(hdd_ctx, false);
10585 
10586 	if (latency_host_flags & WLM_HOST_HBB_FLAG)
10587 		ucfg_dp_set_high_bus_bw_request(hdd_ctx->psoc,
10588 						adapter->deflink->vdev_id,
10589 						true);
10590 	else
10591 		ucfg_dp_set_high_bus_bw_request(hdd_ctx->psoc,
10592 						adapter->deflink->vdev_id,
10593 						false);
10594 
10595 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
10596 	if (!vdev)
10597 		return;
10598 
10599 	if (latency_host_flags & WLM_HOST_RX_THREAD_FLAG)
10600 		ucfg_dp_runtime_disable_rx_thread(vdev, true);
10601 	else
10602 		ucfg_dp_runtime_disable_rx_thread(vdev, false);
10603 
10604 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
10605 }
10606 
10607 #ifdef MULTI_CLIENT_LL_SUPPORT
10608 void
hdd_latency_level_event_handler_cb(const struct latency_level_data * event_data,uint8_t vdev_id)10609 hdd_latency_level_event_handler_cb(const struct latency_level_data *event_data,
10610 				   uint8_t vdev_id)
10611 {
10612 	struct osif_request *request;
10613 	struct latency_level_data *data;
10614 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10615 	struct hdd_adapter *hdd_adapter;
10616 	uint32_t latency_host_flags = 0;
10617 	QDF_STATUS status;
10618 	struct wlan_hdd_link_info *link_info;
10619 
10620 	hdd_enter();
10621 
10622 	if (wlan_hdd_validate_context(hdd_ctx))
10623 		return;
10624 
10625 	if (!event_data) {
10626 		hdd_err("Invalid latency level event data");
10627 		return;
10628 	}
10629 
10630 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
10631 	if (!link_info) {
10632 		hdd_err("adapter is NULL vdev_id = %d", vdev_id);
10633 		return;
10634 	}
10635 
10636 	hdd_adapter = link_info->adapter;
10637 	if (hdd_adapter->multi_ll_resp_expected) {
10638 		request =
10639 			osif_request_get(hdd_adapter->multi_ll_response_cookie);
10640 		if (!request) {
10641 			hdd_err("Invalid request");
10642 			return;
10643 		}
10644 		data = osif_request_priv(request);
10645 		data->latency_level = event_data->latency_level;
10646 		data->vdev_id = event_data->vdev_id;
10647 		osif_request_complete(request);
10648 		osif_request_put(request);
10649 	} else {
10650 		hdd_adapter->latency_level = event_data->latency_level;
10651 		wlan_hdd_set_wlm_mode(hdd_ctx, hdd_adapter->latency_level);
10652 		hdd_debug("adapter->latency_level:%d",
10653 			  hdd_adapter->latency_level);
10654 		status = ucfg_mlme_get_latency_host_flags(hdd_ctx->psoc,
10655 						hdd_adapter->latency_level,
10656 						&latency_host_flags);
10657 		if (QDF_IS_STATUS_ERROR(status))
10658 			hdd_err("failed to get latency host flags");
10659 		else
10660 			hdd_set_wlm_host_latency_level(hdd_ctx, hdd_adapter,
10661 						       latency_host_flags);
10662 		}
10663 
10664 	hdd_exit();
10665 }
10666 
wlan_hdd_get_client_id_bitmap(struct hdd_adapter * adapter)10667 uint8_t wlan_hdd_get_client_id_bitmap(struct hdd_adapter *adapter)
10668 {
10669 	uint8_t i, client_id_bitmap = 0;
10670 
10671 	for (i = 0; i < WLM_MAX_HOST_CLIENT; i++) {
10672 		if (!adapter->client_info[i].in_use)
10673 			continue;
10674 		client_id_bitmap |=
10675 			BIT(adapter->client_info[i].client_id);
10676 	}
10677 
10678 	return client_id_bitmap;
10679 }
10680 
wlan_hdd_get_set_client_info_id(struct hdd_adapter * adapter,uint32_t port_id,uint32_t * client_id)10681 QDF_STATUS wlan_hdd_get_set_client_info_id(struct hdd_adapter *adapter,
10682 					   uint32_t port_id,
10683 					   uint32_t *client_id)
10684 {
10685 	uint8_t i;
10686 	QDF_STATUS status = QDF_STATUS_E_INVAL;
10687 
10688 	for (i = 0; i < WLM_MAX_HOST_CLIENT; i++) {
10689 		if (adapter->client_info[i].in_use) {
10690 			/* Receives set latency cmd for an existing port id */
10691 			if (port_id == adapter->client_info[i].port_id) {
10692 				*client_id = adapter->client_info[i].client_id;
10693 				status = QDF_STATUS_SUCCESS;
10694 				break;
10695 			}
10696 			continue;
10697 		} else {
10698 			/* Process set latency level from a new client */
10699 			adapter->client_info[i].in_use = true;
10700 			adapter->client_info[i].port_id = port_id;
10701 			*client_id = adapter->client_info[i].client_id;
10702 			status = QDF_STATUS_SUCCESS;
10703 			break;
10704 		}
10705 	}
10706 
10707 	if (i == WLM_MAX_HOST_CLIENT)
10708 		hdd_debug("Max client ID reached");
10709 
10710 	return status;
10711 }
10712 
wlan_hdd_set_wlm_latency_level(struct hdd_adapter * adapter,uint16_t latency_level,uint32_t client_id_bitmap,bool force_reset)10713 QDF_STATUS wlan_hdd_set_wlm_latency_level(struct hdd_adapter *adapter,
10714 					  uint16_t latency_level,
10715 					  uint32_t client_id_bitmap,
10716 					  bool force_reset)
10717 {
10718 	QDF_STATUS status;
10719 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10720 	int ret;
10721 	struct osif_request *request = NULL;
10722 	struct latency_level_data *priv;
10723 	static const struct osif_request_params params = {
10724 		.priv_size = sizeof(*priv),
10725 		.timeout_ms = WLAN_WAIT_WLM_LATENCY_LEVEL,
10726 		.dealloc = NULL,
10727 	};
10728 
10729 	/* ignore unless in STA mode */
10730 	if (adapter->device_mode != QDF_STA_MODE) {
10731 		hdd_debug_rl("WLM offload is supported in STA mode only");
10732 		return QDF_STATUS_E_FAILURE;
10733 	}
10734 
10735 	adapter->multi_ll_resp_expected = true;
10736 
10737 	request = osif_request_alloc(&params);
10738 	if (!request) {
10739 		hdd_err("Request allocation failure");
10740 		return QDF_STATUS_E_FAILURE;
10741 	}
10742 	adapter->multi_ll_response_cookie = osif_request_cookie(request);
10743 	adapter->multi_ll_req_in_progress = true;
10744 
10745 	status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
10746 					   adapter->deflink->vdev_id,
10747 					   latency_level, client_id_bitmap,
10748 					   force_reset);
10749 	if (QDF_IS_STATUS_ERROR(status)) {
10750 		hdd_err("Failure while sending command to fw");
10751 		goto err;
10752 	}
10753 
10754 	ret = osif_request_wait_for_response(request);
10755 	if (ret) {
10756 		hdd_err("SME timed out while retrieving latency level");
10757 		status = qdf_status_from_os_return(ret);
10758 		goto err;
10759 	}
10760 	priv = osif_request_priv(request);
10761 	if (!priv) {
10762 		hdd_err("invalid get latency level");
10763 		status = QDF_STATUS_E_FAILURE;
10764 		goto err;
10765 	}
10766 
10767 	hdd_debug("latency level received from FW:%d", priv->latency_level);
10768 	adapter->latency_level = priv->latency_level;
10769 err:
10770 	if (request)
10771 		osif_request_put(request);
10772 	adapter->multi_ll_req_in_progress = false;
10773 	adapter->multi_ll_resp_expected = false;
10774 	adapter->multi_ll_response_cookie = NULL;
10775 
10776 	return status;
10777 }
10778 
hdd_get_multi_client_ll_support(struct hdd_adapter * adapter)10779 bool hdd_get_multi_client_ll_support(struct hdd_adapter *adapter)
10780 {
10781 	return adapter->multi_client_ll_support;
10782 }
10783 
10784 /**
10785  * wlan_hdd_reset_client_info() - reset multi client info table
10786  * @adapter: adapter context
10787  * @client_id: client id
10788  *
10789  * Return: none
10790  */
wlan_hdd_reset_client_info(struct hdd_adapter * adapter,uint32_t client_id)10791 static void wlan_hdd_reset_client_info(struct hdd_adapter *adapter,
10792 				       uint32_t client_id)
10793 {
10794 	adapter->client_info[client_id].in_use = false;
10795 	adapter->client_info[client_id].port_id = 0;
10796 	adapter->client_info[client_id].client_id = client_id;
10797 }
10798 
wlan_hdd_set_wlm_client_latency_level(struct hdd_adapter * adapter,uint32_t port_id,uint16_t latency_level)10799 QDF_STATUS wlan_hdd_set_wlm_client_latency_level(struct hdd_adapter *adapter,
10800 						 uint32_t port_id,
10801 						 uint16_t latency_level)
10802 {
10803 	uint32_t client_id, client_id_bitmap;
10804 	QDF_STATUS status;
10805 
10806 	status = wlan_hdd_get_set_client_info_id(adapter, port_id,
10807 						 &client_id);
10808 	if (QDF_IS_STATUS_ERROR(status))
10809 		return status;
10810 
10811 	client_id_bitmap = BIT(client_id);
10812 	status = wlan_hdd_set_wlm_latency_level(adapter,
10813 						latency_level,
10814 						client_id_bitmap,
10815 						false);
10816 	if (QDF_IS_STATUS_ERROR(status)) {
10817 		hdd_debug("Fail to set latency level for client_id:%d",
10818 			  client_id);
10819 		wlan_hdd_reset_client_info(adapter, client_id);
10820 		return status;
10821 	}
10822 	return status;
10823 }
10824 
10825 /**
10826  * wlan_hdd_get_multi_ll_req_in_progress() - get multi_ll_req_in_progress flag
10827  * @adapter: adapter context
10828  *
10829  * Return: true if multi ll req in progress
10830  */
wlan_hdd_get_multi_ll_req_in_progress(struct hdd_adapter * adapter)10831 static bool wlan_hdd_get_multi_ll_req_in_progress(struct hdd_adapter *adapter)
10832 {
10833 	return adapter->multi_ll_req_in_progress;
10834 }
10835 #else
10836 static inline bool
wlan_hdd_get_multi_ll_req_in_progress(struct hdd_adapter * adapter)10837 wlan_hdd_get_multi_ll_req_in_progress(struct hdd_adapter *adapter)
10838 {
10839 	return false;
10840 }
10841 #endif
10842 
10843 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
hdd_get_netlink_sender_portid(struct hdd_context * hdd_ctx,uint32_t * port_id)10844 static QDF_STATUS hdd_get_netlink_sender_portid(struct hdd_context *hdd_ctx,
10845 						uint32_t *port_id)
10846 {
10847 	struct wiphy *wiphy = hdd_ctx->wiphy;
10848 
10849 	/* get netlink portid of sender */
10850 	*port_id =  cfg80211_vendor_cmd_get_sender(wiphy);
10851 
10852 	return QDF_STATUS_SUCCESS;
10853 }
10854 #else
10855 static inline QDF_STATUS
hdd_get_netlink_sender_portid(struct hdd_context * hdd_ctx,uint32_t * port_id)10856 hdd_get_netlink_sender_portid(struct hdd_context *hdd_ctx, uint32_t *port_id)
10857 {
10858 	return QDF_STATUS_E_NOSUPPORT;
10859 }
10860 #endif
10861 
hdd_config_latency_level(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10862 static int hdd_config_latency_level(struct wlan_hdd_link_info *link_info,
10863 				    const struct nlattr *attr)
10864 {
10865 	struct hdd_adapter *adapter = link_info->adapter;
10866 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10867 	uint32_t port_id;
10868 	uint16_t latency_level, host_latency_level;
10869 	QDF_STATUS status;
10870 	uint32_t latency_host_flags = 0;
10871 	int ret;
10872 
10873 	if (hdd_validate_adapter(adapter))
10874 		return -EINVAL;
10875 
10876 	if (!hdd_is_wlm_latency_manager_supported(hdd_ctx))
10877 		return -ENOTSUPP;
10878 
10879 	latency_level = nla_get_u16(attr);
10880 	switch (latency_level) {
10881 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
10882 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR:
10883 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
10884 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
10885 		/* valid values */
10886 		break;
10887 	default:
10888 		hdd_err("Invalid value %u", latency_level);
10889 		return -EINVAL;
10890 	}
10891 
10892 	host_latency_level = latency_level - 1;
10893 
10894 	if (hdd_get_multi_client_ll_support(adapter)) {
10895 		if (wlan_hdd_get_multi_ll_req_in_progress(adapter)) {
10896 			hdd_err_rl("multi ll request already in progress");
10897 			return -EBUSY;
10898 		}
10899 		/* get netlink portid of sender */
10900 		status = hdd_get_netlink_sender_portid(hdd_ctx, &port_id);
10901 		if (QDF_IS_STATUS_ERROR(status))
10902 			goto error;
10903 		status = wlan_hdd_set_wlm_client_latency_level(adapter, port_id,
10904 							host_latency_level);
10905 		if (QDF_IS_STATUS_ERROR(status)) {
10906 			hdd_debug("Fail to set latency level");
10907 			goto error;
10908 		}
10909 	} else {
10910 		status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
10911 						   link_info->vdev_id,
10912 						   host_latency_level, 0,
10913 						   false);
10914 		if (QDF_IS_STATUS_ERROR(status)) {
10915 			hdd_err("set latency level failed, %u", status);
10916 			goto error;
10917 		}
10918 		adapter->latency_level = host_latency_level;
10919 	}
10920 
10921 	wlan_hdd_set_wlm_mode(hdd_ctx, adapter->latency_level);
10922 	hdd_debug("adapter->latency_level:%d", adapter->latency_level);
10923 
10924 	status = ucfg_mlme_get_latency_host_flags(hdd_ctx->psoc,
10925 						  adapter->latency_level,
10926 						  &latency_host_flags);
10927 	if (QDF_IS_STATUS_ERROR(status))
10928 		hdd_err("failed to get latency host flags");
10929 	else
10930 		hdd_set_wlm_host_latency_level(hdd_ctx, adapter,
10931 					       latency_host_flags);
10932 error:
10933 	ret = qdf_status_to_os_return(status);
10934 
10935 	return ret;
10936 }
10937 
hdd_config_disable_fils(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10938 static int hdd_config_disable_fils(struct wlan_hdd_link_info *link_info,
10939 				   const struct nlattr *attr)
10940 {
10941 	struct hdd_adapter *adapter = link_info->adapter;
10942 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10943 	uint8_t disable_fils;
10944 	bool enabled;
10945 	QDF_STATUS status;
10946 
10947 	/* ignore unless in STA mode */
10948 	if (adapter->device_mode != QDF_STA_MODE)
10949 		return 0;
10950 
10951 	disable_fils = nla_get_u8(attr);
10952 	hdd_debug("%u", disable_fils);
10953 
10954 	enabled = !disable_fils;
10955 	status = ucfg_mlme_set_fils_enabled_info(hdd_ctx->psoc, enabled);
10956 	if (QDF_IS_STATUS_ERROR(status))
10957 		hdd_err("could not set fils enabled info, %d", status);
10958 
10959 	status = ucfg_mlme_set_enable_bcast_probe_rsp(hdd_ctx->psoc, enabled);
10960 	if (QDF_IS_STATUS_ERROR(status))
10961 		hdd_err("could not set enable bcast probe resp info, %d",
10962 			status);
10963 
10964 	status = wma_cli_set_command(link_info->vdev_id,
10965 				     wmi_vdev_param_enable_bcast_probe_response,
10966 				     !disable_fils, VDEV_CMD);
10967 	if (QDF_IS_STATUS_ERROR(status))
10968 		hdd_err("failed to set enable bcast probe resp, %d",
10969 			status);
10970 
10971 	return qdf_status_to_os_return(status);
10972 }
10973 
hdd_set_primary_interface(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)10974 static int hdd_set_primary_interface(struct wlan_hdd_link_info *link_info,
10975 				     const struct nlattr *attr)
10976 {
10977 	struct hdd_adapter *adapter = link_info->adapter;
10978 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10979 	bool is_set_primary_iface;
10980 	QDF_STATUS status;
10981 	uint8_t vdev_id,  primary_vdev_id, dual_sta_policy;
10982 	int set_value;
10983 	uint32_t count;
10984 	bool enable_mcc_adaptive_sch = false;
10985 
10986 	/* ignore unless in STA mode */
10987 	if (adapter->device_mode != QDF_STA_MODE)
10988 		return 0;
10989 
10990 	is_set_primary_iface = nla_get_u8(attr);
10991 
10992 	vdev_id = link_info->vdev_id;
10993 	primary_vdev_id =
10994 		is_set_primary_iface ? vdev_id : WLAN_UMAC_VDEV_ID_MAX;
10995 
10996 	status = ucfg_mlme_set_primary_interface(hdd_ctx->psoc,
10997 						 primary_vdev_id);
10998 	if (QDF_IS_STATUS_ERROR(status)) {
10999 		hdd_err("could not set primary interface, %d", status);
11000 		return -EINVAL;
11001 	}
11002 
11003 	/* After SSR, the dual sta configuration is lost. As SSR is hidden from
11004 	 * userland, this command will not come from userspace after a SSR. To
11005 	 * restore this configuration, save this in hdd context and restore
11006 	 * after re-init.
11007 	 */
11008 	hdd_ctx->dual_sta_policy.primary_vdev_id = primary_vdev_id;
11009 
11010 	count = policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
11011 							  PM_STA_MODE, NULL);
11012 
11013 	if (count < 2) {
11014 		hdd_debug("STA + STA concurrency not present, count:%d", count);
11015 		return 0;
11016 	}
11017 
11018 	/* If dual sta roaming enabled and sta concurrency on different mac then
11019 	 * no need to enable roaming on primary as both STA's have roaming
11020 	 * enabled.
11021 	 * If dual sta roaming enabled and both sta in MCC or SCC then need
11022 	 * to enable roaming on primary vdev.
11023 	 * If dual sta roaming NOT enabled then need to enable roaming on
11024 	 * primary vdev for sta concurrency on different mac.
11025 	 */
11026 	if (wlan_mlme_is_primary_interface_configured(hdd_ctx->psoc))
11027 		if ((ucfg_mlme_get_dual_sta_roaming_enabled(hdd_ctx->psoc) &&
11028 		     !policy_mgr_concurrent_sta_on_different_mac(hdd_ctx->psoc)) ||
11029 		    !ucfg_mlme_get_dual_sta_roaming_enabled(hdd_ctx->psoc)) {
11030 			hdd_err("Enable roaming on requested interface: %d",
11031 				link_info->vdev_id);
11032 			hdd_debug("Enable roaming on requested interface: %d",
11033 				  link_info->vdev_id);
11034 			wlan_cm_roam_state_change(hdd_ctx->pdev,
11035 						  link_info->vdev_id,
11036 						  WLAN_ROAM_RSO_ENABLED,
11037 						  REASON_ROAM_SET_PRIMARY);
11038 	}
11039 
11040 	/*
11041 	 * send duty cycle percentage to FW only if STA + STA
11042 	 * concurrency is in MCC.
11043 	 */
11044 	if (!policy_mgr_current_concurrency_is_mcc(hdd_ctx->psoc)) {
11045 		hdd_debug("STA + STA concurrency not in MCC");
11046 		return 0;
11047 	}
11048 
11049 	status = ucfg_mlme_get_dual_sta_policy(hdd_ctx->psoc, &dual_sta_policy);
11050 	if (QDF_IS_STATUS_ERROR(status)) {
11051 		hdd_err("could not get dual sta policy, %d", status);
11052 		return -EINVAL;
11053 	}
11054 
11055 	hdd_debug("is_set_primary_iface: %d, primary vdev id: %d, dual_sta_policy:%d",
11056 		  is_set_primary_iface, primary_vdev_id, dual_sta_policy);
11057 
11058 	if (is_set_primary_iface && dual_sta_policy ==
11059 	    QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY) {
11060 		hdd_debug("Disable mcc_adaptive_scheduler");
11061 		ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc,
11062 						     &enable_mcc_adaptive_sch);
11063 		if (enable_mcc_adaptive_sch) {
11064 			ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch(
11065 							hdd_ctx->psoc, false);
11066 			if (QDF_IS_STATUS_ERROR(sme_set_mas(false))) {
11067 				hdd_err("Fail to disable mcc adaptive sched.");
11068 					return -EINVAL;
11069 			}
11070 		}
11071 		/* Configure mcc duty cycle percentage */
11072 		set_value =
11073 		   ucfg_mlme_get_mcc_duty_cycle_percentage(hdd_ctx->pdev);
11074 		if (set_value < 0) {
11075 			hdd_err("Invalid mcc duty cycle");
11076 			return -EINVAL;
11077 		}
11078 		wlan_hdd_send_mcc_vdev_quota(adapter, set_value);
11079 	} else {
11080 		hdd_debug("Enable mcc_adaptive_scheduler");
11081 		ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc,
11082 						     &enable_mcc_adaptive_sch);
11083 		if (enable_mcc_adaptive_sch) {
11084 			ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch(
11085 							hdd_ctx->psoc, true);
11086 			if (QDF_STATUS_SUCCESS != sme_set_mas(true)) {
11087 				hdd_err("Fail to enable mcc_adaptive_sched.");
11088 				return -EAGAIN;
11089 			}
11090 		}
11091 	}
11092 
11093 	return 0;
11094 }
11095 
hdd_config_rsn_ie(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11096 static int hdd_config_rsn_ie(struct wlan_hdd_link_info *link_info,
11097 			     const struct nlattr *attr)
11098 {
11099 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11100 	uint8_t force_rsne_override;
11101 
11102 	force_rsne_override = nla_get_u8(attr);
11103 	if (force_rsne_override > 1) {
11104 		hdd_err("Invalid value %d", force_rsne_override);
11105 		return -EINVAL;
11106 	}
11107 
11108 	hdd_ctx->force_rsne_override = force_rsne_override;
11109 	hdd_debug("force_rsne_override - %d", force_rsne_override);
11110 
11111 	return 0;
11112 }
11113 
hdd_config_gtx(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11114 static int hdd_config_gtx(struct wlan_hdd_link_info *link_info,
11115 			  const struct nlattr *attr)
11116 {
11117 	uint8_t config_gtx;
11118 	int errno;
11119 
11120 	config_gtx = nla_get_u8(attr);
11121 	if (config_gtx > 1) {
11122 		hdd_err_rl("Invalid config_gtx value %d", config_gtx);
11123 		return -EINVAL;
11124 	}
11125 
11126 	errno = sme_cli_set_command(link_info->vdev_id,
11127 				    wmi_vdev_param_gtx_enable,
11128 				    config_gtx, VDEV_CMD);
11129 	if (errno)
11130 		hdd_err("Failed to set GTX, %d", errno);
11131 
11132 	return errno;
11133 }
11134 
11135 /**
11136  * hdd_config_disconnect_ies() - Configure disconnect IEs
11137  * @link_info: Link info pointer in HDD adapter
11138  * @attr: array of pointer to struct nlattr
11139  *
11140  * Return: 0 on success; error number otherwise
11141  */
hdd_config_disconnect_ies(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11142 static int hdd_config_disconnect_ies(struct wlan_hdd_link_info *link_info,
11143 				     const struct nlattr *attr)
11144 {
11145 	struct hdd_adapter *adapter = link_info->adapter;
11146 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11147 	QDF_STATUS status;
11148 
11149 	hdd_debug("IE len %u session %u device mode %u",
11150 		  nla_len(attr), link_info->vdev_id,
11151 		  adapter->device_mode);
11152 	if (!nla_len(attr) ||
11153 	    nla_len(attr) > SIR_MAC_MAX_ADD_IE_LENGTH + 2 ||
11154 	    !wlan_is_ie_valid(nla_data(attr), nla_len(attr))) {
11155 		hdd_err("Invalid disconnect IEs");
11156 		return -EINVAL;
11157 	}
11158 
11159 	status = sme_set_disconnect_ies(hdd_ctx->mac_handle,
11160 					link_info->vdev_id,
11161 					nla_data(attr),
11162 					nla_len(attr));
11163 	if (QDF_IS_STATUS_ERROR(status))
11164 		hdd_err("Failed to set disconnect_ies");
11165 
11166 	return qdf_status_to_os_return(status);
11167 }
11168 
11169 #ifdef WLAN_FEATURE_ELNA
11170 /**
11171  * hdd_set_elna_bypass() - Set eLNA bypass
11172  * @link_info: Link info pointer in HDD adapter
11173  * @attr: Pointer to struct nlattr
11174  *
11175  * Return: 0 on success; error number otherwise
11176  */
hdd_set_elna_bypass(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11177 static int hdd_set_elna_bypass(struct wlan_hdd_link_info *link_info,
11178 			       const struct nlattr *attr)
11179 {
11180 	int ret;
11181 	struct wlan_objmgr_vdev *vdev;
11182 
11183 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_FWOL_NB_ID);
11184 	if (!vdev)
11185 		return -EINVAL;
11186 
11187 	ret = os_if_fwol_set_elna_bypass(vdev, attr);
11188 
11189 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_FWOL_NB_ID);
11190 
11191 	return ret;
11192 }
11193 #endif
11194 
11195 /**
11196  * hdd_mac_chwidth_to_bonding_mode() - get bonding_mode from chan width
11197  * @chwidth: chan width
11198  *
11199  * Return: bonding mode
11200  */
hdd_mac_chwidth_to_bonding_mode(enum eSirMacHTChannelWidth chwidth)11201 static uint32_t hdd_mac_chwidth_to_bonding_mode(
11202 			enum eSirMacHTChannelWidth chwidth)
11203 {
11204 	uint32_t bonding_mode;
11205 
11206 	switch (chwidth) {
11207 	case eHT_CHANNEL_WIDTH_20MHZ:
11208 		bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
11209 		break;
11210 	default:
11211 		bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
11212 	}
11213 
11214 	return bonding_mode;
11215 }
11216 
hdd_set_mac_chan_width(struct wlan_hdd_link_info * link_info,enum eSirMacHTChannelWidth chwidth,uint8_t link_id,bool is_restore)11217 int hdd_set_mac_chan_width(struct wlan_hdd_link_info *link_info,
11218 			   enum eSirMacHTChannelWidth chwidth,
11219 			   uint8_t link_id, bool is_restore)
11220 {
11221 	uint32_t bonding_mode;
11222 
11223 	bonding_mode = hdd_mac_chwidth_to_bonding_mode(chwidth);
11224 
11225 	return hdd_update_channel_width(link_info, chwidth,
11226 					bonding_mode, link_id, is_restore);
11227 }
11228 
11229 /**
11230  * hdd_set_channel_width() - set channel width
11231  * @link_info: Link info pointer in HDD adapter.
11232  * @tb: array of pointer to struct nlattr
11233  *
11234  * Return: 0 on success, negative errno on failure
11235  */
hdd_set_channel_width(struct wlan_hdd_link_info * link_info,struct nlattr * tb[])11236 static int hdd_set_channel_width(struct wlan_hdd_link_info *link_info,
11237 				 struct nlattr *tb[])
11238 {
11239 	int rem;
11240 	uint8_t nl80211_chwidth = CH_WIDTH_INVALID;
11241 	uint8_t link_id = WLAN_INVALID_LINK_ID;
11242 	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
11243 	struct nlattr *curr_attr;
11244 	struct nlattr *chn_bd = NULL;
11245 	struct nlattr *mlo_link_id;
11246 	enum eSirMacHTChannelWidth chwidth;
11247 	struct wlan_objmgr_psoc *psoc;
11248 	bool update_cw_allowed;
11249 
11250 	psoc = wlan_vdev_get_psoc(link_info->vdev);
11251 	if (!psoc) {
11252 		hdd_debug("psoc is null");
11253 		return -EINVAL;
11254 	}
11255 
11256 	ucfg_mlme_get_update_chan_width_allowed(psoc, &update_cw_allowed);
11257 	if (!update_cw_allowed) {
11258 		hdd_debug("update_channel_width is disabled via INI");
11259 		return -EINVAL;
11260 	}
11261 
11262 	if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS])
11263 		goto skip_mlo;
11264 
11265 	nla_for_each_nested(curr_attr,
11266 			    tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS], rem) {
11267 		if (wlan_cfg80211_nla_parse_nested(tb2,
11268 						QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
11269 						   curr_attr,
11270 						   bandwidth_mlo_policy)){
11271 			hdd_err_rl("nla_parse failed");
11272 			return -EINVAL;
11273 		}
11274 
11275 		chn_bd = tb2[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH];
11276 		mlo_link_id = tb2[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID];
11277 
11278 		if (!chn_bd || !mlo_link_id)
11279 			return -EINVAL;
11280 
11281 		nl80211_chwidth = nla_get_u8(chn_bd);
11282 		chwidth = hdd_nl80211_chwidth_to_chwidth(nl80211_chwidth);
11283 		if (chwidth < eHT_CHANNEL_WIDTH_20MHZ ||
11284 		    chwidth >= eHT_MAX_CHANNEL_WIDTH) {
11285 			hdd_err("Invalid channel width:%u", chwidth);
11286 			return -EINVAL;
11287 		}
11288 
11289 		link_id = nla_get_u8(mlo_link_id);
11290 		if (link_id > WLAN_MAX_LINK_ID) {
11291 			hdd_debug("invalid link_id:%u", link_id);
11292 			return -EINVAL;
11293 		}
11294 	}
11295 
11296 	if (link_id != WLAN_INVALID_LINK_ID)
11297 		goto set_chan_width;
11298 
11299 skip_mlo:
11300 	chn_bd = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH];
11301 
11302 	if (!chn_bd)
11303 		return 0;
11304 
11305 	nl80211_chwidth = nla_get_u8(chn_bd);
11306 	chwidth = hdd_nl80211_chwidth_to_chwidth(nl80211_chwidth);
11307 
11308 	if (chwidth < eHT_CHANNEL_WIDTH_20MHZ ||
11309 	    chwidth >= eHT_MAX_CHANNEL_WIDTH) {
11310 		hdd_err("Invalid channel width %u", chwidth);
11311 		return -EINVAL;
11312 	}
11313 
11314 set_chan_width:
11315 	hdd_debug("channel width:%u, link_id:%u", chwidth, link_id);
11316 	return hdd_set_mac_chan_width(link_info, chwidth, link_id, true);
11317 }
11318 
11319 /**
11320  * hdd_set_dynamic_bw() - enable / disable dynamic bandwidth
11321  * @link_info: Link info in adapter
11322  * @attr: nla attr sent by supplicant
11323  *
11324  * Return: 0 on success, negative errno on failure
11325  */
hdd_set_dynamic_bw(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11326 static int hdd_set_dynamic_bw(struct wlan_hdd_link_info *link_info,
11327 			      const struct nlattr *attr)
11328 {
11329 	uint8_t enable;
11330 
11331 	enable = nla_get_u8(attr);
11332 	return wma_cli_set_command(link_info->vdev_id,
11333 				   wmi_pdev_param_dynamic_bw,
11334 				   enable, PDEV_CMD);
11335 }
11336 
11337 /**
11338  * hdd_set_nss() - set the number of spatial streams supported by the adapter
11339  * @link_info: Link info pointer in HDD adapter
11340  * @attr: pointer to nla attr
11341  *
11342  * Return: 0 on success, negative errno on failure
11343  */
hdd_set_nss(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11344 static int hdd_set_nss(struct wlan_hdd_link_info *link_info,
11345 		       const struct nlattr *attr)
11346 {
11347 	uint8_t nss;
11348 	int ret;
11349 	QDF_STATUS status;
11350 
11351 	nss = nla_get_u8(attr);
11352 	status = hdd_update_nss(link_info, nss, nss);
11353 	ret = qdf_status_to_os_return(status);
11354 
11355 	if (ret == 0 && link_info->adapter->device_mode == QDF_SAP_MODE)
11356 		ret = wma_cli_set_command(link_info->vdev_id,
11357 					  wmi_vdev_param_nss, nss, VDEV_CMD);
11358 
11359 	return ret;
11360 }
11361 
11362 #ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD
11363 #define DYNAMIC_ARP_NS_ENABLE    1
11364 #define DYNAMIC_ARP_NS_DISABLE   0
11365 
11366 /**
11367  * hdd_set_arp_ns_offload() - enable/disable arp/ns offload feature
11368  * @link_info: Link info pointer in HDD adapter
11369  * @attr: pointer to nla attr
11370  *
11371  * Return: 0 on success, negative errno on failure
11372  */
hdd_set_arp_ns_offload(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11373 static int hdd_set_arp_ns_offload(struct wlan_hdd_link_info *link_info,
11374 				  const struct nlattr *attr)
11375 {
11376 	uint8_t offload_state;
11377 	int errno;
11378 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
11379 	struct hdd_adapter *adapter = link_info->adapter;
11380 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11381 	struct wlan_objmgr_vdev *vdev;
11382 
11383 	errno = wlan_hdd_validate_context(hdd_ctx);
11384 	if (errno)
11385 		return errno;
11386 
11387 	if (!ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc) ||
11388 	    !ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
11389 		hdd_err_rl("ARP/NS Offload is disabled by ini");
11390 		return -EINVAL;
11391 	}
11392 
11393 	if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
11394 		hdd_err_rl("active mode offload is disabled by ini");
11395 		return -EINVAL;
11396 	}
11397 
11398 	if (adapter->device_mode != QDF_STA_MODE &&
11399 	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
11400 		hdd_err_rl("only support on sta/p2p-cli mode");
11401 		return -EINVAL;
11402 	}
11403 
11404 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
11405 	if (!vdev) {
11406 		hdd_err("vdev is NULL");
11407 		return -EINVAL;
11408 	}
11409 
11410 	offload_state = nla_get_u8(attr);
11411 
11412 	if (offload_state == DYNAMIC_ARP_NS_ENABLE)
11413 		qdf_status = ucfg_pmo_dynamic_arp_ns_offload_enable(vdev);
11414 	else if (offload_state == DYNAMIC_ARP_NS_DISABLE)
11415 		qdf_status = ucfg_pmo_dynamic_arp_ns_offload_disable(vdev);
11416 
11417 	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
11418 		if (offload_state == DYNAMIC_ARP_NS_ENABLE)
11419 			ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(vdev);
11420 		else
11421 			ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(vdev);
11422 	}
11423 
11424 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
11425 		if (qdf_status == QDF_STATUS_E_ALREADY) {
11426 			hdd_info_rl("already set arp/ns offload %d",
11427 				    offload_state);
11428 			errno = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
11429 		} else {
11430 			errno = qdf_status_to_os_return(qdf_status);
11431 		}
11432 
11433 		goto vdev_ref;
11434 	}
11435 
11436 	if (!hdd_is_vdev_in_conn_state(link_info)) {
11437 		hdd_info("set not in connect state, updated state %d",
11438 			 offload_state);
11439 		errno = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
11440 		goto vdev_ref;
11441 	}
11442 
11443 	if (offload_state == DYNAMIC_ARP_NS_ENABLE) {
11444 		hdd_enable_arp_offload(adapter, vdev,
11445 				       pmo_arp_ns_offload_dynamic_update);
11446 		hdd_enable_ns_offload(adapter, vdev,
11447 				      pmo_arp_ns_offload_dynamic_update);
11448 	} else if (offload_state == DYNAMIC_ARP_NS_DISABLE) {
11449 		hdd_disable_arp_offload(adapter, vdev,
11450 					pmo_arp_ns_offload_dynamic_update);
11451 		hdd_disable_ns_offload(adapter, vdev,
11452 				       pmo_arp_ns_offload_dynamic_update);
11453 	}
11454 
11455 vdev_ref:
11456 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11457 	return errno;
11458 }
11459 
11460 #undef DYNAMIC_ARP_NS_ENABLE
11461 #undef DYNAMIC_ARP_NS_DISABLE
11462 #endif
11463 
11464 #ifdef WLAN_FEATURE_DBAM_CONFIG
11465 
11466 static int
hdd_convert_qca_dbam_config_mode(enum qca_dbam_config qca_dbam,enum coex_dbam_config_mode * coex_dbam)11467 hdd_convert_qca_dbam_config_mode(enum qca_dbam_config qca_dbam,
11468 				 enum coex_dbam_config_mode *coex_dbam)
11469 {
11470 	switch (qca_dbam) {
11471 	case QCA_DBAM_DISABLE:
11472 		*coex_dbam = COEX_DBAM_DISABLE;
11473 		break;
11474 	case QCA_DBAM_ENABLE:
11475 		*coex_dbam = COEX_DBAM_ENABLE;
11476 		break;
11477 	case QCA_DBAM_FORCE_ENABLE:
11478 		*coex_dbam = COEX_DBAM_FORCE_ENABLE;
11479 		break;
11480 	default:
11481 		hdd_err("Invalid dbam config mode %d", qca_dbam);
11482 		return -EINVAL;
11483 	}
11484 
11485 	return 0;
11486 }
11487 
11488 static int
hdd_convert_dbam_comp_status(enum coex_dbam_comp_status dbam_resp)11489 hdd_convert_dbam_comp_status(enum coex_dbam_comp_status dbam_resp)
11490 {
11491 	switch (dbam_resp) {
11492 	case COEX_DBAM_COMP_SUCCESS:
11493 		return 0;
11494 	case COEX_DBAM_COMP_NOT_SUPPORT:
11495 		return -ENOTSUPP;
11496 	case COEX_DBAM_COMP_FAIL:
11497 		return -EINVAL;
11498 	default:
11499 		hdd_err("Invalid dbam config resp received from FW");
11500 		break;
11501 	}
11502 
11503 	return -EINVAL;
11504 }
11505 
11506 /**
11507  * hdd_dbam_config_resp_cb() - DBAM config response callback
11508  * @context: request manager context
11509  * @resp: pointer to dbam config fw response
11510  *
11511  * Return: 0 on success, negative errno on failure
11512  */
11513 static void
hdd_dbam_config_resp_cb(void * context,enum coex_dbam_comp_status * resp)11514 hdd_dbam_config_resp_cb(void *context,
11515 			enum coex_dbam_comp_status *resp)
11516 {
11517 	struct osif_request *request;
11518 	struct coex_dbam_config_resp *priv;
11519 
11520 	request = osif_request_get(context);
11521 	if (!request) {
11522 		osif_err("Obsolete request");
11523 		return;
11524 	}
11525 
11526 	priv = osif_request_priv(request);
11527 	priv->dbam_resp = *resp;
11528 
11529 	osif_request_complete(request);
11530 	osif_request_put(request);
11531 }
11532 
hdd_send_dbam_config(struct hdd_adapter * adapter,enum coex_dbam_config_mode dbam_mode)11533 int hdd_send_dbam_config(struct hdd_adapter *adapter,
11534 			 enum coex_dbam_config_mode dbam_mode)
11535 {
11536 	int errno;
11537 	QDF_STATUS status;
11538 	struct wlan_objmgr_vdev *vdev;
11539 	enum coex_dbam_comp_status dbam_resp;
11540 	struct coex_dbam_config_params dbam_params = {0};
11541 	void *cookie;
11542 	struct osif_request *request;
11543 	struct coex_dbam_config_resp *priv;
11544 	static const struct osif_request_params params = {
11545 		.priv_size = sizeof(*priv),
11546 		.timeout_ms = WLAN_SET_DBAM_CONFIG_TIMEOUT,
11547 	};
11548 
11549 	errno = hdd_validate_adapter(adapter);
11550 	if (errno)
11551 		return errno;
11552 
11553 	request = osif_request_alloc(&params);
11554 	if (!request) {
11555 		osif_err("Request allocation failure");
11556 		return -ENOMEM;
11557 	}
11558 	cookie = osif_request_cookie(request);
11559 
11560 	dbam_params.vdev_id = adapter->deflink->vdev_id;
11561 	dbam_params.dbam_mode = dbam_mode;
11562 
11563 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
11564 	if (!vdev) {
11565 		hdd_err("vdev is NULL");
11566 		errno = -EINVAL;
11567 		goto err;
11568 	}
11569 
11570 	status = ucfg_coex_send_dbam_config(vdev, &dbam_params,
11571 					    hdd_dbam_config_resp_cb, cookie);
11572 
11573 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11574 
11575 	if (!QDF_IS_STATUS_SUCCESS(status)) {
11576 		hdd_err("Unable to set dbam config to [%u]", dbam_mode);
11577 		errno = qdf_status_to_os_return(status);
11578 		goto err;
11579 	}
11580 
11581 	errno = osif_request_wait_for_response(request);
11582 	if (errno) {
11583 		osif_err("DBAM config operation timed out");
11584 		goto err;
11585 	}
11586 
11587 	priv = osif_request_priv(request);
11588 	dbam_resp = priv->dbam_resp;
11589 	errno = hdd_convert_dbam_comp_status(dbam_resp);
11590 err:
11591 	osif_request_put(request);
11592 	return errno;
11593 }
11594 
11595 /**
11596  * hdd_set_dbam_config() - set DBAM config
11597  * @link_info: Link info pointer in HDD adapter
11598  * @attr: pointer to nla attr
11599  *
11600  * Return: 0 on success, negative errno on failure
11601  */
hdd_set_dbam_config(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11602 static int hdd_set_dbam_config(struct wlan_hdd_link_info *link_info,
11603 			       const struct nlattr *attr)
11604 {
11605 	struct hdd_adapter *adapter = link_info->adapter;
11606 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11607 	int errno;
11608 	enum qca_dbam_config dbam_config;
11609 	enum coex_dbam_config_mode dbam_mode;
11610 
11611 	errno = wlan_hdd_validate_context(hdd_ctx);
11612 	if (errno)
11613 		return -EINVAL;
11614 
11615 	if (hdd_ctx->num_rf_chains < 2) {
11616 		hdd_debug("Num of chains [%u] < 2, DBAM config is not allowed",
11617 			  hdd_ctx->num_rf_chains);
11618 		return -EINVAL;
11619 	}
11620 
11621 	dbam_config = nla_get_u8(attr);
11622 	errno = hdd_convert_qca_dbam_config_mode(dbam_config, &dbam_mode);
11623 	if (errno)
11624 		return errno;
11625 
11626 	/* Store dbam config in hdd_ctx, to restore in case of an SSR */
11627 	adapter->is_dbam_configured = true;
11628 	hdd_ctx->dbam_mode = dbam_mode;
11629 
11630 	return hdd_send_dbam_config(adapter, dbam_mode);
11631 }
11632 #endif
11633 
11634 /**
11635  * hdd_set_beamformer_periodic_sounding() - enable/disable Tx Beamforming
11636  * @link_info: Link info pointer in HDD adapter
11637  * @attr: pointer to nla attr
11638  *
11639  * Return: 0 on success, negative on failure
11640  */
11641 static int
hdd_set_beamformer_periodic_sounding(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11642 hdd_set_beamformer_periodic_sounding(struct wlan_hdd_link_info *link_info,
11643 				     const struct nlattr *attr)
11644 {
11645 	uint8_t cfg_val;
11646 	int set_val;
11647 
11648 	cfg_val = nla_get_u8(attr);
11649 
11650 	set_val = cfg_val ? TX_BFER_NDP_PERIODICITY : 0;
11651 	return wma_cli_set_command(link_info->vdev_id,
11652 				   WMI_PDEV_PARAM_TXBF_SOUND_PERIOD_CMDID,
11653 				   set_val, PDEV_CMD);
11654 }
11655 
11656 /**
11657  * hdd_set_wfc_state() - Set wfc state
11658  * @link_info: Link info pointer in HDD adapter
11659  * @attr: pointer to nla attr
11660  *
11661  * Return: 0 on success, negative on failure
11662  */
hdd_set_wfc_state(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11663 static int hdd_set_wfc_state(struct wlan_hdd_link_info *link_info,
11664 			     const struct nlattr *attr)
11665 {
11666 	uint8_t cfg_val;
11667 	enum pld_wfc_mode set_val;
11668 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11669 	int errno;
11670 
11671 	errno = wlan_hdd_validate_context(hdd_ctx);
11672 	if (errno)
11673 		return errno;
11674 
11675 	cfg_val = nla_get_u8(attr);
11676 
11677 	hdd_debug_rl("set wfc state %d", cfg_val);
11678 	if (cfg_val == 0)
11679 		set_val = PLD_WFC_MODE_OFF;
11680 	else if (cfg_val == 1)
11681 		set_val = PLD_WFC_MODE_ON;
11682 	else
11683 		return -EINVAL;
11684 
11685 	return pld_set_wfc_mode(hdd_ctx->parent_dev, set_val);
11686 
11687 }
11688 
11689 /**
11690  * hdd_set_ul_mu_config() - Configure UL MU i.e suspend/enable
11691  * @link_info: Link info pointer in HDD adapter
11692  * @attr: pointer to nla attr
11693  *
11694  * Return: 0 on success, negative on failure
11695  */
11696 
hdd_set_ul_mu_config(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11697 static int hdd_set_ul_mu_config(struct wlan_hdd_link_info *link_info,
11698 				const struct nlattr *attr)
11699 {
11700 	uint8_t ulmu;
11701 	uint8_t ulmu_disable;
11702 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11703 	int errno;
11704 	QDF_STATUS qdf_status;
11705 
11706 	errno = wlan_hdd_validate_context(hdd_ctx);
11707 	if (errno) {
11708 		hdd_err("Invalid HDD ctx, errno : %d", errno);
11709 		return errno;
11710 	}
11711 
11712 	ulmu = nla_get_u8(attr);
11713 	if (ulmu != QCA_UL_MU_SUSPEND && ulmu != QCA_UL_MU_ENABLE) {
11714 		hdd_err("Invalid ulmu value, ulmu : %d", ulmu);
11715 		return -EINVAL;
11716 	}
11717 
11718 	hdd_debug("UL MU value : %d", ulmu);
11719 
11720 	if (ulmu == QCA_UL_MU_SUSPEND)
11721 		ulmu_disable = 1;
11722 	else
11723 		ulmu_disable = 0;
11724 
11725 	qdf_status = ucfg_mlme_set_ul_mu_config(hdd_ctx->psoc,
11726 						link_info->vdev_id,
11727 						ulmu_disable);
11728 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
11729 		errno = -EINVAL;
11730 		hdd_err("Failed to set UL MU, errno : %d", errno);
11731 	}
11732 
11733 	return errno;
11734 }
11735 
11736 /**
11737  * hdd_set_coex_traffic_shaping_mode() - Configure coex traffic
11738  * shaping mode
11739  * @link_info: Link info pointer in HDD adapter
11740  * @attr: pointer to nla attr
11741  *
11742  * Return: 0 on success, negative on failure
11743  */
11744 
11745 static int
hdd_set_coex_traffic_shaping_mode(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11746 hdd_set_coex_traffic_shaping_mode(struct wlan_hdd_link_info *link_info,
11747 				  const struct nlattr *attr)
11748 {
11749 	uint8_t mode;
11750 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11751 	int errno, ret;
11752 
11753 	errno = wlan_hdd_validate_context(hdd_ctx);
11754 	if (errno) {
11755 		hdd_err("Invalid HDD ctx, errno : %d", errno);
11756 		return errno;
11757 	}
11758 
11759 	mode = nla_get_u8(attr);
11760 	if (mode > QCA_COEX_TRAFFIC_SHAPING_MODE_ENABLE) {
11761 		hdd_err("Invalid traffic shaping mode : %d", mode);
11762 		return -EINVAL;
11763 	}
11764 
11765 	hdd_debug("Coex Traffic shaping mode : %d", mode);
11766 
11767 	ret = hdd_send_coex_traffic_shaping_mode(link_info->vdev_id, mode);
11768 
11769 	return ret;
11770 }
11771 
11772 #define STA_KEEPALIVE_INTERVAL_MAX 255
11773 #define STA_KEEPALIVE_INTERVAL_MIN 5
11774 
hdd_vdev_send_sta_keep_alive_interval(struct wlan_hdd_link_info * link_info,struct hdd_context * hdd_ctx,uint16_t keep_alive_interval)11775 int hdd_vdev_send_sta_keep_alive_interval(
11776 				struct wlan_hdd_link_info *link_info,
11777 				struct hdd_context *hdd_ctx,
11778 				uint16_t keep_alive_interval)
11779 {
11780 	struct keep_alive_req request;
11781 
11782 	qdf_mem_zero(&request, sizeof(request));
11783 
11784 	request.timePeriod = keep_alive_interval;
11785 	request.packetType = WLAN_KEEP_ALIVE_NULL_PKT;
11786 
11787 	if (QDF_STATUS_SUCCESS !=
11788 	    sme_set_keep_alive(hdd_ctx->mac_handle, link_info->vdev_id,
11789 			       &request)) {
11790 		hdd_err("Failure to execute Keep Alive");
11791 		return -EINVAL;
11792 	}
11793 
11794 	return 0;
11795 }
11796 
wlan_hdd_save_sta_keep_alive_interval(struct hdd_adapter * adapter,uint16_t keep_alive_interval)11797 void wlan_hdd_save_sta_keep_alive_interval(struct hdd_adapter *adapter,
11798 					   uint16_t keep_alive_interval)
11799 {
11800 	adapter->keep_alive_interval = keep_alive_interval;
11801 }
11802 
11803 #ifdef WLAN_FEATURE_11BE_MLO
11804 /**
11805  * hdd_ml_vdev_set_sta_keep_alive_interval() - Set STA KEEPALIVE interval for
11806  *                                             all connected ml vdev
11807  * @vdev: Pointer to vdev
11808  * @hdd_ctx: Pointer to hdd context
11809  * @keep_alive_interval: KEEPALIVE interval
11810  *
11811  * Return: 0 on success, negative on failure
11812  */
hdd_ml_vdev_set_sta_keep_alive_interval(struct wlan_objmgr_vdev * vdev,struct hdd_context * hdd_ctx,uint16_t keep_alive_interval)11813 static int hdd_ml_vdev_set_sta_keep_alive_interval(
11814 						struct wlan_objmgr_vdev *vdev,
11815 						struct hdd_context *hdd_ctx,
11816 						uint16_t keep_alive_interval)
11817 {
11818 	struct wlan_objmgr_vdev *ml_vdev;
11819 	uint8_t ml_vdev_id;
11820 	struct wlan_mlo_dev_context *mlo_dev_ctx;
11821 	struct wlan_hdd_link_info *link_info;
11822 	int status, i;
11823 
11824 	mlo_dev_ctx = vdev->mlo_dev_ctx;
11825 	if (!mlo_dev_ctx) {
11826 		hdd_err("MLO dev context null");
11827 		return -EINVAL;
11828 	}
11829 
11830 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS ; i++) {
11831 		ml_vdev = mlo_dev_ctx->wlan_vdev_list[i];
11832 		if (!ml_vdev)
11833 			continue;
11834 
11835 		ml_vdev_id = ml_vdev->vdev_objmgr.vdev_id;
11836 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, ml_vdev_id);
11837 		if (!link_info)
11838 			continue;
11839 
11840 		if (!hdd_is_vdev_in_conn_state(link_info)) {
11841 			hdd_debug("Vdev (id %d) not in connected/started state",
11842 				  link_info->vdev_id);
11843 			continue;
11844 		}
11845 
11846 		status = hdd_vdev_send_sta_keep_alive_interval(link_info,
11847 							hdd_ctx,
11848 							keep_alive_interval);
11849 		if (status)
11850 			return status;
11851 	}
11852 
11853 	return 0;
11854 }
11855 #else
hdd_ml_vdev_set_sta_keep_alive_interval(struct wlan_objmgr_vdev * vdev,struct hdd_context * hdd_ctx,uint16_t keep_alive_interval)11856 static inline int hdd_ml_vdev_set_sta_keep_alive_interval(
11857 						struct wlan_objmgr_vdev *vdev,
11858 						struct hdd_context *hdd_ctx,
11859 						uint16_t keep_alive_interval)
11860 {
11861 	return -EINVAL;
11862 }
11863 #endif
11864 /**
11865  * hdd_vdev_set_sta_keep_alive_interval() - Set sta keep alive interval
11866  * @link_info: Link info pointer.
11867  * @attr: NL attribute pointer.
11868  *
11869  * Return: 0 on success, negative on failure.
11870  */
hdd_vdev_set_sta_keep_alive_interval(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11871 static int hdd_vdev_set_sta_keep_alive_interval(
11872 				struct wlan_hdd_link_info *link_info,
11873 				const struct nlattr *attr)
11874 {
11875 	struct hdd_adapter *adapter = link_info->adapter;
11876 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11877 	enum QDF_OPMODE device_mode = link_info->adapter->device_mode;
11878 	uint16_t keep_alive_interval;
11879 	struct wlan_objmgr_vdev *vdev = link_info->vdev;
11880 
11881 	keep_alive_interval = nla_get_u16(attr);
11882 	if (keep_alive_interval > STA_KEEPALIVE_INTERVAL_MAX ||
11883 	    keep_alive_interval < STA_KEEPALIVE_INTERVAL_MIN) {
11884 		hdd_err("Sta keep alive period: %d is out of range",
11885 			keep_alive_interval);
11886 		return -EINVAL;
11887 	}
11888 
11889 	if (device_mode != QDF_STA_MODE) {
11890 		hdd_debug("This command is not supported for %s device mode",
11891 			  device_mode_to_string(device_mode));
11892 		return -EINVAL;
11893 	}
11894 
11895 	hdd_debug("sta keep alive interval = %u", keep_alive_interval);
11896 	wlan_hdd_save_sta_keep_alive_interval(adapter, keep_alive_interval);
11897 
11898 	if (!hdd_is_vdev_in_conn_state(link_info)) {
11899 		hdd_debug("Vdev (id %d) not in connected/started state, configure KEEPALIVE interval after connection",
11900 			  link_info->vdev_id);
11901 		return 0;
11902 	}
11903 
11904 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
11905 		return hdd_vdev_send_sta_keep_alive_interval(link_info,
11906 							hdd_ctx,
11907 							keep_alive_interval);
11908 
11909 	return hdd_ml_vdev_set_sta_keep_alive_interval(vdev, hdd_ctx,
11910 						       keep_alive_interval);
11911 }
11912 
11913 #ifdef WLAN_FEATURE_11BE_MLO
hdd_test_config_emlsr_mode(struct hdd_context * hdd_ctx,bool cfg_val)11914 static int hdd_test_config_emlsr_mode(struct hdd_context *hdd_ctx,
11915 				      bool cfg_val)
11916 
11917 {
11918 	hdd_debug("11be op mode setting %d", cfg_val);
11919 	if (cfg_val && policy_mgr_is_hw_emlsr_capable(hdd_ctx->psoc)) {
11920 		hdd_debug("HW supports EMLSR mode, set caps");
11921 		ucfg_mlme_set_emlsr_mode_enabled(hdd_ctx->psoc, cfg_val);
11922 	} else {
11923 		hdd_debug("Default mode: MLMR, no action required");
11924 	}
11925 
11926 	return 0;
11927 }
11928 
11929 static int
hdd_test_config_emlsr_action_mode(struct hdd_adapter * adapter,enum wlan_emlsr_action_mode emlsr_mode)11930 hdd_test_config_emlsr_action_mode(struct hdd_adapter *adapter,
11931 				  enum wlan_emlsr_action_mode emlsr_mode)
11932 {
11933 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11934 	uint8_t i, num_links = 0;
11935 	uint16_t vdev_count = 0;
11936 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
11937 	struct qdf_mac_addr active_link_addr[2];
11938 
11939 	mlo_sta_get_vdev_list(adapter->deflink->vdev, &vdev_count,
11940 			      wlan_vdev_list);
11941 	for (i = 0; i < vdev_count; i++) {
11942 		if (!wlan_vdev_list[i])
11943 			continue;
11944 		qdf_mem_copy(&active_link_addr[i],
11945 			     wlan_vdev_mlme_get_macaddr(wlan_vdev_list[i]),
11946 			     QDF_MAC_ADDR_SIZE);
11947 		num_links++;
11948 		if (emlsr_mode == WLAN_EMLSR_MODE_EXIT)
11949 			break;
11950 	}
11951 
11952 	for (i = 0; i < vdev_count; i++)
11953 		mlo_release_vdev_ref(wlan_vdev_list[i]);
11954 
11955 	hdd_debug("number of links to force enable: %d", num_links);
11956 
11957 	if (num_links >= 1)
11958 		sme_activate_mlo_links(hdd_ctx->mac_handle,
11959 				       adapter->deflink->vdev_id,
11960 				       num_links, active_link_addr);
11961 
11962 	return 0;
11963 }
11964 
11965 /**
11966  * hdd_set_epcs_capability() - Set EPCS capability enable or not
11967  * @link_info: link info pointer
11968  * @attr: pointer to nla attr
11969  *
11970  * Return: 0 on success, negative on failure
11971  */
hdd_set_epcs_capability(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)11972 static int hdd_set_epcs_capability(struct wlan_hdd_link_info *link_info,
11973 				   const struct nlattr *attr)
11974 {
11975 	uint8_t cfg_val;
11976 	struct wlan_objmgr_vdev *vdev;
11977 
11978 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
11979 	if (!vdev)
11980 		return -EINVAL;
11981 
11982 	cfg_val = nla_get_u8(attr);
11983 	hdd_debug("Configure EPCS capability %s(%d)",
11984 		  cfg_val ? "Enable" : "Disable", cfg_val);
11985 	if (cfg_val < WLAN_EPCS_CAP_DISABLED ||
11986 	    cfg_val > WLAN_EPCS_CAP_ENABLE) {
11987 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11988 		return -EINVAL;
11989 	}
11990 
11991 	ucfg_epcs_set_config(vdev, cfg_val);
11992 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11993 
11994 	return 0;
11995 }
11996 
11997 /**
11998  * hdd_trigger_epcs_function() - Trigger EPCS function to enable or disable
11999  * @link_info: link info pointer
12000  * @attr: pointer to nla attr
12001  *
12002  * Return: 0 on success, negative on failure
12003  */
hdd_trigger_epcs_function(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12004 static int hdd_trigger_epcs_function(struct wlan_hdd_link_info *link_info,
12005 				     const struct nlattr *attr)
12006 {
12007 	uint8_t cfg_val;
12008 	struct wlan_objmgr_vdev *vdev;
12009 	enum wlan_epcs_evt event;
12010 	int status = -EINVAL;
12011 
12012 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
12013 	if (!vdev)
12014 		return status;
12015 
12016 	cfg_val = nla_get_u8(attr);
12017 	hdd_debug("Trigger EPCS %d", cfg_val);
12018 
12019 	switch (cfg_val) {
12020 	/* enable EPCS function to send request frame */
12021 	case WLAN_EPCS_FRAME_REQUEST:
12022 		event = WLAN_EPCS_EV_ACTION_FRAME_TX_REQ;
12023 		break;
12024 	/* disable EPCS function to send teardown frame */
12025 	case WLAN_EPCS_FRAME_TEARDOWN:
12026 		event = WLAN_EPCS_EV_ACTION_FRAME_TX_TEARDOWN;
12027 		break;
12028 	default:
12029 		goto rel_ref;
12030 	}
12031 
12032 	ucfg_epcs_deliver_cmd(vdev, event);
12033 	status = 0;
12034 
12035 rel_ref:
12036 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12037 	return status;
12038 }
12039 #else
12040 static inline int
hdd_test_config_emlsr_mode(struct hdd_context * hdd_ctx,bool cfg_val)12041 hdd_test_config_emlsr_mode(struct hdd_context *hdd_ctx, bool cfg_val)
12042 {
12043 	return 0;
12044 }
12045 
12046 static inline int
hdd_test_config_emlsr_action_mode(struct hdd_adapter * adapter,enum wlan_emlsr_action_mode emlsr_mode)12047 hdd_test_config_emlsr_action_mode(struct hdd_adapter *adapter,
12048 				  enum wlan_emlsr_action_mode emlsr_mode)
12049 {
12050 	return 0;
12051 }
12052 #endif
12053 
12054 /**
12055  * hdd_set_btm_support_config() - Update BTM support policy
12056  * @link_info: Link info pointer in HDD adapter
12057  * @attr: pointer to nla attr
12058  *
12059  * Return: 0 on success, negative on failure
12060  */
hdd_set_btm_support_config(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12061 static int hdd_set_btm_support_config(struct wlan_hdd_link_info *link_info,
12062 				      const struct nlattr *attr)
12063 {
12064 	uint8_t cfg_val;
12065 	struct hdd_adapter *adapter = link_info->adapter;
12066 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
12067 	enum QDF_OPMODE op_mode = adapter->device_mode;
12068 	bool is_vdev_in_conn_state, is_disable_btm;
12069 
12070 	is_vdev_in_conn_state = hdd_is_vdev_in_conn_state(link_info);
12071 	cfg_val = nla_get_u8(attr);
12072 
12073 	hdd_debug("vdev: %d, cfg_val: %d for op_mode: %d, conn_state:%d",
12074 		  link_info->vdev_id, cfg_val, op_mode,
12075 		  is_vdev_in_conn_state);
12076 
12077 	/*
12078 	 * Change in BTM support configuration is applicable only for STA
12079 	 * interface and not allowed in connected state.
12080 	 */
12081 	if (op_mode != QDF_STA_MODE || is_vdev_in_conn_state)
12082 		return -EINVAL;
12083 
12084 	switch (cfg_val) {
12085 	case QCA_WLAN_BTM_SUPPORT_DISABLE:
12086 		is_disable_btm = true;
12087 		break;
12088 	case QCA_WLAN_BTM_SUPPORT_DEFAULT:
12089 		is_disable_btm = false;
12090 		break;
12091 	default:
12092 		return -EINVAL;
12093 	}
12094 
12095 	ucfg_cm_set_btm_config(hdd_ctx->psoc, link_info->vdev_id,
12096 			       is_disable_btm);
12097 
12098 	return 0;
12099 }
12100 
12101 #ifdef WLAN_FEATURE_11BE
12102 /**
12103  * hdd_set_eht_emlsr_capability() - Set EMLSR capability for EHT STA
12104  * @link_info: Link info pointer in HDD adapter
12105  * @attr: pointer to nla attr
12106  *
12107  * Return: 0 on success, negative on failure
12108  */
12109 static int
hdd_set_eht_emlsr_capability(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12110 hdd_set_eht_emlsr_capability(struct wlan_hdd_link_info *link_info,
12111 			     const struct nlattr *attr)
12112 {
12113 	uint8_t cfg_val;
12114 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12115 
12116 	cfg_val = nla_get_u8(attr);
12117 	hdd_debug("EMLSR capable: %d", cfg_val);
12118 	hdd_test_config_emlsr_mode(hdd_ctx, cfg_val);
12119 
12120 	return 0;
12121 }
12122 
12123 /**
12124  * hdd_set_eht_max_simultaneous_links() - Set EHT maximum number of
12125  * simultaneous links
12126  * @link_info: Link info pointer in HDD adapter
12127  * @attr: pointer to nla attr
12128  *
12129  * Return: 0 on success, negative on failure
12130  */
12131 static int
hdd_set_eht_max_simultaneous_links(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12132 hdd_set_eht_max_simultaneous_links(struct wlan_hdd_link_info *link_info,
12133 				   const struct nlattr *attr)
12134 {
12135 	uint8_t cfg_val;
12136 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12137 
12138 	cfg_val = nla_get_u8(attr);
12139 	if (cfg_val > MAX_SIMULTANEOUS_STA_ML_LINKS)
12140 		return -EINVAL;
12141 
12142 	sme_set_mlo_max_simultaneous_links(hdd_ctx->mac_handle,
12143 					   link_info->vdev_id, cfg_val);
12144 
12145 	return 0;
12146 }
12147 
12148 /**
12149  * hdd_set_eht_max_num_links() - Set EHT maximum number of links
12150  * @link_info: Link info pointer in HDD adapter
12151  * @attr: pointer to nla attr
12152  *
12153  * Return: 0 on success, negative on failure
12154  */
hdd_set_eht_max_num_links(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12155 static int hdd_set_eht_max_num_links(struct wlan_hdd_link_info *link_info,
12156 				     const struct nlattr *attr)
12157 {
12158 	uint8_t cfg_val;
12159 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12160 
12161 	cfg_val = nla_get_u8(attr);
12162 	if (cfg_val > MAX_NUM_STA_ML_LINKS)
12163 		return -EINVAL;
12164 
12165 	sme_set_mlo_max_links(hdd_ctx->mac_handle,
12166 			      link_info->vdev_id, cfg_val);
12167 
12168 	return 0;
12169 }
12170 
12171 /**
12172  * hdd_get_cfg_eht_mode() - Convert qca wlan EHT mode enum to cfg wlan EHT mode
12173  * @qca_wlan_eht_mode: qca wlan eht mode
12174  *
12175  * Return: EHT mode on success, 0 on failure
12176  */
12177 static enum wlan_eht_mode
hdd_get_cfg_eht_mode(enum qca_wlan_eht_mlo_mode qca_wlan_eht_mode)12178 hdd_get_cfg_eht_mode(enum qca_wlan_eht_mlo_mode qca_wlan_eht_mode)
12179 {
12180 	switch (qca_wlan_eht_mode) {
12181 	case QCA_WLAN_EHT_MLSR:
12182 		return WLAN_EHT_MODE_MLSR;
12183 	case QCA_WLAN_EHT_EMLSR:
12184 		return WLAN_EHT_MODE_EMLSR;
12185 	case QCA_WLAN_EHT_NON_STR_MLMR:
12186 	case QCA_WLAN_EHT_STR_MLMR:
12187 		return WLAN_EHT_MODE_MLMR;
12188 	default:
12189 		hdd_debug("Invalid EHT mode");
12190 		return WLAN_EHT_MODE_DISABLED;
12191 	}
12192 }
12193 
12194 /**
12195  * hdd_set_eht_mlo_mode() - Set EHT MLO mode of operation
12196  * @link_info: Link info pointer in HDD adapter
12197  * @attr: pointer to nla attr
12198  *
12199  * Return: 0 on success, negative on failure
12200  */
hdd_set_eht_mlo_mode(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12201 static int hdd_set_eht_mlo_mode(struct wlan_hdd_link_info *link_info,
12202 				const struct nlattr *attr)
12203 {
12204 	uint8_t cfg_val;
12205 	struct hdd_adapter *adapter = link_info->adapter;
12206 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
12207 	enum wlan_eht_mode eht_mode;
12208 
12209 	cfg_val = nla_get_u8(attr);
12210 	hdd_debug("Configure EHT mode of operation: %d", cfg_val);
12211 
12212 	eht_mode = hdd_get_cfg_eht_mode(cfg_val);
12213 
12214 	if (eht_mode == WLAN_EHT_MODE_EMLSR &&
12215 	    adapter->device_mode == QDF_STA_MODE) {
12216 		hdd_test_config_emlsr_mode(hdd_ctx, true);
12217 		ucfg_mlme_set_bss_color_collision_det_sta(hdd_ctx->psoc, false);
12218 	}
12219 
12220 	ucfg_mlme_set_eht_mode(hdd_ctx->psoc, eht_mode);
12221 
12222 	return 0;
12223 }
12224 #else
12225 static inline int
hdd_set_eht_emlsr_capability(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12226 hdd_set_eht_emlsr_capability(struct wlan_hdd_link_info *link_info,
12227 			     const struct nlattr *attr)
12228 {
12229 	return 0;
12230 }
12231 
12232 static inline int
hdd_set_eht_max_simultaneous_links(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12233 hdd_set_eht_max_simultaneous_links(struct wlan_hdd_link_info *link_info,
12234 				   const struct nlattr *attr)
12235 {
12236 	return 0;
12237 }
12238 
12239 static inline int
hdd_set_eht_max_num_links(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12240 hdd_set_eht_max_num_links(struct wlan_hdd_link_info  *link_info,
12241 			  const struct nlattr *attr)
12242 {
12243 	return 0;
12244 }
12245 
12246 static inline int
hdd_set_eht_mlo_mode(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12247 hdd_set_eht_mlo_mode(struct wlan_hdd_link_info *link_info,
12248 		     const struct nlattr *attr)
12249 {
12250 	return 0;
12251 }
12252 #endif
12253 
12254 #ifdef WLAN_FEATURE_11BE_MLO
hdd_set_link_force_active(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12255 static int hdd_set_link_force_active(struct wlan_hdd_link_info *link_info,
12256 				     const struct nlattr *attr)
12257 {
12258 	struct hdd_context *hdd_ctx = NULL;
12259 	struct nlattr *curr_attr;
12260 	struct qdf_mac_addr active_link_addr[2];
12261 	struct qdf_mac_addr *mac_addr_ptr;
12262 	uint32_t num_links = 0;
12263 	int32_t len;
12264 	struct hdd_adapter *adapter = link_info->adapter;
12265 
12266 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
12267 	if (!hdd_ctx)
12268 		return -EINVAL;
12269 
12270 	if (attr && adapter->device_mode == QDF_STA_MODE) {
12271 		nla_for_each_nested(curr_attr, &attr[0], len) {
12272 			mac_addr_ptr = &active_link_addr[num_links];
12273 			qdf_mem_copy(mac_addr_ptr, nla_data(curr_attr),
12274 				     ETH_ALEN);
12275 			hdd_debug(QDF_MAC_ADDR_FMT " is link[%d] mac address",
12276 				  QDF_MAC_ADDR_REF(mac_addr_ptr->bytes),
12277 				  num_links);
12278 			num_links++;
12279 		}
12280 		sme_activate_mlo_links(hdd_ctx->mac_handle,
12281 				       link_info->vdev_id, num_links,
12282 				       active_link_addr);
12283 	}
12284 	hdd_debug("number of links to force active: %d", num_links);
12285 
12286 	return 0;
12287 }
12288 
12289 /**
12290  * hdd_get_cfg_emlsr_mode() - Convert qca wlan EMLSR mode enum to cfg wlan
12291  * EMLSR action mode
12292  * @qca_wlan_emlsr_mode: qca wlan EMLSR mode
12293  *
12294  * Return: EMLSR mode on success, 0 on failure
12295  */
12296 static enum wlan_emlsr_action_mode
hdd_get_cfg_emlsr_mode(enum qca_wlan_eht_mlo_mode qca_wlan_emlsr_mode)12297 hdd_get_cfg_emlsr_mode(enum qca_wlan_eht_mlo_mode qca_wlan_emlsr_mode)
12298 {
12299 	switch (qca_wlan_emlsr_mode) {
12300 	case QCA_WLAN_EMLSR_MODE_ENTER:
12301 		return WLAN_EMLSR_MODE_ENTER;
12302 	case QCA_WLAN_EMLSR_MODE_EXIT:
12303 		return WLAN_EMLSR_MODE_EXIT;
12304 	default:
12305 		hdd_debug("Invalid EMLSR action mode");
12306 		return WLAN_EMLSR_MODE_DISABLED;
12307 	}
12308 }
12309 
12310 /**
12311  * hdd_get_cfg_t2lm_neg_support_type() - Convert qca wlan TID-to-link mapping
12312  * enum to cfg wlan
12313  *
12314  * @qca_wlan_t2lm_support: qca wlan TID-to-link mapping
12315  *
12316  * Return: TID-to-link mapping support on success, 0 on failure
12317  */
12318 static enum wlan_t2lm_negotiation_support
hdd_get_cfg_t2lm_neg_support_type(enum qca_wlan_ttlm_negotiation_support qca_wlan_t2lm_support)12319 hdd_get_cfg_t2lm_neg_support_type(enum qca_wlan_ttlm_negotiation_support
12320 				  qca_wlan_t2lm_support)
12321 {
12322 	switch (qca_wlan_t2lm_support) {
12323 	case QCA_WLAN_TTLM_DISABLE:
12324 		return WLAN_T2LM_DISABLE;
12325 	case QCA_WLAN_TTLM_SAME_LINK_SET:
12326 		return WLAN_T2LM_SAME_LINK_SET;
12327 	case QCA_WLAN_TTLM_SAME_DIFF_LINK_SET:
12328 		return WLAN_T2LM_SAME_DIFF_LINK_SET;
12329 	default:
12330 		hdd_debug("Invalid T2LM negotiation support");
12331 		return WLAN_T2LM_DISABLE;
12332 	}
12333 }
12334 
hdd_set_emlsr_mode(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12335 static int hdd_set_emlsr_mode(struct wlan_hdd_link_info *link_info,
12336 			      const struct nlattr *attr)
12337 {
12338 	uint8_t cfg_val;
12339 	enum wlan_emlsr_action_mode emlsr_action_mode;
12340 
12341 	if (!attr)
12342 		return -EINVAL;
12343 
12344 	cfg_val = nla_get_u8(attr);
12345 
12346 	emlsr_action_mode = hdd_get_cfg_emlsr_mode(cfg_val);
12347 
12348 	hdd_debug("EMLSR mode: %s", emlsr_action_mode == WLAN_EMLSR_MODE_ENTER ?
12349 		  "Enter" : "Exit");
12350 
12351 	hdd_test_config_emlsr_action_mode(link_info->adapter,
12352 					  emlsr_action_mode);
12353 
12354 	return 0;
12355 }
12356 
hdd_set_t2lm_negotiation_support(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12357 static int hdd_set_t2lm_negotiation_support(struct wlan_hdd_link_info *link_info,
12358 					    const struct nlattr *attr)
12359 {
12360 	struct hdd_context *hdd_ctx = NULL;
12361 	uint8_t cfg_val;
12362 	enum wlan_t2lm_negotiation_support t2lm_support;
12363 
12364 	if (!attr)
12365 		return -EINVAL;
12366 
12367 	cfg_val = nla_get_u8(attr);
12368 
12369 	t2lm_support = hdd_get_cfg_t2lm_neg_support_type(cfg_val);
12370 	hdd_debug("T2LM negotiation support: %d", t2lm_support);
12371 
12372 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12373 
12374 	wlan_mlme_set_t2lm_negotiation_supported(hdd_ctx->psoc,
12375 						 t2lm_support);
12376 
12377 	return 0;
12378 }
12379 #else
12380 static inline int
hdd_set_link_force_active(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12381 hdd_set_link_force_active(struct wlan_hdd_link_info *link_info,
12382 			  const struct nlattr *attr)
12383 {
12384 	return 0;
12385 }
12386 
12387 static inline
hdd_set_emlsr_mode(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12388 int hdd_set_emlsr_mode(struct wlan_hdd_link_info *link_info,
12389 		       const struct nlattr *attr)
12390 {
12391 	return 0;
12392 }
12393 
12394 static inline
hdd_set_t2lm_negotiation_support(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12395 int hdd_set_t2lm_negotiation_support(struct wlan_hdd_link_info *link_info,
12396 				     const struct nlattr *attr)
12397 {
12398 	return 0;
12399 }
12400 
12401 static inline int
hdd_set_epcs_capability(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12402 hdd_set_epcs_capability(struct wlan_hdd_link_info *link_info,
12403 			const struct nlattr *attr)
12404 {
12405 	return 0;
12406 }
12407 
12408 static inline int
hdd_trigger_epcs_function(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12409 hdd_trigger_epcs_function(struct wlan_hdd_link_info *link_info,
12410 			  const struct nlattr *attr)
12411 {
12412 	return 0;
12413 }
12414 #endif
12415 
12416 /**
12417  * hdd_set_master_channel_list() - set master channel list from set wifi
12418  * attribute
12419  * @link_info: hdd link info
12420  * @attr: Pointer to struct nlattr
12421  *
12422  * Return: 0 on success, else error number
12423  */
12424 static int
hdd_set_master_channel_list(struct wlan_hdd_link_info * link_info,const struct nlattr * attr)12425 hdd_set_master_channel_list(struct wlan_hdd_link_info *link_info,
12426 			    const struct nlattr *attr)
12427 {
12428 	struct sap_config *sap_config;
12429 	qdf_freq_t freq;
12430 	uint16_t count = 0;
12431 	qdf_freq_t *freq_list;
12432 	struct nlattr *nested_attr;
12433 	int tmp, ret = 0;
12434 
12435 	if (link_info->adapter->device_mode != QDF_SAP_MODE) {
12436 		hdd_debug("command not received for sap");
12437 		return -EINVAL;
12438 	}
12439 	freq_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(qdf_freq_t));
12440 	if (!freq_list)
12441 		return -ENOMEM;
12442 
12443 	sap_config = &link_info->adapter->deflink->session.ap.sap_config;
12444 
12445 	nla_for_each_nested(nested_attr, attr, tmp) {
12446 		freq = nla_get_u32(nested_attr);
12447 		if (!freq) {
12448 			hdd_err("invalid freq");
12449 			ret = -EINVAL;
12450 			goto out;
12451 		}
12452 		freq_list[count] = freq;
12453 		count++;
12454 		if (count >= NUM_CHANNELS)
12455 			break;
12456 	}
12457 	if (!count) {
12458 		hdd_err("no valid freq found");
12459 		ret = -EINVAL;
12460 		goto out;
12461 	}
12462 	ret = wlansap_update_sap_chan_list(sap_config, freq_list, count);
12463 	if (ret)
12464 		hdd_err("sap chan list update failure");
12465 out:
12466 	qdf_mem_free(freq_list);
12467 
12468 	return ret;
12469 }
12470 
12471 /**
12472  * typedef independent_setter_fn - independent attribute handler
12473  * @link_info: Link info pointer in HDD adapter
12474  * @attr: The nl80211 attribute being applied
12475  *
12476  * Defines the signature of functions in the independent attribute vtable
12477  *
12478  * Return: 0 if the attribute was handled successfully, otherwise an errno
12479  */
12480 typedef int (*independent_setter_fn)(struct wlan_hdd_link_info *link_info,
12481 				     const struct nlattr *attr);
12482 
12483 /**
12484  * struct independent_setters
12485  * @id: vendor attribute which this entry handles
12486  * @cb: callback function to invoke to process the attribute when present
12487  */
12488 struct independent_setters {
12489 	uint32_t id;
12490 	independent_setter_fn cb;
12491 };
12492 
12493 /* vtable for independent setters */
12494 static const struct independent_setters independent_setters[] = {
12495 	{QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
12496 	 hdd_config_scan_default_ies},
12497 	{QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT,
12498 	 hdd_config_fine_time_measurement},
12499 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM,
12500 	 hdd_config_dynamic_dtim},
12501 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
12502 	 hdd_config_listen_interval},
12503 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LRO,
12504 	 hdd_config_lro},
12505 	{QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE,
12506 	 hdd_config_scan_enable},
12507 	{QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR,
12508 	 hdd_config_stats_avg_factor},
12509 	{QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME,
12510 	 hdd_config_guard_time},
12511 	{QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY,
12512 	 hdd_config_non_agg_retry},
12513 	{QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY,
12514 	 hdd_config_agg_retry},
12515 	{QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY,
12516 	 hdd_config_mgmt_retry},
12517 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY,
12518 	 hdd_config_ctrl_retry},
12519 	{QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY,
12520 	 hdd_config_propagation_delay},
12521 	{QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY,
12522 	 hdd_config_propagation_abs_delay},
12523 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT,
12524 	 hdd_config_tx_fail_count},
12525 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND,
12526 	 hdd_config_channel_avoidance_ind},
12527 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA,
12528 	 hdd_config_ant_div_ena},
12529 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF,
12530 	 hdd_config_ant_div_snr_diff},
12531 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME,
12532 	 hdd_config_ant_div_probe_dwell_time},
12533 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN,
12534 	 hdd_config_ant_div_chain},
12535 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST,
12536 	 hdd_config_ant_div_selftest},
12537 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL,
12538 	 hdd_config_ant_div_selftest_intvl},
12539 	{QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED,
12540 	 hdd_config_ignore_assoc_disallowed},
12541 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL,
12542 	 hdd_config_restrict_offchannel},
12543 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT,
12544 	 hdd_config_total_beacon_miss_count},
12545 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL,
12546 	 hdd_config_latency_level},
12547 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS,
12548 	 hdd_config_disable_fils},
12549 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE,
12550 	 hdd_config_rsn_ie},
12551 	{QCA_WLAN_VENDOR_ATTR_CONFIG_GTX,
12552 	 hdd_config_gtx},
12553 	{QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES,
12554 	 hdd_config_disconnect_ies},
12555 #ifdef WLAN_FEATURE_ELNA
12556 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
12557 	 hdd_set_elna_bypass},
12558 #endif
12559 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
12560 	 hdd_set_roam_reason_vsie_status},
12561 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC,
12562 	 hdd_config_ldpc},
12563 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC,
12564 	 hdd_config_tx_stbc},
12565 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
12566 	 hdd_config_rx_stbc},
12567 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
12568 	 hdd_set_dynamic_bw},
12569 	{QCA_WLAN_VENDOR_ATTR_CONFIG_NSS,
12570 	 hdd_set_nss},
12571 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE,
12572 	 hdd_config_udp_qos_upgrade_threshold},
12573 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY,
12574 	 hdd_set_primary_interface},
12575 	{QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS,
12576 	 hdd_set_ft_over_ds},
12577 #ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD
12578 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD,
12579 	 hdd_set_arp_ns_offload},
12580 #endif
12581 #ifdef WLAN_FEATURE_DBAM_CONFIG
12582 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DBAM,
12583 	 hdd_set_dbam_config},
12584 #endif
12585 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE_FOR_BE_BK,
12586 	 hdd_config_udp_qos_upgrade_be_bk},
12587 	{QCA_WLAN_VENDOR_ATTR_CONFIG_BEAMFORMER_PERIODIC_SOUNDING,
12588 	 hdd_set_beamformer_periodic_sounding},
12589 
12590 	{QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE,
12591 	 hdd_set_wfc_state},
12592 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_EML_CAPABILITY,
12593 	 hdd_set_eht_emlsr_capability},
12594 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_SIMULTANEOUS_LINKS,
12595 	 hdd_set_eht_max_simultaneous_links},
12596 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_CAPABILITY,
12597 	 hdd_set_epcs_capability},
12598 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_FUNCTION,
12599 	 hdd_trigger_epcs_function},
12600 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_NUM_LINKS,
12601 	 hdd_set_eht_max_num_links},
12602 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MODE,
12603 	 hdd_set_eht_mlo_mode},
12604 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_ACTIVE_LINKS,
12605 	 hdd_set_link_force_active},
12606 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EMLSR_MODE_SWITCH,
12607 	 hdd_set_emlsr_mode},
12608 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UL_MU_CONFIG,
12609 	 hdd_set_ul_mu_config},
12610 	{QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST,
12611 	 hdd_set_master_channel_list},
12612 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TTLM_NEGOTIATION_SUPPORT,
12613 	 hdd_set_t2lm_negotiation_support},
12614 	{QCA_WLAN_VENDOR_ATTR_CONFIG_COEX_TRAFFIC_SHAPING_MODE,
12615 	 hdd_set_coex_traffic_shaping_mode},
12616 	{QCA_WLAN_VENDOR_ATTR_CONFIG_BTM_SUPPORT,
12617 	 hdd_set_btm_support_config},
12618 	{QCA_WLAN_VENDOR_ATTR_CONFIG_KEEP_ALIVE_INTERVAL,
12619 	 hdd_vdev_set_sta_keep_alive_interval},
12620 };
12621 
12622 #ifdef WLAN_FEATURE_ELNA
12623 /**
12624  * hdd_get_elna_bypass() - Get eLNA bypass
12625  * @link_info: Link info pointer in HDD adapter
12626  * @skb: sk buffer to hold nl80211 attributes
12627  * @attr: Pointer to struct nlattr
12628  *
12629  * Return: 0 on success; error number otherwise
12630  */
hdd_get_elna_bypass(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12631 static int hdd_get_elna_bypass(struct wlan_hdd_link_info *link_info,
12632 			       struct sk_buff *skb,
12633 			       const struct nlattr *attr)
12634 {
12635 	int ret;
12636 	struct wlan_objmgr_vdev *vdev;
12637 
12638 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_FWOL_NB_ID);
12639 	if (!vdev)
12640 		return -EINVAL;
12641 
12642 	ret = os_if_fwol_get_elna_bypass(vdev, skb, attr);
12643 
12644 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_FWOL_NB_ID);
12645 
12646 	return ret;
12647 }
12648 #endif
12649 
12650 /**
12651  * hdd_get_roam_reason_vsie_status() - Get roam_reason_vsie
12652  * @link_info: Link info pointer in HDD adapter
12653  * @skb: sk buffer to hold nl80211 attributes
12654  * @attr: Pointer to struct nlattr
12655  *
12656  * Return: 0 on success; error number otherwise
12657  */
12658 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
hdd_get_roam_reason_vsie_status(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12659 static int hdd_get_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
12660 					   struct sk_buff *skb,
12661 					   const struct nlattr *attr)
12662 {
12663 	uint8_t roam_reason_vsie_enabled;
12664 	struct hdd_context *hdd_ctx = NULL;
12665 	QDF_STATUS status;
12666 
12667 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12668 
12669 	status = ucfg_mlme_get_roam_reason_vsie_status
12670 			       (hdd_ctx->psoc,
12671 				&roam_reason_vsie_enabled);
12672 	if (QDF_IS_STATUS_ERROR(status)) {
12673 		hdd_err("get roam reason vsie failed");
12674 		return -EINVAL;
12675 	}
12676 	hdd_debug("is roam_reason_vsie_enabled %d", roam_reason_vsie_enabled);
12677 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
12678 		       roam_reason_vsie_enabled)) {
12679 		hdd_err("nla_put failure");
12680 		return -EINVAL;
12681 	}
12682 
12683 	return 0;
12684 }
12685 #else
12686 static inline int
hdd_get_roam_reason_vsie_status(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12687 hdd_get_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
12688 				struct sk_buff *skb, const struct nlattr *attr)
12689 {
12690 	return -EINVAL;
12691 }
12692 #endif
12693 
hdd_vendor_attr_ldpc_get(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12694 static int hdd_vendor_attr_ldpc_get(struct wlan_hdd_link_info *link_info,
12695 				    struct sk_buff *skb,
12696 				    const struct nlattr *attr)
12697 {
12698 	int ldpc, ret;
12699 
12700 	ret = hdd_get_ldpc(link_info->adapter, &ldpc);
12701 	if (ret) {
12702 		hdd_err("get ldpc failed");
12703 		return -EINVAL;
12704 	}
12705 
12706 	hdd_debug("ldpc %u", ldpc);
12707 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC,
12708 		       (uint8_t)ldpc)) {
12709 		hdd_err("nla_put failure");
12710 		return -EINVAL;
12711 	}
12712 
12713 	return 0;
12714 }
12715 
hdd_vendor_attr_tx_stbc_get(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12716 static int hdd_vendor_attr_tx_stbc_get(struct wlan_hdd_link_info *link_info,
12717 				       struct sk_buff *skb,
12718 				       const struct nlattr *attr)
12719 {
12720 	int tx_stbc;
12721 	int ret;
12722 
12723 	ret = hdd_get_tx_stbc(link_info->adapter, &tx_stbc);
12724 	if (ret) {
12725 		hdd_err("get tx_stbc failed");
12726 		return -EINVAL;
12727 	}
12728 
12729 	hdd_debug("tx_stbc %u", tx_stbc);
12730 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC,
12731 		       (uint8_t)tx_stbc)) {
12732 		hdd_err("nla_put failure");
12733 		return -EINVAL;
12734 	}
12735 
12736 	return 0;
12737 }
12738 
hdd_vendor_attr_rx_stbc_get(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12739 static int hdd_vendor_attr_rx_stbc_get(struct wlan_hdd_link_info *link_info,
12740 				       struct sk_buff *skb,
12741 				       const struct nlattr *attr)
12742 {
12743 	int rx_stbc;
12744 	int ret;
12745 
12746 	ret = hdd_get_rx_stbc(link_info->adapter, &rx_stbc);
12747 	if (ret) {
12748 		hdd_err("get rx_stbc failed");
12749 		return -EINVAL;
12750 	}
12751 
12752 	hdd_debug("rx_stbc %u", rx_stbc);
12753 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
12754 		       (uint8_t)rx_stbc)) {
12755 		hdd_err("nla_put failure");
12756 		return -EINVAL;
12757 	}
12758 
12759 	return 0;
12760 }
12761 
12762 /**
12763  * hdd_get_tx_ampdu() - Get TX AMPDU
12764  * @link_info: Link info in HDD adapter
12765  * @skb: sk buffer to hold nl80211 attributes
12766  * @attr: Pointer to struct nlattr
12767  *
12768  * Return: 0 on success; error number otherwise
12769  */
hdd_get_tx_ampdu(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12770 static int hdd_get_tx_ampdu(struct wlan_hdd_link_info *link_info,
12771 			    struct sk_buff *skb, const struct nlattr *attr)
12772 {
12773 	int value;
12774 
12775 	value = wma_cli_get_command(link_info->vdev_id,
12776 				    GEN_VDEV_PARAM_TX_AMPDU, GEN_CMD);
12777 	if (value < 0) {
12778 		hdd_err("Failed to get tx_ampdu");
12779 		return -EINVAL;
12780 	}
12781 
12782 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION,
12783 		       (uint8_t)value)) {
12784 		hdd_err("nla_put failure");
12785 		return -EINVAL;
12786 	}
12787 
12788 	return 0;
12789 }
12790 
12791 /**
12792  * hdd_get_rx_ampdu() - Get RX AMPDU
12793  * @link_info: Link info in HDD adapter
12794  * @skb: sk buffer to hold nl80211 attributes
12795  * @attr: Pointer to struct nlattr
12796  *
12797  * Return: 0 on success; error number otherwise
12798  */
hdd_get_rx_ampdu(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12799 static int hdd_get_rx_ampdu(struct wlan_hdd_link_info *link_info,
12800 			    struct sk_buff *skb, const struct nlattr *attr)
12801 {
12802 	int value;
12803 
12804 	value = wma_cli_get_command(link_info->vdev_id,
12805 				    GEN_VDEV_PARAM_RX_AMPDU, GEN_CMD);
12806 	if (value < 0) {
12807 		hdd_err("Failed to get rx_ampdu");
12808 		return -EINVAL;
12809 	}
12810 
12811 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION,
12812 		       (uint8_t)value)) {
12813 		hdd_err("nla_put failure");
12814 		return -EINVAL;
12815 	}
12816 
12817 	return 0;
12818 }
12819 
12820 /**
12821  * hdd_get_tx_amsdu() - Get TX AMSDU
12822  * @link_info: Link info pointer in HDD adapter
12823  * @skb: sk buffer to hold nl80211 attributes
12824  * @attr: Pointer to struct nlattr
12825  *
12826  * Return: 0 on success; error number otherwise
12827  */
hdd_get_tx_amsdu(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12828 static int hdd_get_tx_amsdu(struct wlan_hdd_link_info *link_info,
12829 			    struct sk_buff *skb, const struct nlattr *attr)
12830 {
12831 	int value;
12832 
12833 	value = wma_cli_get_command(link_info->vdev_id,
12834 				    GEN_VDEV_PARAM_TX_AMSDU, GEN_CMD);
12835 	if (value < 0) {
12836 		hdd_err("Failed to get tx_amsdu");
12837 		return -EINVAL;
12838 	}
12839 
12840 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION,
12841 		       (uint8_t)value)) {
12842 		hdd_err("nla_put failure");
12843 		return -EINVAL;
12844 	}
12845 
12846 	return 0;
12847 }
12848 
12849 /**
12850  * hdd_get_rx_amsdu() - Get RX AMSDU
12851  * @link_info: Link info pointer in HDD adapter
12852  * @skb: sk buffer to hold nl80211 attributes
12853  * @attr: Pointer to struct nlattr
12854  *
12855  * Return: 0 on success; error number otherwise
12856  */
hdd_get_rx_amsdu(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12857 static int hdd_get_rx_amsdu(struct wlan_hdd_link_info *link_info,
12858 			    struct sk_buff *skb, const struct nlattr *attr)
12859 {
12860 	int value;
12861 
12862 	value = wma_cli_get_command(link_info->vdev_id,
12863 				    GEN_VDEV_PARAM_RX_AMSDU, GEN_CMD);
12864 	if (value < 0) {
12865 		hdd_err("Failed to get rx_amsdu");
12866 		return -EINVAL;
12867 	}
12868 
12869 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION,
12870 		       (uint8_t)value)) {
12871 		hdd_err("nla_put failure");
12872 		return -EINVAL;
12873 	}
12874 
12875 	return 0;
12876 }
12877 
12878 /**
12879  * hdd_get_channel_width() - Get channel width
12880  * @link_info: Link info pointer in HDD adapter
12881  * @skb: sk buffer to hold nl80211 attributes
12882  * @attr: Pointer to struct nlattr
12883  *
12884  * Return: 0 on success; error number otherwise
12885  */
hdd_get_channel_width(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12886 static int hdd_get_channel_width(struct wlan_hdd_link_info *link_info,
12887 				 struct sk_buff *skb, const struct nlattr *attr)
12888 {
12889 	uint8_t nl80211_chwidth;
12890 	struct wlan_channel *bss_chan;
12891 	struct wlan_objmgr_vdev *vdev;
12892 
12893 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
12894 	if (!vdev)
12895 		return -EINVAL;
12896 
12897 	bss_chan = wlan_vdev_mlme_get_bss_chan(vdev);
12898 	if (!bss_chan) {
12899 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12900 		hdd_err("get bss_chan failed");
12901 		return QDF_STATUS_E_FAILURE;
12902 	}
12903 
12904 	nl80211_chwidth = hdd_phy_chwidth_to_nl80211_chwidth(bss_chan->ch_width);
12905 	if (nla_put_u8(skb, CONFIG_CHANNEL_WIDTH, nl80211_chwidth)) {
12906 		hdd_err("nla_put chn width failure");
12907 		return -EINVAL;
12908 	}
12909 
12910 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12911 	return 0;
12912 }
12913 
12914 /**
12915  * hdd_get_mlo_max_band_info() - Get channel width
12916  * @link_info: Link info pointer in HDD adapter
12917  * @skb: sk buffer to hold nl80211 attributes
12918  * @attr: Pointer to struct nlattr
12919  *
12920  * Return: 0 on success; error number otherwise
12921  */
12922 #ifdef WLAN_FEATURE_11BE_MLO
hdd_get_mlo_max_band_info(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)12923 static int hdd_get_mlo_max_band_info(struct wlan_hdd_link_info *link_info,
12924 				     struct sk_buff *skb,
12925 				     const struct nlattr *attr)
12926 {
12927 	enum eSirMacHTChannelWidth chwidth;
12928 	struct nlattr *mlo_bd = NULL;
12929 	struct nlattr *mlo_bd_info = NULL;
12930 	uint32_t i = 0;
12931 	uint32_t link_id = 0;
12932 	struct wlan_objmgr_vdev *vdev;
12933 	struct wlan_objmgr_vdev *link_vdev = NULL;
12934 	struct wlan_channel *bss_chan;
12935 	struct wlan_hdd_link_info *link_info_t;
12936 	struct hdd_station_ctx *sta_ctx;
12937 	uint8_t nl80211_chwidth;
12938 	uint8_t chn_width;
12939 	int8_t ret = 0;
12940 
12941 	chwidth = wma_cli_get_command(link_info->vdev_id,
12942 				      wmi_vdev_param_chwidth, VDEV_CMD);
12943 	if (chwidth < 0) {
12944 		hdd_err("Failed to get chwidth %u", chwidth);
12945 		return -EINVAL;
12946 	}
12947 
12948 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
12949 	if (!vdev)
12950 		return -EINVAL;
12951 
12952 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
12953 		hdd_err("not mlo vdev");
12954 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12955 		return -EINVAL;
12956 	}
12957 
12958 	mlo_bd_info = nla_nest_start(skb, CONFIG_MLO_LINKS);
12959 	hdd_adapter_for_each_link_info(link_info->adapter, link_info_t) {
12960 		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info_t);
12961 		if (sta_ctx->conn_info.ieee_link_id == WLAN_INVALID_LINK_ID)
12962 			continue;
12963 
12964 		link_id = sta_ctx->conn_info.ieee_link_id;
12965 
12966 		mlo_bd = nla_nest_start(skb, i);
12967 		if (!mlo_bd) {
12968 			hdd_err("nla_nest_start fail");
12969 			ret = -EINVAL;
12970 			goto end;
12971 		}
12972 
12973 		if (nla_put_u8(skb, CONFIG_MLO_LINK_ID, link_id)) {
12974 			hdd_err("nla_put failure");
12975 			ret = -EINVAL;
12976 			goto end;
12977 		}
12978 
12979 		link_vdev = mlo_get_vdev_by_link_id(vdev, link_id,
12980 						    WLAN_OSIF_ID);
12981 
12982 		if (link_vdev) {
12983 			bss_chan = wlan_vdev_mlme_get_bss_chan(link_vdev);
12984 			if (!bss_chan) {
12985 				hdd_err("fail to get bss_chan info");
12986 				ret = -EINVAL;
12987 				goto end;
12988 			}
12989 			chn_width = bss_chan->ch_width;
12990 		} else if (link_info_t->vdev_id == WLAN_INVALID_VDEV_ID) {
12991 			chn_width = sta_ctx->user_cfg_chn_width;
12992 		} else {
12993 			chn_width = CH_WIDTH_INVALID;
12994 		}
12995 
12996 		hdd_debug("get link_id:%u ch width:%u", link_id, chn_width);
12997 
12998 		nl80211_chwidth = hdd_phy_chwidth_to_nl80211_chwidth(chn_width);
12999 		if (nla_put_u8(skb, CONFIG_CHANNEL_WIDTH, nl80211_chwidth)) {
13000 			hdd_err("nla_put failure");
13001 			ret = -EINVAL;
13002 			goto end;
13003 		}
13004 		nla_nest_end(skb, mlo_bd);
13005 		i++;
13006 
13007 		if (link_vdev)
13008 			hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
13009 	}
13010 	nla_nest_end(skb, mlo_bd_info);
13011 end:
13012 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
13013 
13014 	if (link_vdev)
13015 		hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
13016 
13017 	return ret;
13018 }
13019 #else
hdd_get_mlo_max_band_info(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13020 static int hdd_get_mlo_max_band_info(struct wlan_hdd_link_info *link_info,
13021 				     struct sk_buff *skb,
13022 				     const struct nlattr *attr)
13023 {
13024 	return 0;
13025 }
13026 #endif
13027 
13028 /**
13029  * hdd_get_dynamic_bw() - Get dynamic bandwidth disabled / enabled
13030  * @link_info: Link info pointer in HDD adapter
13031  * @skb: sk buffer to hold nl80211 attributes
13032  * @attr: Pointer to struct nlattr
13033  *
13034  * Return: 0 on success; error number otherwise
13035  */
hdd_get_dynamic_bw(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13036 static int hdd_get_dynamic_bw(struct wlan_hdd_link_info *link_info,
13037 			      struct sk_buff *skb, const struct nlattr *attr)
13038 {
13039 	int enable;
13040 
13041 	enable = wma_cli_get_command(link_info->vdev_id,
13042 				     wmi_pdev_param_dynamic_bw, PDEV_CMD);
13043 	if (enable < 0) {
13044 		hdd_err("Failed to get dynamic_bw");
13045 		return -EINVAL;
13046 	}
13047 
13048 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
13049 		       (uint8_t)enable)) {
13050 		hdd_err("nla_put failure");
13051 		return -EINVAL;
13052 	}
13053 
13054 	return 0;
13055 }
13056 
13057 /**
13058  * hdd_get_nss_config() - Get the number of spatial streams supported by
13059  * the adapter
13060  * @link_info: Link info pointer in HDD adapter
13061  * @skb: sk buffer to hold nl80211 attributes
13062  * @attr: Pointer to struct nlattr
13063  *
13064  * Return: 0 on success; error number otherwise
13065  */
hdd_get_nss_config(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13066 static int hdd_get_nss_config(struct wlan_hdd_link_info *link_info,
13067 			      struct sk_buff *skb, const struct nlattr *attr)
13068 {
13069 	uint8_t nss;
13070 	struct hdd_adapter *adapter = link_info->adapter;
13071 
13072 	if (adapter->device_mode == QDF_SAP_MODE) {
13073 		int value;
13074 
13075 		value = wma_cli_get_command(link_info->vdev_id,
13076 					    wmi_vdev_param_nss, VDEV_CMD);
13077 		if (value < 0) {
13078 			hdd_err("Failed to get nss");
13079 			return -EINVAL;
13080 		}
13081 		nss = (uint8_t)value;
13082 	} else {
13083 		QDF_STATUS status;
13084 
13085 		status = hdd_get_nss(adapter, &nss);
13086 		if (!QDF_IS_STATUS_SUCCESS(status)) {
13087 			hdd_err("Failed to get nss");
13088 			return -EINVAL;
13089 		}
13090 	}
13091 
13092 	hdd_debug("nss %d", nss);
13093 
13094 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_NSS, nss)) {
13095 		hdd_err("nla_put failure");
13096 		return -EINVAL;
13097 	}
13098 
13099 	return 0;
13100 }
13101 
13102 /**
13103  * hdd_get_num_tx_chains_config() - Get the number of tx chains supported by
13104  * the adapter
13105  * @link_info: Link info pointer in HDD adapter
13106  * @skb: sk buffer to hold nl80211 attributes
13107  * @attr: Pointer to struct nlattr
13108  *
13109  * Return: 0 on success; error number otherwise
13110  */
hdd_get_num_tx_chains_config(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13111 static int hdd_get_num_tx_chains_config(struct wlan_hdd_link_info *link_info,
13112 					struct sk_buff *skb,
13113 					const struct nlattr *attr)
13114 {
13115 	uint8_t tx_chains;
13116 	QDF_STATUS status;
13117 
13118 	if (!hdd_is_vdev_in_conn_state(link_info)) {
13119 		hdd_err("Not in connected state");
13120 		return -EINVAL;
13121 	}
13122 
13123 	status = hdd_get_num_tx_chains(link_info, &tx_chains);
13124 	if (!QDF_IS_STATUS_SUCCESS(status)) {
13125 		hdd_err("Failed to get num tx chains");
13126 		return -EINVAL;
13127 	}
13128 
13129 	hdd_debug("num_tx_chains %d", tx_chains);
13130 	if (nla_put_u8(skb,
13131 		       QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS, tx_chains)) {
13132 		hdd_err("nla_put failure");
13133 		return -EINVAL;
13134 	}
13135 
13136 	return 0;
13137 }
13138 
13139 /**
13140  * hdd_get_tx_nss_config() - Get the number of tx spatial streams supported by
13141  * the adapter
13142  * @link_info: Link info pointer in HDD adapter
13143  * @skb: sk buffer to hold nl80211 attributes
13144  * @attr: Pointer to struct nlattr
13145  *
13146  * Return: 0 on success; error number otherwise
13147  */
hdd_get_tx_nss_config(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13148 static int hdd_get_tx_nss_config(struct wlan_hdd_link_info *link_info,
13149 				 struct sk_buff *skb, const struct nlattr *attr)
13150 {
13151 	uint8_t tx_nss;
13152 	QDF_STATUS status;
13153 
13154 	if (!hdd_is_vdev_in_conn_state(link_info)) {
13155 		hdd_err("Not in connected state");
13156 		return -EINVAL;
13157 	}
13158 
13159 	status = hdd_get_tx_nss(link_info, &tx_nss);
13160 	if (!QDF_IS_STATUS_SUCCESS(status)) {
13161 		hdd_err("Failed to get nss");
13162 		return -EINVAL;
13163 	}
13164 
13165 	hdd_debug("tx_nss %d", tx_nss);
13166 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS, tx_nss)) {
13167 		hdd_err("nla_put failure");
13168 		return -EINVAL;
13169 	}
13170 
13171 	return 0;
13172 }
13173 
13174 /**
13175  * hdd_get_num_rx_chains_config() - Get the number of rx chains supported by
13176  * the adapter
13177  * @link_info: Link info pointer in HDD adapter
13178  * @skb: sk buffer to hold nl80211 attributes
13179  * @attr: Pointer to struct nlattr
13180  *
13181  * Return: 0 on success; error number otherwise
13182  */
hdd_get_num_rx_chains_config(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13183 static int hdd_get_num_rx_chains_config(struct wlan_hdd_link_info *link_info,
13184 					struct sk_buff *skb,
13185 					const struct nlattr *attr)
13186 {
13187 	uint8_t rx_chains;
13188 	QDF_STATUS status;
13189 
13190 	if (!hdd_is_vdev_in_conn_state(link_info)) {
13191 		hdd_err("Not in connected state");
13192 		return -EINVAL;
13193 	}
13194 
13195 	status = hdd_get_num_rx_chains(link_info, &rx_chains);
13196 	if (!QDF_IS_STATUS_SUCCESS(status)) {
13197 		hdd_err("Failed to get num rx chains");
13198 		return -EINVAL;
13199 	}
13200 
13201 	hdd_debug("num_rx_chains %d", rx_chains);
13202 	if (nla_put_u8(skb,
13203 		       QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS, rx_chains)) {
13204 		hdd_err("nla_put failure");
13205 		return -EINVAL;
13206 	}
13207 
13208 	return 0;
13209 }
13210 
13211 /**
13212  * hdd_get_rx_nss_config() - Get the number of rx spatial streams supported by
13213  * the adapter
13214  * @link_info: Link info pointer in HDD adapter
13215  * @skb: sk buffer to hold nl80211 attributes
13216  * @attr: Pointer to struct nlattr
13217  *
13218  * Return: 0 on success; error number otherwise
13219  */
hdd_get_rx_nss_config(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13220 static int hdd_get_rx_nss_config(struct wlan_hdd_link_info *link_info,
13221 				 struct sk_buff *skb, const struct nlattr *attr)
13222 {
13223 	uint8_t rx_nss;
13224 	QDF_STATUS status;
13225 
13226 	if (!hdd_is_vdev_in_conn_state(link_info)) {
13227 		hdd_err("Not in connected state");
13228 		return -EINVAL;
13229 	}
13230 
13231 	status = hdd_get_rx_nss(link_info, &rx_nss);
13232 	if (!QDF_IS_STATUS_SUCCESS(status)) {
13233 		hdd_err("Failed to get nss");
13234 		return -EINVAL;
13235 	}
13236 
13237 	hdd_debug("rx_nss %d", rx_nss);
13238 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS, rx_nss)) {
13239 		hdd_err("nla_put failure");
13240 		return -EINVAL;
13241 	}
13242 
13243 	return 0;
13244 }
13245 
13246 /**
13247  * hdd_get_listen_interval_config() - Get listen interval from driver
13248  * @link_info: Link info pointer in HDD adapter
13249  * @skb: sk buffer to hold nl80211 attributes
13250  * @attr: Pointer to struct nlattr
13251  *
13252  * Return: 0 on success; error number otherwise
13253  */
hdd_get_listen_interval_config(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13254 static int hdd_get_listen_interval_config(struct wlan_hdd_link_info *link_info,
13255 					  struct sk_buff *skb,
13256 					  const struct nlattr *attr)
13257 {
13258 	uint32_t listen_interval = 0;
13259 	QDF_STATUS status;
13260 	struct hdd_adapter *adapter = link_info->adapter;
13261 	struct wlan_objmgr_vdev *vdev;
13262 
13263 	if (adapter->device_mode != QDF_STA_MODE &&
13264 	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
13265 		hdd_err("Device not in STA / P2P-CLI mode");
13266 		return -EINVAL;
13267 	}
13268 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
13269 	if (!vdev) {
13270 		hdd_err("Failed to get vdev");
13271 		return -EINVAL;
13272 	}
13273 
13274 	status = ucfg_pmo_get_listen_interval(vdev, &listen_interval);
13275 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
13276 	if (status != QDF_STATUS_SUCCESS) {
13277 		hdd_err("vdev/vdev ctx NULL for getting listen interval");
13278 		return -EINVAL;
13279 	}
13280 
13281 	hdd_debug("listen interval %d", listen_interval);
13282 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
13283 			listen_interval)) {
13284 		hdd_err("nla_put failure");
13285 		return -EINVAL;
13286 	}
13287 
13288 	return 0;
13289 }
13290 
13291 /**
13292  * hdd_get_optimized_power_config() - Get the number of spatial streams
13293  * supported by the adapter
13294  * @link_info: Link info pointer in HDD adapter
13295  * @skb: sk buffer to hold nl80211 attributes
13296  * @attr: Pointer to struct nlattr
13297  *
13298  * Return: 0 on success; error number otherwise
13299  */
hdd_get_optimized_power_config(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13300 static int hdd_get_optimized_power_config(struct wlan_hdd_link_info *link_info,
13301 					  struct sk_buff *skb,
13302 					  const struct nlattr *attr)
13303 {
13304 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
13305 	uint8_t optimized_power_cfg;
13306 	int errno;
13307 
13308 	errno = wlan_hdd_validate_context(hdd_ctx);
13309 	if (errno)
13310 		return errno;
13311 
13312 	optimized_power_cfg  = ucfg_pmo_get_power_save_mode(hdd_ctx->psoc);
13313 
13314 	if (nla_put_u8(skb,
13315 		       QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT,
13316 		       optimized_power_cfg)) {
13317 		hdd_err_rl("nla_put failure");
13318 		return -EINVAL;
13319 	}
13320 
13321 	return 0;
13322 }
13323 
13324 /**
13325  * hdd_get_sta_keepalive_interval() - Get keep alive interval
13326  * @link_info: Link info pointer in HDD adapter
13327  * @skb: sk buffer to hold nl80211 attributes
13328  * @attr: Pointer to struct nlattr
13329  *
13330  * Return: 0 on success; error number otherwise
13331  */
hdd_get_sta_keepalive_interval(struct wlan_hdd_link_info * link_info,struct sk_buff * skb,const struct nlattr * attr)13332 static int hdd_get_sta_keepalive_interval(struct wlan_hdd_link_info *link_info,
13333 					  struct sk_buff *skb,
13334 					  const struct nlattr *attr)
13335 {
13336 	struct hdd_adapter *adapter = link_info->adapter;
13337 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
13338 	enum QDF_OPMODE device_mode = adapter->device_mode;
13339 	uint32_t keep_alive_interval;
13340 	struct wlan_objmgr_vdev *vdev;
13341 
13342 	if (device_mode != QDF_STA_MODE) {
13343 		hdd_debug("This command is not supported for %s device mode",
13344 			  device_mode_to_string(device_mode));
13345 		return -EINVAL;
13346 	}
13347 
13348 	if (!hdd_is_vdev_in_conn_state(link_info)) {
13349 		if (adapter->keep_alive_interval)
13350 			keep_alive_interval = adapter->keep_alive_interval;
13351 		else
13352 			ucfg_mlme_get_sta_keep_alive_period(
13353 							hdd_ctx->psoc,
13354 							&keep_alive_interval);
13355 	} else {
13356 		vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_CM_ID);
13357 		if (!vdev) {
13358 			hdd_err("vdev is NULL");
13359 			return -EINVAL;
13360 		}
13361 
13362 		keep_alive_interval = ucfg_mlme_get_keepalive_period(vdev);
13363 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_CM_ID);
13364 	}
13365 
13366 	hdd_debug("STA KEEPALIVE interval = %d", keep_alive_interval);
13367 	if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_KEEP_ALIVE_INTERVAL,
13368 			keep_alive_interval)) {
13369 		hdd_err("nla_put failure");
13370 		return -EINVAL;
13371 	}
13372 
13373 	return 0;
13374 }
13375 
13376 /**
13377  * typedef config_getter_fn - get configuration handler
13378  * @link_info: Link info pointer in HDD adapter
13379  * @skb: sk buffer to hold nl80211 attributes
13380  * @attr: The nl80211 attribute being applied
13381  *
13382  * Defines the signature of functions in the attribute vtable
13383  *
13384  * Return: 0 if the attribute was handled successfully, otherwise an errno
13385  */
13386 typedef int (*config_getter_fn)(struct wlan_hdd_link_info *link_info,
13387 				struct sk_buff *skb,
13388 				const struct nlattr *attr);
13389 
13390 /**
13391  * struct config_getters
13392  * @id: vendor attribute which this entry handles
13393  * @max_attr_len: Maximum length of the attribute
13394  * @cb: callback function to invoke to process the attribute when present
13395  */
13396 struct config_getters {
13397 	uint32_t id;
13398 	size_t max_attr_len;
13399 	config_getter_fn cb;
13400 };
13401 
13402 /* vtable for config getters */
13403 static const struct config_getters config_getters[] = {
13404 #ifdef WLAN_FEATURE_ELNA
13405 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
13406 	 sizeof(uint8_t),
13407 	 hdd_get_elna_bypass},
13408 #endif
13409 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
13410 	 sizeof(uint8_t),
13411 	 hdd_get_roam_reason_vsie_status},
13412 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION,
13413 	 sizeof(uint8_t),
13414 	 hdd_get_tx_ampdu},
13415 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION,
13416 	 sizeof(uint8_t),
13417 	 hdd_get_rx_ampdu},
13418 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION,
13419 	 sizeof(uint8_t),
13420 	 hdd_get_tx_amsdu},
13421 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION,
13422 	 sizeof(uint8_t),
13423 	 hdd_get_rx_amsdu},
13424 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC,
13425 	 sizeof(uint8_t),
13426 	 hdd_vendor_attr_ldpc_get},
13427 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC,
13428 	 sizeof(uint8_t),
13429 	 hdd_vendor_attr_tx_stbc_get},
13430 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
13431 	 sizeof(uint8_t),
13432 	 hdd_vendor_attr_rx_stbc_get},
13433 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH,
13434 	 sizeof(uint8_t),
13435 	 hdd_get_channel_width},
13436 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
13437 	 sizeof(uint8_t),
13438 	 hdd_get_dynamic_bw},
13439 	{QCA_WLAN_VENDOR_ATTR_CONFIG_NSS,
13440 	 sizeof(uint8_t),
13441 	 hdd_get_nss_config},
13442 	{QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT,
13443 	 sizeof(uint8_t),
13444 	 hdd_get_optimized_power_config},
13445 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS,
13446 	 sizeof(uint8_t),
13447 	 hdd_get_tx_nss_config},
13448 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS,
13449 	 sizeof(uint8_t),
13450 	 hdd_get_rx_nss_config},
13451 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
13452 	 sizeof(uint32_t),
13453 	 hdd_get_listen_interval_config},
13454 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS,
13455 	 sizeof(uint8_t),
13456 	 hdd_get_num_tx_chains_config},
13457 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS,
13458 	 sizeof(uint8_t),
13459 	 hdd_get_num_rx_chains_config},
13460 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS,
13461 	 WLAN_MAX_ML_BSS_LINKS * sizeof(uint8_t) * 2,
13462 	 hdd_get_mlo_max_band_info},
13463 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_KEEP_ALIVE_INTERVAL,
13464 	  sizeof(uint16_t),
13465 	  hdd_get_sta_keepalive_interval},
13466 };
13467 
13468 /**
13469  * hdd_get_configuration() - Handle get configuration
13470  * @link_info: Link info pointer in HDD adapter
13471  * @tb: parsed attribute array
13472  *
13473  * This is a table-driven function which dispatches attributes
13474  * in a QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION
13475  * vendor command.
13476  *
13477  * Return: 0 if there were no issues, otherwise errno of the last issue
13478  */
hdd_get_configuration(struct wlan_hdd_link_info * link_info,struct nlattr ** tb)13479 static int hdd_get_configuration(struct wlan_hdd_link_info *link_info,
13480 				 struct nlattr **tb)
13481 {
13482 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
13483 	uint32_t i, id;
13484 	unsigned long nl_buf_len = NLMSG_HDRLEN;
13485 	struct sk_buff *skb;
13486 	struct nlattr *attr;
13487 	config_getter_fn cb;
13488 	int errno = 0;
13489 
13490 	for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
13491 		id = config_getters[i].id;
13492 		attr = tb[id];
13493 		if (!attr)
13494 			continue;
13495 
13496 		nl_buf_len += NLA_HDRLEN +
13497 			      NLA_ALIGN(config_getters[i].max_attr_len);
13498 	}
13499 
13500 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
13501 						       nl_buf_len);
13502 	if (!skb) {
13503 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
13504 		return -ENOMEM;
13505 	}
13506 
13507 	for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
13508 		id = config_getters[i].id;
13509 		attr = tb[id];
13510 		if (!attr)
13511 			continue;
13512 
13513 		hdd_debug("Get wifi configuration %d", id);
13514 
13515 		cb = config_getters[i].cb;
13516 		errno = cb(link_info, skb, attr);
13517 		if (errno)
13518 			break;
13519 	}
13520 
13521 	if (errno) {
13522 		hdd_err("Failed to get wifi configuration, errno = %d", errno);
13523 		wlan_cfg80211_vendor_free_skb(skb);
13524 		return -EINVAL;
13525 	}
13526 
13527 	wlan_cfg80211_vendor_cmd_reply(skb);
13528 
13529 	return errno;
13530 }
13531 
13532 /**
13533  * hdd_set_independent_configuration() - Handle independent attributes
13534  * @link_info: Link info pointer in HDD adapter
13535  * @tb: parsed attribute array
13536  *
13537  * This is a table-driven function which dispatches independent
13538  * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
13539  * vendor command. An attribute is considered independent if it
13540  * doesn't depend upon any other attributes
13541  *
13542  * Return: 0 if there were no issues, otherwise errno of the last issue
13543  */
13544 static int
hdd_set_independent_configuration(struct wlan_hdd_link_info * link_info,struct nlattr ** tb)13545 hdd_set_independent_configuration(struct wlan_hdd_link_info *link_info,
13546 				  struct nlattr **tb)
13547 {
13548 	uint32_t i;
13549 	uint32_t id;
13550 	struct nlattr *attr;
13551 	independent_setter_fn cb;
13552 	int errno = 0;
13553 	int ret;
13554 
13555 	for (i = 0; i < QDF_ARRAY_SIZE(independent_setters); i++) {
13556 		id = independent_setters[i].id;
13557 		attr = tb[id];
13558 		if (!attr)
13559 			continue;
13560 
13561 		hdd_debug("Set wifi configuration %d", id);
13562 
13563 		cb = independent_setters[i].cb;
13564 		ret = cb(link_info, attr);
13565 		if (ret)
13566 			errno = ret;
13567 	}
13568 
13569 	return errno;
13570 }
13571 
13572 /**
13573  * typedef interdependent_setter_fn - interdependent attribute handler
13574  * @link_info: Link info pointer in HDD adapter
13575  * @tb: The parsed nl80211 attributes being applied
13576  *
13577  * Defines the signature of functions in the interdependent attribute vtable
13578  *
13579  * Return: 0 if attributes were handled successfully, otherwise an errno
13580  */
13581 typedef int (*interdependent_setter_fn)(struct wlan_hdd_link_info *link_info,
13582 					struct nlattr **tb);
13583 
13584 /* vtable for interdependent setters */
13585 static const interdependent_setter_fn interdependent_setters[] = {
13586 	hdd_config_access_policy,
13587 	hdd_config_mpdu_aggregation,
13588 	hdd_config_ant_div_period,
13589 	hdd_config_ant_div_snr_weight,
13590 	wlan_hdd_cfg80211_wifi_set_reorder_timeout,
13591 	wlan_hdd_cfg80211_wifi_set_rx_blocksize,
13592 	hdd_config_msdu_aggregation,
13593 	hdd_config_vdev_chains,
13594 	hdd_config_ani,
13595 	hdd_config_tx_rx_nss,
13596 	hdd_process_generic_set_cmd,
13597 	hdd_config_phy_mode,
13598 	hdd_config_power,
13599 	hdd_set_channel_width,
13600 	hdd_config_peer_ampdu,
13601 };
13602 
13603 /**
13604  * hdd_set_interdependent_configuration() - Handle interdependent attributes
13605  * @link_info: Link info pointer in hdd adapter
13606  * @tb: parsed attribute array
13607  *
13608  * This is a table-driven function which handles interdependent
13609  * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
13610  * vendor command. A set of attributes is considered interdependent if
13611  * they depend upon each other. In the typical case if one of the
13612  * attributes is present in the the attribute array, then all of the
13613  * attributes must be present.
13614  *
13615  * Return: 0 if there were no issues, otherwise errno of the last issue
13616  */
13617 static int
hdd_set_interdependent_configuration(struct wlan_hdd_link_info * link_info,struct nlattr ** tb)13618 hdd_set_interdependent_configuration(struct wlan_hdd_link_info *link_info,
13619 				     struct nlattr **tb)
13620 {
13621 	uint32_t i;
13622 	interdependent_setter_fn cb;
13623 	int errno = 0;
13624 	int ret;
13625 
13626 	for (i = 0; i < QDF_ARRAY_SIZE(interdependent_setters); i++) {
13627 		cb = interdependent_setters[i];
13628 		ret = cb(link_info, tb);
13629 		if (ret)
13630 			errno = ret;
13631 	}
13632 
13633 	return errno;
13634 }
13635 
13636 /**
13637  * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
13638  * vendor command
13639  *
13640  * @wiphy: wiphy device pointer
13641  * @wdev: wireless device pointer
13642  * @data: Vendor command data buffer
13643  * @data_len: Buffer length
13644  *
13645  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
13646  *
13647  * Return: Error code.
13648  */
13649 static int
__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)13650 __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
13651 					   struct wireless_dev *wdev,
13652 					   const void *data,
13653 					   int data_len)
13654 {
13655 	struct net_device *dev = wdev->netdev;
13656 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13657 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
13658 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
13659 	int errno, ret;
13660 
13661 	hdd_enter_dev(dev);
13662 
13663 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13664 		hdd_err("Command not allowed in FTM mode");
13665 		return -EPERM;
13666 	}
13667 
13668 	errno = wlan_hdd_validate_context(hdd_ctx);
13669 	if (errno)
13670 		return errno;
13671 
13672 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
13673 				    data_len, wlan_hdd_wifi_config_policy)) {
13674 		hdd_err("invalid attr");
13675 		return -EINVAL;
13676 	}
13677 
13678 	ret = hdd_set_independent_configuration(adapter->deflink, tb);
13679 	if (ret)
13680 		errno = ret;
13681 
13682 	ret = hdd_set_interdependent_configuration(adapter->deflink, tb);
13683 	if (ret)
13684 		errno = ret;
13685 
13686 	return errno;
13687 }
13688 
13689 /**
13690  * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
13691  * vendor command
13692  *
13693  * @wiphy: wiphy device pointer
13694  * @wdev: wireless device pointer
13695  * @data: Vendor command data buffer
13696  * @data_len: Buffer length
13697  *
13698  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
13699  *
13700  * Return: EOK or other error codes.
13701  */
wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)13702 static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
13703 						    struct wireless_dev *wdev,
13704 						    const void *data,
13705 						    int data_len)
13706 {
13707 	int errno;
13708 	struct osif_vdev_sync *vdev_sync;
13709 
13710 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13711 	if (errno)
13712 		return errno;
13713 
13714 	errno = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
13715 							   data, data_len);
13716 
13717 	osif_vdev_sync_op_stop(vdev_sync);
13718 
13719 	return errno;
13720 }
13721 
13722 /**
13723  * __wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
13724  * vendor command
13725  * @wiphy: wiphy device pointer
13726  * @wdev: wireless device pointer
13727  * @data: Vendor command data buffer
13728  * @data_len: Buffer length
13729  *
13730  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
13731  *
13732  * Return: Error code.
13733  */
13734 static int
__wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)13735 __wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
13736 					   struct wireless_dev *wdev,
13737 					   const void *data,
13738 					   int data_len)
13739 {
13740 	struct net_device *dev = wdev->netdev;
13741 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13742 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
13743 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
13744 	int errno, ret;
13745 
13746 	hdd_enter_dev(dev);
13747 
13748 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13749 		hdd_err("Command not allowed in FTM mode");
13750 		return -EPERM;
13751 	}
13752 
13753 	errno = wlan_hdd_validate_context(hdd_ctx);
13754 	if (errno)
13755 		return errno;
13756 
13757 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
13758 				    data_len, wlan_hdd_wifi_config_policy)) {
13759 		hdd_err("invalid attr");
13760 		return -EINVAL;
13761 	}
13762 
13763 	/* Generic command is used by EasyMesh,
13764 	 * route the command to SON module if it is Generic
13765 	 *
13766 	 * GENERIC_COMMAND to get configs can not be done as part of dispatch
13767 	 * table because, for each command sent as part of GENERIC command,
13768 	 * return value is different and is handled in SON module as well.
13769 	 * Hence having return type with dispatch table is not possible as
13770 	 * we will not be able to generalize the return for each of get sub
13771 	 * command sent as part of GENERIC command.
13772 	 */
13773 	if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND])
13774 		return hdd_son_send_get_wifi_generic_command(wiphy, wdev, tb);
13775 
13776 	ret = hdd_get_configuration(adapter->deflink, tb);
13777 	if (ret)
13778 		errno = ret;
13779 
13780 	return errno;
13781 }
13782 
13783 /**
13784  * wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
13785  * vendor command
13786  *
13787  * @wiphy: wiphy device pointer
13788  * @wdev: wireless device pointer
13789  * @data: Vendor command data buffer
13790  * @data_len: Buffer length
13791  *
13792  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
13793  *
13794  * Return: EOK or other error codes.
13795  */
wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)13796 static int wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
13797 						    struct wireless_dev *wdev,
13798 						    const void *data,
13799 						    int data_len)
13800 {
13801 	int errno;
13802 	struct osif_vdev_sync *vdev_sync;
13803 
13804 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13805 	if (errno)
13806 		return errno;
13807 
13808 	errno = __wlan_hdd_cfg80211_wifi_configuration_get(wiphy, wdev,
13809 							   data, data_len);
13810 
13811 	osif_vdev_sync_op_stop(vdev_sync);
13812 
13813 	return errno;
13814 }
13815 
hdd_disable_runtime_pm_for_user(struct hdd_context * hdd_ctx)13816 static void hdd_disable_runtime_pm_for_user(struct hdd_context *hdd_ctx)
13817 {
13818 	struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
13819 
13820 	if (!ctx)
13821 		return;
13822 
13823 	if (ctx->is_user_wakelock_acquired)
13824 		return;
13825 
13826 	ctx->is_user_wakelock_acquired = true;
13827 	qdf_runtime_pm_prevent_suspend(&ctx->user);
13828 }
13829 
hdd_test_config_6ghz_security_test_mode(struct hdd_context * hdd_ctx,struct nlattr * attr)13830 static int hdd_test_config_6ghz_security_test_mode(struct hdd_context *hdd_ctx,
13831 						   struct nlattr *attr)
13832 
13833 {
13834 	uint8_t cfg_val;
13835 	bool rf_test_mode = false;
13836 	QDF_STATUS status;
13837 
13838 	status = ucfg_mlme_is_rf_test_mode_enabled(hdd_ctx->psoc,
13839 						   &rf_test_mode);
13840 	if (!QDF_IS_STATUS_SUCCESS(status)) {
13841 		hdd_err("Get rf test mode failed");
13842 		return -EINVAL;
13843 	}
13844 	if (rf_test_mode) {
13845 		hdd_err("rf test mode is enabled, ignore setting");
13846 		return 0;
13847 	}
13848 
13849 	cfg_val = nla_get_u8(attr);
13850 	hdd_debug("safe mode setting %d", cfg_val);
13851 	wlan_mlme_set_safe_mode_enable(hdd_ctx->psoc, cfg_val);
13852 	if (cfg_val) {
13853 		wlan_cm_set_check_6ghz_security(hdd_ctx->psoc, false);
13854 		wlan_cm_set_6ghz_key_mgmt_mask(hdd_ctx->psoc,
13855 					       DEFAULT_KEYMGMT_6G_MASK);
13856 	} else {
13857 		wlan_cm_set_check_6ghz_security(hdd_ctx->psoc, true);
13858 		wlan_cm_set_6ghz_key_mgmt_mask(hdd_ctx->psoc,
13859 					       ALLOWED_KEYMGMT_6G_MASK);
13860 	}
13861 
13862 	return 0;
13863 }
13864 
13865 #ifdef WLAN_FEATURE_11BE_MLO
wlan_hdd_set_listen_interval(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)13866 static void wlan_hdd_set_listen_interval(struct hdd_context *hdd_ctx,
13867 					 struct hdd_adapter *adapter)
13868 {
13869 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
13870 	enum wlan_eht_mode eht_mode;
13871 	uint16_t max_simult_link_num;
13872 
13873 	ucfg_mlme_get_eht_mode(psoc, &eht_mode);
13874 	max_simult_link_num = wlan_mlme_get_sta_mlo_simultaneous_links(psoc);
13875 
13876 	if (eht_mode == WLAN_EHT_MODE_MLSR && max_simult_link_num == 0)
13877 		sme_set_listen_interval(hdd_ctx->mac_handle,
13878 					adapter->deflink->vdev_id);
13879 
13880 	hdd_debug("EHT mode: %d, max simultaneous link num: %d",
13881 		  eht_mode, max_simult_link_num);
13882 }
13883 #else
wlan_hdd_set_listen_interval(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)13884 static inline void wlan_hdd_set_listen_interval(struct hdd_context *hdd_ctx,
13885 					        struct hdd_adapter *adapter)
13886 {
13887 }
13888 #endif
13889 
13890 /**
13891  * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
13892  * vendor command
13893  *
13894  * @wiphy: wiphy device pointer
13895  * @wdev: wireless device pointer
13896  * @data: Vendor command data buffer
13897  * @data_len: Buffer length
13898  *
13899  * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
13900  *
13901  * Return: Error code.
13902  */
13903 static int
__wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)13904 __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
13905 		struct wireless_dev *wdev, const void *data, int data_len)
13906 {
13907 	struct net_device *dev = wdev->netdev;
13908 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13909 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
13910 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
13911 	int ret_val = 0;
13912 	uint8_t cfg_val = 0;
13913 	uint8_t ini_val = 0;
13914 	uint8_t set_val = 0;
13915 	struct sme_config_params *sme_config;
13916 	bool update_sme_cfg = false;
13917 	uint8_t tid = 0, ac;
13918 	uint16_t buff_size = 0;
13919 	mac_handle_t mac_handle;
13920 	QDF_STATUS status;
13921 	bool bval = false;
13922 	uint8_t value = 0;
13923 	uint8_t wmm_mode = 0;
13924 	uint32_t bss_max_idle_period = 0;
13925 	uint32_t cmd_id;
13926 	uint8_t link_id = 0xFF;
13927 	struct keep_alive_req keep_alive_req = {0};
13928 	struct set_wfatest_params wfa_param = {0};
13929 	struct wlan_hdd_link_info *link_info = adapter->deflink;
13930 	struct hdd_station_ctx *hdd_sta_ctx =
13931 			WLAN_HDD_GET_STATION_CTX_PTR(link_info);
13932 	uint8_t op_mode;
13933 
13934 	hdd_enter_dev(dev);
13935 
13936 	sme_config = qdf_mem_malloc(sizeof(*sme_config));
13937 	if (!sme_config)
13938 		return -ENOMEM;
13939 
13940 	mac_handle = hdd_ctx->mac_handle;
13941 	sme_get_config_param(mac_handle, sme_config);
13942 
13943 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13944 		hdd_err("Command not allowed in FTM mode");
13945 		ret_val = -EPERM;
13946 		goto send_err;
13947 	}
13948 
13949 	ret_val = wlan_hdd_validate_context(hdd_ctx);
13950 	if (ret_val)
13951 		goto send_err;
13952 
13953 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
13954 		hdd_err("Driver Modules are closed, can not start logger");
13955 		ret_val = -EINVAL;
13956 		goto send_err;
13957 	}
13958 
13959 	if (wlan_cfg80211_nla_parse(tb,
13960 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
13961 			data, data_len, wlan_hdd_wifi_test_config_policy)) {
13962 		hdd_err("invalid attr");
13963 		ret_val = -EINVAL;
13964 		goto send_err;
13965 	}
13966 
13967 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
13968 		cfg_val = nla_get_u8(tb[
13969 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
13970 			);
13971 		hdd_debug("set addba accept req from peer value %d", cfg_val);
13972 		ret_val = sme_set_addba_accept(mac_handle,
13973 					       link_info->vdev_id,
13974 					       cfg_val);
13975 		if (ret_val)
13976 			goto send_err;
13977 	}
13978 
13979 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
13980 		cfg_val = nla_get_u8(tb[
13981 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
13982 		hdd_debug("set HE MCS value 0x%0X", cfg_val);
13983 		ret_val = sme_update_he_mcs(mac_handle,
13984 					    link_info->vdev_id, cfg_val);
13985 		if (ret_val)
13986 			goto send_err;
13987 	}
13988 
13989 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
13990 		cfg_val = nla_get_u8(tb[
13991 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
13992 		if (!cfg_val) {
13993 			sme_config->csr_config.WMMSupportMode =
13994 				hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
13995 			hdd_debug("wmm is disabled");
13996 		} else {
13997 			status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc,
13998 							&wmm_mode);
13999 			if (!QDF_IS_STATUS_SUCCESS(status)) {
14000 				hdd_err("Get wmm_mode failed");
14001 				ret_val = -EINVAL;
14002 				goto send_err;
14003 			}
14004 			sme_config->csr_config.WMMSupportMode =
14005 				hdd_to_csr_wmm_mode(wmm_mode);
14006 			hdd_debug("using wmm default value");
14007 		}
14008 		update_sme_cfg = true;
14009 	}
14010 
14011 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
14012 		cfg_val = nla_get_u8(tb[
14013 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
14014 		if (cfg_val) {
14015 			/*Auto BA mode*/
14016 			set_val = HDD_BA_MODE_AUTO;
14017 			hdd_debug("BA operating mode is set to auto");
14018 		} else {
14019 			/*Manual BA mode*/
14020 			set_val = HDD_BA_MODE_MANUAL;
14021 			hdd_debug("BA operating mode is set to Manual");
14022 		}
14023 
14024 		op_mode = wlan_get_opmode_from_vdev_id(
14025 						hdd_ctx->pdev,
14026 						link_info->vdev_id);
14027 
14028 		sme_set_per_link_ba_mode(mac_handle, set_val);
14029 
14030 		if (!cfg_val) {
14031 			ret_val = wma_cli_set_command(
14032 				link_info->vdev_id,
14033 				wmi_vdev_param_amsdu_aggregation_size_optimization,
14034 				0, VDEV_CMD);
14035 		}
14036 	}
14037 
14038 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
14039 		cfg_val = nla_get_u8(tb[
14040 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
14041 			);
14042 		if (cfg_val > HE_FRAG_LEVEL1)
14043 			set_val = HE_FRAG_LEVEL1;
14044 		else
14045 			set_val = cfg_val;
14046 
14047 		hdd_debug("set HE fragmention to %d", set_val);
14048 		ret_val = sme_update_he_frag_supp(mac_handle,
14049 						  link_info->vdev_id,
14050 						  set_val);
14051 	}
14052 
14053 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
14054 		cfg_val = nla_get_u8(tb[
14055 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
14056 		sme_config->csr_config.wep_tkip_in_he = cfg_val;
14057 		hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
14058 
14059 		update_sme_cfg = true;
14060 	}
14061 
14062 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
14063 		if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
14064 			tid = nla_get_u8(tb[
14065 				QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
14066 		} else {
14067 			hdd_err("TID is not set for ADD/DEL BA cfg");
14068 			ret_val = -EINVAL;
14069 			goto send_err;
14070 		}
14071 		cfg_val = nla_get_u8(tb[
14072 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
14073 		if (cfg_val == QCA_WLAN_ADD_BA) {
14074 			if (tb[
14075 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
14076 				buff_size = nla_get_u16(tb[
14077 				QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
14078 			ret_val = sme_send_addba_req(mac_handle,
14079 						     link_info->vdev_id,
14080 						     tid, buff_size);
14081 		} else if (cfg_val == QCA_WLAN_DELETE_BA) {
14082 		} else {
14083 			hdd_err("Invalid BA session cfg");
14084 			ret_val = -EINVAL;
14085 			goto send_err;
14086 		}
14087 	} else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
14088 		uint32_t arg[2];
14089 		buff_size = nla_get_u16(tb[
14090 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
14091 		hdd_debug("set buff size to %d for all tids", buff_size);
14092 		ret_val = sme_set_ba_buff_size(mac_handle,
14093 					       link_info->vdev_id,
14094 					       buff_size);
14095 		if (ret_val)
14096 			goto send_err;
14097 
14098 		if (buff_size > 512)
14099 			/* Configure ADDBA req buffer size to 1024 */
14100 			set_val = HDD_BA_MODE_1024;
14101 		else if (buff_size > 256)
14102 			/* Configure ADDBA req buffer size to 512 */
14103 			set_val = HDD_BA_MODE_512;
14104 		else if (buff_size > 64)
14105 			/* Configure ADDBA req buffer size to 256 */
14106 			set_val = HDD_BA_MODE_256;
14107 		else
14108 			/* Configure ADDBA req buffer size to 64 */
14109 			set_val = HDD_BA_MODE_64;
14110 
14111 		sme_set_per_link_ba_mode(mac_handle, set_val);
14112 
14113 		ret_val = wma_cli_set_command(link_info->vdev_id,
14114 					      GEN_VDEV_PARAM_AMPDU,
14115 					      buff_size, GEN_CMD);
14116 
14117 		if (set_val == HDD_BA_MODE_512) {
14118 			arg[0] = 703;
14119 			arg[1] = 0;
14120 			ret_val = sme_send_unit_test_cmd(
14121 						adapter->deflink->vdev_id,
14122 						0x48, 2, arg);
14123 			if (ret_val)
14124 				hdd_err("Failed to set Full state BA support");
14125 		}
14126 	}
14127 
14128 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
14129 		int he_mcs_val;
14130 
14131 		if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
14132 			ac = nla_get_u8(tb[
14133 			     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
14134 		} else {
14135 			hdd_err("AC is not set for NO ACK policy config");
14136 			ret_val = -EINVAL;
14137 			goto send_err;
14138 		}
14139 		cfg_val = nla_get_u8(tb[
14140 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
14141 		hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
14142 		ret_val = sme_set_no_ack_policy(mac_handle,
14143 						link_info->vdev_id,
14144 						cfg_val, ac);
14145 		if (cfg_val) {
14146 			status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc,
14147 							     &bval);
14148 			if (!QDF_IS_STATUS_SUCCESS(status))
14149 				hdd_err("unable to get vht_enable2x2");
14150 			if (bval)
14151 				/*2x2 MCS 5 value*/
14152 				he_mcs_val = 0x45;
14153 			else
14154 				/*1x1 MCS 5 value*/
14155 				he_mcs_val = 0x25;
14156 
14157 			if (hdd_set_11ax_rate(adapter, he_mcs_val, NULL))
14158 				hdd_err("HE MCS set failed, MCS val %0x",
14159 						he_mcs_val);
14160 		} else {
14161 			if (hdd_set_11ax_rate(adapter, 0xFF, NULL))
14162 				hdd_err("disable fixed rate failed");
14163 		}
14164 	}
14165 
14166 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE;
14167 	if (tb[cmd_id]) {
14168 		cfg_val = nla_get_u8(tb[cmd_id]);
14169 		hdd_debug("Keep alive data type %d", cfg_val);
14170 		if (cfg_val == QCA_WLAN_KEEP_ALIVE_DATA) {
14171 			ret_val = hdd_set_grat_arp_keepalive(adapter);
14172 			if (ret_val) {
14173 				hdd_err("Keep alive data type set failed");
14174 				goto send_err;
14175 			}
14176 		} else {
14177 			if (cfg_val == QCA_WLAN_KEEP_ALIVE_MGMT)
14178 				keep_alive_req.packetType =
14179 						SIR_KEEP_ALIVE_MGMT_FRAME;
14180 			else
14181 				keep_alive_req.packetType =
14182 						SIR_KEEP_ALIVE_NULL_PKT;
14183 			ucfg_mlme_get_sta_keep_alive_period(
14184 						hdd_ctx->psoc,
14185 						&keep_alive_req.timePeriod);
14186 			keep_alive_req.sessionId = link_info->vdev_id;
14187 			status = sme_set_keep_alive(hdd_ctx->mac_handle,
14188 						    link_info->vdev_id,
14189 						    &keep_alive_req);
14190 			if (QDF_IS_STATUS_ERROR(status)) {
14191 				hdd_err("Failed to set keepalive");
14192 				ret_val = qdf_status_to_os_return(status);
14193 				goto send_err;
14194 			}
14195 		}
14196 	}
14197 
14198 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]) {
14199 		cfg_val = nla_get_u8(tb[
14200 				QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]);
14201 		hdd_debug("Set HE LTF to %d", cfg_val);
14202 		ret_val = sme_set_auto_rate_he_ltf(mac_handle,
14203 						   link_info->vdev_id,
14204 						   cfg_val);
14205 		if (ret_val)
14206 			sme_err("Failed to set auto rate HE LTF");
14207 
14208 		ret_val = wma_cli_set_command(link_info->vdev_id,
14209 					      wmi_vdev_param_set_he_ltf,
14210 					      cfg_val, VDEV_CMD);
14211 		if (ret_val)
14212 			goto send_err;
14213 	}
14214 
14215 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE;
14216 	if (tb[cmd_id]) {
14217 		cfg_val = nla_get_u8(tb[
14218 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]);
14219 		hdd_debug("Set Tx beamformee to %d", cfg_val);
14220 		ret_val = sme_update_tx_bfee_supp(mac_handle,
14221 						  link_info->vdev_id,
14222 						  cfg_val);
14223 		if (ret_val)
14224 			sme_err("Failed to update Tx beamformee support");
14225 
14226 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14227 					      cfg_val, EHT_TX_BFEE_ENABLE,
14228 					      adapter->device_mode);
14229 		if (ret_val)
14230 			sme_err("Failed to set Tx beamformee cap");
14231 
14232 	}
14233 
14234 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS;
14235 	if (tb[cmd_id]) {
14236 		cfg_val = nla_get_u8(tb[cmd_id]);
14237 		ret_val = sme_update_he_capabilities(mac_handle,
14238 						     link_info->vdev_id,
14239 						     cfg_val, cmd_id);
14240 		if (ret_val)
14241 			sme_err("Failed to update HE cap");
14242 	}
14243 
14244 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT;
14245 	if (tb[cmd_id]) {
14246 		cfg_val = nla_get_u8(tb[cmd_id]);
14247 		ret_val = sme_update_he_capabilities(mac_handle,
14248 						     link_info->vdev_id,
14249 						     cfg_val, cmd_id);
14250 		if (ret_val)
14251 			sme_err("Failed to update HE cap");
14252 	}
14253 
14254 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]) {
14255 		cfg_val = nla_get_u8(tb[
14256 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]);
14257 		status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
14258 								&value);
14259 		if (!QDF_IS_STATUS_SUCCESS(status))
14260 			hdd_err("unable to get tx_bfee_ant_supp");
14261 
14262 		if (!cfg_in_range(CFG_VHT_BEAMFORMEE_ANT_SUPP, cfg_val)) {
14263 			hdd_err("NSTS %d not supported, supp_val %d", cfg_val,
14264 				value);
14265 			ret_val = -ENOTSUPP;
14266 			goto send_err;
14267 		}
14268 		hdd_debug("Set Tx beamformee NSTS to %d", cfg_val);
14269 		ret_val = sme_update_tx_bfee_nsts(hdd_ctx->mac_handle,
14270 						  link_info->vdev_id,
14271 						  cfg_val,
14272 						  value);
14273 		if (ret_val)
14274 			sme_err("Failed to set Tx beamformee cap");
14275 
14276 	}
14277 
14278 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]) {
14279 		cfg_val = nla_get_u8(tb[
14280 				     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]);
14281 		if (cfg_val) {
14282 			hdd_debug("Set HE mac padding dur to %d", cfg_val);
14283 			ret_val = sme_cli_set_command(
14284 					link_info->vdev_id,
14285 					wmi_vdev_param_mu_edca_fw_update_en,
14286 					0, VDEV_CMD);
14287 			if (ret_val)
14288 				hdd_err("MU_EDCA update disable failed");
14289 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
14290 			sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
14291 			if (sme_update_mu_edca_params(
14292 						hdd_ctx->mac_handle,
14293 						link_info->vdev_id))
14294 				hdd_err("Failed to send mu edca params");
14295 		} else {
14296 			ret_val = sme_cli_set_command(
14297 					link_info->vdev_id,
14298 					wmi_vdev_param_mu_edca_fw_update_en,
14299 					1, VDEV_CMD);
14300 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
14301 		}
14302 		ret_val = sme_update_he_trigger_frm_mac_pad(
14303 						    hdd_ctx->mac_handle,
14304 						    link_info->vdev_id,
14305 						    cfg_val);
14306 		if (ret_val)
14307 			hdd_err("Failed to set Trig frame mac padding cap");
14308 	}
14309 
14310 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]) {
14311 		cfg_val = nla_get_u8(tb[
14312 				     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]);
14313 		if (cfg_val) {
14314 			ret_val = sme_cli_set_command(
14315 					link_info->vdev_id,
14316 					wmi_vdev_param_mu_edca_fw_update_en,
14317 					0, VDEV_CMD);
14318 			if (ret_val)
14319 				hdd_err("MU_EDCA update disable failed");
14320 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
14321 			sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
14322 			if (sme_update_mu_edca_params(
14323 						hdd_ctx->mac_handle,
14324 						link_info->vdev_id))
14325 				hdd_err("Failed to send mu edca params");
14326 		} else {
14327 			ret_val = sme_cli_set_command(
14328 					link_info->vdev_id,
14329 					wmi_vdev_param_mu_edca_fw_update_en,
14330 					1, VDEV_CMD);
14331 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
14332 		}
14333 	}
14334 
14335 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]) {
14336 		cfg_val = nla_get_u8(tb[
14337 				     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]);
14338 		ret_val = sme_update_he_om_ctrl_supp(hdd_ctx->mac_handle,
14339 						     link_info->vdev_id,
14340 						     cfg_val);
14341 	}
14342 
14343 	cmd_id =
14344 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA;
14345 	if (tb[cmd_id]) {
14346 		cfg_val = nla_get_u8(tb[cmd_id]);
14347 		if (cfg_val)
14348 			status = ucfg_mlme_set_scan_probe_unicast_ra(
14349 							hdd_ctx->psoc, true);
14350 		else
14351 			status = ucfg_mlme_set_scan_probe_unicast_ra(
14352 							hdd_ctx->psoc, false);
14353 		if (!QDF_IS_STATUS_SUCCESS(status))
14354 			hdd_err("unable to set unicat probe ra cfg");
14355 	}
14356 
14357 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OMI_TX;
14358 	if (tb[cmd_id]) {
14359 		struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_OMI_MAX + 1];
14360 		struct nlattr *curr_attr;
14361 		int tmp, rc;
14362 		struct omi_ctrl_tx omi_data = {0};
14363 
14364 		nla_for_each_nested(curr_attr, tb[cmd_id], tmp) {
14365 			rc = wlan_cfg80211_nla_parse(
14366 					tb2, QCA_WLAN_VENDOR_ATTR_OMI_MAX,
14367 					nla_data(curr_attr),
14368 					nla_len(curr_attr),
14369 					qca_wlan_vendor_attr_omi_tx_policy);
14370 			if (rc) {
14371 				hdd_err("Invalid ATTR");
14372 				goto send_err;
14373 			}
14374 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW;
14375 			if (tb2[cmd_id]) {
14376 				cfg_val = nla_get_u8(tb2[cmd_id]);
14377 				ret_val = sme_set_he_om_ctrl_param(
14378 						    hdd_ctx->mac_handle,
14379 						    link_info->vdev_id,
14380 						    cmd_id, cfg_val);
14381 			}
14382 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS;
14383 			if (tb2[cmd_id]) {
14384 				cfg_val = nla_get_u8(tb2[cmd_id]);
14385 				ret_val = sme_set_he_om_ctrl_param(
14386 						    hdd_ctx->mac_handle,
14387 						    link_info->vdev_id,
14388 						    cmd_id, cfg_val);
14389 			}
14390 
14391 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE;
14392 			if (tb2[cmd_id]) {
14393 				cfg_val = nla_get_u8(tb2[cmd_id]);
14394 				ret_val = sme_set_he_om_ctrl_param(
14395 						    hdd_ctx->mac_handle,
14396 						    link_info->vdev_id,
14397 						    cmd_id, cfg_val);
14398 			}
14399 
14400 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS;
14401 			if (tb2[cmd_id]) {
14402 				cfg_val = nla_get_u8(tb2[cmd_id]);
14403 				ret_val = sme_set_he_om_ctrl_param(
14404 						    hdd_ctx->mac_handle,
14405 						    link_info->vdev_id,
14406 						    cmd_id, cfg_val);
14407 			}
14408 
14409 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE;
14410 			if (tb2[cmd_id]) {
14411 				cfg_val = nla_get_u8(tb2[cmd_id]);
14412 				ret_val = sme_set_he_om_ctrl_param(
14413 						    hdd_ctx->mac_handle,
14414 						    link_info->vdev_id,
14415 						    cmd_id, cfg_val);
14416 			}
14417 
14418 			cmd_id = QCA_WLAN_VENDOR_ATTR_EHT_OMI_RX_NSS_EXTN;
14419 			if (tb2[cmd_id]) {
14420 				cfg_val = nla_get_u8(tb2[cmd_id]);
14421 				hdd_debug("EHT OM ctrl Rx Nss %d", cfg_val);
14422 				omi_data.eht_rx_nss_ext = cfg_val;
14423 			}
14424 
14425 			cmd_id = QCA_WLAN_VENDOR_ATTR_EHT_OMI_CH_BW_EXTN;
14426 			if (tb2[cmd_id]) {
14427 				cfg_val = nla_get_u8(tb2[cmd_id]);
14428 				hdd_debug("Set EHT OM ctrl BW to %d", cfg_val);
14429 				omi_data.eht_ch_bw_ext = cfg_val;
14430 			}
14431 
14432 			cmd_id = QCA_WLAN_VENDOR_ATTR_EHT_OMI_TX_NSS_EXTN;
14433 			if (tb2[cmd_id]) {
14434 				cfg_val = nla_get_u8(tb2[cmd_id]);
14435 				hdd_debug("EHT OM ctrl Tx Nss %d", cfg_val);
14436 				omi_data.eht_tx_nss_ext = cfg_val;
14437 			}
14438 		}
14439 
14440 		if (ret_val) {
14441 			sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
14442 			goto send_err;
14443 		}
14444 		ret_val = sme_send_he_om_ctrl_update(hdd_ctx->mac_handle,
14445 						     link_info->vdev_id,
14446 						     &omi_data);
14447 	}
14448 
14449 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG])
14450 		sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
14451 
14452 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU;
14453 	if (tb[cmd_id]) {
14454 		int i;
14455 		enum wlan_eht_mode eht_mode;
14456 		uint8_t op_mode;
14457 
14458 		cfg_val = nla_get_u8(tb[cmd_id]);
14459 		ucfg_mlme_get_eht_mode(hdd_ctx->psoc, &eht_mode);
14460 		if (eht_mode == WLAN_EHT_MODE_MLMR ||
14461 		    eht_mode == WLAN_EHT_MODE_MLSR ||
14462 		    eht_mode == WLAN_EHT_MODE_EMLSR) {
14463 			for (i = 0; i < WLAN_MAX_VDEVS; i++) {
14464 				op_mode = wlan_get_opmode_from_vdev_id(
14465 						hdd_ctx->pdev, i);
14466 				if (op_mode != QDF_STA_MODE) {
14467 					hdd_debug("vdev_id %d is not STA", i);
14468 					continue;
14469 				}
14470 				hdd_debug("Tx SU PPDU enable %d, vdev_id %d",
14471 					  cfg_val, i);
14472 				if (cfg_val)
14473 					sme_config_su_ppdu_queue(i, true);
14474 				else
14475 					sme_config_su_ppdu_queue(i, false);
14476 			}
14477 		} else {
14478 			if (cfg_val)
14479 				sme_config_su_ppdu_queue(link_info->vdev_id,
14480 							 true);
14481 			else
14482 				sme_config_su_ppdu_queue(link_info->vdev_id,
14483 							 false);
14484 		}
14485 	}
14486 
14487 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT;
14488 	if (tb[cmd_id]) {
14489 		cfg_val = nla_get_u8(tb[cmd_id]);
14490 		hdd_debug("Configure 2G VHT support %d", cfg_val);
14491 		ucfg_mlme_set_vht_for_24ghz(hdd_ctx->psoc,
14492 					    (cfg_val ? true : false));
14493 	}
14494 
14495 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP;
14496 	if (tb[cmd_id]) {
14497 		cfg_val = nla_get_u8(tb[cmd_id]);
14498 		hdd_debug("Configure +HTC_HE support %d", cfg_val);
14499 		sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
14500 					  link_info->vdev_id,
14501 					  (cfg_val ? true : false));
14502 	}
14503 
14504 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX;
14505 	if (tb[cmd_id]) {
14506 		cfg_val = nla_get_u8(tb[cmd_id]);
14507 		hdd_debug("Configure Punctured preamble Rx %d", cfg_val);
14508 		ret_val = sme_update_he_capabilities(mac_handle,
14509 						     link_info->vdev_id,
14510 						     cfg_val, cmd_id);
14511 		if (ret_val)
14512 			sme_err("Failed to update HE cap");
14513 	}
14514 
14515 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS;
14516 	if (tb[cmd_id]) {
14517 		hdd_disable_runtime_pm_for_user(hdd_ctx);
14518 		cfg_val = nla_get_u8(tb[cmd_id]);
14519 		hdd_debug("Configure HE testbed defaults %d", cfg_val);
14520 		if (!cfg_val)
14521 			sme_reset_he_caps(hdd_ctx->mac_handle,
14522 					  link_info->vdev_id);
14523 		else
14524 			sme_set_he_testbed_def(hdd_ctx->mac_handle,
14525 					       link_info->vdev_id);
14526 	}
14527 
14528 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU;
14529 	if (tb[cmd_id]) {
14530 		cfg_val = nla_get_u8(tb[cmd_id]);
14531 		hdd_debug("Configure Action frame Tx in TB PPDU %d", cfg_val);
14532 		sme_config_action_tx_in_tb_ppdu(hdd_ctx->mac_handle,
14533 						link_info->vdev_id,
14534 						cfg_val);
14535 	}
14536 
14537 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP]) {
14538 		ret_val = hdd_test_config_twt_setup_session(adapter, tb);
14539 		if (ret_val)
14540 			goto send_err;
14541 	}
14542 
14543 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE]) {
14544 		ret_val = hdd_test_config_twt_terminate_session(adapter, tb);
14545 		if (ret_val)
14546 			goto send_err;
14547 	}
14548 
14549 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT;
14550 	if (tb[cmd_id]) {
14551 		cfg_val = nla_get_u8(tb[cmd_id]);
14552 		hdd_debug("twt_request: val %d", cfg_val);
14553 		ret_val = sme_update_he_twt_req_support(
14554 						hdd_ctx->mac_handle,
14555 						link_info->vdev_id,
14556 						cfg_val);
14557 	}
14558 
14559 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO;
14560 	if (tb[cmd_id]) {
14561 		cfg_val = nla_get_u8(tb[cmd_id]);
14562 		ini_val = cfg_get(hdd_ctx->psoc, CFG_HE_UL_MUMIMO);
14563 		hdd_debug("fullbw_ulmumimo: cfg %d, ini %d", cfg_val, ini_val);
14564 		if (cfg_val) {
14565 			switch (ini_val) {
14566 			case CFG_NO_SUPPORT_UL_MUMIMO:
14567 			case CFG_FULL_BW_SUPPORT_UL_MUMIMO:
14568 				cfg_val = CFG_FULL_BW_SUPPORT_UL_MUMIMO;
14569 				break;
14570 			case CFG_PARTIAL_BW_SUPPORT_UL_MUMIMO:
14571 			case CFG_FULL_PARTIAL_BW_SUPPORT_UL_MUMIMO:
14572 				cfg_val = CFG_FULL_PARTIAL_BW_SUPPORT_UL_MUMIMO;
14573 				break;
14574 			}
14575 		} else {
14576 			switch (ini_val) {
14577 			case CFG_NO_SUPPORT_UL_MUMIMO:
14578 			case CFG_FULL_BW_SUPPORT_UL_MUMIMO:
14579 				cfg_val = CFG_NO_SUPPORT_UL_MUMIMO;
14580 				break;
14581 			case CFG_PARTIAL_BW_SUPPORT_UL_MUMIMO:
14582 			case CFG_FULL_PARTIAL_BW_SUPPORT_UL_MUMIMO:
14583 				cfg_val = CFG_PARTIAL_BW_SUPPORT_UL_MUMIMO;
14584 				break;
14585 			}
14586 		}
14587 		ret_val = sme_update_he_full_ul_mumimo(
14588 						hdd_ctx->mac_handle,
14589 						link_info->vdev_id,
14590 						cfg_val);
14591 	}
14592 
14593 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX;
14594 	if (tb[cmd_id]) {
14595 		cfg_val = nla_get_u8(tb[cmd_id]);
14596 		hdd_debug("disable Tx cfg: val %d", cfg_val);
14597 		sme_set_cfg_disable_tx(hdd_ctx->mac_handle,
14598 				       link_info->vdev_id, cfg_val);
14599 	}
14600 
14601 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION;
14602 	if (tb[cmd_id]) {
14603 		cfg_val = nla_get_u8(tb[cmd_id]);
14604 		hdd_debug("pmf cfg: val %d", cfg_val);
14605 		sme_set_pmf_wep_cfg(hdd_ctx->mac_handle, cfg_val);
14606 	}
14607 
14608 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD;
14609 	if (tb[cmd_id]) {
14610 		cfg_val = nla_get_u16(tb[cmd_id]);
14611 		hdd_debug("bss max idle period %d", cfg_val);
14612 		sme_set_bss_max_idle_period(hdd_ctx->mac_handle, cfg_val);
14613 	}
14614 
14615 	cmd_id =
14616 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE;
14617 	if (tb[cmd_id]) {
14618 		cfg_val = nla_get_u8(tb[cmd_id]);
14619 		if (cfg_val)
14620 			ucfg_mlme_get_sta_keep_alive_period(
14621 							hdd_ctx->psoc,
14622 							&bss_max_idle_period);
14623 		hdd_debug("bss max idle period %d", bss_max_idle_period);
14624 		sme_set_bss_max_idle_period(hdd_ctx->mac_handle,
14625 					    bss_max_idle_period);
14626 	}
14627 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX;
14628 	if (tb[cmd_id]) {
14629 		hdd_info("Send disassoc mgmt frame");
14630 		sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
14631 					    link_info->vdev_id,
14632 					    hdd_sta_ctx->conn_info.bssid.bytes,
14633 					    1, false);
14634 	}
14635 
14636 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX;
14637 	if (tb[cmd_id]) {
14638 		cfg_val = nla_get_u8(tb[cmd_id]);
14639 		hdd_info("RU 242 tone Tx enable: %d", cfg_val);
14640 		sme_set_ru_242_tone_tx_cfg(hdd_ctx->mac_handle, cfg_val);
14641 		if (cfg_val)
14642 			hdd_update_channel_width(
14643 					link_info, eHT_CHANNEL_WIDTH_20MHZ,
14644 					WNI_CFG_CHANNEL_BONDING_MODE_DISABLE,
14645 					link_id, false);
14646 	}
14647 
14648 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE;
14649 	if (tb[cmd_id]) {
14650 		cfg_val = nla_get_u8(tb[cmd_id]);
14651 		hdd_debug("EU SU PPDU type Tx enable: %d", cfg_val);
14652 		if (cfg_val) {
14653 			hdd_update_channel_width(
14654 					link_info, eHT_CHANNEL_WIDTH_20MHZ,
14655 					WNI_CFG_CHANNEL_BONDING_MODE_DISABLE,
14656 					link_id, false);
14657 			hdd_set_tx_stbc(link_info, 0);
14658 			hdd_set_11ax_rate(adapter, 0x400, NULL);
14659 			status = wma_cli_set_command(
14660 					link_info->vdev_id,
14661 					wmi_vdev_param_he_range_ext,
14662 					1, VDEV_CMD);
14663 			if (QDF_IS_STATUS_ERROR(status))
14664 				hdd_err("failed to set HE_RANGE_EXT, %d",
14665 					status);
14666 			status = wma_cli_set_command(
14667 					link_info->vdev_id,
14668 					wmi_vdev_param_non_data_he_range_ext,
14669 					1, VDEV_CMD);
14670 			if (QDF_IS_STATUS_ERROR(status))
14671 				hdd_err("fail to set NON_DATA_HE_RANGE_EXT %d",
14672 					status);
14673 		} else {
14674 			hdd_update_channel_width(
14675 					link_info, eHT_CHANNEL_WIDTH_160MHZ,
14676 					WNI_CFG_CHANNEL_BONDING_MODE_ENABLE,
14677 					link_id, false);
14678 			hdd_set_tx_stbc(link_info, 1);
14679 			hdd_set_11ax_rate(adapter, 0xFFFF, NULL);
14680 			status = wma_cli_set_command(
14681 					link_info->vdev_id,
14682 					wmi_vdev_param_he_range_ext,
14683 					0, VDEV_CMD);
14684 			if (QDF_IS_STATUS_ERROR(status))
14685 				hdd_err("failed to set HE_RANGE_EXT, %d",
14686 					status);
14687 			status = wma_cli_set_command(
14688 					link_info->vdev_id,
14689 					wmi_vdev_param_non_data_he_range_ext,
14690 					0, VDEV_CMD);
14691 			if (QDF_IS_STATUS_ERROR(status))
14692 				hdd_err("fail to set NON_DATA_HE_RANGE_EXT %d",
14693 					status);
14694 		}
14695 
14696 	}
14697 
14698 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED;
14699 	if (tb[cmd_id]) {
14700 		wfa_param.vdev_id = link_info->vdev_id;
14701 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14702 
14703 		if (wfa_param.value < RSNXE_DEFAULT ||
14704 		    wfa_param.value > RSNXE_OVERRIDE_2) {
14705 			hdd_debug("Invalid RSNXE override %d", wfa_param.value);
14706 			goto send_err;
14707 		}
14708 		wfa_param.cmd = WFA_CONFIG_RXNE;
14709 		hdd_info("send wfa test config RXNE used %d", wfa_param.value);
14710 
14711 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14712 						&wfa_param);
14713 	}
14714 
14715 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA;
14716 	if (tb[cmd_id]) {
14717 		wfa_param.vdev_id = link_info->vdev_id;
14718 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14719 
14720 		if (wfa_param.value != CSA_DEFAULT &&
14721 		    wfa_param.value != CSA_IGNORE) {
14722 			hdd_debug("Invalid CSA config %d", wfa_param.value);
14723 			goto send_err;
14724 		}
14725 		wfa_param.cmd = WFA_CONFIG_CSA;
14726 		hdd_info("send wfa test config CSA used %d", wfa_param.value);
14727 
14728 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14729 						&wfa_param);
14730 	}
14731 
14732 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE;
14733 	if (tb[cmd_id]) {
14734 		ret_val = hdd_test_config_6ghz_security_test_mode(hdd_ctx,
14735 								  tb[cmd_id]);
14736 		if (ret_val)
14737 			goto send_err;
14738 	}
14739 
14740 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE;
14741 	if (tb[cmd_id]) {
14742 		struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX + 1];
14743 
14744 		wfa_param.vdev_id = link_info->vdev_id;
14745 		wfa_param.cmd = WFA_CONFIG_OCV;
14746 		if (wlan_cfg80211_nla_parse_nested(
14747 				tb2, QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX,
14748 				tb[cmd_id], wlan_oci_override_policy)) {
14749 			hdd_debug("Failed to parse OCI override");
14750 			goto send_err;
14751 		}
14752 
14753 		if (!(tb2[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE] &&
14754 		      tb2[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY])) {
14755 			hdd_debug("Invalid ATTR FRAME_TYPE/FREQUENCY");
14756 			goto send_err;
14757 		}
14758 
14759 		wfa_param.ocv_param = qdf_mem_malloc(
14760 				sizeof(struct ocv_wfatest_params));
14761 		if (!wfa_param.ocv_param) {
14762 			hdd_err("Failed to alloc memory for ocv param");
14763 			goto send_err;
14764 		}
14765 
14766 		cmd_id = QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE;
14767 		switch (nla_get_u8(tb2[cmd_id])) {
14768 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ:
14769 			wfa_param.ocv_param->frame_type =
14770 				WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_SAQUERY_REQ;
14771 			break;
14772 
14773 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP:
14774 			wfa_param.ocv_param->frame_type =
14775 				WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_SAQUERY_RSP;
14776 			break;
14777 
14778 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ:
14779 			wfa_param.ocv_param->frame_type =
14780 				WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_FT_REASSOC_REQ;
14781 			break;
14782 
14783 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FILS_REASSOC_REQ:
14784 			wfa_param.ocv_param->frame_type =
14785 			WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_FILS_REASSOC_REQ;
14786 			break;
14787 
14788 		default:
14789 			hdd_debug("Invalid frame type for ocv test config %d",
14790 				  nla_get_u8(tb2[cmd_id]));
14791 			qdf_mem_free(wfa_param.ocv_param);
14792 				goto send_err;
14793 		}
14794 
14795 		cmd_id = QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY;
14796 		wfa_param.ocv_param->freq = nla_get_u32(tb2[cmd_id]);
14797 
14798 		if (!WLAN_REG_IS_24GHZ_CH_FREQ(wfa_param.ocv_param->freq) &&
14799 		    !WLAN_REG_IS_5GHZ_CH_FREQ(wfa_param.ocv_param->freq) &&
14800 		    !WLAN_REG_IS_6GHZ_CHAN_FREQ(wfa_param.ocv_param->freq)) {
14801 			hdd_debug("Invalid Freq %d", wfa_param.ocv_param->freq);
14802 			qdf_mem_free(wfa_param.ocv_param);
14803 			goto send_err;
14804 		}
14805 
14806 		hdd_info("send wfa test config OCV frame type %d freq %d",
14807 			 wfa_param.ocv_param->frame_type,
14808 			 wfa_param.ocv_param->freq);
14809 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14810 						&wfa_param);
14811 		qdf_mem_free(wfa_param.ocv_param);
14812 	}
14813 
14814 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT;
14815 	if (tb[cmd_id]) {
14816 		wfa_param.vdev_id = link_info->vdev_id;
14817 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14818 
14819 		if (wfa_param.value != SA_QUERY_TIMEOUT_DEFAULT &&
14820 		    wfa_param.value != SA_QUERY_TIMEOUT_IGNORE) {
14821 			hdd_debug("Invalid SA query timeout config %d",
14822 				  wfa_param.value);
14823 			goto send_err;
14824 		}
14825 		wfa_param.cmd = WFA_CONFIG_SA_QUERY;
14826 		hdd_info("send wfa test config SAquery %d", wfa_param.value);
14827 
14828 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14829 						&wfa_param);
14830 	}
14831 
14832 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX;
14833 	if (tb[cmd_id] && adapter->device_mode == QDF_SAP_MODE) {
14834 		wfa_param.vdev_id = link_info->vdev_id;
14835 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14836 
14837 		if (!(wfa_param.value == FILS_DISCV_FRAMES_DISABLE ||
14838 		      wfa_param.value == FILS_DISCV_FRAMES_ENABLE)) {
14839 			hdd_debug("Invalid FILS_DISCV_FRAMES config %d",
14840 				  wfa_param.value);
14841 			goto send_err;
14842 		}
14843 		wfa_param.cmd = WFA_FILS_DISCV_FRAMES;
14844 		hdd_info("send wfa FILS_DISCV_FRAMES TX config %d",
14845 			 wfa_param.value);
14846 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14847 						&wfa_param);
14848 	}
14849 
14850 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE;
14851 	if (tb[cmd_id]) {
14852 		wfa_param.vdev_id = link_info->vdev_id;
14853 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14854 
14855 		if (!(wfa_param.value == H2E_RSNXE_DEFAULT ||
14856 		      wfa_param.value == H2E_RSNXE_IGNORE)) {
14857 			hdd_debug("Invalid RSNXE_IGNORE config %d",
14858 				  wfa_param.value);
14859 			goto send_err;
14860 		}
14861 		wfa_param.cmd = WFA_IGNORE_H2E_RSNXE;
14862 		hdd_info("send wfa WFA_IGNORE_H2E_RSNXE config %d",
14863 			 wfa_param.value);
14864 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14865 						&wfa_param);
14866 	}
14867 
14868 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_11BE_EMLSR_MODE;
14869 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14870 		cfg_val = nla_get_u8(tb[cmd_id]);
14871 
14872 		ret_val = hdd_test_config_emlsr_mode(hdd_ctx, cfg_val);
14873 	}
14874 
14875 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BEAMFORMER_PERIODIC_SOUNDING;
14876 	if (tb[cmd_id]) {
14877 		cfg_val = nla_get_u8(tb[cmd_id]);
14878 
14879 		set_val = cfg_val ? TX_BFER_NDP_PERIODICITY : 0;
14880 
14881 		ret_val = wma_cli_set_command(
14882 					link_info->vdev_id,
14883 					WMI_PDEV_PARAM_TXBF_SOUND_PERIOD_CMDID,
14884 					set_val, PDEV_CMD);
14885 	}
14886 
14887 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_80MHZ;
14888 	if (tb[cmd_id]) {
14889 		cfg_val = nla_get_u8(tb[cmd_id]);
14890 		hdd_debug("Configure Tx BF < 80 MHz: %d", cfg_val);
14891 
14892 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14893 					      cfg_val, EHT_TX_BFEE_SS_80MHZ,
14894 					      adapter->device_mode);
14895 		if (ret_val)
14896 			sme_err("Failed to update EHT Tx BFEE cap");
14897 	}
14898 
14899 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_160MHZ;
14900 	if (tb[cmd_id]) {
14901 		cfg_val = nla_get_u8(tb[cmd_id]);
14902 		hdd_debug("Configure Tx BF for 160 MHz: %d", cfg_val);
14903 
14904 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14905 					      cfg_val, EHT_TX_BFEE_SS_160MHZ,
14906 					      adapter->device_mode);
14907 		if (ret_val)
14908 			sme_err("Failed to update EHT Tx BFEE cap");
14909 	}
14910 
14911 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_320MHZ;
14912 	if (tb[cmd_id]) {
14913 		cfg_val = nla_get_u8(tb[cmd_id]);
14914 		hdd_debug("Configure Tx BF for 320 MHz: %d", cfg_val);
14915 
14916 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14917 					      cfg_val, EHT_TX_BFEE_SS_320MHZ,
14918 					      adapter->device_mode);
14919 		if (ret_val)
14920 			sme_err("Failed to update EHT Tx BFEE cap");
14921 	}
14922 
14923 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EXCLUDE_STA_PROF_IN_PROBE_REQ;
14924 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14925 		cfg_val = nla_get_u8(tb[cmd_id]);
14926 
14927 		if (cfg_val) {
14928 			wlan_vdev_obj_lock(link_info->vdev);
14929 			wlan_vdev_mlme_cap_set(
14930 					link_info->vdev,
14931 					WLAN_VDEV_C_EXCL_STA_PROF_PRB_REQ);
14932 			wlan_vdev_obj_unlock(link_info->vdev);
14933 		} else {
14934 			wlan_vdev_obj_lock(link_info->vdev);
14935 			wlan_vdev_mlme_cap_clear(
14936 					link_info->vdev,
14937 					WLAN_VDEV_C_EXCL_STA_PROF_PRB_REQ);
14938 			wlan_vdev_obj_unlock(link_info->vdev);
14939 		}
14940 		hdd_debug("Sta profile in Probe req frame: %d", cfg_val);
14941 	}
14942 
14943 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_EHT_TESTBED_DEFAULTS;
14944 	if (tb[cmd_id]) {
14945 		cfg_val = nla_get_u8(tb[cmd_id]);
14946 		hdd_debug("Configure EHT testbed defaults %d", cfg_val);
14947 		if (!cfg_val)
14948 			sme_reset_eht_caps(hdd_ctx->mac_handle,
14949 					   link_info->vdev_id);
14950 		else
14951 			sme_set_eht_testbed_def(hdd_ctx->mac_handle,
14952 						link_info->vdev_id);
14953 
14954 		sme_set_vdev_ies_per_band(hdd_ctx->mac_handle,
14955 					  link_info->vdev_id,
14956 					  adapter->device_mode);
14957 	}
14958 
14959 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MCS;
14960 	if (tb[cmd_id]) {
14961 		cfg_val = nla_get_u8(tb[cmd_id]);
14962 		sme_update_eht_cap_mcs(hdd_ctx->mac_handle, link_info->vdev_id,
14963 				       cfg_val);
14964 		sme_set_vdev_ies_per_band(hdd_ctx->mac_handle,
14965 					  link_info->vdev_id,
14966 					  adapter->device_mode);
14967 	}
14968 
14969 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_TB_SOUNDING_FB_RL;
14970 	if (tb[cmd_id]) {
14971 		cfg_val = nla_get_u8(tb[cmd_id]);
14972 		hdd_debug("Configure TB sounding feedback rate limit: %d",
14973 			  cfg_val);
14974 
14975 		ret_val = sme_update_eht_caps(
14976 					mac_handle, link_info->vdev_id,
14977 					cfg_val,
14978 					EHT_TX_BFEE_SOUNDING_FEEDBACK_RATELIMIT,
14979 					adapter->device_mode);
14980 		if (ret_val)
14981 			sme_err("Failed to update EHT Tx BFEE cap");
14982 	}
14983 
14984 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_OM_CTRL_SUPPORT;
14985 	if (tb[cmd_id]) {
14986 		cfg_val = nla_get_u8(tb[cmd_id]);
14987 		hdd_debug("EHT OM control support: %d", cfg_val);
14988 
14989 		ret_val = sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
14990 						    link_info->vdev_id,
14991 						    true);
14992 		if (ret_val)
14993 			hdd_err("Could not set htc_he");
14994 
14995 		ret_val = sme_update_eht_om_ctrl_supp(hdd_ctx->mac_handle,
14996 						      link_info->vdev_id,
14997 						      cfg_val);
14998 		if (ret_val)
14999 			hdd_err("Could not update EHT OM control fields");
15000 	}
15001 
15002 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EMLSR_PADDING_DELAY;
15003 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
15004 		cfg_val = nla_get_u8(tb[cmd_id]);
15005 		hdd_debug("Configure EMLSR padding delay subfield to %d",
15006 			  cfg_val);
15007 		if (cfg_val)
15008 			wlan_mlme_cfg_set_emlsr_pad_delay(hdd_ctx->psoc,
15009 							  cfg_val);
15010 	}
15011 
15012 	cmd_id =  QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FORCE_MLO_POWER_SAVE_BCN_PERIOD;
15013 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
15014 		uint32_t bitmap = 0;
15015 		uint32_t vdev_id, idx;
15016 
15017 		cfg_val = nla_get_u8(tb[cmd_id]);
15018 		hdd_debug("Send vdev pause on ML sta vdev for %d beacon periods",
15019 			  cfg_val);
15020 		bitmap = policy_mgr_get_active_vdev_bitmap(hdd_ctx->psoc);
15021 		for (idx = 0; idx < 32; idx++) {
15022 			if (bitmap & (1 << idx)) {
15023 				vdev_id = idx;
15024 				ret_val = sme_send_vdev_pause_for_bcn_period(
15025 							mac_handle,
15026 							vdev_id, cfg_val);
15027 				if (ret_val)
15028 					hdd_err("Failed to send vdev pause");
15029 			}
15030 		}
15031 	}
15032 
15033 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_STR_TX;
15034 	if (tb[cmd_id]) {
15035 		uint32_t arg[2];
15036 
15037 		hdd_debug("Send EHT MLO STR TX indication to FW");
15038 		arg[0] = 676;
15039 		arg[1] = 1;
15040 
15041 		ret_val = sme_send_unit_test_cmd(link_info->vdev_id,
15042 						 0x48, 2, arg);
15043 
15044 		if (ret_val)
15045 			hdd_err("Failed to send STR TX indication");
15046 	}
15047 
15048 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_LINK_POWER_SAVE;
15049 	if (tb[cmd_id]) {
15050 		struct nlattr *curr_attr;
15051 		int len;
15052 		uint8_t link_id, timeout = 0, num_links = 0;
15053 		bool allow_ps = true;
15054 
15055 		nla_for_each_nested(curr_attr, tb[cmd_id], len) {
15056 			if (nla_len(curr_attr) != sizeof(uint8_t)) {
15057 				hdd_err("len is not correct for idx %d",
15058 					num_links);
15059 				goto send_err;
15060 			}
15061 			link_id = nla_get_u8(curr_attr);
15062 			hdd_debug("link id[%d]: %d", num_links, link_id);
15063 			wlan_hdd_set_mlo_ps(adapter, allow_ps, timeout,
15064 					    link_id);
15065 			num_links++;
15066 		}
15067 
15068 		wlan_hdd_set_listen_interval(hdd_ctx, adapter);
15069 	}
15070 
15071 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MLD_ID_ML_PROBE_REQ;
15072 	if (tb[cmd_id]) {
15073 		cfg_val = nla_get_u8(tb[cmd_id]);
15074 		hdd_debug("MLD ID in ML probe request: %d", cfg_val);
15075 		ret_val = ucfg_mlme_set_eht_mld_id(hdd_ctx->psoc, cfg_val);
15076 		if (ret_val)
15077 			hdd_err("Failed to set MLD ID");
15078 	}
15079 
15080 	if (update_sme_cfg)
15081 		sme_update_config(mac_handle, sme_config);
15082 
15083 send_err:
15084 	qdf_mem_free(sme_config);
15085 
15086 	return ret_val;
15087 }
15088 
15089 /**
15090  * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
15091  * vendor command
15092  *
15093  * @wiphy: wiphy device pointer
15094  * @wdev: wireless device pointer
15095  * @data: Vendor command data buffer
15096  * @data_len: Buffer length
15097  *
15098  * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
15099  *
15100  * Return: EOK or other error codes.
15101  */
wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)15102 static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
15103 		struct wireless_dev *wdev, const void *data, int data_len)
15104 {
15105 	int errno;
15106 	struct osif_vdev_sync *vdev_sync;
15107 
15108 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
15109 	if (errno)
15110 		return errno;
15111 
15112 	errno = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
15113 							 data, data_len);
15114 
15115 	osif_vdev_sync_op_stop(vdev_sync);
15116 
15117 	return errno;
15118 }
15119 
15120 const struct nla_policy qca_wlan_vendor_wifi_logger_start_policy[
15121 		QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
15122 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
15123 		= {.type = NLA_U32 },
15124 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
15125 		= {.type = NLA_U32 },
15126 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
15127 		= {.type = NLA_U32 },
15128 };
15129 
15130 /**
15131  * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
15132  * or disable the collection of packet statistics from the firmware
15133  * @wiphy:    WIPHY structure pointer
15134  * @wdev:     Wireless device structure pointer
15135  * @data:     Pointer to the data received
15136  * @data_len: Length of the data received
15137  *
15138  * This function enables or disables the collection of packet statistics from
15139  * the firmware
15140  *
15141  * Return: 0 on success and errno on failure
15142  */
__wlan_hdd_cfg80211_wifi_logger_start(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)15143 static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
15144 		struct wireless_dev *wdev,
15145 		const void *data,
15146 		int data_len)
15147 {
15148 	QDF_STATUS status;
15149 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15150 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
15151 	struct sir_wifi_start_log start_log = { 0 };
15152 	mac_handle_t mac_handle;
15153 
15154 	hdd_enter_dev(wdev->netdev);
15155 
15156 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15157 		hdd_err("Command not allowed in FTM mode");
15158 		return -EPERM;
15159 	}
15160 
15161 	status = wlan_hdd_validate_context(hdd_ctx);
15162 	if (status)
15163 		return status;
15164 
15165 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
15166 		hdd_err("Driver Modules are closed, can not start logger");
15167 		return -EINVAL;
15168 	}
15169 
15170 	if (wlan_cfg80211_nla_parse(tb,
15171 				    QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
15172 				    data, data_len,
15173 				    qca_wlan_vendor_wifi_logger_start_policy)) {
15174 		hdd_err("Invalid attribute");
15175 		return -EINVAL;
15176 	}
15177 
15178 	/* Parse and fetch ring id */
15179 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
15180 		hdd_err("attr ATTR failed");
15181 		return -EINVAL;
15182 	}
15183 	start_log.ring_id = nla_get_u32(
15184 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
15185 	hdd_debug("Ring ID=%d", start_log.ring_id);
15186 
15187 	/* Parse and fetch verbose level */
15188 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
15189 		hdd_err("attr verbose_level failed");
15190 		return -EINVAL;
15191 	}
15192 	start_log.verbose_level = nla_get_u32(
15193 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
15194 	hdd_debug("verbose_level=%d", start_log.verbose_level);
15195 
15196 	/* Parse and fetch flag */
15197 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
15198 		hdd_err("attr flag failed");
15199 		return -EINVAL;
15200 	}
15201 	start_log.is_iwpriv_command = nla_get_u32(
15202 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
15203 
15204 	start_log.user_triggered = 1;
15205 
15206 	/* size is buff size which can be set using iwpriv command*/
15207 	start_log.size = 0;
15208 	start_log.is_pktlog_buff_clear = false;
15209 
15210 	cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
15211 
15212 	if (start_log.ring_id == RING_ID_WAKELOCK) {
15213 		/* Start/stop wakelock events */
15214 		if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
15215 			cds_set_wakelock_logging(true);
15216 		else
15217 			cds_set_wakelock_logging(false);
15218 		return 0;
15219 	}
15220 
15221 	if (start_log.ring_id == RING_ID_PER_PACKET_STATS) {
15222 		if (hdd_ctx->is_pktlog_enabled &&
15223 		    (start_log.verbose_level == WLAN_LOG_LEVEL_ACTIVE))
15224 			return 0;
15225 
15226 		if ((!hdd_ctx->is_pktlog_enabled) &&
15227 		    (start_log.verbose_level != WLAN_LOG_LEVEL_ACTIVE))
15228 			return 0;
15229 	}
15230 
15231 	mac_handle = hdd_ctx->mac_handle;
15232 	status = sme_wifi_start_logger(mac_handle, start_log);
15233 	if (!QDF_IS_STATUS_SUCCESS(status)) {
15234 		hdd_err("sme_wifi_start_logger failed(err=%d)",
15235 				status);
15236 		return -EINVAL;
15237 	}
15238 
15239 	if (start_log.ring_id == RING_ID_PER_PACKET_STATS) {
15240 		if (start_log.verbose_level == WLAN_LOG_LEVEL_ACTIVE)
15241 			hdd_ctx->is_pktlog_enabled = true;
15242 		else
15243 			hdd_ctx->is_pktlog_enabled = false;
15244 	}
15245 
15246 	return 0;
15247 }
15248 
15249 /**
15250  * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
15251  * or disable the collection of packet statistics from the firmware
15252  * @wiphy:    WIPHY structure pointer
15253  * @wdev:     Wireless device structure pointer
15254  * @data:     Pointer to the data received
15255  * @data_len: Length of the data received
15256  *
15257  * This function is used to enable or disable the collection of packet
15258  * statistics from the firmware
15259  *
15260  * Return: 0 on success and errno on failure
15261  */
wlan_hdd_cfg80211_wifi_logger_start(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)15262 static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
15263 		struct wireless_dev *wdev,
15264 		const void *data,
15265 		int data_len)
15266 {
15267 	struct osif_psoc_sync *psoc_sync;
15268 	int errno;
15269 
15270 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
15271 	if (errno)
15272 		return errno;
15273 
15274 	errno = __wlan_hdd_cfg80211_wifi_logger_start(wiphy, wdev,
15275 						      data, data_len);
15276 
15277 	osif_psoc_sync_op_stop(psoc_sync);
15278 
15279 	return errno;
15280 }
15281 
15282 const struct nla_policy qca_wlan_vendor_wifi_logger_get_ring_data_policy[
15283 		QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
15284 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
15285 		= {.type = NLA_U32 },
15286 };
15287 
15288 /**
15289  * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
15290  * @wiphy:    WIPHY structure pointer
15291  * @wdev:     Wireless device structure pointer
15292  * @data:     Pointer to the data received
15293  * @data_len: Length of the data received
15294  *
15295  * This function is used to flush or retrieve the per packet statistics from
15296  * the driver
15297  *
15298  * Return: 0 on success and errno on failure
15299  */
__wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)15300 static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
15301 		struct wireless_dev *wdev,
15302 		const void *data,
15303 		int data_len)
15304 {
15305 	QDF_STATUS status;
15306 	uint32_t ring_id;
15307 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15308 	struct nlattr *tb
15309 		[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
15310 
15311 	hdd_enter();
15312 
15313 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15314 		hdd_err("Command not allowed in FTM mode");
15315 		return -EPERM;
15316 	}
15317 
15318 	status = wlan_hdd_validate_context(hdd_ctx);
15319 	if (status)
15320 		return status;
15321 
15322 	if (wlan_cfg80211_nla_parse(tb,
15323 			    QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
15324 			    data, data_len,
15325 			    qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
15326 		hdd_err("Invalid attribute");
15327 		return -EINVAL;
15328 	}
15329 
15330 	/* Parse and fetch ring id */
15331 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
15332 		hdd_err("attr ATTR failed");
15333 		return -EINVAL;
15334 	}
15335 
15336 	ring_id = nla_get_u32(
15337 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
15338 
15339 	if (ring_id == RING_ID_PER_PACKET_STATS) {
15340 		wlan_logging_set_per_pkt_stats();
15341 		hdd_debug("Flushing/Retrieving packet stats");
15342 	} else if (ring_id == RING_ID_DRIVER_DEBUG) {
15343 		/*
15344 		 * As part of DRIVER ring ID, flush both driver and fw logs.
15345 		 * For other Ring ID's driver doesn't have any rings to flush
15346 		 */
15347 		hdd_debug("Bug report triggered by framework");
15348 
15349 		status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
15350 				WLAN_LOG_INDICATOR_FRAMEWORK,
15351 				WLAN_LOG_REASON_CODE_UNUSED,
15352 				false, false);
15353 		if (QDF_STATUS_SUCCESS != status) {
15354 			hdd_err("Failed to trigger bug report");
15355 			return -EINVAL;
15356 		}
15357 
15358 		wlan_set_chipset_stats_bit();
15359 
15360 		status = wlan_logging_wait_for_flush_log_completion();
15361 		if (!QDF_IS_STATUS_SUCCESS(status)) {
15362 			hdd_err("wait for flush log timed out");
15363 			return qdf_status_to_os_return(status);
15364 		}
15365 	} else {
15366 		wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
15367 					   WLAN_LOG_INDICATOR_FRAMEWORK,
15368 					   WLAN_LOG_REASON_CODE_UNUSED,
15369 					   ring_id);
15370 	}
15371 	return 0;
15372 }
15373 
15374 /**
15375  * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
15376  * @wiphy:    WIPHY structure pointer
15377  * @wdev:     Wireless device structure pointer
15378  * @data:     Pointer to the data received
15379  * @data_len: Length of the data received
15380  *
15381  * This function is used to flush or retrieve the per packet statistics from
15382  * the driver
15383  *
15384  * Return: 0 on success and errno on failure
15385  */
wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)15386 static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
15387 		struct wireless_dev *wdev,
15388 		const void *data,
15389 		int data_len)
15390 {
15391 	struct osif_psoc_sync *psoc_sync;
15392 	int errno;
15393 
15394 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
15395 	if (errno)
15396 		return errno;
15397 
15398 	errno = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy, wdev,
15399 							      data, data_len);
15400 
15401 	osif_psoc_sync_op_stop(psoc_sync);
15402 
15403 	return errno;
15404 }
15405 
15406 #ifdef WLAN_FEATURE_OFFLOAD_PACKETS
15407 /**
15408  * hdd_map_req_id_to_pattern_id() - map request id to pattern id
15409  * @hdd_ctx: HDD context
15410  * @request_id: [input] request id
15411  * @pattern_id: [output] pattern id
15412  *
15413  * This function loops through request id to pattern id array
15414  * if the slot is available, store the request id and return pattern id
15415  * if entry exists, return the pattern id
15416  *
15417  * Return: 0 on success and errno on failure
15418  */
hdd_map_req_id_to_pattern_id(struct hdd_context * hdd_ctx,uint32_t request_id,uint8_t * pattern_id)15419 static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
15420 					  uint32_t request_id,
15421 					  uint8_t *pattern_id)
15422 {
15423 	uint32_t i;
15424 
15425 	mutex_lock(&hdd_ctx->op_ctx.op_lock);
15426 	for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
15427 		if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
15428 			hdd_ctx->op_ctx.op_table[i].request_id = request_id;
15429 			*pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
15430 			mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15431 			return 0;
15432 		} else if (hdd_ctx->op_ctx.op_table[i].request_id ==
15433 					request_id) {
15434 			*pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
15435 			mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15436 			return 0;
15437 		}
15438 	}
15439 	mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15440 	return -ENOBUFS;
15441 }
15442 
15443 /**
15444  * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
15445  * @hdd_ctx: HDD context
15446  * @request_id: [input] request id
15447  * @pattern_id: [output] pattern id
15448  *
15449  * This function loops through request id to pattern id array
15450  * reset request id to 0 (slot available again) and
15451  * return pattern id
15452  *
15453  * Return: 0 on success and errno on failure
15454  */
hdd_unmap_req_id_to_pattern_id(struct hdd_context * hdd_ctx,uint32_t request_id,uint8_t * pattern_id)15455 static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
15456 					  uint32_t request_id,
15457 					  uint8_t *pattern_id)
15458 {
15459 	uint32_t i;
15460 
15461 	mutex_lock(&hdd_ctx->op_ctx.op_lock);
15462 	for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
15463 		if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
15464 			hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
15465 			*pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
15466 			mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15467 			return 0;
15468 		}
15469 	}
15470 	mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15471 	return -EINVAL;
15472 }
15473 
15474 
15475 /*
15476  * define short names for the global vendor params
15477  * used by __wlan_hdd_cfg80211_offloaded_packets()
15478  */
15479 #define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
15480 #define PARAM_REQUEST_ID \
15481 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
15482 #define PARAM_CONTROL \
15483 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
15484 #define PARAM_IP_PACKET \
15485 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
15486 #define PARAM_SRC_MAC_ADDR \
15487 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
15488 #define PARAM_DST_MAC_ADDR \
15489 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
15490 #define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
15491 #define PARAM_PROTO_TYPE \
15492 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE
15493 
15494 const struct nla_policy offloaded_packet_policy[
15495 			QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX + 1] = {
15496 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL] = {
15497 			.type = NLA_U32},
15498 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID] = {.type = NLA_U32},
15499 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA] = {
15500 			.type = NLA_BINARY},
15501 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR] = {
15502 			.type = NLA_BINARY,
15503 			.len = QDF_MAC_ADDR_SIZE },
15504 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR] = {
15505 			.type = NLA_BINARY,
15506 			.len = QDF_MAC_ADDR_SIZE },
15507 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD] = {
15508 			.type = NLA_U32},
15509 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE] = {
15510 			.type = NLA_U16},
15511 };
15512 
15513 /**
15514  * wlan_hdd_add_tx_ptrn() - add tx pattern
15515  * @adapter: adapter pointer
15516  * @hdd_ctx: hdd context
15517  * @tb: nl attributes
15518  *
15519  * This function reads the NL attributes and forms a AddTxPtrn message
15520  * posts it to SME.
15521  *
15522  */
15523 static int
wlan_hdd_add_tx_ptrn(struct hdd_adapter * adapter,struct hdd_context * hdd_ctx,struct nlattr ** tb)15524 wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
15525 			struct nlattr **tb)
15526 {
15527 	struct sSirAddPeriodicTxPtrn *add_req;
15528 	QDF_STATUS status;
15529 	uint32_t request_id, len;
15530 	int32_t ret;
15531 	uint8_t pattern_id = 0;
15532 	struct qdf_mac_addr dst_addr;
15533 	uint16_t eth_type = htons(ETH_P_IP);
15534 	mac_handle_t mac_handle;
15535 
15536 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
15537 		hdd_err("Not in Connected state!");
15538 		return -ENOTSUPP;
15539 	}
15540 
15541 	add_req = qdf_mem_malloc(sizeof(*add_req));
15542 	if (!add_req)
15543 		return -ENOMEM;
15544 
15545 	/* Parse and fetch request Id */
15546 	if (!tb[PARAM_REQUEST_ID]) {
15547 		hdd_err("attr request id failed");
15548 		ret = -EINVAL;
15549 		goto fail;
15550 	}
15551 
15552 	request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
15553 	if (request_id == MAX_REQUEST_ID) {
15554 		hdd_err("request_id cannot be MAX");
15555 		ret = -EINVAL;
15556 		goto fail;
15557 	}
15558 	hdd_debug("Request Id: %u", request_id);
15559 
15560 	if (!tb[PARAM_PERIOD]) {
15561 		hdd_err("attr period failed");
15562 		ret = -EINVAL;
15563 		goto fail;
15564 	}
15565 
15566 	add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
15567 	hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
15568 	if (add_req->usPtrnIntervalMs == 0) {
15569 		hdd_err("Invalid interval zero, return failure");
15570 		ret = -EINVAL;
15571 		goto fail;
15572 	}
15573 
15574 	if (!tb[PARAM_SRC_MAC_ADDR]) {
15575 		hdd_err("attr source mac address failed");
15576 		ret = -EINVAL;
15577 		goto fail;
15578 	}
15579 	nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
15580 			QDF_MAC_ADDR_SIZE);
15581 	hdd_debug("input src mac address: "QDF_MAC_ADDR_FMT,
15582 			QDF_MAC_ADDR_REF(add_req->mac_address.bytes));
15583 
15584 	if (!qdf_is_macaddr_equal(&add_req->mac_address,
15585 				  &adapter->mac_addr)) {
15586 		hdd_err("input src mac address and connected ap bssid are different");
15587 		ret = -EINVAL;
15588 		goto fail;
15589 	}
15590 
15591 	if (!tb[PARAM_DST_MAC_ADDR]) {
15592 		hdd_err("attr dst mac address failed");
15593 		ret = -EINVAL;
15594 		goto fail;
15595 	}
15596 	nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
15597 	hdd_debug("input dst mac address: "QDF_MAC_ADDR_FMT,
15598 			QDF_MAC_ADDR_REF(dst_addr.bytes));
15599 
15600 	if (!tb[PARAM_IP_PACKET]) {
15601 		hdd_err("attr ip packet failed");
15602 		ret = -EINVAL;
15603 		goto fail;
15604 	}
15605 	add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
15606 	hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
15607 
15608 	if (add_req->ucPtrnSize < 0 ||
15609 		add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
15610 					ETH_HLEN)) {
15611 		hdd_err("Invalid IP packet len: %d",
15612 				add_req->ucPtrnSize);
15613 		ret = -EINVAL;
15614 		goto fail;
15615 	}
15616 
15617 	if (!tb[PARAM_PROTO_TYPE])
15618 		eth_type = htons(ETH_P_IP);
15619 	else
15620 		eth_type = htons(nla_get_u16(tb[PARAM_PROTO_TYPE]));
15621 
15622 	hdd_debug("packet proto type: %u", eth_type);
15623 
15624 	len = 0;
15625 	qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
15626 	len += QDF_MAC_ADDR_SIZE;
15627 	qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
15628 			QDF_MAC_ADDR_SIZE);
15629 	len += QDF_MAC_ADDR_SIZE;
15630 	qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
15631 	len += 2;
15632 
15633 	/*
15634 	 * This is the IP packet, add 14 bytes Ethernet (802.3) header
15635 	 * ------------------------------------------------------------
15636 	 * | 14 bytes Ethernet (802.3) header | IP header and payload |
15637 	 * ------------------------------------------------------------
15638 	 */
15639 	qdf_mem_copy(&add_req->ucPattern[len],
15640 			nla_data(tb[PARAM_IP_PACKET]),
15641 			add_req->ucPtrnSize);
15642 	add_req->ucPtrnSize += len;
15643 
15644 	ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
15645 	if (ret) {
15646 		hdd_err("req id to pattern id failed (ret=%d)", ret);
15647 		goto fail;
15648 	}
15649 	add_req->ucPtrnId = pattern_id;
15650 	hdd_debug("pattern id: %d", add_req->ucPtrnId);
15651 
15652 	mac_handle = hdd_ctx->mac_handle;
15653 	status = sme_add_periodic_tx_ptrn(mac_handle, add_req);
15654 	if (!QDF_IS_STATUS_SUCCESS(status)) {
15655 		hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
15656 		ret = qdf_status_to_os_return(status);
15657 		goto fail;
15658 	}
15659 
15660 	hdd_exit();
15661 
15662 fail:
15663 	qdf_mem_free(add_req);
15664 	return ret;
15665 }
15666 
15667 /**
15668  * wlan_hdd_del_tx_ptrn() - delete tx pattern
15669  * @adapter: adapter pointer
15670  * @hdd_ctx: hdd context
15671  * @tb: nl attributes
15672  *
15673  * This function reads the NL attributes and forms a DelTxPtrn message
15674  * posts it to SME.
15675  *
15676  */
15677 static int
wlan_hdd_del_tx_ptrn(struct hdd_adapter * adapter,struct hdd_context * hdd_ctx,struct nlattr ** tb)15678 wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
15679 			struct nlattr **tb)
15680 {
15681 	struct sSirDelPeriodicTxPtrn *del_req;
15682 	QDF_STATUS status;
15683 	uint32_t request_id, ret;
15684 	uint8_t pattern_id = 0;
15685 	mac_handle_t mac_handle;
15686 
15687 	/* Parse and fetch request Id */
15688 	if (!tb[PARAM_REQUEST_ID]) {
15689 		hdd_err("attr request id failed");
15690 		return -EINVAL;
15691 	}
15692 	request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
15693 	if (request_id == MAX_REQUEST_ID) {
15694 		hdd_err("request_id cannot be MAX");
15695 		return -EINVAL;
15696 	}
15697 
15698 	ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
15699 	if (ret) {
15700 		hdd_err("req id to pattern id failed (ret=%d)", ret);
15701 		return -EINVAL;
15702 	}
15703 
15704 	del_req = qdf_mem_malloc(sizeof(*del_req));
15705 	if (!del_req)
15706 		return -ENOMEM;
15707 
15708 	qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
15709 	hdd_debug(QDF_MAC_ADDR_FMT,
15710 		  QDF_MAC_ADDR_REF(del_req->mac_address.bytes));
15711 	del_req->ucPtrnId = pattern_id;
15712 	hdd_debug("Request Id: %u Pattern id: %d",
15713 			 request_id, del_req->ucPtrnId);
15714 
15715 	mac_handle = hdd_ctx->mac_handle;
15716 	status = sme_del_periodic_tx_ptrn(mac_handle, del_req);
15717 	if (!QDF_IS_STATUS_SUCCESS(status)) {
15718 		hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
15719 		goto fail;
15720 	}
15721 
15722 	hdd_exit();
15723 	qdf_mem_free(del_req);
15724 	return 0;
15725 
15726 fail:
15727 	qdf_mem_free(del_req);
15728 	return -EINVAL;
15729 }
15730 
15731 
15732 /**
15733  * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
15734  * @wiphy: Pointer to wireless phy
15735  * @wdev: Pointer to wireless device
15736  * @data: Pointer to data
15737  * @data_len: Data length
15738  *
15739  * Return: 0 on success, negative errno on failure
15740  */
15741 static int
__wlan_hdd_cfg80211_offloaded_packets(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)15742 __wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
15743 				     struct wireless_dev *wdev,
15744 				     const void *data,
15745 				     int data_len)
15746 {
15747 	struct net_device *dev = wdev->netdev;
15748 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15749 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15750 	struct nlattr *tb[PARAM_MAX + 1];
15751 	uint8_t control;
15752 	int ret;
15753 
15754 	hdd_enter_dev(dev);
15755 
15756 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15757 		hdd_err("Command not allowed in FTM mode");
15758 		return -EPERM;
15759 	}
15760 
15761 	ret = wlan_hdd_validate_context(hdd_ctx);
15762 	if (ret)
15763 		return ret;
15764 
15765 	if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
15766 		hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
15767 		return -ENOTSUPP;
15768 	}
15769 
15770 	if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len,
15771 				    offloaded_packet_policy)) {
15772 		hdd_err("Invalid ATTR");
15773 		return -EINVAL;
15774 	}
15775 
15776 	if (!tb[PARAM_CONTROL]) {
15777 		hdd_err("attr control failed");
15778 		return -EINVAL;
15779 	}
15780 	control = nla_get_u32(tb[PARAM_CONTROL]);
15781 	hdd_debug("Control: %d", control);
15782 
15783 	if (control == WLAN_START_OFFLOADED_PACKETS)
15784 		return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
15785 	if (control == WLAN_STOP_OFFLOADED_PACKETS)
15786 		return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
15787 
15788 	hdd_err("Invalid control: %d", control);
15789 	return -EINVAL;
15790 }
15791 
15792 /*
15793  * done with short names for the global vendor params
15794  * used by __wlan_hdd_cfg80211_offloaded_packets()
15795  */
15796 #undef PARAM_MAX
15797 #undef PARAM_REQUEST_ID
15798 #undef PARAM_CONTROL
15799 #undef PARAM_IP_PACKET
15800 #undef PARAM_SRC_MAC_ADDR
15801 #undef PARAM_DST_MAC_ADDR
15802 #undef PARAM_PERIOD
15803 #undef PARAM_PROTO_TYPE
15804 
15805 /**
15806  * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
15807  * @wiphy:    wiphy structure pointer
15808  * @wdev:     Wireless device structure pointer
15809  * @data:     Pointer to the data received
15810  * @data_len: Length of @data
15811  *
15812  * Return: 0 on success; errno on failure
15813  */
wlan_hdd_cfg80211_offloaded_packets(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)15814 static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
15815 						struct wireless_dev *wdev,
15816 						const void *data,
15817 						int data_len)
15818 {
15819 	int errno;
15820 	struct osif_vdev_sync *vdev_sync;
15821 
15822 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
15823 	if (errno)
15824 		return errno;
15825 
15826 	errno = __wlan_hdd_cfg80211_offloaded_packets(wiphy, wdev,
15827 						      data, data_len);
15828 
15829 	osif_vdev_sync_op_stop(vdev_sync);
15830 
15831 	return errno;
15832 }
15833 #endif
15834 
15835 #ifdef WLAN_NS_OFFLOAD
15836 const struct nla_policy ns_offload_set_policy[
15837 			QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
15838 	[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
15839 };
15840 
15841 /**
15842  * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
15843  * @wiphy: Pointer to wireless phy
15844  * @wdev: Pointer to wireless device
15845  * @data: Pointer to data
15846  * @data_len: Length of @data
15847  *
15848  * Return: 0 on success, negative errno on failure
15849  */
15850 static int
__wlan_hdd_cfg80211_set_ns_offload(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)15851 __wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
15852 			struct wireless_dev *wdev,
15853 			const void *data, int data_len)
15854 {
15855 	int status;
15856 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
15857 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15858 	struct net_device *dev = wdev->netdev;
15859 	struct hdd_adapter *adapter =  WLAN_HDD_GET_PRIV_PTR(dev);
15860 	struct wlan_objmgr_vdev *vdev;
15861 
15862 	hdd_enter_dev(wdev->netdev);
15863 
15864 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15865 		hdd_err("Command not allowed in FTM mode");
15866 		return -EPERM;
15867 	}
15868 
15869 	status = wlan_hdd_validate_context(hdd_ctx);
15870 	if (0 != status)
15871 		return status;
15872 
15873 	if (!ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
15874 		hdd_err("ND Offload not supported");
15875 		return -EINVAL;
15876 	}
15877 
15878 	if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
15879 		hdd_warn("Active mode offload is disabled");
15880 		return -EINVAL;
15881 	}
15882 
15883 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
15884 				    (struct nlattr *)data, data_len,
15885 				    ns_offload_set_policy)) {
15886 		hdd_err("nla_parse failed");
15887 		return -EINVAL;
15888 	}
15889 
15890 	if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
15891 		hdd_err("ND Offload flag attribute not present");
15892 		return -EINVAL;
15893 	}
15894 
15895 	hdd_ctx->ns_offload_enable =
15896 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
15897 
15898 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
15899 	if (!vdev)
15900 		return -EINVAL;
15901 
15902 	/* update ns offload in case it is already enabled/disabled */
15903 	if (hdd_ctx->ns_offload_enable)
15904 		hdd_enable_ns_offload(adapter, vdev,
15905 				      pmo_ns_offload_dynamic_update);
15906 	else
15907 		hdd_disable_ns_offload(adapter, vdev,
15908 				       pmo_ns_offload_dynamic_update);
15909 
15910 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
15911 	return 0;
15912 }
15913 
15914 /**
15915  * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
15916  * @wiphy:   pointer to wireless wiphy structure.
15917  * @wdev:    pointer to wireless_dev structure.
15918  * @data:    Pointer to the data to be passed via vendor interface
15919  * @data_len:Length of the data to be passed
15920  *
15921  * Return:   Return the Success or Failure code.
15922  */
wlan_hdd_cfg80211_set_ns_offload(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)15923 static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
15924 					struct wireless_dev *wdev,
15925 					const void *data, int data_len)
15926 {
15927 	int errno;
15928 	struct osif_vdev_sync *vdev_sync;
15929 
15930 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
15931 	if (errno)
15932 		return errno;
15933 
15934 	errno = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
15935 
15936 	osif_vdev_sync_op_stop(vdev_sync);
15937 
15938 	return errno;
15939 }
15940 #endif /* WLAN_NS_OFFLOAD */
15941 
15942 /**
15943  * struct weighed_pcl: Preferred channel info
15944  * @freq: Channel frequency
15945  * @weight: Weightage of the channel
15946  * @flag: Validity of the channel in p2p negotiation
15947  */
15948 struct weighed_pcl {
15949 		u32 freq;
15950 		u32 weight;
15951 		u32 flag;
15952 };
15953 
15954 const struct nla_policy get_preferred_freq_list_policy[
15955 		QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
15956 	[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
15957 		.type = NLA_U32},
15958 };
15959 
wlan_hdd_populate_weigh_pcl(struct wlan_objmgr_psoc * psoc,struct policy_mgr_pcl_chan_weights * chan_weights,struct weighed_pcl * w_pcl,enum policy_mgr_con_mode intf_mode)15960 static uint32_t wlan_hdd_populate_weigh_pcl(
15961 				struct wlan_objmgr_psoc *psoc,
15962 				struct policy_mgr_pcl_chan_weights *
15963 				chan_weights,
15964 				struct weighed_pcl *w_pcl,
15965 				enum policy_mgr_con_mode intf_mode)
15966 {
15967 	u32 i, j, valid_weight;
15968 	u32 chan_idx = 0;
15969 	u32 pcl_len = chan_weights->pcl_len;
15970 	u32 conn_count = policy_mgr_get_connection_count(psoc);
15971 
15972 	/* convert channel number to frequency */
15973 	for (i = 0; i < chan_weights->pcl_len; i++) {
15974 		w_pcl[i].freq = chan_weights->pcl_list[i];
15975 		w_pcl[i].weight = chan_weights->weight_list[i];
15976 
15977 		if (policy_mgr_is_beaconing_mode(intf_mode))
15978 			w_pcl[i].flag = PCL_CHANNEL_SUPPORT_GO;
15979 		else
15980 			w_pcl[i].flag = PCL_CHANNEL_SUPPORT_CLI;
15981 	}
15982 	chan_idx = pcl_len;
15983 	if (!conn_count || policy_mgr_is_hw_dbs_capable(psoc) ||
15984 	    policy_mgr_is_interband_mcc_supported(psoc)) {
15985 		if (pcl_len && chan_weights->weight_list[pcl_len - 1] >
15986 		    PCL_GROUPS_WEIGHT_DIFFERENCE)
15987 		/*
15988 		 * Set non-pcl channels weight 20 point less than the
15989 		 * last PCL entry
15990 		 */
15991 			valid_weight = chan_weights->weight_list[pcl_len - 1] -
15992 					PCL_GROUPS_WEIGHT_DIFFERENCE;
15993 		else
15994 			valid_weight = 1;
15995 
15996 		/* Include rest of the valid channels */
15997 		for (i = 0; i < chan_weights->saved_num_chan; i++) {
15998 			for (j = 0; j < chan_weights->pcl_len; j++) {
15999 				if (chan_weights->saved_chan_list[i] ==
16000 					chan_weights->pcl_list[j])
16001 					break;
16002 			}
16003 			if (j == chan_weights->pcl_len) {
16004 				w_pcl[chan_idx].freq =
16005 					chan_weights->saved_chan_list[i];
16006 
16007 				if (!chan_weights->weighed_valid_list[i]) {
16008 					w_pcl[chan_idx].flag =
16009 						PCL_CHANNEL_EXCLUDE_IN_GO_NEG;
16010 					w_pcl[chan_idx].weight = 0;
16011 				} else {
16012 					if (policy_mgr_is_beaconing_mode(
16013 								intf_mode))
16014 						w_pcl[chan_idx].flag =
16015 						      PCL_CHANNEL_SUPPORT_GO;
16016 					else
16017 						w_pcl[chan_idx].flag =
16018 						      PCL_CHANNEL_SUPPORT_CLI;
16019 					w_pcl[chan_idx].weight = valid_weight;
16020 				}
16021 				chan_idx++;
16022 			}
16023 		}
16024 	}
16025 	return chan_idx;
16026 }
16027 
16028 /** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
16029  * @wiphy: Pointer to wireless phy
16030  * @wdev: Pointer to wireless device
16031  * @data: Pointer to data
16032  * @data_len: Data length
16033  *
16034  * This function return the preferred frequency list generated by the policy
16035  * manager.
16036  *
16037  * Return: success or failure code
16038  */
__wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16039 static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
16040 						 struct wireless_dev
16041 						 *wdev, const void *data,
16042 						 int data_len)
16043 {
16044 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16045 	int i, ret = 0;
16046 	QDF_STATUS status;
16047 	uint32_t pcl_len = 0;
16048 	uint32_t pcl_len_legacy = 0;
16049 	uint32_t freq_list[NUM_CHANNELS];
16050 	uint32_t freq_list_legacy[NUM_CHANNELS];
16051 	enum policy_mgr_con_mode intf_mode;
16052 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
16053 	struct sk_buff *reply_skb;
16054 	struct weighed_pcl *w_pcl;
16055 	struct nlattr *nla_attr, *channel;
16056 	struct policy_mgr_pcl_chan_weights *chan_weights;
16057 	struct net_device *ndev = wdev->netdev;
16058 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
16059 
16060 	hdd_enter_dev(wdev->netdev);
16061 
16062 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16063 		hdd_err("Command not allowed in FTM mode");
16064 		return -EPERM;
16065 	}
16066 
16067 	ret = wlan_hdd_validate_context(hdd_ctx);
16068 	if (ret)
16069 		return -EINVAL;
16070 
16071 	if (wlan_cfg80211_nla_parse(tb,
16072 			       QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
16073 			       data, data_len,
16074 			       get_preferred_freq_list_policy)) {
16075 		hdd_err("Invalid ATTR");
16076 		return -EINVAL;
16077 	}
16078 
16079 	if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
16080 		hdd_err("attr interface type failed");
16081 		return -EINVAL;
16082 	}
16083 
16084 	intf_mode = nla_get_u32(tb
16085 		    [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
16086 
16087 	if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
16088 		hdd_err("Invalid interface type");
16089 		return -EINVAL;
16090 	}
16091 
16092 	hdd_debug("Userspace requested pref freq list");
16093 
16094 	chan_weights =
16095 		qdf_mem_malloc(sizeof(struct policy_mgr_pcl_chan_weights));
16096 	if (!chan_weights)
16097 		return -ENOMEM;
16098 
16099 	status = policy_mgr_get_pcl(
16100 			hdd_ctx->psoc, intf_mode, chan_weights->pcl_list,
16101 			&chan_weights->pcl_len, chan_weights->weight_list,
16102 			QDF_ARRAY_SIZE(chan_weights->weight_list),
16103 			adapter->deflink->vdev_id);
16104 	if (status != QDF_STATUS_SUCCESS) {
16105 		hdd_err("Get pcl failed");
16106 		qdf_mem_free(chan_weights);
16107 		return -EINVAL;
16108 	}
16109 	/*
16110 	 * save the pcl in freq_list_legacy to be sent up with
16111 	 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST.
16112 	 * freq_list will carry the extended pcl in
16113 	 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL.
16114 	 */
16115 	pcl_len_legacy = chan_weights->pcl_len;
16116 	for (i = 0; i < pcl_len_legacy; i++)
16117 		freq_list_legacy[i] = chan_weights->pcl_list[i];
16118 	chan_weights->saved_num_chan = NUM_CHANNELS;
16119 	ucfg_mlme_get_valid_channels(hdd_ctx->psoc,
16120 				     chan_weights->saved_chan_list,
16121 				     &chan_weights->saved_num_chan);
16122 	policy_mgr_get_valid_chan_weights(hdd_ctx->psoc, chan_weights,
16123 					  intf_mode,
16124 					  adapter->deflink->vdev);
16125 	w_pcl = qdf_mem_malloc(sizeof(struct weighed_pcl) * NUM_CHANNELS);
16126 	if (!w_pcl) {
16127 		qdf_mem_free(chan_weights);
16128 		return -ENOMEM;
16129 	}
16130 	pcl_len = wlan_hdd_populate_weigh_pcl(hdd_ctx->psoc, chan_weights,
16131 					      w_pcl, intf_mode);
16132 	qdf_mem_free(chan_weights);
16133 
16134 	for (i = 0; i < pcl_len; i++)
16135 		freq_list[i] = w_pcl[i].freq;
16136 
16137 	/* send the freq_list back to supplicant */
16138 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(
16139 			wiphy,
16140 			(sizeof(u32) + NLA_HDRLEN) +
16141 			(sizeof(u32) * pcl_len_legacy + NLA_HDRLEN) +
16142 			NLA_HDRLEN +
16143 			(NLA_HDRLEN * 4 + sizeof(u32) * 3) * pcl_len +
16144 			NLMSG_HDRLEN);
16145 
16146 	if (!reply_skb) {
16147 		hdd_err("Allocate reply_skb failed");
16148 		qdf_mem_free(w_pcl);
16149 		return -EINVAL;
16150 	}
16151 
16152 	if (nla_put_u32(reply_skb,
16153 		QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
16154 			intf_mode) ||
16155 	    nla_put(reply_skb,
16156 		    QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
16157 		    sizeof(uint32_t) * pcl_len_legacy,
16158 		    freq_list_legacy)) {
16159 		hdd_err("nla put fail");
16160 		wlan_cfg80211_vendor_free_skb(reply_skb);
16161 		qdf_mem_free(w_pcl);
16162 		return -EINVAL;
16163 	}
16164 
16165 	i = QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL;
16166 	nla_attr = nla_nest_start(reply_skb, i);
16167 
16168 	if (!nla_attr) {
16169 		hdd_err("nla nest start fail");
16170 		wlan_cfg80211_vendor_free_skb(reply_skb);
16171 		qdf_mem_free(w_pcl);
16172 		return -EINVAL;
16173 	}
16174 
16175 	for (i = 0; i < pcl_len; i++) {
16176 		channel = nla_nest_start(reply_skb, i);
16177 		if (!channel) {
16178 			hdd_err("updating pcl list failed");
16179 			wlan_cfg80211_vendor_free_skb(reply_skb);
16180 			qdf_mem_free(w_pcl);
16181 			return -EINVAL;
16182 		}
16183 		if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
16184 				w_pcl[i].freq) ||
16185 		    nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
16186 				w_pcl[i].weight) ||
16187 		    nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FLAG,
16188 				w_pcl[i].flag)) {
16189 			hdd_err("nla put fail");
16190 			wlan_cfg80211_vendor_free_skb(reply_skb);
16191 			qdf_mem_free(w_pcl);
16192 			return -EINVAL;
16193 		}
16194 		nla_nest_end(reply_skb, channel);
16195 	}
16196 	nla_nest_end(reply_skb, nla_attr);
16197 	qdf_mem_free(w_pcl);
16198 
16199 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
16200 }
16201 
16202 /** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
16203  * @wiphy: Pointer to wireless phy
16204  * @wdev: Pointer to wireless device
16205  * @data: Pointer to data
16206  * @data_len: Data length
16207  *
16208  * This function return the preferred frequency list generated by the policy
16209  * manager.
16210  *
16211  * Return: success or failure code
16212  */
wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16213 static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
16214 						 struct wireless_dev
16215 						 *wdev, const void *data,
16216 						 int data_len)
16217 {
16218 	struct osif_psoc_sync *psoc_sync;
16219 	int errno;
16220 
16221 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
16222 	if (errno)
16223 		return errno;
16224 
16225 	errno = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
16226 							    data, data_len);
16227 
16228 	osif_psoc_sync_op_stop(psoc_sync);
16229 
16230 	return errno;
16231 }
16232 
16233 const struct nla_policy set_probable_oper_channel_policy[
16234 		QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
16235 	[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
16236 		.type = NLA_U32},
16237 	[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
16238 		.type = NLA_U32},
16239 };
16240 
16241 /**
16242  * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
16243  * @wiphy: Pointer to wireless phy
16244  * @wdev: Pointer to wireless device
16245  * @data: Pointer to data
16246  * @data_len: Data length
16247  *
16248  * Return: 0 on success, negative errno on failure
16249  */
__wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16250 static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
16251 						struct wireless_dev *wdev,
16252 						const void *data,
16253 						int data_len)
16254 {
16255 	struct net_device *ndev = wdev->netdev;
16256 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
16257 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16258 	int ret = 0;
16259 	enum policy_mgr_con_mode intf_mode;
16260 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
16261 	uint32_t ch_freq, conc_ext_flags;
16262 
16263 	hdd_enter_dev(ndev);
16264 
16265 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16266 		hdd_err("Command not allowed in FTM mode");
16267 		return -EPERM;
16268 	}
16269 
16270 	ret = wlan_hdd_validate_context(hdd_ctx);
16271 	if (ret)
16272 		return ret;
16273 
16274 	if (wlan_cfg80211_nla_parse(tb,
16275 				 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
16276 				 data, data_len,
16277 				 set_probable_oper_channel_policy)) {
16278 		hdd_err("Invalid ATTR");
16279 		return -EINVAL;
16280 	}
16281 
16282 	if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
16283 		hdd_err("attr interface type failed");
16284 		return -EINVAL;
16285 	}
16286 
16287 	intf_mode = nla_get_u32(tb
16288 		    [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
16289 
16290 	if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
16291 		hdd_err("Invalid interface type");
16292 		return -EINVAL;
16293 	}
16294 
16295 	if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
16296 		hdd_err("attr probable freq failed");
16297 		return -EINVAL;
16298 	}
16299 
16300 	ch_freq = nla_get_u32(tb[
16301 			      QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]);
16302 	conc_ext_flags = policy_mgr_get_conc_ext_flags(adapter->deflink->vdev,
16303 						       false);
16304 
16305 	/* check pcl table */
16306 	if (!policy_mgr_allow_concurrency(hdd_ctx->psoc, intf_mode,
16307 					  ch_freq, HW_MODE_20_MHZ,
16308 					  conc_ext_flags,
16309 					  adapter->deflink->vdev_id)) {
16310 		hdd_err("Set channel hint failed due to concurrency check");
16311 		return -EINVAL;
16312 	}
16313 
16314 	if (QDF_P2P_GO_MODE != adapter->device_mode)
16315 		wlan_hdd_cleanup_remain_on_channel_ctx(adapter->deflink);
16316 
16317 	if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, ch_freq,
16318 				POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
16319 		hdd_err("Failed to change hw mode");
16320 		return -EINVAL;
16321 	}
16322 
16323 	return 0;
16324 }
16325 
16326 /**
16327  * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
16328  * @wiphy: Pointer to wireless phy
16329  * @wdev: Pointer to wireless device
16330  * @data: Pointer to data
16331  * @data_len: Data length
16332  *
16333  * Return: 0 on success, negative errno on failure
16334  */
wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16335 static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
16336 						struct wireless_dev *wdev,
16337 						const void *data,
16338 						int data_len)
16339 {
16340 	int errno;
16341 	struct osif_vdev_sync *vdev_sync;
16342 
16343 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16344 	if (errno)
16345 		return errno;
16346 
16347 	errno = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
16348 							      data, data_len);
16349 
16350 	osif_vdev_sync_op_stop(vdev_sync);
16351 
16352 	return errno;
16353 }
16354 
16355 static const struct
16356 nla_policy
16357 wlan_hdd_get_link_properties_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
16358 	[QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
16359 		.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
16360 };
16361 
16362 /**
16363  * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
16364  * @wiphy: WIPHY structure pointer
16365  * @wdev: Wireless device structure pointer
16366  * @data: Pointer to the data received
16367  * @data_len: Length of the data received
16368  *
16369  * This function is used to get link properties like nss, rate flags and
16370  * operating frequency for the active connection with the given peer.
16371  *
16372  * Return: 0 on success and errno on failure
16373  */
__wlan_hdd_cfg80211_get_link_properties(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16374 static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
16375 						   struct wireless_dev *wdev,
16376 						   const void *data,
16377 						   int data_len)
16378 {
16379 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16380 	struct net_device *dev = wdev->netdev;
16381 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16382 	struct hdd_station_ctx *hdd_sta_ctx;
16383 	struct hdd_ap_ctx *ap_ctx;
16384 	struct hdd_station_info *sta_info;
16385 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
16386 	uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
16387 	struct sk_buff *reply_skb;
16388 	uint32_t rate_flags = 0;
16389 	uint8_t nss;
16390 	uint8_t final_rate_flags = 0;
16391 	uint32_t freq;
16392 
16393 	hdd_enter_dev(dev);
16394 
16395 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16396 		hdd_err("Command not allowed in FTM mode");
16397 		return -EPERM;
16398 	}
16399 
16400 	if (0 != wlan_hdd_validate_context(hdd_ctx))
16401 		return -EINVAL;
16402 
16403 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
16404 				    data_len,
16405 				    wlan_hdd_get_link_properties_policy)) {
16406 		hdd_err("Invalid attribute");
16407 		return -EINVAL;
16408 	}
16409 
16410 	if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
16411 		hdd_err("Attribute peerMac not provided for mode=%d",
16412 		       adapter->device_mode);
16413 		return -EINVAL;
16414 	}
16415 
16416 	if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
16417 		hdd_err("Attribute peerMac is invalid for mode=%d",
16418 			adapter->device_mode);
16419 		return -EINVAL;
16420 	}
16421 
16422 	qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
16423 		     QDF_MAC_ADDR_SIZE);
16424 	hdd_debug("peerMac="QDF_MAC_ADDR_FMT" for device_mode:%d",
16425 		  QDF_MAC_ADDR_REF(peer_mac), adapter->device_mode);
16426 
16427 	if (adapter->device_mode == QDF_STA_MODE ||
16428 	    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
16429 		hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
16430 		if (!hdd_cm_is_vdev_associated(adapter->deflink) ||
16431 		    qdf_mem_cmp(hdd_sta_ctx->conn_info.bssid.bytes,
16432 			peer_mac, QDF_MAC_ADDR_SIZE)) {
16433 			hdd_err("Not Associated to mac "QDF_MAC_ADDR_FMT,
16434 			       QDF_MAC_ADDR_REF(peer_mac));
16435 			return -EINVAL;
16436 		}
16437 
16438 		nss  = hdd_sta_ctx->conn_info.nss;
16439 		freq = hdd_sta_ctx->conn_info.chan_freq;
16440 		rate_flags = hdd_sta_ctx->conn_info.rate_flags;
16441 	} else if (adapter->device_mode == QDF_P2P_GO_MODE ||
16442 		   adapter->device_mode == QDF_SAP_MODE) {
16443 
16444 		if (QDF_IS_ADDR_BROADCAST(peer_mac)) {
16445 			hdd_err("Ignore bcast/self sta");
16446 			return -EINVAL;
16447 		}
16448 
16449 		sta_info = hdd_get_sta_info_by_mac(
16450 					&adapter->sta_info_list, peer_mac,
16451 					STA_INFO_CFG80211_GET_LINK_PROPERTIES);
16452 
16453 		if (!sta_info) {
16454 			hdd_err("No active peer with mac = " QDF_MAC_ADDR_FMT,
16455 				QDF_MAC_ADDR_REF(peer_mac));
16456 			return -EINVAL;
16457 		}
16458 
16459 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
16460 		nss = sta_info->nss;
16461 		freq = ap_ctx->operating_chan_freq;
16462 		rate_flags = sta_info->rate_flags;
16463 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
16464 				     STA_INFO_CFG80211_GET_LINK_PROPERTIES);
16465 	} else {
16466 		hdd_err("Not Associated! with mac "QDF_MAC_ADDR_FMT,
16467 		       QDF_MAC_ADDR_REF(peer_mac));
16468 		return -EINVAL;
16469 	}
16470 
16471 	if (!(rate_flags & TX_RATE_LEGACY)) {
16472 		if (rate_flags & TX_RATE_VHT80) {
16473 			final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
16474 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
16475 			final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
16476 #endif
16477 		} else if (rate_flags & TX_RATE_VHT40) {
16478 			final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
16479 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
16480 			final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
16481 #endif
16482 		} else if (rate_flags & TX_RATE_VHT20) {
16483 			final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
16484 		} else if (rate_flags &
16485 				(TX_RATE_HT20 | TX_RATE_HT40)) {
16486 			final_rate_flags |= RATE_INFO_FLAGS_MCS;
16487 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
16488 			if (rate_flags & TX_RATE_HT40)
16489 				final_rate_flags |=
16490 					RATE_INFO_FLAGS_40_MHZ_WIDTH;
16491 #endif
16492 		}
16493 
16494 		if (rate_flags & TX_RATE_SGI) {
16495 			if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
16496 				final_rate_flags |= RATE_INFO_FLAGS_MCS;
16497 			final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
16498 		}
16499 	}
16500 
16501 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
16502 							     sizeof(u8) +
16503 							     sizeof(u8) +
16504 							     sizeof(u32) +
16505 							     NLMSG_HDRLEN);
16506 	if (!reply_skb) {
16507 		hdd_err("getLinkProperties: skb alloc failed");
16508 		return -EINVAL;
16509 	}
16510 
16511 	if (nla_put_u8(reply_skb,
16512 		QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
16513 		nss) ||
16514 	    nla_put_u8(reply_skb,
16515 		QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
16516 		final_rate_flags) ||
16517 	    nla_put_u32(reply_skb,
16518 		QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
16519 		freq)) {
16520 		hdd_err("nla_put failed");
16521 		wlan_cfg80211_vendor_free_skb(reply_skb);
16522 		return -EINVAL;
16523 	}
16524 
16525 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
16526 }
16527 
16528 /**
16529  * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
16530  * properties.
16531  * @wiphy: WIPHY structure pointer
16532  * @wdev: Wireless device structure pointer
16533  * @data: Pointer to the data received
16534  * @data_len: Length of the data received
16535  *
16536  * This function is used to get link properties like nss, rate flags and
16537  * operating frequency for the active connection with the given peer.
16538  *
16539  * Return: 0 on success and errno on failure
16540  */
wlan_hdd_cfg80211_get_link_properties(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16541 static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
16542 						 struct wireless_dev *wdev,
16543 						 const void *data,
16544 						 int data_len)
16545 {
16546 	int errno;
16547 	struct osif_vdev_sync *vdev_sync;
16548 
16549 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16550 	if (errno)
16551 		return errno;
16552 
16553 	errno = __wlan_hdd_cfg80211_get_link_properties(wiphy, wdev,
16554 							data, data_len);
16555 
16556 	osif_vdev_sync_op_stop(vdev_sync);
16557 
16558 	return errno;
16559 }
16560 
16561 const struct nla_policy
16562 wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
16563 	[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8},
16564 	[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY] = {.type = NLA_U32},
16565 	[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
16566 							.type = NLA_BINARY},
16567 };
16568 
16569 const struct nla_policy
16570 wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
16571 	[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8},
16572 	[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8},
16573 	[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT] = {.type = NLA_U32},
16574 };
16575 
16576 /**
16577  * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
16578  * @wiphy: Pointer to wireless phy
16579  * @wdev: Pointer to wireless device
16580  * @data: Pointer to data
16581  * @data_len: Length of @data
16582  *
16583  * This function parses the incoming NL vendor command data attributes and
16584  * updates the SAP context about channel_hint and DFS mode.
16585  * If channel_hint is set, SAP will choose that channel
16586  * as operating channel.
16587  *
16588  * If DFS mode is enabled, driver will include DFS channels
16589  * in ACS else driver will skip DFS channels.
16590  *
16591  * Return: 0 on success, negative errno on failure
16592  */
16593 static int
__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16594 __wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
16595 		struct wireless_dev *wdev,
16596 		const void *data, int data_len)
16597 {
16598 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16599 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
16600 	int ret;
16601 	struct acs_dfs_policy *acs_policy;
16602 	int mode = DFS_MODE_NONE;
16603 	uint32_t freq_hint = 0;
16604 
16605 	hdd_enter_dev(wdev->netdev);
16606 
16607 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16608 		hdd_err("Command not allowed in FTM mode");
16609 		return -EINVAL;
16610 	}
16611 
16612 	ret = wlan_hdd_validate_context(hdd_ctx);
16613 	if (0 != ret)
16614 		return ret;
16615 
16616 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
16617 				    data, data_len,
16618 				    wlan_hdd_set_acs_dfs_config_policy)) {
16619 		hdd_err("invalid attr");
16620 		return -EINVAL;
16621 	}
16622 
16623 	acs_policy = &hdd_ctx->acs_policy;
16624 	/*
16625 	 * SCM sends this attribute to restrict SAP from choosing
16626 	 * DFS channels from ACS.
16627 	 */
16628 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
16629 		mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
16630 
16631 	if (!IS_DFS_MODE_VALID(mode)) {
16632 		hdd_err("attr acs dfs mode is not valid");
16633 		return -EINVAL;
16634 	}
16635 	acs_policy->acs_dfs_mode = mode;
16636 
16637 	/*
16638 	 * SCM sends this attribute to provide an active channel,
16639 	 * to skip redundant ACS between drivers, and save driver start up time
16640 	 */
16641 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]) {
16642 		freq_hint = nla_get_u32(
16643 				tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]);
16644 	} else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]) {
16645 		uint32_t channel_hint = nla_get_u8(
16646 				tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
16647 
16648 		freq_hint = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
16649 							 channel_hint);
16650 	}
16651 
16652 	if (freq_hint && !WLAN_REG_IS_24GHZ_CH_FREQ(freq_hint) &&
16653 	    !WLAN_REG_IS_5GHZ_CH_FREQ(freq_hint) &&
16654 	    !WLAN_REG_IS_6GHZ_CHAN_FREQ(freq_hint)) {
16655 		hdd_err("acs channel frequency is not valid");
16656 		return -EINVAL;
16657 	}
16658 
16659 	acs_policy->acs_chan_freq = freq_hint;
16660 
16661 	return 0;
16662 }
16663 
16664 /**
16665  * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
16666  * @wiphy:    wiphy structure pointer
16667  * @wdev:     Wireless device structure pointer
16668  * @data:     Pointer to the data received
16669  * @data_len: Length of @data
16670  *
16671  * This function parses the incoming NL vendor command data attributes and
16672  * updates the SAP context about channel_hint and DFS mode.
16673  *
16674  * Return: 0 on success; errno on failure
16675  */
wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16676 static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
16677 		struct wireless_dev *wdev,
16678 		const void *data, int data_len)
16679 {
16680 	struct osif_psoc_sync *psoc_sync;
16681 	int errno;
16682 
16683 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
16684 	if (errno)
16685 		return errno;
16686 
16687 	errno = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
16688 
16689 	osif_psoc_sync_op_stop(psoc_sync);
16690 
16691 	return errno;
16692 }
16693 
16694 /**
16695  * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
16696  * @mode : cfg80211 dfs mode
16697  *
16698  * Return: return csr sta roam dfs mode else return NONE
16699  */
wlan_hdd_get_sta_roam_dfs_mode(enum dfs_mode mode)16700 static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
16701 		enum dfs_mode mode)
16702 {
16703 	switch (mode) {
16704 	case DFS_MODE_ENABLE:
16705 		return STA_ROAM_POLICY_DFS_ENABLED;
16706 	case DFS_MODE_DISABLE:
16707 		return STA_ROAM_POLICY_DFS_DISABLED;
16708 	case DFS_MODE_DEPRIORITIZE:
16709 		return STA_ROAM_POLICY_DFS_DEPRIORITIZE;
16710 	default:
16711 		hdd_err("STA Roam policy dfs mode is NONE");
16712 		return  STA_ROAM_POLICY_NONE;
16713 	}
16714 }
16715 
16716 uint8_t
hdd_get_sap_operating_band_by_link_info(struct wlan_hdd_link_info * link_info)16717 hdd_get_sap_operating_band_by_link_info(struct wlan_hdd_link_info *link_info)
16718 {
16719 	uint32_t operating_chan_freq;
16720 	uint8_t sap_operating_band = 0;
16721 	struct hdd_ap_ctx *ap_ctx;
16722 	enum QDF_OPMODE opmode = link_info->adapter->device_mode;
16723 
16724 	if (opmode != QDF_SAP_MODE && opmode != QDF_P2P_GO_MODE)
16725 		return BAND_UNKNOWN;
16726 
16727 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
16728 	operating_chan_freq = ap_ctx->operating_chan_freq;
16729 
16730 	if (WLAN_REG_IS_24GHZ_CH_FREQ(operating_chan_freq))
16731 		sap_operating_band = BAND_2G;
16732 	else if (WLAN_REG_IS_5GHZ_CH_FREQ(operating_chan_freq) ||
16733 		 WLAN_REG_IS_6GHZ_CHAN_FREQ(operating_chan_freq))
16734 		sap_operating_band = BAND_5G;
16735 	else
16736 		sap_operating_band = BAND_UNKNOWN;
16737 
16738 	return sap_operating_band;
16739 }
16740 
16741 /*
16742  * hdd_get_sap_operating_band:  Get current operating channel
16743  * for sap.
16744  * @hdd_ctx: hdd context
16745  *
16746  * Return : Corresponding band for SAP operating channel
16747  */
hdd_get_sap_operating_band(struct hdd_context * hdd_ctx)16748 uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
16749 {
16750 	struct hdd_adapter *adapter, *next_adapter = NULL;
16751 	uint8_t operating_band = 0;
16752 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_SAP_OPERATING_BAND;
16753 	struct wlan_hdd_link_info *link_info;
16754 
16755 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
16756 					   dbgid) {
16757 		if (adapter->device_mode != QDF_SAP_MODE) {
16758 			hdd_adapter_dev_put_debug(adapter, dbgid);
16759 			continue;
16760 		}
16761 
16762 		link_info = adapter->deflink;
16763 		operating_band =
16764 			hdd_get_sap_operating_band_by_link_info(link_info);
16765 
16766 		hdd_adapter_dev_put_debug(adapter, dbgid);
16767 	}
16768 
16769 	return operating_band;
16770 }
16771 
16772 static inline QDF_STATUS
wlan_hdd_config_dp_direct_link_profile(struct hdd_adapter * adapter,enum host_concurrent_ap_policy ap_policy)16773 wlan_hdd_config_dp_direct_link_profile(struct hdd_adapter *adapter,
16774 				       enum host_concurrent_ap_policy ap_policy)
16775 {
16776 	struct wlan_objmgr_vdev *vdev = adapter->deflink->vdev;
16777 	enum host_concurrent_ap_policy prev_ap_policy;
16778 
16779 	prev_ap_policy = ucfg_mlme_get_ap_policy(vdev);
16780 
16781 	hdd_debug("Current AP policy %d prev AP policy %d", ap_policy,
16782 		  prev_ap_policy);
16783 
16784 	switch (prev_ap_policy) {
16785 	case HOST_CONCURRENT_AP_POLICY_UNSPECIFIED:
16786 		switch (ap_policy) {
16787 		case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
16788 			return ucfg_dp_config_direct_link(adapter->dev, true,
16789 							  false);
16790 		case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
16791 			return ucfg_dp_config_direct_link(adapter->dev, true,
16792 							  true);
16793 		default:
16794 			break;
16795 		}
16796 		break;
16797 	case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
16798 		switch (ap_policy) {
16799 		case HOST_CONCURRENT_AP_POLICY_UNSPECIFIED:
16800 		case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
16801 			return ucfg_dp_config_direct_link(adapter->dev, true,
16802 							  false);
16803 		default:
16804 			break;
16805 		}
16806 		break;
16807 	case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
16808 		switch (ap_policy) {
16809 		case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
16810 			return ucfg_dp_config_direct_link(adapter->dev, true,
16811 							  true);
16812 		default:
16813 			break;
16814 		}
16815 		break;
16816 	default:
16817 		break;
16818 	}
16819 
16820 	return QDF_STATUS_SUCCESS;
16821 }
16822 
16823 const struct nla_policy
16824 wlan_hdd_set_sta_roam_config_policy[
16825 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
16826 	[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
16827 	[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
16828 };
16829 
16830 /**
16831  * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
16832  * for station connection or roaming.
16833  * @wiphy: Pointer to wireless phy
16834  * @wdev: Pointer to wireless device
16835  * @data: Pointer to data
16836  * @data_len: Length of @data
16837  *
16838  * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
16839  * channels needs to be skipped in scanning or not.
16840  * If dfs_mode is disabled, driver will not scan DFS channels.
16841  * If skip_unsafe_channels is set, driver will skip unsafe channels
16842  * in Scanning.
16843  *
16844  * Return: 0 on success, negative errno on failure
16845  */
16846 static int
__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16847 __wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
16848 				    struct wireless_dev *wdev,
16849 				    const void *data, int data_len)
16850 {
16851 	struct net_device *dev = wdev->netdev;
16852 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16853 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16854 	struct nlattr *tb[
16855 		QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
16856 	int ret;
16857 	enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
16858 	enum dfs_mode mode = DFS_MODE_NONE;
16859 	bool skip_unsafe_channels = false;
16860 	QDF_STATUS status;
16861 	uint8_t sap_operating_band;
16862 	mac_handle_t mac_handle;
16863 
16864 	hdd_enter_dev(dev);
16865 
16866 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16867 		hdd_err("Command not allowed in FTM mode");
16868 		return -EINVAL;
16869 	}
16870 
16871 	ret = wlan_hdd_validate_context(hdd_ctx);
16872 	if (0 != ret)
16873 		return ret;
16874 	if (wlan_cfg80211_nla_parse(tb,
16875 			       QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
16876 			       data, data_len,
16877 			       wlan_hdd_set_sta_roam_config_policy)) {
16878 		hdd_err("invalid attr");
16879 		return -EINVAL;
16880 	}
16881 	if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
16882 		mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
16883 	if (!IS_DFS_MODE_VALID(mode)) {
16884 		hdd_err("attr sta roam dfs mode policy is not valid");
16885 		return -EINVAL;
16886 	}
16887 
16888 	sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
16889 
16890 	if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
16891 		skip_unsafe_channels = nla_get_u8(
16892 			tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
16893 	sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
16894 	mac_handle = hdd_ctx->mac_handle;
16895 	status = sme_update_sta_roam_policy(mac_handle, sta_roam_dfs_mode,
16896 					    skip_unsafe_channels,
16897 					    adapter->deflink->vdev_id,
16898 					    sap_operating_band);
16899 
16900 	if (!QDF_IS_STATUS_SUCCESS(status)) {
16901 		hdd_err("sme_update_sta_roam_policy (err=%d)", status);
16902 		return -EINVAL;
16903 	}
16904 	return 0;
16905 }
16906 
16907 /**
16908  * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
16909  * connection and roaming for station.
16910  * @wiphy:    wiphy structure pointer
16911  * @wdev:     Wireless device structure pointer
16912  * @data:     Pointer to the data received
16913  * @data_len: Length of @data
16914  *
16915  * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
16916  * channels needs to be skipped in scanning or not.
16917  * If dfs_mode is disabled, driver will not scan DFS channels.
16918  * If skip_unsafe_channels is set, driver will skip unsafe channels
16919  * in Scanning.
16920  * Return: 0 on success; errno on failure
16921  */
16922 static int
wlan_hdd_cfg80211_sta_roam_policy(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)16923 wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
16924 				  struct wireless_dev *wdev, const void *data,
16925 				  int data_len)
16926 {
16927 	int errno;
16928 	struct osif_vdev_sync *vdev_sync;
16929 
16930 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16931 	if (errno)
16932 		return errno;
16933 
16934 	errno = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev,
16935 						    data, data_len);
16936 
16937 	osif_vdev_sync_op_stop(vdev_sync);
16938 
16939 	return errno;
16940 }
16941 
16942 const struct nla_policy
16943 wlan_hdd_set_concurrent_session_policy[
16944 QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX + 1] = {
16945 	[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG] = {.type = NLA_U8 },
16946 	[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG] = {.type = NLA_U8 },
16947 };
16948 
16949 /**
16950  * __wlan_hdd_cfg80211_dual_sta_policy() - Wrapper to configure the concurrent
16951  * session policies
16952  * @hdd_ctx: Pointer to HDD context
16953  * @tb: parsed attribute array
16954  *
16955  * Configure the concurrent session policies when multiple STA ifaces are
16956  * (getting) active.
16957  * Return: 0 on success; errno on failure
16958  */
__wlan_hdd_cfg80211_dual_sta_policy(struct hdd_context * hdd_ctx,struct nlattr ** tb)16959 static int __wlan_hdd_cfg80211_dual_sta_policy(struct hdd_context *hdd_ctx,
16960 					       struct nlattr **tb)
16961 {
16962 	QDF_STATUS status;
16963 	uint8_t dual_sta_config =
16964 		QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED;
16965 
16966 	dual_sta_config = nla_get_u8(
16967 			tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG]);
16968 	hdd_debug("Concurrent STA policy : %d", dual_sta_config);
16969 
16970 	if (dual_sta_config > QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED)
16971 		return -EINVAL;
16972 
16973 	status = ucfg_mlme_set_dual_sta_policy(hdd_ctx->psoc, dual_sta_config);
16974 	if (QDF_IS_STATUS_ERROR(status)) {
16975 		hdd_err("failed to set MLME dual sta config");
16976 		return -EINVAL;
16977 	}
16978 
16979 	/* After SSR, the dual sta configuration is lost. As SSR is hidden from
16980 	 * userland, this command will not come from userspace after a SSR. To
16981 	 * restore this configuration, save this in hdd context and restore
16982 	 * after re-init.
16983 	 */
16984 	hdd_ctx->dual_sta_policy.dual_sta_policy = dual_sta_config;
16985 
16986 	return 0;
16987 }
16988 
16989 /**
16990  * __wlan_hdd_cfg80211_ap_policy() - Wrapper to configure the concurrent
16991  * session policies
16992  * @adapter: HDD adapter
16993  * @tb: parsed attribute array
16994  *
16995  * Configure the concurrent session policies when multiple STA ifaces are
16996  * (getting) active.
16997  * Return: 0 on success; errno on failure
16998  */
__wlan_hdd_cfg80211_ap_policy(struct hdd_adapter * adapter,struct nlattr ** tb)16999 static int __wlan_hdd_cfg80211_ap_policy(struct hdd_adapter *adapter,
17000 					 struct nlattr **tb)
17001 {
17002 	QDF_STATUS status;
17003 	uint8_t vdev_id;
17004 	int ret;
17005 	uint8_t ap_cfg_policy;
17006 	uint32_t profile = 0;
17007 	enum QDF_OPMODE device_mode;
17008 	uint8_t ap_config =
17009 		QCA_WLAN_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING;
17010 
17011 	vdev_id = wlan_vdev_get_id(adapter->deflink->vdev);
17012 	device_mode = hdd_get_device_mode(vdev_id);
17013 	if (device_mode != QDF_SAP_MODE) {
17014 		hdd_err_rl("command not allowed in %d mode, vdev_id: %d",
17015 			   device_mode, vdev_id);
17016 		return -EINVAL;
17017 	}
17018 
17019 	ap_config = nla_get_u8(
17020 		tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG]);
17021 	hdd_debug("AP policy : %d", ap_config);
17022 
17023 	if (ap_config > QCA_WLAN_CONCURRENT_AP_POLICY_XR) {
17024 		hdd_err_rl("Invalid concurrent policy ap config %d", ap_config);
17025 		return -EINVAL;
17026 	}
17027 
17028 	ap_cfg_policy = wlan_mlme_convert_ap_policy_config(ap_config);
17029 	if (ap_cfg_policy == HOST_CONCURRENT_AP_POLICY_XR)
17030 		profile = AP_PROFILE_XR_ENABLE;
17031 	else if (ap_cfg_policy == HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO ||
17032 		 ap_cfg_policy ==
17033 		 HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING)
17034 		profile = AP_PROFILE_XPAN_ENABLE;
17035 	ret = wma_cli_set_command(vdev_id, wmi_vdev_param_set_profile,
17036 				  profile, VDEV_CMD);
17037 	if (ret) {
17038 		hdd_err("Failed to set profile %d", profile);
17039 		return -EINVAL;
17040 	}
17041 	status = wlan_hdd_config_dp_direct_link_profile(adapter, ap_cfg_policy);
17042 	if (QDF_IS_STATUS_ERROR(status)) {
17043 		hdd_err("failed to set DP ap config");
17044 		return -EINVAL;
17045 	}
17046 	status = ucfg_mlme_set_ap_policy(adapter->deflink->vdev, ap_cfg_policy);
17047 	if (QDF_IS_STATUS_ERROR(status)) {
17048 		hdd_err("failed to set MLME ap config");
17049 		return -EINVAL;
17050 	}
17051 
17052 	wlan_mlme_ll_lt_sap_send_oce_flags_fw(adapter->deflink->vdev);
17053 	wlan_vdev_mlme_feat_ext_cap_clear(adapter->deflink->vdev,
17054 					  WLAN_VDEV_FEXT_FILS_DISC_6G_SAP);
17055 	return 0;
17056 }
17057 
17058 /**
17059  * __wlan_hdd_cfg80211_concurrent_session_policy() - Wrapper to configure the
17060  * concurrent session policies
17061  * @wiphy:    wiphy structure pointer
17062  * @wdev:     Wireless device structure pointer
17063  * @data:     Pointer to the data received
17064  * @data_len: Length of @data
17065  *
17066  * Configure the concurrent session policies when low latency SAP or multiple
17067  * STA ifaces are (getting) active.
17068  * Return: 0 on success; errno on failure
17069  */
__wlan_hdd_cfg80211_concurrent_session_policy(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17070 static int __wlan_hdd_cfg80211_concurrent_session_policy(
17071 						struct wiphy *wiphy,
17072 						struct wireless_dev *wdev,
17073 						const void *data, int data_len)
17074 {
17075 	struct net_device *ndev = wdev->netdev;
17076 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
17077 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX + 1];
17078 
17079 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17080 		hdd_err_rl("Command not allowed in FTM mode");
17081 		return -EPERM;
17082 	}
17083 
17084 	if (hdd_validate_adapter(adapter)) {
17085 		hdd_err_rl("Invalid adapter");
17086 		return -EINVAL;
17087 	}
17088 
17089 	if (wlan_hdd_validate_context(adapter->hdd_ctx)) {
17090 		hdd_err_rl("Invalid hdd context");
17091 		return -EINVAL;
17092 	}
17093 
17094 	if (wlan_cfg80211_nla_parse(
17095 				tb,
17096 				QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX,
17097 				data, data_len,
17098 				wlan_hdd_set_concurrent_session_policy)) {
17099 		hdd_err_rl("nla_parse failed");
17100 		return -EINVAL;
17101 	}
17102 
17103 	if (!tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG] &&
17104 	    !tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG]) {
17105 		hdd_err_rl("concurrent session policy attr not present");
17106 		return -EINVAL;
17107 	}
17108 
17109 	if (tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG])
17110 		__wlan_hdd_cfg80211_dual_sta_policy(adapter->hdd_ctx, tb);
17111 
17112 	if (tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG])
17113 		__wlan_hdd_cfg80211_ap_policy(adapter, tb);
17114 
17115 	return 0;
17116 }
17117 
17118 /**
17119  * wlan_hdd_cfg80211_concurrent_session_policy() -  Wrapper to configure the
17120  * concurrent session policies
17121  * @wiphy:    wiphy structure pointer
17122  * @wdev:     Wireless device structure pointer
17123  * @data:     Pointer to the data received
17124  * @data_len: Length of @data
17125  *
17126  * Configure the concurrent session policies when multiple STA ifaces are
17127  * (getting) active.
17128  * Return: 0 on success; errno on failure
17129  */
wlan_hdd_cfg80211_concurrent_session_policy(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17130 static int wlan_hdd_cfg80211_concurrent_session_policy(
17131 						struct wiphy *wiphy,
17132 						struct wireless_dev *wdev,
17133 						const void *data,
17134 						int data_len)
17135 {
17136 	int errno;
17137 	struct osif_vdev_sync *vdev_sync;
17138 
17139 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
17140 	if (errno)
17141 		return errno;
17142 
17143 	errno = __wlan_hdd_cfg80211_concurrent_session_policy(
17144 						wiphy, wdev, data,
17145 						data_len);
17146 
17147 
17148 	osif_vdev_sync_op_stop(vdev_sync);
17149 
17150 	return errno;
17151 }
17152 
17153 #ifdef FEATURE_WLAN_CH_AVOID
17154 /**
17155  * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
17156  * is on unsafe channel.
17157  * @wiphy:    wiphy structure pointer
17158  * @wdev:     Wireless device structure pointer
17159  * @data:     Pointer to the data received
17160  * @data_len: Length of @data
17161  *
17162  * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
17163  * on any of unsafe channels.
17164  * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
17165  * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
17166  *
17167  * Return: 0 on success; errno on failure
17168  */
17169 static int
__wlan_hdd_cfg80211_avoid_freq(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17170 __wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
17171 		struct wireless_dev *wdev,
17172 		const void *data, int data_len)
17173 {
17174 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17175 	int ret;
17176 	qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
17177 	struct ch_avoid_ind_type *channel_list;
17178 	struct ch_avoid_ind_type avoid_freq_list;
17179 	enum QDF_GLOBAL_MODE curr_mode;
17180 	uint8_t num_args = 0;
17181 
17182 	hdd_enter_dev(wdev->netdev);
17183 
17184 	if (!qdf_ctx)
17185 		return -EINVAL;
17186 
17187 	curr_mode = hdd_get_conparam();
17188 	if (QDF_GLOBAL_FTM_MODE == curr_mode ||
17189 	    QDF_GLOBAL_MONITOR_MODE == curr_mode) {
17190 		hdd_err("Command not allowed in FTM/MONITOR mode");
17191 		return -EINVAL;
17192 	}
17193 
17194 	ret = wlan_hdd_validate_context(hdd_ctx);
17195 	if (0 != ret)
17196 		return ret;
17197 	qdf_mem_zero(&avoid_freq_list, sizeof(struct ch_avoid_ind_type));
17198 
17199 	if (!data && data_len == 0) {
17200 		hdd_debug("Clear avoid frequency list");
17201 		goto process_unsafe_channel;
17202 	}
17203 	if (!data || data_len < (sizeof(channel_list->ch_avoid_range_cnt) +
17204 				 sizeof(struct ch_avoid_freq_type))) {
17205 		hdd_err("Avoid frequency channel list empty");
17206 		return -EINVAL;
17207 	}
17208 	num_args = (data_len - sizeof(channel_list->ch_avoid_range_cnt)) /
17209 		   sizeof(channel_list->avoid_freq_range[0].start_freq);
17210 
17211 
17212 	if (num_args < 2 || num_args > CH_AVOID_MAX_RANGE * 2 ||
17213 	    num_args % 2 != 0) {
17214 		hdd_err("Invalid avoid frequency channel list");
17215 		return -EINVAL;
17216 	}
17217 
17218 	channel_list = (struct ch_avoid_ind_type *)data;
17219 	if (channel_list->ch_avoid_range_cnt == 0 ||
17220 	    channel_list->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE ||
17221 	    2 * channel_list->ch_avoid_range_cnt != num_args) {
17222 		hdd_err("Invalid frequency range count %d",
17223 			channel_list->ch_avoid_range_cnt);
17224 		return -EINVAL;
17225 	}
17226 
17227 	qdf_mem_copy(&avoid_freq_list, channel_list, data_len);
17228 
17229 process_unsafe_channel:
17230 	ucfg_reg_ch_avoid(hdd_ctx->psoc, &avoid_freq_list);
17231 
17232 	return 0;
17233 }
17234 
17235 /**
17236  * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
17237  * is on unsafe channel.
17238  * @wiphy:    wiphy structure pointer
17239  * @wdev:     Wireless device structure pointer
17240  * @data:     Pointer to the data received
17241  * @data_len: Length of @data
17242  *
17243  * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
17244  * on any of unsafe channels.
17245  * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
17246  * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
17247  *
17248  * Return: 0 on success; errno on failure
17249  */
wlan_hdd_cfg80211_avoid_freq(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17250 static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
17251 		struct wireless_dev *wdev,
17252 		const void *data, int data_len)
17253 {
17254 	struct osif_psoc_sync *psoc_sync;
17255 	int errno;
17256 
17257 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
17258 	if (errno)
17259 		return errno;
17260 
17261 	errno = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
17262 
17263 	osif_psoc_sync_op_stop(psoc_sync);
17264 
17265 	return errno;
17266 }
17267 
17268 #endif
17269 /**
17270  * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
17271  * SAP is on unsafe channel.
17272  * @wiphy:    wiphy structure pointer
17273  * @wdev:     Wireless device structure pointer
17274  * @data:     Pointer to the data received
17275  * @data_len: Length of @data
17276  *
17277  * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
17278  * driver.
17279  * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
17280  * will initiate restart of sap.
17281  *
17282  * Return: 0 on success; errno on failure
17283  */
17284 static int
__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17285 __wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
17286 		struct wireless_dev *wdev,
17287 		const void *data, int data_len)
17288 {
17289 	struct net_device *ndev = wdev->netdev;
17290 	struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
17291 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17292 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
17293 	struct hdd_ap_ctx *ap_ctx;
17294 	int ret;
17295 	uint32_t chan_freq = 0;
17296 	bool chan_freq_present = false;
17297 	QDF_STATUS status;
17298 	struct wlan_hdd_link_info *link_info;
17299 
17300 	hdd_enter();
17301 
17302 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17303 		hdd_err("Command not allowed in FTM mode");
17304 		return -EINVAL;
17305 	}
17306 
17307 	ret = wlan_hdd_validate_context(hdd_ctx);
17308 	if (0 != ret)
17309 		return -EINVAL;
17310 
17311 	link_info = hostapd_adapter->deflink;
17312 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
17313 				    data, data_len,
17314 				    wlan_hdd_sap_config_policy)) {
17315 		hdd_err("invalid attr");
17316 		return -EINVAL;
17317 	}
17318 
17319 	if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]) {
17320 		chan_freq = nla_get_u32(
17321 				tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]);
17322 		chan_freq_present = true;
17323 	} else if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
17324 		uint32_t config_channel =
17325 			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
17326 
17327 		chan_freq = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
17328 							 config_channel);
17329 		chan_freq_present = true;
17330 	}
17331 
17332 	if (chan_freq_present) {
17333 		if (!test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
17334 			hdd_err("SAP is not started yet. Restart sap will be invalid");
17335 			return -EINVAL;
17336 		}
17337 
17338 		if (!WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq) &&
17339 		    !WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq) &&
17340 		    !WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq)) {
17341 			hdd_err("Channel frequency %u is invalid to restart SAP",
17342 				chan_freq);
17343 			return -ENOTSUPP;
17344 		}
17345 
17346 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
17347 		ap_ctx->sap_config.chan_freq = chan_freq;
17348 		ap_ctx->sap_config.ch_params.ch_width =
17349 					ap_ctx->sap_config.ch_width_orig;
17350 		ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
17351 
17352 		if (sap_phymode_is_eht(ap_ctx->sap_config.SapHw_mode))
17353 			wlan_reg_set_create_punc_bitmap(
17354 				&ap_ctx->sap_config.ch_params, true);
17355 		wlan_reg_set_channel_params_for_pwrmode(
17356 				hdd_ctx->pdev, chan_freq,
17357 				ap_ctx->sap_config.sec_ch_freq,
17358 				&ap_ctx->sap_config.ch_params,
17359 				REG_CURRENT_PWR_MODE);
17360 
17361 		hdd_restart_sap(link_info);
17362 	}
17363 
17364 	if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
17365 		uint32_t freq_len, i;
17366 		uint32_t *freq;
17367 
17368 		hdd_debug("setting mandatory freq/chan list");
17369 
17370 		freq_len = nla_len(
17371 		    tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
17372 		    sizeof(uint32_t);
17373 
17374 		if (freq_len > NUM_CHANNELS) {
17375 			hdd_err("insufficient space to hold channels");
17376 			return -ENOMEM;
17377 		}
17378 
17379 		freq = nla_data(
17380 		    tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
17381 
17382 		hdd_debug("freq_len=%d", freq_len);
17383 
17384 		for (i = 0; i < freq_len; i++) {
17385 			hdd_debug("freq[%d]=%d", i, freq[i]);
17386 		}
17387 
17388 		status = policy_mgr_set_sap_mandatory_channels(
17389 			hdd_ctx->psoc, freq, freq_len);
17390 		if (QDF_IS_STATUS_ERROR(status))
17391 			return -EINVAL;
17392 	}
17393 
17394 	return 0;
17395 }
17396 
17397 /**
17398  * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
17399  * @wiphy:    wiphy structure pointer
17400  * @wdev:     Wireless device structure pointer
17401  * @data:     Pointer to the data received
17402  * @data_len: Length of @data
17403  *
17404  * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
17405  * driver.
17406  * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
17407  * will initiate restart of sap.
17408  *
17409  * Return: 0 on success; errno on failure
17410  */
wlan_hdd_cfg80211_sap_configuration_set(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17411 static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
17412 		struct wireless_dev *wdev,
17413 		const void *data, int data_len)
17414 {
17415 	int errno;
17416 	struct osif_vdev_sync *vdev_sync;
17417 
17418 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
17419 	if (errno)
17420 		return errno;
17421 
17422 	errno = __wlan_hdd_cfg80211_sap_configuration_set(wiphy, wdev,
17423 							  data, data_len);
17424 
17425 	osif_vdev_sync_op_stop(vdev_sync);
17426 
17427 	return errno;
17428 }
17429 
17430 /**
17431  * wlan_hdd_process_wake_lock_stats() - wrapper function to absract cp_stats
17432  * or legacy get_wake_lock_stats API.
17433  * @hdd_ctx: pointer to hdd_ctx
17434  *
17435  * Return: 0 on success; error number otherwise.
17436  */
wlan_hdd_process_wake_lock_stats(struct hdd_context * hdd_ctx)17437 static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
17438 {
17439 	return wlan_cfg80211_mc_cp_stats_get_wakelock_stats(hdd_ctx->psoc,
17440 							    hdd_ctx->wiphy);
17441 }
17442 
17443 /**
17444  * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
17445  * @wiphy: wiphy pointer
17446  * @wdev: pointer to struct wireless_dev
17447  * @data: pointer to incoming NL vendor data
17448  * @data_len: length of @data
17449  *
17450  * This function parses the incoming NL vendor command data attributes and
17451  * invokes the SME Api and blocks on a completion variable.
17452  * WMA copies required data and invokes callback
17453  * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
17454  *
17455  * Return: 0 on success; error number otherwise.
17456  */
__wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17457 static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
17458 					struct wireless_dev *wdev,
17459 					const void *data,
17460 					int data_len)
17461 {
17462 	int ret;
17463 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17464 
17465 	hdd_enter();
17466 
17467 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17468 		hdd_err("Command not allowed in FTM mode");
17469 		return -EINVAL;
17470 	}
17471 
17472 	ret = wlan_hdd_validate_context(hdd_ctx);
17473 	if (0 != ret)
17474 		return -EINVAL;
17475 
17476 	ret = wlan_hdd_process_wake_lock_stats(hdd_ctx);
17477 	hdd_exit();
17478 	return ret;
17479 }
17480 
17481 /**
17482  * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
17483  * @wiphy: wiphy pointer
17484  * @wdev: pointer to struct wireless_dev
17485  * @data: pointer to incoming NL vendor data
17486  * @data_len: length of @data
17487  *
17488  * This function parses the incoming NL vendor command data attributes and
17489  * invokes the SME Api and blocks on a completion variable.
17490  * WMA copies required data and invokes callback
17491  * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
17492  *
17493  * Return: 0 on success; error number otherwise.
17494  */
wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17495 static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
17496 						struct wireless_dev *wdev,
17497 						const void *data, int data_len)
17498 {
17499 	struct osif_psoc_sync *psoc_sync;
17500 	int errno;
17501 
17502 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
17503 	if (errno)
17504 		return errno;
17505 
17506 	errno = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev,
17507 						       data, data_len);
17508 
17509 	osif_psoc_sync_op_stop(psoc_sync);
17510 
17511 	return errno;
17512 }
17513 
17514 /**
17515  * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
17516  * @wiphy:    wiphy structure pointer
17517  * @wdev:     Wireless device structure pointer
17518  * @data:     Pointer to the data received
17519  * @data_len: Length of @data
17520  *
17521  * This function reads wmi max bus size and fill in the skb with
17522  * NL attributes and send up the NL event.
17523  * Return: 0 on success; errno on failure
17524  */
17525 static int
__wlan_hdd_cfg80211_get_bus_size(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17526 __wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
17527 				 struct wireless_dev *wdev,
17528 				 const void *data, int data_len)
17529 {
17530 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17531 	int ret_val;
17532 	struct sk_buff *skb;
17533 	uint32_t nl_buf_len;
17534 
17535 	hdd_enter();
17536 
17537 	ret_val = wlan_hdd_validate_context(hdd_ctx);
17538 	if (ret_val)
17539 		return ret_val;
17540 
17541 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17542 		hdd_err("Command not allowed in FTM mode");
17543 		return -EINVAL;
17544 	}
17545 
17546 	hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
17547 
17548 	nl_buf_len = NLMSG_HDRLEN;
17549 	nl_buf_len +=  (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
17550 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
17551 						       nl_buf_len);
17552 	if (!skb) {
17553 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
17554 		return -ENOMEM;
17555 	}
17556 
17557 	if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
17558 			hdd_ctx->wmi_max_len)) {
17559 		hdd_err("nla put failure");
17560 		goto nla_put_failure;
17561 	}
17562 
17563 	wlan_cfg80211_vendor_cmd_reply(skb);
17564 
17565 	hdd_exit();
17566 
17567 	return 0;
17568 
17569 nla_put_failure:
17570 	wlan_cfg80211_vendor_free_skb(skb);
17571 	return -EINVAL;
17572 }
17573 
17574 /**
17575  * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
17576  * @wiphy:    wiphy structure pointer
17577  * @wdev:     Wireless device structure pointer
17578  * @data:     Pointer to the data received
17579  * @data_len: Length of @data
17580  *
17581  * Return: 0 on success; errno on failure
17582  */
wlan_hdd_cfg80211_get_bus_size(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17583 static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
17584 					  struct wireless_dev *wdev,
17585 					  const void *data, int data_len)
17586 {
17587 	struct osif_psoc_sync *psoc_sync;
17588 	int errno;
17589 
17590 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
17591 	if (errno)
17592 		return errno;
17593 
17594 	errno = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
17595 
17596 	osif_psoc_sync_op_stop(psoc_sync);
17597 
17598 	return errno;
17599 }
17600 
17601 /**
17602  * __wlan_hdd_cfg80211_get_radio_combination_matrix() - get radio matrix info
17603  * @wiphy:   pointer to wireless wiphy structure.
17604  * @wdev:    pointer to wireless_dev structure.
17605  * @data:    Pointer to the data to be passed via vendor interface
17606  * @data_len:Length of the data to be passed
17607  *
17608  * Return:   Return the Success or Failure code.
17609  */
17610 static int
__wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17611 __wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy *wiphy,
17612 						 struct wireless_dev *wdev,
17613 						 const void *data,
17614 						 int data_len)
17615 {
17616 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17617 	struct sk_buff *reply_skb;
17618 	int ret;
17619 	int skb_len;
17620 	struct nlattr *combination, *combination_cfg, *radio, *radio_comb;
17621 	uint32_t comb_num = 0;
17622 	struct radio_combination comb[MAX_RADIO_COMBINATION];
17623 	int comb_idx, radio_idx;
17624 	enum qca_set_band qca_band;
17625 
17626 	hdd_enter();
17627 
17628 	ret = wlan_hdd_validate_context(hdd_ctx);
17629 	if (ret)
17630 		return ret;
17631 
17632 	ucfg_policy_mgr_get_radio_combinations(hdd_ctx->psoc, comb,
17633 					       QDF_ARRAY_SIZE(comb),
17634 					       &comb_num);
17635 	if (!comb_num) {
17636 		hdd_err("invalid combination 0");
17637 		return -EINVAL;
17638 	}
17639 
17640 	/* band and antenna */
17641 	skb_len = nla_total_size(sizeof(uint32_t)) +
17642 		  nla_total_size(sizeof(uint8_t));
17643 	/* radio nested for max 2 MACs*/
17644 	skb_len = nla_total_size(skb_len) * MAX_MAC;
17645 	/* one radio combination */
17646 	skb_len = nla_total_size(nla_total_size(skb_len));
17647 	/* total combinations */
17648 	skb_len = nla_total_size(comb_num * nla_total_size(skb_len));
17649 	skb_len = NLMSG_HDRLEN + skb_len;
17650 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
17651 	if (!reply_skb) {
17652 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed, len %d",
17653 			skb_len);
17654 		return -EINVAL;
17655 	}
17656 
17657 	combination_cfg = nla_nest_start(reply_skb,
17658 			QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_SUPPORTED_CFGS);
17659 	if (!combination_cfg) {
17660 		ret = -ENOMEM;
17661 		goto err;
17662 	}
17663 	for (comb_idx = 0; comb_idx < comb_num; comb_idx++) {
17664 		combination = nla_nest_start(reply_skb, comb_idx);
17665 		if (!combination) {
17666 			ret = -ENOMEM;
17667 			goto err;
17668 		}
17669 		radio_comb = nla_nest_start(reply_skb,
17670 				QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_CFGS);
17671 		if (!radio_comb) {
17672 			ret = -ENOMEM;
17673 			goto err;
17674 		}
17675 		for (radio_idx = 0; radio_idx < MAX_MAC; radio_idx++) {
17676 			if (!comb[comb_idx].band_mask[radio_idx])
17677 				break;
17678 			radio = nla_nest_start(reply_skb, radio_idx);
17679 			if (!radio) {
17680 				ret = -ENOMEM;
17681 				goto err;
17682 			}
17683 			if (comb[comb_idx].band_mask[radio_idx] ==
17684 							BIT(REG_BAND_5G)) {
17685 				qca_band = QCA_SETBAND_5G;
17686 			} else if (comb[comb_idx].band_mask[radio_idx] ==
17687 							BIT(REG_BAND_6G)) {
17688 				qca_band = QCA_SETBAND_6G;
17689 			} else if (comb[comb_idx].band_mask[radio_idx] ==
17690 							BIT(REG_BAND_2G)) {
17691 				qca_band = QCA_SETBAND_2G;
17692 			} else {
17693 				hdd_err("invalid band mask 0 for comb %d radio %d",
17694 					comb_idx, radio_idx);
17695 				ret = -EINVAL;
17696 				goto err;
17697 			}
17698 
17699 			if (nla_put_u32(reply_skb,
17700 				       QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_BAND,
17701 				       qca_band)) {
17702 				ret = -ENOMEM;
17703 				goto err;
17704 			}
17705 			if (nla_put_u8(reply_skb,
17706 				       QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_ANTENNA,
17707 				       comb[comb_idx].antenna[radio_idx])) {
17708 				ret = -ENOMEM;
17709 				goto err;
17710 			}
17711 			hdd_debug("comb[%d]:cfg[%d]: band %d, antenna %d",
17712 				  comb_idx, radio_idx, qca_band,
17713 				  comb[comb_idx].antenna[radio_idx]);
17714 			nla_nest_end(reply_skb, radio);
17715 		}
17716 		nla_nest_end(reply_skb, radio_comb);
17717 		nla_nest_end(reply_skb, combination);
17718 	}
17719 	nla_nest_end(reply_skb, combination_cfg);
17720 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
17721 
17722 err:
17723 	wlan_cfg80211_vendor_free_skb(reply_skb);
17724 	return ret;
17725 }
17726 
17727 /**
17728  * wlan_hdd_cfg80211_get_radio_combination_matrix() - get radio matrix info
17729  * @wiphy:   pointer to wireless wiphy structure.
17730  * @wdev:    pointer to wireless_dev structure.
17731  * @data:    Pointer to the data to be passed via vendor interface
17732  * @data_len:Length of the data to be passed
17733  *
17734  * Return:   Return the Success or Failure code.
17735  */
17736 static int
wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17737 wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy *wiphy,
17738 					       struct wireless_dev *wdev,
17739 					       const void *data, int data_len)
17740 {
17741 	struct osif_psoc_sync *psoc_sync;
17742 	int errno;
17743 
17744 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
17745 	if (errno)
17746 		return errno;
17747 
17748 	errno = __wlan_hdd_cfg80211_get_radio_combination_matrix(wiphy, wdev,
17749 								 data,
17750 								 data_len);
17751 
17752 	osif_psoc_sync_op_stop(psoc_sync);
17753 
17754 	return errno;
17755 }
17756 
17757 const struct nla_policy setband_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
17758 	[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = {.type = NLA_U32},
17759 	[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK] = {.type = NLA_U32},
17760 };
17761 
17762 /**
17763  *__wlan_hdd_cfg80211_setband() - set band
17764  * @wiphy: Pointer to wireless phy
17765  * @wdev: Pointer to wireless device
17766  * @data: Pointer to data
17767  * @data_len: Length of @data
17768  *
17769  * Return: 0 on success, negative errno on failure
17770  */
__wlan_hdd_cfg80211_setband(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)17771 static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
17772 				       struct wireless_dev *wdev,
17773 				       const void *data, int data_len)
17774 {
17775 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17776 	struct net_device *dev = wdev->netdev;
17777 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
17778 	int ret;
17779 	uint32_t reg_wifi_band_bitmap = 0, band_val, band_mask;
17780 
17781 	hdd_enter();
17782 
17783 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17784 		hdd_err("Command not allowed in FTM mode");
17785 		return -EPERM;
17786 	}
17787 
17788 	ret = wlan_hdd_validate_context(hdd_ctx);
17789 	if (ret)
17790 		return ret;
17791 
17792 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
17793 				    data, data_len, setband_policy)) {
17794 		hdd_err("Invalid ATTR");
17795 		return -EINVAL;
17796 	}
17797 
17798 	if (tb[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK]) {
17799 		band_mask = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK]);
17800 		reg_wifi_band_bitmap =
17801 			wlan_vendor_bitmap_to_reg_wifi_band_bitmap(hdd_ctx->psoc,
17802 								   band_mask);
17803 		hdd_debug("[SET BAND] set band mask:%d", reg_wifi_band_bitmap);
17804 	} else if (tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
17805 		band_val = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]);
17806 		reg_wifi_band_bitmap =
17807 			hdd_reg_legacy_setband_to_reg_wifi_band_bitmap(
17808 								      band_val);
17809 	}
17810 
17811 	if (!reg_wifi_band_bitmap) {
17812 		hdd_err("attr SETBAND_VALUE failed");
17813 		return -EINVAL;
17814 	}
17815 
17816 	ret = hdd_reg_set_band(dev, reg_wifi_band_bitmap);
17817 
17818 	hdd_exit();
17819 	return ret;
17820 }
17821 
17822 /**
17823  * wlan_hdd_validate_acs_channel() - validate channel frequency provided by ACS
17824  * @link_info: Pointer to link_info in adapter
17825  * @chan_freq: channel frequency in MHz
17826  * @chan_bw: channel bandiodth in MHz
17827  *
17828  * return: QDF status based on success or failure
17829  */
17830 static QDF_STATUS
wlan_hdd_validate_acs_channel(struct wlan_hdd_link_info * link_info,uint32_t chan_freq,int chan_bw)17831 wlan_hdd_validate_acs_channel(struct wlan_hdd_link_info *link_info,
17832 			      uint32_t chan_freq, int chan_bw)
17833 {
17834 	struct hdd_context *hdd_ctx;
17835 	struct sap_context *sap_context;
17836 
17837 	hdd_ctx = link_info->adapter->hdd_ctx;
17838 	if (QDF_STATUS_SUCCESS !=
17839 	    wlan_hdd_validate_operation_channel(hdd_ctx, chan_freq))
17840 		return QDF_STATUS_E_FAILURE;
17841 
17842 	sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
17843 	if ((wlansap_is_channel_in_nol_list(sap_context, chan_freq,
17844 					    PHY_SINGLE_CHANNEL_CENTERED))) {
17845 		hdd_info("channel %d is in nol", chan_freq);
17846 		return -EINVAL;
17847 	}
17848 
17849 	if ((wlansap_is_channel_leaking_in_nol(sap_context,
17850 					       chan_freq, chan_bw))) {
17851 		hdd_info("channel freq %d is leaking in nol", chan_freq);
17852 		return -EINVAL;
17853 	}
17854 
17855 	return 0;
17856 
17857 }
17858 
hdd_update_acs_sap_config(struct hdd_context * hdd_ctx,struct sap_config * sap_config,struct hdd_vendor_chan_info * channel_list)17859 static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
17860 				     struct sap_config *sap_config,
17861 				     struct hdd_vendor_chan_info *channel_list)
17862 {
17863 	uint8_t ch_width;
17864 	QDF_STATUS status;
17865 	uint32_t channel_bonding_mode;
17866 
17867 	sap_config->chan_freq = channel_list->pri_chan_freq;
17868 
17869 	sap_config->ch_params.center_freq_seg0 =
17870 		wlan_reg_freq_to_chan(hdd_ctx->pdev,
17871 				      channel_list->vht_seg0_center_chan_freq);
17872 	sap_config->ch_params.center_freq_seg1 =
17873 		wlan_reg_freq_to_chan(hdd_ctx->pdev,
17874 				      channel_list->vht_seg1_center_chan_freq);
17875 
17876 	sap_config->ch_params.sec_ch_offset =
17877 		wlan_reg_freq_to_chan(hdd_ctx->pdev,
17878 				      channel_list->ht_sec_chan_freq);
17879 
17880 	sap_config->ch_params.ch_width =
17881 				hdd_map_nl_chan_width(channel_list->chan_width);
17882 	if (!WLAN_REG_IS_24GHZ_CH_FREQ(sap_config->chan_freq)) {
17883 		status =
17884 			ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
17885 							&ch_width);
17886 		if (!QDF_IS_STATUS_SUCCESS(status))
17887 			hdd_err("Failed to set channel_width");
17888 		sap_config->ch_width_orig = ch_width;
17889 	} else {
17890 		ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
17891 						    &channel_bonding_mode);
17892 		sap_config->ch_width_orig = channel_bonding_mode ?
17893 			CH_WIDTH_40MHZ : CH_WIDTH_20MHZ;
17894 	}
17895 	sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
17896 	sap_config->acs_cfg.ch_width =
17897 				hdd_map_nl_chan_width(channel_list->chan_width);
17898 	sap_config->acs_cfg.vht_seg0_center_ch_freq =
17899 			channel_list->vht_seg0_center_chan_freq;
17900 	sap_config->acs_cfg.vht_seg1_center_ch_freq =
17901 			channel_list->vht_seg1_center_chan_freq;
17902 	sap_config->acs_cfg.ht_sec_ch_freq =
17903 			channel_list->ht_sec_chan_freq;
17904 }
17905 
hdd_update_acs_channel(struct wlan_hdd_link_info * link_info,uint8_t reason,uint8_t channel_cnt,struct hdd_vendor_chan_info * channel_list)17906 static int hdd_update_acs_channel(struct wlan_hdd_link_info *link_info,
17907 				  uint8_t reason, uint8_t channel_cnt,
17908 				  struct hdd_vendor_chan_info *channel_list)
17909 {
17910 	struct sap_config *sap_config;
17911 	struct hdd_ap_ctx *hdd_ap_ctx;
17912 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
17913 	QDF_STATUS status = QDF_STATUS_SUCCESS;
17914 	mac_handle_t mac_handle;
17915 	uint32_t ch;
17916 
17917 	if (!channel_list) {
17918 		hdd_err("channel_list is NULL");
17919 		return -EINVAL;
17920 	}
17921 
17922 	hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
17923 	sap_config = &link_info->session.ap.sap_config;
17924 
17925 	if (QDF_TIMER_STATE_RUNNING ==
17926 	    qdf_mc_timer_get_current_state(&hdd_ap_ctx->vendor_acs_timer)) {
17927 		qdf_mc_timer_stop(&hdd_ap_ctx->vendor_acs_timer);
17928 	}
17929 
17930 	if (channel_list->pri_chan_freq == 0) {
17931 		/* Check mode, set default channel */
17932 		channel_list->pri_chan_freq = 2437;
17933 		/*
17934 		 * sap_select_default_oper_chan(mac_handle,
17935 		 *      sap_config->acs_cfg.hw_mode);
17936 		 */
17937 	}
17938 
17939 	mac_handle = hdd_ctx->mac_handle;
17940 	switch (reason) {
17941 	/* SAP init case */
17942 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
17943 		hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
17944 		/* Update Hostapd */
17945 		wlan_hdd_cfg80211_acs_ch_select_evt(link_info, true);
17946 		break;
17947 
17948 	/* DFS detected on current channel */
17949 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
17950 		ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
17951 					   channel_list->pri_chan_freq);
17952 
17953 		wlan_sap_update_next_channel(
17954 			WLAN_HDD_GET_SAP_CTX_PTR(link_info), (uint8_t)ch,
17955 			hdd_map_nl_chan_width(channel_list->chan_width));
17956 		status = sme_update_new_channel_event(
17957 					mac_handle, link_info->vdev_id);
17958 		break;
17959 
17960 	/* LTE coex event on current channel */
17961 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
17962 		ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
17963 					   channel_list->pri_chan_freq);
17964 		sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
17965 		sap_config->acs_cfg.ch_width =
17966 				hdd_map_nl_chan_width(channel_list->chan_width);
17967 		hdd_ap_ctx->sap_config.ch_width_orig =
17968 				sap_config->acs_cfg.ch_width;
17969 		wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc,
17970 					    link_info->vdev_id,
17971 					    CSA_REASON_LTE_COEX);
17972 		hdd_switch_sap_channel(link_info, (uint8_t)ch, true);
17973 		break;
17974 
17975 	default:
17976 		hdd_info("invalid reason for timer invoke");
17977 	}
17978 	hdd_exit();
17979 	return qdf_status_to_os_return(status);
17980 }
17981 
17982 /*
17983  * Define short name for vendor channel set config
17984  */
17985 #define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
17986 #define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
17987 #define SET_CHAN_PRIMARY_CHANNEL \
17988 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
17989 #define SET_CHAN_SECONDARY_CHANNEL \
17990 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
17991 #define SET_CHAN_SEG0_CENTER_CHANNEL \
17992 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
17993 #define	SET_CHAN_SEG1_CENTER_CHANNEL \
17994 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
17995 #define	SET_CHAN_CHANNEL_WIDTH \
17996 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
17997 
17998 #define SET_CHAN_FREQ_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST
17999 #define SET_CHAN_FREQUENCY_PRIMARY \
18000 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY
18001 #define SET_CHAN_FREQUENCY_SECONDARY \
18002 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY
18003 #define SET_CHAN_SEG0_CENTER_FREQUENCY \
18004 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0
18005 #define SET_CHAN_SEG1_CENTER_FREQUENCY \
18006 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1
18007 
18008 #define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
18009 #define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
18010 
18011 static const struct nla_policy acs_chan_config_policy[SET_CHAN_MAX + 1] = {
18012 	[SET_CHAN_REASON] = {.type = NLA_U8},
18013 	[SET_CHAN_CHAN_LIST] = {.type = NLA_NESTED},
18014 	[SET_CHAN_FREQ_LIST] = {.type = NLA_NESTED},
18015 };
18016 
18017 static const struct nla_policy acs_chan_list_policy[SET_CHAN_MAX + 1] = {
18018 	[SET_CHAN_PRIMARY_CHANNEL] = {.type = NLA_U8},
18019 	[SET_CHAN_SECONDARY_CHANNEL] = {.type = NLA_U8},
18020 	[SET_CHAN_SEG0_CENTER_CHANNEL] = {.type = NLA_U8},
18021 	[SET_CHAN_SEG1_CENTER_CHANNEL] = {.type = NLA_U8},
18022 	[SET_CHAN_CHANNEL_WIDTH] = {.type = NLA_U8},
18023 	[SET_EXT_ACS_BAND] = {.type = NLA_U8},
18024 
18025 	[SET_CHAN_FREQUENCY_PRIMARY] = {.type = NLA_U32},
18026 	[SET_CHAN_FREQUENCY_SECONDARY] = {.type = NLA_U32},
18027 	[SET_CHAN_SEG0_CENTER_FREQUENCY] = {.type = NLA_U32},
18028 	[SET_CHAN_SEG1_CENTER_FREQUENCY] = {.type = NLA_U32},
18029 };
18030 
18031 /**
18032  * hdd_extract_external_acs_frequencies() - API to parse and extract vendor acs
18033  * channel frequency (in MHz) configuration.
18034  * @hdd_ctx: pointer to hdd context
18035  * @list_ptr: pointer to hdd_vendor_chan_info
18036  * @channel_cnt: channel count
18037  * @data: data
18038  * @data_len: data len
18039  *
18040  * Return: 0 on success, negative errno on failure
18041  */
18042 static int
hdd_extract_external_acs_frequencies(struct hdd_context * hdd_ctx,struct hdd_vendor_chan_info ** list_ptr,uint8_t * channel_cnt,const void * data,int data_len)18043 hdd_extract_external_acs_frequencies(struct hdd_context *hdd_ctx,
18044 				     struct hdd_vendor_chan_info **list_ptr,
18045 				     uint8_t *channel_cnt,
18046 				     const void *data, int data_len)
18047 {
18048 	int rem;
18049 	uint32_t i = 0;
18050 	struct nlattr *tb[SET_CHAN_MAX + 1];
18051 	struct nlattr *tb2[SET_CHAN_MAX + 1];
18052 	struct nlattr *curr_attr;
18053 	struct hdd_vendor_chan_info *channel_list;
18054 
18055 	if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
18056 				    acs_chan_config_policy)) {
18057 		hdd_err("Invalid ATTR");
18058 		return -EINVAL;
18059 	}
18060 
18061 	nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem)
18062 		i++;
18063 
18064 	if (!i) {
18065 		hdd_err_rl("Error: channel count is zero");
18066 		return -EINVAL;
18067 	}
18068 
18069 	if (i > NUM_CHANNELS) {
18070 		hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
18071 		return -ENOMEM;
18072 	}
18073 
18074 	channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
18075 	if (!channel_list)
18076 		return -ENOMEM;
18077 
18078 	*channel_cnt = (uint8_t)i;
18079 	i = 0;
18080 	nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem) {
18081 		if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
18082 						   curr_attr,
18083 						   acs_chan_list_policy)) {
18084 			hdd_err_rl("nla_parse failed");
18085 			qdf_mem_free(channel_list);
18086 			*channel_cnt = 0;
18087 			return -EINVAL;
18088 		}
18089 
18090 		if (tb2[SET_EXT_ACS_BAND])
18091 			channel_list[i].band =
18092 				nla_get_u8(tb2[SET_EXT_ACS_BAND]);
18093 
18094 		if (tb2[SET_CHAN_FREQUENCY_PRIMARY])
18095 			channel_list[i].pri_chan_freq =
18096 				nla_get_u32(tb2[SET_CHAN_FREQUENCY_PRIMARY]);
18097 
18098 		if (tb2[SET_CHAN_FREQUENCY_SECONDARY])
18099 			channel_list[i].ht_sec_chan_freq =
18100 				nla_get_u32(tb2[SET_CHAN_FREQUENCY_SECONDARY]);
18101 
18102 		if (tb2[SET_CHAN_SEG0_CENTER_FREQUENCY])
18103 			channel_list[i].vht_seg0_center_chan_freq =
18104 			 nla_get_u32(tb2[SET_CHAN_SEG0_CENTER_FREQUENCY]);
18105 
18106 		if (tb2[SET_CHAN_SEG1_CENTER_FREQUENCY])
18107 			channel_list[i].vht_seg1_center_chan_freq =
18108 			 nla_get_u32(tb2[SET_CHAN_SEG1_CENTER_FREQUENCY]);
18109 
18110 		if (tb2[SET_CHAN_CHANNEL_WIDTH])
18111 			channel_list[i].chan_width =
18112 				nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
18113 
18114 		hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
18115 			  i, channel_list[i].pri_chan_freq,
18116 			  channel_list[i].ht_sec_chan_freq,
18117 			  channel_list[i].vht_seg0_center_chan_freq,
18118 			  channel_list[i].vht_seg1_center_chan_freq,
18119 			  channel_list[i].chan_width);
18120 		i++;
18121 	}
18122 	*list_ptr = channel_list;
18123 
18124 	return 0;
18125 }
18126 
18127 /**
18128  * hdd_extract_external_acs_channels() - API to parse and extract vendor acs
18129  * channel configuration.
18130  * @hdd_ctx: pointer to hdd context
18131  * @list_ptr: pointer to hdd_vendor_chan_info
18132  * @channel_cnt: channel count
18133  * @data: data
18134  * @data_len: data len
18135  *
18136  * Return: 0 on success, negative errno on failure
18137  */
18138 static int
hdd_extract_external_acs_channels(struct hdd_context * hdd_ctx,struct hdd_vendor_chan_info ** list_ptr,uint8_t * channel_cnt,const void * data,int data_len)18139 hdd_extract_external_acs_channels(struct hdd_context *hdd_ctx,
18140 				  struct hdd_vendor_chan_info **list_ptr,
18141 				  uint8_t *channel_cnt,
18142 				  const void *data, int data_len)
18143 {
18144 	int rem;
18145 	uint32_t i = 0;
18146 	struct nlattr *tb[SET_CHAN_MAX + 1];
18147 	struct nlattr *tb2[SET_CHAN_MAX + 1];
18148 	struct nlattr *curr_attr;
18149 	struct hdd_vendor_chan_info *channel_list;
18150 
18151 	if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
18152 				    acs_chan_config_policy)) {
18153 		hdd_err("Invalid ATTR");
18154 		return -EINVAL;
18155 	}
18156 
18157 	nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
18158 		i++;
18159 
18160 	if (!i) {
18161 		hdd_err_rl("Error: channel count is zero");
18162 		return -EINVAL;
18163 	}
18164 
18165 	if (i > NUM_CHANNELS) {
18166 		hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
18167 		return -ENOMEM;
18168 	}
18169 
18170 	channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
18171 	if (!channel_list)
18172 		return -ENOMEM;
18173 
18174 	*channel_cnt = (uint8_t)i;
18175 	i = 0;
18176 	nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
18177 		if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
18178 						   curr_attr,
18179 						   acs_chan_list_policy)) {
18180 			hdd_err("nla_parse failed");
18181 			qdf_mem_free(channel_list);
18182 			*channel_cnt = 0;
18183 			return -EINVAL;
18184 		}
18185 
18186 		if (tb2[SET_EXT_ACS_BAND]) {
18187 			channel_list[i].band =
18188 				nla_get_u8(tb2[SET_EXT_ACS_BAND]);
18189 		}
18190 
18191 		if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
18192 			uint32_t ch =
18193 				nla_get_u8(tb2[SET_CHAN_PRIMARY_CHANNEL]);
18194 
18195 			channel_list[i].pri_chan_freq =
18196 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
18197 		}
18198 
18199 		if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
18200 			uint32_t ch =
18201 				nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
18202 
18203 			channel_list[i].ht_sec_chan_freq =
18204 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
18205 		}
18206 
18207 		if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
18208 			uint32_t ch =
18209 				nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
18210 
18211 			channel_list[i].vht_seg0_center_chan_freq =
18212 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
18213 		}
18214 
18215 		if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
18216 			uint32_t ch =
18217 				nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
18218 
18219 			channel_list[i].vht_seg1_center_chan_freq =
18220 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
18221 		}
18222 
18223 		if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
18224 			channel_list[i].chan_width =
18225 				nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
18226 		}
18227 		hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
18228 			  i, channel_list[i].pri_chan_freq,
18229 			  channel_list[i].ht_sec_chan_freq,
18230 			  channel_list[i].vht_seg0_center_chan_freq,
18231 			  channel_list[i].vht_seg1_center_chan_freq,
18232 			  channel_list[i].chan_width);
18233 		i++;
18234 	}
18235 	*list_ptr = channel_list;
18236 
18237 	return 0;
18238 }
18239 
18240 /**
18241  * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
18242  * @hdd_ctx: pointer to hdd context
18243  * @chan_list_ptr: pointer to hdd_vendor_chan_info
18244  * @reason: channel change reason
18245  * @channel_cnt: channel count
18246  * @data: data
18247  * @data_len: data len
18248  *
18249  * Return: 0 on success, negative errno on failure
18250  */
18251 static int
hdd_parse_vendor_acs_chan_config(struct hdd_context * hdd_ctx,struct hdd_vendor_chan_info ** chan_list_ptr,uint8_t * reason,uint8_t * channel_cnt,const void * data,int data_len)18252 hdd_parse_vendor_acs_chan_config(struct hdd_context *hdd_ctx,
18253 				 struct hdd_vendor_chan_info **chan_list_ptr,
18254 				 uint8_t *reason, uint8_t *channel_cnt,
18255 				 const void *data, int data_len)
18256 {
18257 	struct nlattr *tb[SET_CHAN_MAX + 1];
18258 	int ret;
18259 
18260 	if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
18261 				    acs_chan_config_policy)) {
18262 		hdd_err("Invalid ATTR");
18263 		return -EINVAL;
18264 	}
18265 
18266 	if (tb[SET_CHAN_REASON])
18267 		*reason = nla_get_u8(tb[SET_CHAN_REASON]);
18268 
18269 	if (!tb[SET_CHAN_FREQ_LIST] && !tb[SET_CHAN_CHAN_LIST]) {
18270 		hdd_err("Both channel list and frequency list are empty");
18271 		return -EINVAL;
18272 	}
18273 
18274 	if (tb[SET_CHAN_FREQ_LIST]) {
18275 		ret = hdd_extract_external_acs_frequencies(hdd_ctx,
18276 							   chan_list_ptr,
18277 							   channel_cnt,
18278 							   data, data_len);
18279 		if (ret) {
18280 			hdd_err("Failed to extract frequencies");
18281 			return ret;
18282 		}
18283 
18284 		return 0;
18285 	}
18286 
18287 	ret = hdd_extract_external_acs_channels(hdd_ctx, chan_list_ptr,
18288 						channel_cnt, data, data_len);
18289 	if (ret)
18290 		hdd_err("Failed to extract channels");
18291 
18292 	return ret;
18293 }
18294 
18295 /*
18296  * Undef short names for vendor set channel configuration
18297  */
18298 #undef SET_CHAN_REASON
18299 #undef SET_CHAN_CHAN_LIST
18300 #undef SET_CHAN_PRIMARY_CHANNEL
18301 #undef SET_CHAN_SECONDARY_CHANNEL
18302 #undef SET_CHAN_SEG0_CENTER_CHANNEL
18303 #undef SET_CHAN_SEG1_CENTER_CHANNEL
18304 
18305 #undef SET_CHAN_FREQ_LIST
18306 #undef SET_CHAN_FREQUENCY_PRIMARY
18307 #undef SET_CHAN_FREQUENCY_SECONDARY
18308 #undef SET_CHAN_SEG0_CENTER_FREQUENCY
18309 #undef SET_CHAN_SEG1_CENTER_FREQUENCY
18310 
18311 #undef SET_CHAN_CHANNEL_WIDTH
18312 #undef SET_CHAN_MAX
18313 
18314 /**
18315  * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
18316  * @wiphy: Pointer to wireless phy
18317  * @wdev: Pointer to wireless device
18318  * @data: Pointer to data
18319  * @data_len: Length of @data
18320  *
18321  * Return: 0 on success, negative errno on failure
18322  */
__wlan_hdd_cfg80211_update_vendor_channel(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18323 static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
18324 						     struct wireless_dev *wdev,
18325 						     const void *data,
18326 						     int data_len)
18327 {
18328 	int ret_val;
18329 	QDF_STATUS status;
18330 	enum phy_ch_width phy_ch_width;
18331 	uint8_t channel_cnt = 0, reason = -1;
18332 	struct hdd_vendor_chan_info *chan_list = NULL;
18333 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
18334 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18335 	struct hdd_vendor_chan_info *chan_list_ptr;
18336 	struct wlan_hdd_link_info *link_info = adapter->deflink;
18337 
18338 	hdd_enter();
18339 
18340 	ret_val = wlan_hdd_validate_context(hdd_ctx);
18341 	if (ret_val)
18342 		return ret_val;
18343 
18344 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
18345 		hdd_err("Command not allowed in FTM mode");
18346 		return -EINVAL;
18347 	}
18348 
18349 	if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &link_info->link_flags)) {
18350 		clear_bit(VENDOR_ACS_RESPONSE_PENDING, &link_info->link_flags);
18351 	} else {
18352 		hdd_err("already timeout happened for acs");
18353 		return -EINVAL;
18354 	}
18355 
18356 	ret_val = hdd_parse_vendor_acs_chan_config(hdd_ctx, &chan_list,
18357 						   &reason, &channel_cnt, data,
18358 						   data_len);
18359 	chan_list_ptr = chan_list;
18360 	if (ret_val)
18361 		return ret_val;
18362 
18363 	/* Validate channel to be set */
18364 	while (channel_cnt && chan_list) {
18365 		phy_ch_width = hdd_map_nl_chan_width(chan_list->chan_width);
18366 		status = wlan_hdd_validate_acs_channel(link_info,
18367 						       chan_list->pri_chan_freq,
18368 						       phy_ch_width);
18369 		if (status == QDF_STATUS_SUCCESS)
18370 			break;
18371 		else if (channel_cnt == 1) {
18372 			hdd_err("invalid channel frequ %u received from app",
18373 				chan_list->pri_chan_freq);
18374 			chan_list->pri_chan_freq = 0;
18375 			break;
18376 		}
18377 
18378 		channel_cnt--;
18379 		chan_list++;
18380 	}
18381 
18382 	if ((channel_cnt <= 0) || !chan_list) {
18383 		hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
18384 			chan_list);
18385 		qdf_mem_free(chan_list_ptr);
18386 		return -EINVAL;
18387 	}
18388 
18389 	hdd_debug("received primary channel freq as %d",
18390 		  chan_list->pri_chan_freq);
18391 
18392 	ret_val = hdd_update_acs_channel(link_info, reason,
18393 					 channel_cnt, chan_list);
18394 	qdf_mem_free(chan_list_ptr);
18395 	return ret_val;
18396 }
18397 
18398 /**
18399  * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
18400  * @wiphy: Pointer to wireless phy
18401  * @wdev: Pointer to wireless device
18402  * @data: Pointer to data
18403  * @data_len: Length of @data
18404  *
18405  * Return: 0 on success, negative errno on failure
18406  */
wlan_hdd_cfg80211_update_vendor_channel(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18407 static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
18408 						struct wireless_dev *wdev,
18409 						const void *data, int data_len)
18410 {
18411 	int errno;
18412 	struct osif_vdev_sync *vdev_sync;
18413 
18414 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18415 	if (errno)
18416 		return errno;
18417 
18418 	errno = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev,
18419 							  data, data_len);
18420 
18421 	osif_vdev_sync_op_stop(vdev_sync);
18422 
18423 	return errno;
18424 }
18425 
18426 /**
18427  * wlan_hdd_cfg80211_setband() - Wrapper to setband
18428  * @wiphy:    wiphy structure pointer
18429  * @wdev:     Wireless device structure pointer
18430  * @data:     Pointer to the data received
18431  * @data_len: Length of @data
18432  *
18433  * Return: 0 on success; errno on failure
18434  */
wlan_hdd_cfg80211_setband(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18435 static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
18436 				    struct wireless_dev *wdev,
18437 				    const void *data, int data_len)
18438 {
18439 	int errno;
18440 	struct osif_vdev_sync *vdev_sync;
18441 
18442 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18443 	if (errno)
18444 		return errno;
18445 
18446 	errno = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
18447 
18448 	osif_vdev_sync_op_stop(vdev_sync);
18449 
18450 	return errno;
18451 }
18452 
18453 /**
18454  *__wlan_hdd_cfg80211_getband() - get band
18455  * @wiphy: Pointer to wireless phy
18456  * @wdev: Pointer to wireless device
18457  * @data: Pointer to data
18458  * @data_len: Length of @data
18459  *
18460  * Return: 0 on success, negative errno on failure
18461  */
__wlan_hdd_cfg80211_getband(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18462 static int __wlan_hdd_cfg80211_getband(struct wiphy *wiphy,
18463 				       struct wireless_dev *wdev,
18464 				       const void *data, int data_len)
18465 {
18466 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18467 	struct sk_buff *skb;
18468 	QDF_STATUS status = QDF_STATUS_SUCCESS;
18469 	int ret;
18470 	uint32_t reg_wifi_band_bitmap, vendor_band_mask;
18471 
18472 	hdd_enter();
18473 
18474 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18475 		hdd_err("Command not allowed in FTM mode");
18476 		return -EPERM;
18477 	}
18478 
18479 	ret = wlan_hdd_validate_context(hdd_ctx);
18480 	if (ret)
18481 		return ret;
18482 
18483 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
18484 						       sizeof(uint32_t) +
18485 						       NLA_HDRLEN);
18486 
18487 	if (!skb) {
18488 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
18489 		return -ENOMEM;
18490 	}
18491 
18492 	status = ucfg_reg_get_band(hdd_ctx->pdev, &reg_wifi_band_bitmap);
18493 	if (!QDF_IS_STATUS_SUCCESS(status)) {
18494 		hdd_err("failed to get band");
18495 		goto failure;
18496 	}
18497 
18498 	vendor_band_mask = wlan_reg_wifi_band_bitmap_to_vendor_bitmap(
18499 							reg_wifi_band_bitmap);
18500 
18501 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SETBAND_MASK,
18502 			vendor_band_mask)) {
18503 		hdd_err("nla put failure");
18504 		goto failure;
18505 	}
18506 
18507 	wlan_cfg80211_vendor_cmd_reply(skb);
18508 
18509 	hdd_exit();
18510 
18511 	return 0;
18512 
18513 failure:
18514 	wlan_cfg80211_vendor_free_skb(skb);
18515 	return -EINVAL;
18516 }
18517 
18518 /**
18519  * wlan_hdd_cfg80211_getband() - Wrapper to getband
18520  * @wiphy:    wiphy structure pointer
18521  * @wdev:     Wireless device structure pointer
18522  * @data:     Pointer to the data received
18523  * @data_len: Length of @data
18524  *
18525  * Return: 0 on success; errno on failure
18526  */
wlan_hdd_cfg80211_getband(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18527 static int wlan_hdd_cfg80211_getband(struct wiphy *wiphy,
18528 				     struct wireless_dev *wdev,
18529 				     const void *data, int data_len)
18530 {
18531 	int errno;
18532 	struct osif_vdev_sync *vdev_sync;
18533 
18534 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18535 	if (errno)
18536 		return errno;
18537 
18538 	errno = __wlan_hdd_cfg80211_getband(wiphy, wdev, data, data_len);
18539 
18540 	osif_vdev_sync_op_stop(vdev_sync);
18541 
18542 	return errno;
18543 }
18544 
18545 static const struct
18546 nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
18547 	[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
18548 	[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]       = {.type = NLA_BINARY,
18549 						 .len = QDF_MAC_ADDR_SIZE},
18550 };
18551 
wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,struct rso_cmd_status * rso_status)18552 void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
18553 				struct rso_cmd_status *rso_status)
18554 {
18555 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
18556 	struct wlan_hdd_link_info *link_info;
18557 
18558 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, rso_status->vdev_id);
18559 	if (!link_info) {
18560 		hdd_err("Invalid vdev");
18561 		return;
18562 	}
18563 
18564 	link_info->adapter->lfr_fw_status.is_disabled = rso_status->status;
18565 	complete(&link_info->adapter->lfr_fw_status.disable_lfr_event);
18566 }
18567 
18568 /**
18569  * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
18570  * @wiphy: Pointer to wireless phy
18571  * @wdev: Pointer to wireless device
18572  * @data: Pointer to data
18573  * @data_len: Length of @data
18574  *
18575  * This function is used to enable/disable roaming using vendor commands
18576  *
18577  * Return: 0 on success, negative errno on failure
18578  */
__wlan_hdd_cfg80211_set_fast_roaming(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18579 static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
18580 						struct wireless_dev *wdev,
18581 						const void *data, int data_len)
18582 {
18583 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18584 	struct net_device *dev = wdev->netdev;
18585 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18586 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
18587 	uint32_t is_fast_roam_enabled;
18588 	int ret;
18589 	QDF_STATUS qdf_status;
18590 	unsigned long rc;
18591 	bool roaming_enabled;
18592 
18593 	hdd_enter_dev(dev);
18594 
18595 	ret = wlan_hdd_validate_context(hdd_ctx);
18596 	if (0 != ret)
18597 		return ret;
18598 
18599 	if (adapter->device_mode != QDF_STA_MODE) {
18600 		hdd_err_rl("command not allowed in %d mode, vdev_id: %d",
18601 			   adapter->device_mode, adapter->deflink->vdev_id);
18602 		return -EINVAL;
18603 	}
18604 
18605 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18606 		hdd_err("Command not allowed in FTM mode");
18607 		return -EINVAL;
18608 	}
18609 
18610 	ret = wlan_cfg80211_nla_parse(tb,
18611 				      QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
18612 				      qca_wlan_vendor_attr);
18613 	if (ret) {
18614 		hdd_err("Invalid ATTR");
18615 		return -EINVAL;
18616 	}
18617 
18618 	/* Parse and fetch Enable flag */
18619 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
18620 		hdd_err("attr enable failed");
18621 		return -EINVAL;
18622 	}
18623 
18624 	is_fast_roam_enabled = nla_get_u32(
18625 				tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
18626 	hdd_debug("ROAM_CONFIG: isFastRoamEnabled %d", is_fast_roam_enabled);
18627 
18628 	if (sme_roaming_in_progress(hdd_ctx->mac_handle,
18629 				    adapter->deflink->vdev_id)) {
18630 		hdd_err_rl("Roaming in progress for vdev %d",
18631 			   adapter->deflink->vdev_id);
18632 		return -EAGAIN;
18633 	}
18634 
18635 	/*
18636 	 * Get current roaming state and decide whether to wait for RSO_STOP
18637 	 * response or not.
18638 	 */
18639 	roaming_enabled = ucfg_is_rso_enabled(hdd_ctx->pdev,
18640 					      adapter->deflink->vdev_id);
18641 
18642 	/* Update roaming */
18643 	qdf_status = ucfg_user_space_enable_disable_rso(
18644 						hdd_ctx->pdev,
18645 						adapter->deflink->vdev_id,
18646 						is_fast_roam_enabled);
18647 	if (QDF_IS_STATUS_ERROR(qdf_status))
18648 		hdd_err("ROAM_CONFIG: sme_config_fast_roaming failed with status=%d",
18649 			qdf_status);
18650 
18651 	ret = qdf_status_to_os_return(qdf_status);
18652 
18653 	if (hdd_cm_is_vdev_associated(adapter->deflink) &&
18654 	    roaming_enabled &&
18655 	    QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
18656 		INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
18657 		/*
18658 		 * wait only for LFR disable in fw as LFR enable
18659 		 * is always success
18660 		 */
18661 		rc = wait_for_completion_timeout(
18662 				&adapter->lfr_fw_status.disable_lfr_event,
18663 				msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
18664 		if (!rc) {
18665 			hdd_err("Timed out waiting for RSO CMD status");
18666 			return -ETIMEDOUT;
18667 		}
18668 
18669 		if (!adapter->lfr_fw_status.is_disabled) {
18670 			hdd_err("Roam disable attempt in FW fails");
18671 			return -EBUSY;
18672 		}
18673 	}
18674 
18675 	hdd_exit();
18676 	return ret;
18677 }
18678 
18679 /**
18680  * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
18681  * @wiphy: Pointer to wireless phy
18682  * @wdev: Pointer to wireless device
18683  * @data: Pointer to data
18684  * @data_len: Length of @data
18685  *
18686  * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
18687  *
18688  * Return: 0 on success, negative errno on failure
18689  */
wlan_hdd_cfg80211_set_fast_roaming(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18690 static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
18691 					  struct wireless_dev *wdev,
18692 					  const void *data, int data_len)
18693 {
18694 	int errno;
18695 	struct osif_vdev_sync *vdev_sync;
18696 
18697 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18698 	if (errno)
18699 		return errno;
18700 
18701 	errno = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev,
18702 						     data, data_len);
18703 
18704 	osif_vdev_sync_op_stop(vdev_sync);
18705 
18706 	return errno;
18707 }
18708 
18709 /*
18710  * define short names for the global vendor params
18711  * used by wlan_hdd_cfg80211_setarp_stats_cmd()
18712  */
18713 #define STATS_SET_INVALID \
18714 	QCA_ATTR_NUD_STATS_SET_INVALID
18715 #define STATS_SET_START \
18716 	QCA_ATTR_NUD_STATS_SET_START
18717 #define STATS_GW_IPV4 \
18718 	QCA_ATTR_NUD_STATS_GW_IPV4
18719 #define STATS_SET_DATA_PKT_INFO \
18720 		QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
18721 #define STATS_SET_MAX \
18722 	QCA_ATTR_NUD_STATS_SET_MAX
18723 
18724 const struct nla_policy
18725 qca_wlan_vendor_set_nud_stats_policy[STATS_SET_MAX + 1] = {
18726 	[STATS_SET_START] = {.type = NLA_FLAG },
18727 	[STATS_GW_IPV4] = {.type = NLA_U32 },
18728 	[STATS_SET_DATA_PKT_INFO] = {.type = NLA_NESTED },
18729 };
18730 
18731 /* define short names for the global vendor params */
18732 #define CONNECTIVITY_STATS_SET_INVALID \
18733 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
18734 #define STATS_PKT_INFO_TYPE \
18735 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
18736 #define STATS_DNS_DOMAIN_NAME \
18737 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
18738 #define STATS_SRC_PORT \
18739 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
18740 #define STATS_DEST_PORT \
18741 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
18742 #define STATS_DEST_IPV4 \
18743 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
18744 #define STATS_DEST_IPV6 \
18745 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
18746 #define CONNECTIVITY_STATS_SET_MAX \
18747 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
18748 
18749 const struct nla_policy
18750 qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
18751 	[STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
18752 	[STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
18753 					.len = DNS_DOMAIN_NAME_MAX_LEN },
18754 	[STATS_SRC_PORT] = {.type = NLA_U32 },
18755 	[STATS_DEST_PORT] = {.type = NLA_U32 },
18756 	[STATS_DEST_IPV4] = {.type = NLA_U32 },
18757 	[STATS_DEST_IPV6] = {.type = NLA_BINARY,
18758 					.len = ICMPv6_ADDR_LEN },
18759 };
18760 
18761 const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
18762 		QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
18763 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] =
18764 	VENDOR_NLA_POLICY_NESTED(qca_wlan_vendor_set_trace_level_policy),
18765 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
18766 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
18767 };
18768 
18769 /**
18770  * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
18771  * @wiphy: Pointer to wireless phy
18772  * @wdev: Pointer to wireless device
18773  * @data: Pointer to data
18774  * @data_len: Length of @data
18775  *
18776  * Return: 0 on success, negative errno on failure
18777  */
18778 static int
__wlan_hdd_cfg80211_set_trace_level(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18779 __wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
18780 					struct wireless_dev *wdev,
18781 					const void *data,
18782 					int data_len)
18783 {
18784 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18785 	struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
18786 	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
18787 	struct nlattr *apth;
18788 	int rem;
18789 	int ret = 1;
18790 	int print_idx = -1;
18791 	int module_id = -1;
18792 	int bit_mask = -1;
18793 	int status;
18794 
18795 	hdd_enter();
18796 
18797 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
18798 		hdd_err("Command not allowed in FTM mode");
18799 		return -EINVAL;
18800 	}
18801 
18802 	ret = wlan_hdd_validate_context(hdd_ctx);
18803 	if (ret != 0)
18804 		return -EINVAL;
18805 
18806 	print_idx = qdf_get_pidx();
18807 	if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
18808 		hdd_err("Invalid print control object index");
18809 		return -EINVAL;
18810 	}
18811 
18812 	if (wlan_cfg80211_nla_parse(tb1,
18813 				    QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
18814 				    data, data_len,
18815 				    qca_wlan_vendor_set_trace_level_policy)) {
18816 		hdd_err("Invalid attr");
18817 		return -EINVAL;
18818 	}
18819 
18820 	if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
18821 		hdd_err("attr trace level param failed");
18822 		return -EINVAL;
18823 	}
18824 
18825 	nla_for_each_nested(apth,
18826 			tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
18827 		if (wlan_cfg80211_nla_parse(tb2,
18828 				     QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
18829 				     nla_data(apth), nla_len(apth),
18830 				     qca_wlan_vendor_set_trace_level_policy)) {
18831 			hdd_err("Invalid attr");
18832 			return -EINVAL;
18833 		}
18834 
18835 		if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
18836 			hdd_err("attr Module ID failed");
18837 			return -EINVAL;
18838 		}
18839 		module_id = nla_get_u32
18840 			(tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
18841 
18842 		if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
18843 			hdd_err("attr Verbose mask failed");
18844 			return -EINVAL;
18845 		}
18846 		bit_mask = nla_get_u32
18847 		      (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
18848 
18849 		status = hdd_qdf_trace_enable(module_id, bit_mask);
18850 
18851 		if (status != 0)
18852 			hdd_err("can not set verbose mask %d for the category %d",
18853 				bit_mask, module_id);
18854 	}
18855 
18856 	hdd_exit();
18857 	return ret;
18858 }
18859 
18860 /**
18861  * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
18862  * @wiphy: Pointer to wireless phy
18863  * @wdev: Pointer to wireless device
18864  * @data: Pointer to data
18865  * @data_len: Length of @data
18866  *
18867  * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
18868  *
18869  * Return: 0 on success, negative errno on failure
18870  */
18871 
wlan_hdd_cfg80211_set_trace_level(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18872 static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
18873 						struct wireless_dev *wdev,
18874 						const void *data,
18875 						int data_len)
18876 {
18877 	struct osif_psoc_sync *psoc_sync;
18878 	int errno;
18879 
18880 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
18881 	if (errno)
18882 		return errno;
18883 
18884 	errno = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev,
18885 						    data, data_len);
18886 
18887 	osif_psoc_sync_op_stop(psoc_sync);
18888 
18889 	return errno;
18890 }
18891 
18892 /**
18893  * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
18894  * @wiphy: pointer to wireless wiphy structure.
18895  * @wdev: pointer to wireless_dev structure.
18896  * @data: pointer to apfind configuration data.
18897  * @data_len: the length in byte of apfind data.
18898  *
18899  * This is called when wlan driver needs to send arp stats to
18900  * firmware.
18901  *
18902  * Return: An error code or 0 on success.
18903  */
__wlan_hdd_cfg80211_set_nud_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18904 static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
18905 					     struct wireless_dev *wdev,
18906 					     const void *data, int data_len)
18907 {
18908 	struct net_device   *dev = wdev->netdev;
18909 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18910 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18911 	struct wlan_objmgr_vdev *vdev;
18912 	int err = 0;
18913 
18914 	hdd_enter();
18915 
18916 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18917 		hdd_err("Command not allowed in FTM mode");
18918 		return -EINVAL;
18919 	}
18920 
18921 	err = wlan_hdd_validate_context(hdd_ctx);
18922 	if (0 != err)
18923 		return err;
18924 
18925 	if (adapter->deflink->vdev_id == WLAN_UMAC_VDEV_ID_MAX) {
18926 		hdd_err("Invalid vdev id");
18927 		return -EINVAL;
18928 	}
18929 
18930 	if (adapter->device_mode != QDF_STA_MODE) {
18931 		hdd_err("STATS supported in only STA mode!");
18932 		return -EINVAL;
18933 	}
18934 
18935 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
18936 		hdd_debug("Not Associated");
18937 		return 0;
18938 	}
18939 
18940 	if (hdd_is_roaming_in_progress(hdd_ctx))
18941 		return -EINVAL;
18942 
18943 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
18944 	if (!vdev)
18945 		return -EINVAL;
18946 
18947 	err = osif_dp_set_nud_stats(wiphy, vdev, data, data_len);
18948 
18949 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
18950 
18951 	hdd_exit();
18952 
18953 	return err;
18954 }
18955 
18956 /**
18957  * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
18958  * @wiphy: pointer to wireless wiphy structure.
18959  * @wdev: pointer to wireless_dev structure.
18960  * @data: pointer to apfind configuration data.
18961  * @data_len: the length in byte of apfind data.
18962  *
18963  * This is called when wlan driver needs to send arp stats to
18964  * firmware.
18965  *
18966  * Return: An error code or 0 on success.
18967  */
wlan_hdd_cfg80211_set_nud_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)18968 static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
18969 					   struct wireless_dev *wdev,
18970 					   const void *data, int data_len)
18971 {
18972 	int errno;
18973 	struct osif_vdev_sync *vdev_sync;
18974 
18975 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18976 	if (errno)
18977 		return errno;
18978 
18979 	errno = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
18980 
18981 	osif_vdev_sync_op_stop(vdev_sync);
18982 
18983 	return errno;
18984 }
18985 
18986 #undef STATS_SET_INVALID
18987 #undef STATS_SET_START
18988 #undef STATS_GW_IPV4
18989 #undef STATS_SET_MAX
18990 
18991 /*
18992  * define short names for the global vendor params
18993  * used by wlan_hdd_cfg80211_setarp_stats_cmd()
18994  */
18995 #define STATS_GET_INVALID \
18996 	QCA_ATTR_NUD_STATS_SET_INVALID
18997 #define COUNT_FROM_NETDEV \
18998 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
18999 #define COUNT_TO_LOWER_MAC \
19000 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
19001 #define RX_COUNT_BY_LOWER_MAC \
19002 	QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
19003 #define COUNT_TX_SUCCESS \
19004 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
19005 #define RSP_RX_COUNT_BY_LOWER_MAC \
19006 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
19007 #define RSP_RX_COUNT_BY_UPPER_MAC \
19008 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
19009 #define RSP_COUNT_TO_NETDEV \
19010 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
19011 #define RSP_COUNT_OUT_OF_ORDER_DROP \
19012 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
19013 #define AP_LINK_ACTIVE \
19014 	QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
19015 #define AP_LINK_DAD \
19016 	QCA_ATTR_NUD_STATS_IS_DAD
19017 #define DATA_PKT_STATS \
19018 	QCA_ATTR_NUD_STATS_DATA_PKT_STATS
19019 #define STATS_GET_MAX \
19020 	QCA_ATTR_NUD_STATS_GET_MAX
19021 
19022 #define CHECK_STATS_INVALID \
19023 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
19024 #define CHECK_STATS_PKT_TYPE \
19025 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
19026 #define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
19027 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
19028 #define CHECK_STATS_PKT_SRC_PORT \
19029 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
19030 #define CHECK_STATS_PKT_DEST_PORT \
19031 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
19032 #define CHECK_STATS_PKT_DEST_IPV4 \
19033 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
19034 #define CHECK_STATS_PKT_DEST_IPV6 \
19035 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
19036 #define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
19037 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
19038 #define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
19039 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
19040 #define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
19041 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
19042 #define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
19043 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
19044 #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
19045 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
19046 #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
19047 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
19048 #define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
19049 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
19050 #define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
19051 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
19052 #define CHECK_DATA_STATS_MAX \
19053 	QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
19054 
19055 
19056 const struct nla_policy
19057 qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
19058 	[COUNT_FROM_NETDEV] = {.type = NLA_U16 },
19059 	[COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
19060 	[RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
19061 	[COUNT_TX_SUCCESS] = {.type = NLA_U16 },
19062 	[RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
19063 	[RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
19064 	[RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
19065 	[RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
19066 	[AP_LINK_ACTIVE] = {.type = NLA_FLAG },
19067 	[AP_LINK_DAD] = {.type = NLA_FLAG },
19068 	[DATA_PKT_STATS] = {.type = NLA_U16 },
19069 };
19070 
19071 /**
19072  * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
19073  * @wiphy: pointer to wireless wiphy structure.
19074  * @wdev: pointer to wireless_dev structure.
19075  * @data: pointer to apfind configuration data.
19076  * @data_len: the length in byte of apfind data.
19077  *
19078  * This is called when wlan driver needs to get arp stats to
19079  * firmware.
19080  *
19081  * Return: An error code or 0 on success.
19082  */
__wlan_hdd_cfg80211_get_nud_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)19083 static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
19084 					     struct wireless_dev *wdev,
19085 					     const void *data, int data_len)
19086 {
19087 	int err = 0;
19088 	struct net_device *dev = wdev->netdev;
19089 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19090 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19091 	struct wlan_objmgr_vdev *vdev;
19092 
19093 	hdd_enter();
19094 
19095 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19096 		hdd_err("Command not allowed in FTM mode");
19097 		return -EINVAL;
19098 	}
19099 
19100 	err = wlan_hdd_validate_context(hdd_ctx);
19101 	if (0 != err)
19102 		return err;
19103 
19104 	err = hdd_validate_adapter(adapter);
19105 	if (err)
19106 		return err;
19107 
19108 	if (adapter->device_mode != QDF_STA_MODE) {
19109 		hdd_err("STATS supported in only STA mode!");
19110 		return -EINVAL;
19111 	}
19112 
19113 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
19114 	if (!vdev)
19115 		return -EINVAL;
19116 
19117 	err = osif_dp_get_nud_stats(wiphy, vdev, data, data_len);
19118 
19119 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
19120 
19121 	return err;
19122 }
19123 
19124 /**
19125  * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
19126  * @wiphy: pointer to wireless wiphy structure.
19127  * @wdev: pointer to wireless_dev structure.
19128  * @data: pointer to apfind configuration data.
19129  * @data_len: the length in byte of apfind data.
19130  *
19131  * This is called when wlan driver needs to get arp stats to
19132  * firmware.
19133  *
19134  * Return: An error code or 0 on success.
19135  */
wlan_hdd_cfg80211_get_nud_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)19136 static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
19137 					   struct wireless_dev *wdev,
19138 					   const void *data, int data_len)
19139 {
19140 	int errno;
19141 	struct osif_vdev_sync *vdev_sync;
19142 
19143 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19144 	if (errno)
19145 		return errno;
19146 
19147 	errno = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
19148 
19149 	osif_vdev_sync_op_stop(vdev_sync);
19150 
19151 	return errno;
19152 }
19153 
19154 #undef QCA_ATTR_NUD_STATS_SET_INVALID
19155 #undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
19156 #undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
19157 #undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
19158 #undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
19159 #undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
19160 #undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
19161 #undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
19162 #undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
19163 #undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
19164 #undef QCA_ATTR_NUD_STATS_GET_MAX
19165 
hdd_bt_activity_cb(hdd_handle_t hdd_handle,uint32_t bt_activity)19166 void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity)
19167 {
19168 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
19169 	int status;
19170 
19171 	status = wlan_hdd_validate_context(hdd_ctx);
19172 	if (0 != status)
19173 		return;
19174 
19175 	if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
19176 		hdd_ctx->bt_a2dp_active = 1;
19177 	else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
19178 		hdd_ctx->bt_a2dp_active = 0;
19179 	else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
19180 		hdd_ctx->bt_vo_active = 1;
19181 	else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
19182 		hdd_ctx->bt_vo_active = 0;
19183 	else if (bt_activity == WLAN_COEX_EVENT_BT_PROFILE_CONNECTED)
19184 		hdd_ctx->bt_profile_con = 1;
19185 	else if (bt_activity == WLAN_COEX_EVENT_BT_PROFILE_DISCONNECTED)
19186 		hdd_ctx->bt_profile_con = 0;
19187 	else
19188 		return;
19189 
19190 	ucfg_scan_set_bt_activity(hdd_ctx->psoc, hdd_ctx->bt_a2dp_active);
19191 	ucfg_mlme_set_bt_profile_con(hdd_ctx->psoc, hdd_ctx->bt_profile_con);
19192 	hdd_debug("a2dp_active: %d vo_active: %d connected:%d",
19193 		  hdd_ctx->bt_a2dp_active,
19194 		  hdd_ctx->bt_vo_active, hdd_ctx->bt_profile_con);
19195 }
19196 
19197 /**
19198  * hdd_post_chain_rssi_rsp - send rsp to user space
19199  * @adapter: Pointer to adapter
19200  * @result: chain rssi result
19201  * @update_chain_rssi: update rssi, if this flag is set
19202  * @update_chain_evm: update evm, if this flag is set
19203  * @update_ant_id: update antenna id, if this flag is set
19204  *
19205  * Return: 0 for success, non-zero for failure
19206  */
hdd_post_chain_rssi_rsp(struct hdd_adapter * adapter,struct chain_rssi_result * result,bool update_chain_rssi,bool update_chain_evm,bool update_ant_id)19207 static int hdd_post_chain_rssi_rsp(struct hdd_adapter *adapter,
19208 				   struct chain_rssi_result *result,
19209 				   bool update_chain_rssi,
19210 				   bool update_chain_evm,
19211 				   bool update_ant_id)
19212 {
19213 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
19214 	struct sk_buff *skb;
19215 	int len = NLMSG_HDRLEN;
19216 
19217 	len += update_chain_rssi ?
19218 		nla_total_size(sizeof(result->chain_rssi)) : 0;
19219 	len += update_chain_evm ?
19220 		nla_total_size(sizeof(result->chain_evm)) : 0;
19221 	len += update_ant_id ?
19222 		nla_total_size(sizeof(result->ant_id)) : 0;
19223 
19224 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, len);
19225 	if (!skb) {
19226 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
19227 		return -ENOMEM;
19228 	}
19229 
19230 	if (update_chain_rssi &&
19231 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI,
19232 		    sizeof(result->chain_rssi),
19233 		    result->chain_rssi)) {
19234 		goto nla_put_failure;
19235 	}
19236 
19237 	if (update_chain_evm &&
19238 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_EVM,
19239 		    sizeof(result->chain_evm),
19240 		    result->chain_evm)) {
19241 		goto nla_put_failure;
19242 	}
19243 
19244 	if (update_ant_id &&
19245 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO,
19246 		    sizeof(result->ant_id),
19247 		    result->ant_id)) {
19248 		goto nla_put_failure;
19249 	}
19250 
19251 	wlan_cfg80211_vendor_cmd_reply(skb);
19252 	return 0;
19253 
19254 nla_put_failure:
19255 	hdd_err("nla put fail");
19256 	wlan_cfg80211_vendor_free_skb(skb);
19257 	return -EINVAL;
19258 }
19259 
19260 #ifdef QCA_SUPPORT_CP_STATS
19261 /**
19262  * hdd_process_peer_chain_rssi_req() - fetch per chain rssi of a connected peer
19263  * @adapter: Pointer to adapter
19264  * @peer_macaddr: mac address of desired peer or AP
19265  *
19266  * Return: 0 for success, non-zero for failure
19267  */
hdd_process_peer_chain_rssi_req(struct hdd_adapter * adapter,struct qdf_mac_addr * peer_macaddr)19268 static int hdd_process_peer_chain_rssi_req(struct hdd_adapter *adapter,
19269 					   struct qdf_mac_addr *peer_macaddr)
19270 {
19271 	struct stats_event *stats;
19272 	struct wlan_objmgr_vdev *vdev;
19273 	struct chain_rssi_result chain_rssi;
19274 	int retval, index;
19275 
19276 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
19277 	if (!vdev)
19278 		return -EINVAL;
19279 
19280 	stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(vdev,
19281 							 peer_macaddr->bytes,
19282 							 &retval);
19283 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
19284 
19285 	if (retval || !stats) {
19286 		if (stats)
19287 			wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
19288 		hdd_err("Unable to get chain rssi from fw");
19289 		return retval;
19290 	}
19291 
19292 	for (index = 0; index < WMI_MAX_CHAINS; index++)
19293 		chain_rssi.chain_rssi[index] =
19294 		stats->peer_stats_info_ext->peer_rssi_per_chain[index];
19295 
19296 	wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
19297 
19298 	retval = hdd_post_chain_rssi_rsp(adapter, &chain_rssi,
19299 					 true, false, false);
19300 	if (retval)
19301 		hdd_err("Failed to post chain rssi");
19302 
19303 	return retval;
19304 }
19305 #else
19306 struct chain_rssi_priv {
19307 	struct chain_rssi_result chain_rssi;
19308 };
19309 
19310 /**
19311  * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
19312  * @context: opaque context originally passed to SME. HDD always passes
19313  * a cookie for the request context
19314  * @data: struct for get chain rssi
19315  *
19316  * This function receives the response/data from the lower layer and
19317  * checks to see if the thread is still waiting then post the results to
19318  * upper layer, if the request has timed out then ignore.
19319  *
19320  * Return: None
19321  */
hdd_get_chain_rssi_cb(void * context,struct chain_rssi_result * data)19322 static void hdd_get_chain_rssi_cb(void *context,
19323 				  struct chain_rssi_result *data)
19324 {
19325 	struct osif_request *request;
19326 	struct chain_rssi_priv *priv;
19327 
19328 	hdd_enter();
19329 
19330 	request = osif_request_get(context);
19331 	if (!request) {
19332 		hdd_err("Obsolete request");
19333 		return;
19334 	}
19335 
19336 	priv = osif_request_priv(request);
19337 	priv->chain_rssi = *data;
19338 	osif_request_complete(request);
19339 	osif_request_put(request);
19340 }
19341 
hdd_process_peer_chain_rssi_req(struct hdd_adapter * adapter,struct qdf_mac_addr * peer_macaddr)19342 static int hdd_process_peer_chain_rssi_req(struct hdd_adapter *adapter,
19343 					   struct qdf_mac_addr *peer_macaddr)
19344 {
19345 	mac_handle_t mac_handle;
19346 	struct osif_request *request;
19347 	struct chain_rssi_priv *priv;
19348 	struct get_chain_rssi_req_params req_msg;
19349 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
19350 	QDF_STATUS status;
19351 	int retval;
19352 	void *cookie;
19353 	static const struct osif_request_params params = {
19354 		.priv_size = sizeof(*priv),
19355 		.timeout_ms = WLAN_WAIT_TIME_STATS,
19356 	};
19357 
19358 	memcpy(&req_msg.peer_macaddr, peer_macaddr->bytes, QDF_MAC_ADDR_SIZE);
19359 	req_msg.session_id = adapter->deflink->vdev_id;
19360 
19361 	request = osif_request_alloc(&params);
19362 	if (!request) {
19363 		hdd_err("Request allocation failure");
19364 		return -ENOMEM;
19365 	}
19366 
19367 	cookie = osif_request_cookie(request);
19368 	mac_handle = hdd_ctx->mac_handle;
19369 	status = sme_get_chain_rssi(mac_handle,
19370 				    &req_msg,
19371 				    hdd_get_chain_rssi_cb,
19372 				    cookie);
19373 
19374 	if (status != QDF_STATUS_SUCCESS) {
19375 		hdd_err("Unable to get chain rssi");
19376 		retval = qdf_status_to_os_return(status);
19377 	} else {
19378 		retval = osif_request_wait_for_response(request);
19379 		if (retval) {
19380 			hdd_err("Target response timed out");
19381 		} else {
19382 			priv = osif_request_priv(request);
19383 			retval = hdd_post_chain_rssi_rsp(adapter,
19384 							 &priv->chain_rssi,
19385 							 true, true, true);
19386 			if (retval)
19387 				hdd_err("Failed to post chain rssi");
19388 		}
19389 	}
19390 	osif_request_put(request);
19391 	return retval;
19392 }
19393 #endif
19394 
19395 static const struct
19396 nla_policy get_chain_rssi_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
19397 	[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]       = {.type = NLA_BINARY,
19398 		.len = QDF_MAC_ADDR_SIZE},
19399 };
19400 
19401 static const struct nla_policy
19402 get_chan_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX + 1] = {
19403 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID] = {.type = NLA_U32},
19404 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ] = {.type = NLA_U32},
19405 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ] = {.type = NLA_U32},
19406 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ] = {.type = NLA_U32},
19407 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH] = {.type = NLA_U32},
19408 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK] = {.type = NLA_U32},
19409 };
19410 
19411 static const struct nla_policy
19412 get_usable_channel_policy[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1] = {
19413 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID] = {
19414 		.type = NLA_U32
19415 	},
19416 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK] = {
19417 		.type = NLA_U32
19418 	},
19419 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK] = {
19420 		.type = NLA_U32
19421 	},
19422 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK] = {
19423 		.type = NLA_U32
19424 	},
19425 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO] = {
19426 		.type = NLA_NESTED
19427 	},
19428 };
19429 
19430 #ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
19431 static enum nl80211_chan_width
hdd_convert_phy_bw_to_nl_bw(enum phy_ch_width bw)19432 hdd_convert_phy_bw_to_nl_bw(enum phy_ch_width bw)
19433 {
19434 	switch (bw) {
19435 	case CH_WIDTH_20MHZ:
19436 		return NL80211_CHAN_WIDTH_20;
19437 	case CH_WIDTH_40MHZ:
19438 		return NL80211_CHAN_WIDTH_40;
19439 	case CH_WIDTH_160MHZ:
19440 		return NL80211_CHAN_WIDTH_160;
19441 	case CH_WIDTH_80MHZ:
19442 		return NL80211_CHAN_WIDTH_80;
19443 	case CH_WIDTH_80P80MHZ:
19444 		return NL80211_CHAN_WIDTH_80P80;
19445 	case CH_WIDTH_5MHZ:
19446 		return NL80211_CHAN_WIDTH_5;
19447 	case CH_WIDTH_10MHZ:
19448 		return NL80211_CHAN_WIDTH_10;
19449 #if defined(CFG80211_11BE_BASIC)
19450 	case CH_WIDTH_320MHZ:
19451 		return NL80211_CHAN_WIDTH_320;
19452 #else
19453 	case CH_WIDTH_320MHZ:
19454 		return NL80211_CHAN_WIDTH_20;
19455 #endif
19456 	case CH_WIDTH_INVALID:
19457 	case CH_WIDTH_MAX:
19458 		return NL80211_CHAN_WIDTH_20;
19459 	}
19460 
19461 	return NL80211_CHAN_WIDTH_20;
19462 }
19463 
19464 /**
19465  * hdd_fill_usable_channels_data() - Fill the data requested by userspace
19466  * @skb: SK buffer
19467  * @tb: List of attributes
19468  * @res_msg: structure of usable channel info
19469  * @count: no of usable channels
19470  *
19471  * Get the data corresponding to the attribute list specified in tb and
19472  * update the same to skb by populating the same attributes.
19473  *
19474  * Return: 0 on success; error number on failure
19475  */
19476 static int
hdd_fill_usable_channels_data(struct sk_buff * skb,struct nlattr ** tb,struct get_usable_chan_res_params * res_msg,int count)19477 hdd_fill_usable_channels_data(struct sk_buff *skb, struct nlattr **tb,
19478 			      struct get_usable_chan_res_params *res_msg,
19479 			      int count)
19480 {
19481 	struct nlattr *config, *chan_params;
19482 	uint8_t i, bw, j = 0;
19483 
19484 	config = nla_nest_start(skb,
19485 				QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO);
19486 	if (!config) {
19487 		hdd_err("nla nest start failure");
19488 		return -EINVAL;
19489 	}
19490 	for (i = 0; i < count ; i++) {
19491 		if (!res_msg[i].freq)
19492 			continue;
19493 		chan_params = nla_nest_start(skb, j);
19494 		if (!chan_params)
19495 			return -EINVAL;
19496 		j++;
19497 		bw = hdd_convert_phy_bw_to_nl_bw(res_msg[i].bw);
19498 		if (nla_put_u32(skb,
19499 				QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ,
19500 				res_msg[i].freq) ||
19501 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ,
19502 				res_msg[i].seg0_freq) ||
19503 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ,
19504 				res_msg[i].seg1_freq) ||
19505 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH,
19506 				bw) ||
19507 		    nla_put_u32(skb,
19508 				QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK,
19509 				res_msg[i].iface_mode_mask)) {
19510 			hdd_err("nla put failure");
19511 			return -EINVAL;
19512 		}
19513 
19514 		nla_nest_end(skb, chan_params);
19515 	}
19516 	nla_nest_end(skb, config);
19517 	return 0;
19518 }
19519 
19520 /**
19521  * hdd_get_usable_channel_len() - calculate the length required by skb
19522  * @count: number of usable channels
19523  *
19524  * Find the required length to send usable channel data to upper layer
19525  *
19526  * Return: required len
19527  */
19528 static uint32_t
hdd_get_usable_channel_len(uint32_t count)19529 hdd_get_usable_channel_len(uint32_t count)
19530 {
19531 	uint32_t len = 0;
19532 	struct get_usable_chan_res_params res_msg;
19533 
19534 	len = nla_total_size(sizeof(res_msg.freq)) +
19535 		nla_total_size(sizeof(res_msg.seg0_freq)) +
19536 		nla_total_size(sizeof(res_msg.seg1_freq)) +
19537 		nla_total_size(sizeof(res_msg.bw)) +
19538 		nla_total_size(sizeof(res_msg.iface_mode_mask));
19539 
19540 	return len * count;
19541 }
19542 
19543 /**
19544  * hdd_send_usable_channel() - Send usable channels as vendor cmd reply
19545  * @hdd_ctx: Pointer to hdd context
19546  * @res_msg: pointer to usable channel information
19547  * @count: number of channels
19548  * @tb: List of attributes
19549  *
19550  * Parse the attributes list tb and  get the data corresponding to the
19551  * attributes specified in tb. Send them as a vendor response.
19552  *
19553  * Return: 0 on success; error number on failure
19554  */
19555 static int
hdd_send_usable_channel(struct hdd_context * hdd_ctx,struct get_usable_chan_res_params * res_msg,uint32_t count,struct nlattr ** tb)19556 hdd_send_usable_channel(struct hdd_context *hdd_ctx,
19557 			struct get_usable_chan_res_params *res_msg,
19558 			uint32_t count,
19559 			struct nlattr **tb)
19560 {
19561 	struct sk_buff *skb;
19562 	uint32_t skb_len;
19563 	int status;
19564 
19565 	skb_len = hdd_get_usable_channel_len(count);
19566 	if (!skb_len) {
19567 		hdd_err("No data requested");
19568 		return -EINVAL;
19569 	}
19570 
19571 	skb_len += NLMSG_HDRLEN;
19572 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
19573 	if (!skb) {
19574 		hdd_info("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
19575 		return -ENOMEM;
19576 	}
19577 
19578 	status = hdd_fill_usable_channels_data(skb, tb, res_msg, count);
19579 	if (status)
19580 		goto fail;
19581 
19582 	return wlan_cfg80211_vendor_cmd_reply(skb);
19583 
19584 fail:
19585 	hdd_err("nla put fail");
19586 	wlan_cfg80211_vendor_free_skb(skb);
19587 	return status;
19588 }
19589 
19590 /**
19591  * hdd_get_all_band_mask() - get supported nl80211 bands
19592  *
19593  * Return: supported band mask
19594  */
19595 static uint32_t
hdd_get_all_band_mask(void)19596 hdd_get_all_band_mask(void)
19597 {
19598 	uint32_t band_mask = 0;
19599 
19600 	band_mask =
19601 		(1 << REG_BAND_2G) | (1 << REG_BAND_5G) | (1 << REG_BAND_6G);
19602 
19603 	return band_mask;
19604 }
19605 
19606 /**
19607  * hdd_get_all_iface_mode_mask() - get supported nl80211 iface mode
19608  *
19609  * Return: supported iface mode mask
19610  */
19611 static uint32_t
hdd_get_all_iface_mode_mask(void)19612 hdd_get_all_iface_mode_mask(void)
19613 {
19614 	uint32_t mode_mask = 0;
19615 
19616 	mode_mask = (1 << NL80211_IFTYPE_STATION) |
19617 			(1 << NL80211_IFTYPE_AP) |
19618 			(1 << NL80211_IFTYPE_P2P_GO) |
19619 			(1 << NL80211_IFTYPE_P2P_CLIENT) |
19620 			(1 << NL80211_IFTYPE_P2P_DEVICE) |
19621 			(1 << NL80211_IFTYPE_NAN);
19622 
19623 	return mode_mask;
19624 }
19625 
19626 /**
19627  * hdd_convert_nl80211_to_reg_band_mask() - convert n80211 band to reg band
19628  * @band: nl80211 band
19629  *
19630  * Return: reg band value
19631  */
19632 
19633 static uint32_t
hdd_convert_nl80211_to_reg_band_mask(enum nl80211_band band)19634 hdd_convert_nl80211_to_reg_band_mask(enum nl80211_band band)
19635 {
19636 	uint32_t reg_band = 0;
19637 
19638 	if (band & 1 << NL80211_BAND_2GHZ)
19639 		reg_band |= 1 << REG_BAND_2G;
19640 	if (band & 1 << NL80211_BAND_5GHZ)
19641 		reg_band |= 1 << REG_BAND_5G;
19642 	if (band & 1 << NL80211_BAND_6GHZ)
19643 		reg_band |= 1 << REG_BAND_6G;
19644 	if (band & 1 << NL80211_BAND_60GHZ)
19645 		hdd_err("band: %d not supported", NL80211_BAND_60GHZ);
19646 
19647 	return reg_band;
19648 }
19649 
19650 /**
19651  * __wlan_hdd_cfg80211_get_usable_channel() - get chain rssi
19652  * @wiphy: wiphy pointer
19653  * @wdev: pointer to struct wireless_dev
19654  * @data: pointer to incoming NL vendor data
19655  * @data_len: length of @data
19656  *
19657  * Return: 0 on success; error number otherwise.
19658  */
__wlan_hdd_cfg80211_get_usable_channel(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)19659 static int __wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
19660 						  struct wireless_dev *wdev,
19661 						  const void *data,
19662 						  int data_len)
19663 {
19664 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19665 	struct get_usable_chan_req_params req_msg = {0};
19666 	struct get_usable_chan_res_params *res_msg;
19667 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1];
19668 	int ret = 0;
19669 	uint32_t count = 0;
19670 	QDF_STATUS status;
19671 
19672 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19673 		hdd_err("Command not allowed in FTM mode");
19674 		return -EPERM;
19675 	}
19676 
19677 	ret = wlan_hdd_validate_context(hdd_ctx);
19678 	if (0 != ret)
19679 		return ret;
19680 
19681 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
19682 		hdd_err("Driver Modules are closed");
19683 		return -EINVAL;
19684 	}
19685 
19686 	res_msg = qdf_mem_malloc(NUM_CHANNELS *
19687 				 sizeof(*res_msg));
19688 
19689 	if (!res_msg) {
19690 		hdd_err("res_msg invalid");
19691 		return -EINVAL;
19692 	}
19693 
19694 	if (wlan_cfg80211_nla_parse(
19695 				tb, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX,
19696 				data, data_len, get_usable_channel_policy)) {
19697 		hdd_err("Invalid ATTR");
19698 		ret = -EINVAL;
19699 		goto err;
19700 	}
19701 
19702 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]) {
19703 		hdd_err("band mask not present");
19704 		req_msg.band_mask = hdd_get_all_band_mask();
19705 	} else {
19706 		req_msg.band_mask =
19707 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]);
19708 		if (!req_msg.band_mask)
19709 			req_msg.band_mask = hdd_get_all_band_mask();
19710 		else
19711 			req_msg.band_mask =
19712 			hdd_convert_nl80211_to_reg_band_mask(req_msg.band_mask);
19713 	}
19714 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]) {
19715 		hdd_err("iface mode mask not present");
19716 		req_msg.iface_mode_mask = hdd_get_all_iface_mode_mask();
19717 	} else {
19718 		req_msg.iface_mode_mask = nla_get_u32(
19719 		tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]);
19720 		if (!req_msg.iface_mode_mask)
19721 			req_msg.iface_mode_mask = hdd_get_all_iface_mode_mask();
19722 	}
19723 
19724 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]) {
19725 		hdd_err("usable channels filter mask not present");
19726 		req_msg.filter_mask = 0;
19727 	} else {
19728 		req_msg.filter_mask =
19729 			nla_get_u32(
19730 			tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]);
19731 	}
19732 
19733 	hdd_debug("get usable channel list for band %d mode %d filter %d",
19734 		  req_msg.band_mask, req_msg.iface_mode_mask,
19735 		  req_msg.filter_mask);
19736 
19737 	status = wlan_reg_get_usable_channel(hdd_ctx->pdev, req_msg,
19738 					     res_msg, &count,
19739 					     REG_CURRENT_PWR_MODE);
19740 	if (QDF_STATUS_SUCCESS != status) {
19741 		hdd_err("get usable channel failed %d", status);
19742 		ret = -EINVAL;
19743 		goto err;
19744 	}
19745 	hdd_debug("usable channel count : %d", count);
19746 
19747 	ret = hdd_send_usable_channel(hdd_ctx, res_msg, count, tb);
19748 	if (ret) {
19749 		hdd_err("failed to send usable_channels");
19750 		ret = -EINVAL;
19751 		goto err;
19752 	}
19753 
19754 err:
19755 	qdf_mem_free(res_msg);
19756 	if (ret)
19757 		return ret;
19758 	return qdf_status_to_os_return(status);
19759 }
19760 #endif
19761 
19762 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
19763 /**
19764  * enum roam_stats_set_params - Different types of params to set the roam stats
19765  * @ROAM_RT_STATS_DISABLED:                Roam stats feature disabled
19766  * @ROAM_RT_STATS_ENABLED:                 Roam stats feature enabled
19767  * @ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE: Roam stats enabled in suspend mode
19768  */
19769 enum roam_stats_set_params {
19770 	ROAM_RT_STATS_DISABLED = 0,
19771 	ROAM_RT_STATS_ENABLED = 1,
19772 	ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE = 2,
19773 };
19774 
19775 #define EVENTS_CONFIGURE QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE
19776 #define SUSPEND_STATE    QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE
19777 
19778 static const struct nla_policy
19779 set_roam_events_policy[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX + 1] = {
19780 	[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE] = {.type = NLA_U8},
19781 	[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE] = {.type = NLA_FLAG},
19782 };
19783 
19784 /**
19785  * __wlan_hdd_cfg80211_set_roam_events() - set roam stats
19786  * @wiphy: wiphy pointer
19787  * @wdev: pointer to struct wireless_dev
19788  * @data: pointer to incoming NL vendor data
19789  * @data_len: length of @data
19790  *
19791  * Return: 0 on success; error number otherwise.
19792  */
__wlan_hdd_cfg80211_set_roam_events(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)19793 static int __wlan_hdd_cfg80211_set_roam_events(struct wiphy *wiphy,
19794 					       struct wireless_dev *wdev,
19795 					       const void *data,
19796 					       int data_len)
19797 {
19798 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19799 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
19800 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX + 1];
19801 	QDF_STATUS status;
19802 	int ret;
19803 	uint8_t config, state, param = 0;
19804 
19805 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19806 		hdd_err("Command not allowed in FTM mode");
19807 		return -EPERM;
19808 	}
19809 
19810 	ret = wlan_hdd_validate_context(hdd_ctx);
19811 	if (ret != 0) {
19812 		hdd_err("Invalid hdd_ctx");
19813 		return ret;
19814 	}
19815 
19816 	ret = hdd_validate_adapter(adapter);
19817 	if (ret != 0) {
19818 		hdd_err("Invalid adapter");
19819 		return ret;
19820 	}
19821 
19822 	if (adapter->device_mode != QDF_STA_MODE) {
19823 		hdd_err("STATS supported in only STA mode!");
19824 		return -EINVAL;
19825 	}
19826 
19827 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX,
19828 				    data, data_len, set_roam_events_policy)) {
19829 		hdd_err("Invalid ATTR");
19830 		return -EINVAL;
19831 	}
19832 
19833 	if (!tb[EVENTS_CONFIGURE]) {
19834 		hdd_err("roam events configure not present");
19835 		return -EINVAL;
19836 	}
19837 
19838 	config = nla_get_u8(tb[EVENTS_CONFIGURE]);
19839 	hdd_debug("roam stats configured: %d", config);
19840 
19841 	if (!tb[SUSPEND_STATE]) {
19842 		hdd_debug("suspend state not present");
19843 		param = config ? ROAM_RT_STATS_ENABLED : ROAM_RT_STATS_DISABLED;
19844 	} else if (config == ROAM_RT_STATS_ENABLED) {
19845 		state = nla_get_flag(tb[SUSPEND_STATE]);
19846 		hdd_debug("Suspend state configured: %d", state);
19847 		param = ROAM_RT_STATS_ENABLED |
19848 			ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE;
19849 	}
19850 
19851 	hdd_debug("roam events param: %d", param);
19852 	ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc,
19853 				     param, ROAM_RT_STATS_ENABLE);
19854 
19855 	if (param == (ROAM_RT_STATS_ENABLED |
19856 		      ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE)) {
19857 		ucfg_pmo_enable_wakeup_event(hdd_ctx->psoc,
19858 					     adapter->deflink->vdev_id,
19859 					     WOW_ROAM_STATS_EVENT);
19860 		ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc,
19861 					     ROAM_RT_STATS_ENABLED,
19862 					     ROAM_RT_STATS_SUSPEND_MODE_ENABLE);
19863 	} else if (ucfg_cm_get_roam_rt_stats(hdd_ctx->psoc,
19864 					  ROAM_RT_STATS_SUSPEND_MODE_ENABLE)) {
19865 		ucfg_pmo_disable_wakeup_event(hdd_ctx->psoc,
19866 					      adapter->deflink->vdev_id,
19867 					      WOW_ROAM_STATS_EVENT);
19868 		ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc,
19869 					     ROAM_RT_STATS_DISABLED,
19870 					     ROAM_RT_STATS_SUSPEND_MODE_ENABLE);
19871 	}
19872 
19873 	status = ucfg_cm_roam_send_rt_stats_config(hdd_ctx->pdev,
19874 						   adapter->deflink->vdev_id,
19875 						   param);
19876 
19877 	return qdf_status_to_os_return(status);
19878 }
19879 
19880 #undef EVENTS_CONFIGURE
19881 #undef SUSPEND_STATE
19882 
19883 /**
19884  * wlan_hdd_cfg80211_set_roam_events() - set roam stats
19885  * @wiphy: wiphy pointer
19886  * @wdev: pointer to struct wireless_dev
19887  * @data: pointer to incoming NL vendor data
19888  * @data_len: length of @data
19889  *
19890  * Return: 0 on success; error number otherwise.
19891  */
wlan_hdd_cfg80211_set_roam_events(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)19892 static int wlan_hdd_cfg80211_set_roam_events(struct wiphy *wiphy,
19893 					     struct wireless_dev *wdev,
19894 					     const void *data,
19895 					     int data_len)
19896 {
19897 	int errno;
19898 	struct osif_vdev_sync *vdev_sync;
19899 
19900 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19901 	if (errno)
19902 		return errno;
19903 
19904 	errno = __wlan_hdd_cfg80211_set_roam_events(wiphy, wdev,
19905 						    data, data_len);
19906 
19907 	osif_vdev_sync_op_stop(vdev_sync);
19908 
19909 	return errno;
19910 }
19911 #endif
19912 
19913 /**
19914  * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
19915  * @wiphy: wiphy pointer
19916  * @wdev: pointer to struct wireless_dev
19917  * @data: pointer to incoming NL vendor data
19918  * @data_len: length of @data
19919  *
19920  * Return: 0 on success; error number otherwise.
19921  */
__wlan_hdd_cfg80211_get_chain_rssi(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)19922 static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
19923 					      struct wireless_dev *wdev,
19924 					      const void *data,
19925 					      int data_len)
19926 {
19927 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
19928 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19929 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
19930 	struct qdf_mac_addr peer_macaddr;
19931 	int retval;
19932 
19933 	hdd_enter();
19934 
19935 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19936 		hdd_err("Command not allowed in FTM mode");
19937 		return -EPERM;
19938 	}
19939 
19940 	retval = wlan_hdd_validate_context(hdd_ctx);
19941 	if (0 != retval)
19942 		return retval;
19943 
19944 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
19945 				    data, data_len, get_chain_rssi_policy)) {
19946 		hdd_err("Invalid ATTR");
19947 		return -EINVAL;
19948 	}
19949 
19950 	if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
19951 		hdd_err("attr mac addr failed");
19952 		return -EINVAL;
19953 	}
19954 	if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) != QDF_MAC_ADDR_SIZE) {
19955 		hdd_err("incorrect mac size");
19956 		return -EINVAL;
19957 	}
19958 
19959 	qdf_copy_macaddr(&peer_macaddr,
19960 			 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]));
19961 
19962 	retval = hdd_process_peer_chain_rssi_req(adapter, &peer_macaddr);
19963 	hdd_exit();
19964 	return retval;
19965 }
19966 
19967 #ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
19968 /**
19969  * wlan_hdd_cfg80211_get_usable_channel() - get chain rssi
19970  * @wiphy: wiphy pointer
19971  * @wdev: pointer to struct wireless_dev
19972  * @data: pointer to incoming NL vendor data
19973  * @data_len: length of @data
19974  *
19975  * Return: 0 on success; error number otherwise.
19976  */
wlan_hdd_cfg80211_get_usable_channel(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)19977 static int wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
19978 						struct wireless_dev *wdev,
19979 						const void *data,
19980 						int data_len)
19981 {
19982 	int errno;
19983 	struct osif_vdev_sync *vdev_sync;
19984 
19985 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19986 	if (errno)
19987 		return errno;
19988 
19989 	errno = __wlan_hdd_cfg80211_get_usable_channel(wiphy, wdev,
19990 						       data, data_len);
19991 
19992 	osif_vdev_sync_op_stop(vdev_sync);
19993 
19994 	return errno;
19995 }
19996 #else
wlan_hdd_cfg80211_get_usable_channel(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)19997 static int wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
19998 						struct wireless_dev *wdev,
19999 						const void *data,
20000 						int data_len)
20001 {
20002 	hdd_debug("get usable channel feature not supported");
20003 	return -EPERM;
20004 }
20005 #endif
20006 
20007 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
20008 /**
20009  * os_if_monitor_mode_configure() - Wifi monitor mode configuration
20010  * vendor command
20011  * @adapter: hdd adapter
20012  * @data: Vendor command data buffer
20013  * @data_len: Buffer length
20014  *
20015  * Return: QDF_STATUS
20016  */
20017 static
os_if_monitor_mode_configure(struct hdd_adapter * adapter,const void * data,int data_len)20018 QDF_STATUS os_if_monitor_mode_configure(struct hdd_adapter *adapter,
20019 					const void *data, int data_len)
20020 {
20021 	struct wlan_objmgr_vdev *vdev;
20022 	QDF_STATUS status;
20023 
20024 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
20025 	if (!vdev)
20026 		return QDF_STATUS_E_INVAL;
20027 
20028 	status = os_if_dp_set_lpc_configure(vdev, data, data_len);
20029 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
20030 	return status;
20031 }
20032 
20033 #endif /* WLAN_FEATURE_LOCAL_PKT_CAPTURE */
20034 
20035 #if defined(WLAN_FEATURE_PKT_CAPTURE) || defined(WLAN_FEATURE_LOCAL_PKT_CAPTURE)
20036 
20037 /**
20038  * __wlan_hdd_cfg80211_set_monitor_mode() - Wifi monitor mode configuration
20039  * vendor command
20040  * @wiphy: wiphy device pointer
20041  * @wdev: wireless device pointer
20042  * @data: Vendor command data buffer
20043  * @data_len: Buffer length
20044  *
20045  * Handles .
20046  *
20047  * Return: 0 for Success and negative value for failure
20048  */
20049 static int
__wlan_hdd_cfg80211_set_monitor_mode(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)20050 __wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy,
20051 				     struct wireless_dev *wdev,
20052 				     const void *data, int data_len)
20053 {
20054 	struct net_device *dev = wdev->netdev;
20055 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
20056 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
20057 	int errno;
20058 	QDF_STATUS status;
20059 
20060 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
20061 		hdd_err("Command not allowed in FTM mode");
20062 		return -EPERM;
20063 	}
20064 
20065 	errno = wlan_hdd_validate_context(hdd_ctx);
20066 	if (errno)
20067 		return errno;
20068 
20069 	errno = hdd_validate_adapter(adapter);
20070 	if (errno)
20071 		return errno;
20072 
20073 	if (!(ucfg_pkt_capture_get_mode(hdd_ctx->psoc) ||
20074 	      hdd_is_pkt_capture_mon_enable(adapter) ||
20075 	      ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc)))
20076 		return -EPERM;
20077 
20078 	status = os_if_monitor_mode_configure(adapter, data, data_len);
20079 
20080 	return qdf_status_to_os_return(status);
20081 }
20082 
20083 /**
20084  * wlan_hdd_cfg80211_set_monitor_mode() - set monitor mode
20085  * @wiphy: wiphy pointer
20086  * @wdev: pointer to struct wireless_dev
20087  * @data: pointer to incoming NL vendor data
20088  * @data_len: length of @data
20089  *
20090  * Return: 0 on success; error number otherwise.
20091  */
wlan_hdd_cfg80211_set_monitor_mode(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)20092 static int wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy,
20093 					      struct wireless_dev *wdev,
20094 					      const void *data, int data_len)
20095 {
20096 	int errno;
20097 	struct osif_vdev_sync *vdev_sync;
20098 
20099 	hdd_enter_dev(wdev->netdev);
20100 
20101 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
20102 	if (errno)
20103 		return errno;
20104 
20105 	errno = __wlan_hdd_cfg80211_set_monitor_mode(wiphy, wdev,
20106 						     data, data_len);
20107 
20108 	osif_vdev_sync_op_stop(vdev_sync);
20109 
20110 	hdd_exit();
20111 
20112 	return errno;
20113 }
20114 #endif
20115 
20116 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
20117 
20118 /**
20119  * __wlan_hdd_cfg80211_get_monitor_mode() - Get wifi monitor mode configuration
20120  * vendor command
20121  * @wiphy: wiphy device pointer
20122  * @wdev: wireless device pointer
20123  * @data: Vendor command data buffer
20124  * @data_len: Buffer length
20125  *
20126  * Return: 0 for Success and negative value for failure
20127  */
20128 static int
__wlan_hdd_cfg80211_get_monitor_mode(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)20129 __wlan_hdd_cfg80211_get_monitor_mode(struct wiphy *wiphy,
20130 				     struct wireless_dev *wdev,
20131 				     const void *data, int data_len)
20132 {
20133 	struct net_device *dev = wdev->netdev;
20134 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
20135 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
20136 	struct wlan_objmgr_vdev *vdev;
20137 	int errno;
20138 	QDF_STATUS status;
20139 
20140 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
20141 		hdd_err("Command not allowed in FTM mode");
20142 		return -EPERM;
20143 	}
20144 
20145 	errno = wlan_hdd_validate_context(hdd_ctx);
20146 	if (errno)
20147 		return errno;
20148 
20149 	errno = hdd_validate_adapter(adapter);
20150 	if (errno)
20151 		return errno;
20152 
20153 	if (!ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc))
20154 		return -EPERM;
20155 
20156 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
20157 	if (!vdev)
20158 		return -EINVAL;
20159 
20160 	status = os_if_dp_get_lpc_state(vdev, data, data_len);
20161 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
20162 
20163 	return qdf_status_to_os_return(status);
20164 }
20165 
20166 /**
20167  * wlan_hdd_cfg80211_get_monitor_mode() - get monitor mode
20168  * @wiphy: wiphy pointer
20169  * @wdev: pointer to struct wireless_dev
20170  * @data: pointer to incoming NL vendor data
20171  * @data_len: length of @data
20172  *
20173  * Return: 0 on success; error number otherwise.
20174  */
wlan_hdd_cfg80211_get_monitor_mode(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)20175 static int wlan_hdd_cfg80211_get_monitor_mode(struct wiphy *wiphy,
20176 					      struct wireless_dev *wdev,
20177 					      const void *data, int data_len)
20178 {
20179 	int errno;
20180 	struct osif_vdev_sync *vdev_sync;
20181 
20182 	hdd_enter_dev(wdev->netdev);
20183 
20184 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
20185 	if (errno)
20186 		return errno;
20187 
20188 	errno = __wlan_hdd_cfg80211_get_monitor_mode(wiphy, wdev,
20189 						     data, data_len);
20190 
20191 	osif_vdev_sync_op_stop(vdev_sync);
20192 
20193 	hdd_exit();
20194 
20195 	return errno;
20196 }
20197 #endif
20198 
20199 /**
20200  * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
20201  * @wiphy: wiphy pointer
20202  * @wdev: pointer to struct wireless_dev
20203  * @data: pointer to incoming NL vendor data
20204  * @data_len: length of @data
20205  *
20206  * Return: 0 on success; error number otherwise.
20207  */
wlan_hdd_cfg80211_get_chain_rssi(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)20208 static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
20209 					    struct wireless_dev *wdev,
20210 					    const void *data,
20211 					    int data_len)
20212 {
20213 	int errno;
20214 	struct osif_vdev_sync *vdev_sync;
20215 
20216 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
20217 	if (errno)
20218 		return errno;
20219 
20220 	errno = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
20221 
20222 	osif_vdev_sync_op_stop(vdev_sync);
20223 
20224 	return errno;
20225 }
20226 
20227 /**
20228  * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
20229  * @skb: Pointer to skb
20230  * @info: mac mode info
20231  * @index: attribute type index for nla_nest_start()
20232  *
20233  * Return : 0 on success and errno on failure
20234  */
wlan_hdd_fill_intf_info(struct sk_buff * skb,struct connection_info * info,int index)20235 static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
20236 				   struct connection_info *info, int index)
20237 {
20238 	struct nlattr *attr;
20239 	uint32_t freq;
20240 	struct hdd_context *hdd_ctx;
20241 	struct wlan_hdd_link_info *link_info;
20242 
20243 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
20244 	if (!hdd_ctx)
20245 		goto error;
20246 
20247 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, info->vdev_id);
20248 	if (!link_info)
20249 		goto error;
20250 
20251 	attr = nla_nest_start(skb, index);
20252 	if (!attr)
20253 		goto error;
20254 
20255 	freq = sme_chn_to_freq(info->channel);
20256 
20257 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
20258 	    link_info->adapter->dev->ifindex) ||
20259 	    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
20260 		goto error;
20261 
20262 	nla_nest_end(skb, attr);
20263 
20264 	return 0;
20265 error:
20266 	hdd_err("Fill buffer with interface info failed");
20267 	return -EINVAL;
20268 }
20269 
20270 /**
20271  * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
20272  * @skb: Pointer to skb
20273  * @info: mac mode info
20274  * @mac_id: MAC id
20275  * @conn_count: number of current connections
20276  *
20277  * Return : 0 on success and errno on failure
20278  */
wlan_hdd_fill_mac_info(struct sk_buff * skb,struct connection_info * info,uint32_t mac_id,uint32_t conn_count)20279 static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
20280 				  struct connection_info *info, uint32_t mac_id,
20281 				  uint32_t conn_count)
20282 {
20283 	struct nlattr *attr, *intf_attr;
20284 	uint32_t band = 0, i = 0, j = 0;
20285 	bool present = false;
20286 
20287 	while (i < conn_count) {
20288 		if (info[i].mac_id == mac_id) {
20289 			present = true;
20290 			if (info[i].channel <= SIR_11B_CHANNEL_END)
20291 				band |= 1 << NL80211_BAND_2GHZ;
20292 			else if (info[i].channel <= SIR_11A_CHANNEL_END)
20293 				band |= 1 << NL80211_BAND_5GHZ;
20294 		}
20295 		i++;
20296 	}
20297 
20298 	if (!present)
20299 		return 0;
20300 
20301 	i = 0;
20302 	attr = nla_nest_start(skb, mac_id);
20303 	if (!attr)
20304 		goto error;
20305 
20306 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
20307 	    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
20308 		goto error;
20309 
20310 	intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
20311 	if (!intf_attr)
20312 		goto error;
20313 
20314 	while (i < conn_count) {
20315 		if (info[i].mac_id == mac_id) {
20316 			if (wlan_hdd_fill_intf_info(skb, &info[i], j))
20317 				return -EINVAL;
20318 			j++;
20319 		}
20320 		i++;
20321 	}
20322 
20323 	nla_nest_end(skb, intf_attr);
20324 
20325 	nla_nest_end(skb, attr);
20326 
20327 	return 0;
20328 error:
20329 	hdd_err("Fill buffer with mac info failed");
20330 	return -EINVAL;
20331 }
20332 
20333 
wlan_hdd_send_mode_change_event(void)20334 int wlan_hdd_send_mode_change_event(void)
20335 {
20336 	int err;
20337 	struct hdd_context *hdd_ctx;
20338 	struct sk_buff *skb;
20339 	struct nlattr *attr;
20340 	struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
20341 	uint32_t conn_count, mac_id;
20342 	enum qca_nl80211_vendor_subcmds_index index =
20343 		QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX;
20344 
20345 	hdd_enter();
20346 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
20347 	if (!hdd_ctx)
20348 		return -EINVAL;
20349 
20350 	err = wlan_hdd_validate_context(hdd_ctx);
20351 	if (0 != err)
20352 		return err;
20353 
20354 	conn_count = policy_mgr_get_connection_info(hdd_ctx->psoc, info);
20355 	if (!conn_count)
20356 		return -EINVAL;
20357 
20358 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
20359 					       (sizeof(uint32_t) * 4) *
20360 					       MAX_NUMBER_OF_CONC_CONNECTIONS +
20361 					       NLMSG_HDRLEN,
20362 					       index, GFP_KERNEL);
20363 	if (!skb) {
20364 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
20365 		return -ENOMEM;
20366 	}
20367 
20368 	attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
20369 	if (!attr) {
20370 		hdd_err("nla_nest_start failed");
20371 		wlan_cfg80211_vendor_free_skb(skb);
20372 		return -EINVAL;
20373 	}
20374 
20375 	for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
20376 		if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count)) {
20377 			wlan_cfg80211_vendor_free_skb(skb);
20378 			return -EINVAL;
20379 		}
20380 	}
20381 
20382 	nla_nest_end(skb, attr);
20383 
20384 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
20385 	hdd_exit();
20386 
20387 	return err;
20388 }
20389 
20390 
20391 /* Short name for QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS command */
20392 
20393 #define EXTSCAN_CONFIG_MAX \
20394 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
20395 #define EXTSCAN_CONFIG_REQUEST_ID \
20396 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
20397 #define EXTSCAN_CONFIG_WIFI_BAND \
20398 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND
20399 #define EXTSCAN_CONFIG_MAX_CHANNELS \
20400 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS
20401 #define EXTSCAN_RESULTS_NUM_CHANNELS \
20402 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS
20403 #define EXTSCAN_RESULTS_CHANNELS \
20404 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS
20405 
20406 static const struct nla_policy
20407 wlan_hdd_extscan_get_valid_channels_policy[EXTSCAN_CONFIG_MAX + 1] = {
20408 	[EXTSCAN_CONFIG_REQUEST_ID] = {.type = NLA_U32},
20409 	[EXTSCAN_CONFIG_WIFI_BAND] = {.type = NLA_U32},
20410 	[EXTSCAN_CONFIG_MAX_CHANNELS] = {.type = NLA_U32},
20411 };
20412 
20413 /**
20414  * hdd_remove_passive_channels () - remove passive channels
20415  * @wiphy: Pointer to wireless phy
20416  * @chan_list: channel list
20417  * @num_channels: number of channels
20418  *
20419  * Return: none
20420  */
hdd_remove_passive_channels(struct wiphy * wiphy,uint32_t * chan_list,uint8_t * num_channels)20421 static void hdd_remove_passive_channels(struct wiphy *wiphy,
20422 					uint32_t *chan_list,
20423 					uint8_t *num_channels)
20424 {
20425 	uint8_t num_chan_temp = 0;
20426 	int i, j, k;
20427 
20428 	for (i = 0; i < *num_channels; i++)
20429 		for (j = 0; j < HDD_NUM_NL80211_BANDS; j++) {
20430 			if (!wiphy->bands[j])
20431 				continue;
20432 			for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
20433 				if ((chan_list[i] ==
20434 				     wiphy->bands[j]->channels[k].center_freq)
20435 				    && (!(wiphy->bands[j]->channels[k].flags &
20436 				       IEEE80211_CHAN_PASSIVE_SCAN))
20437 				) {
20438 					chan_list[num_chan_temp] = chan_list[i];
20439 					num_chan_temp++;
20440 				}
20441 			}
20442 		}
20443 
20444 	*num_channels = num_chan_temp;
20445 }
20446 
20447 /**
20448  * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
20449  * @wiphy: Pointer to wireless phy
20450  * @wdev: Pointer to wireless device
20451  * @data: Pointer to data
20452  * @data_len: Data length
20453  *
20454  * Return: none
20455  */
20456 static int
__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)20457 __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
20458 					       struct wireless_dev
20459 					       *wdev, const void *data,
20460 					       int data_len)
20461 {
20462 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
20463 	struct net_device *dev = wdev->netdev;
20464 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
20465 	uint32_t chan_list[CFG_VALID_CHANNEL_LIST_LEN] = {0};
20466 	uint8_t num_channels  = 0, i, buf[256] = {0};
20467 	struct nlattr *tb[EXTSCAN_CONFIG_MAX + 1];
20468 	uint32_t request_id, max_channels;
20469 	tWifiBand wifi_band;
20470 	QDF_STATUS status;
20471 	struct sk_buff *reply_skb;
20472 	int ret, len = 0;
20473 
20474 	/* ENTER_DEV() intentionally not used in a frequently invoked API */
20475 
20476 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
20477 		hdd_err("Command not allowed in FTM mode");
20478 		return -EPERM;
20479 	}
20480 
20481 	ret = wlan_hdd_validate_context(hdd_ctx);
20482 	if (0 != ret)
20483 		return -EINVAL;
20484 
20485 	if (wlan_cfg80211_nla_parse(tb, EXTSCAN_CONFIG_MAX, data, data_len,
20486 				  wlan_hdd_extscan_get_valid_channels_policy)) {
20487 		hdd_err("Invalid ATTR");
20488 		return -EINVAL;
20489 	}
20490 
20491 	/* Parse and fetch request Id */
20492 	if (!tb[EXTSCAN_CONFIG_REQUEST_ID]) {
20493 		hdd_err("attr request id failed");
20494 		return -EINVAL;
20495 	}
20496 	request_id = nla_get_u32(tb[EXTSCAN_CONFIG_REQUEST_ID]);
20497 
20498 	/* Parse and fetch wifi band */
20499 	if (!tb[EXTSCAN_CONFIG_WIFI_BAND]) {
20500 		hdd_err("attr wifi band failed");
20501 		return -EINVAL;
20502 	}
20503 	wifi_band = nla_get_u32(tb[EXTSCAN_CONFIG_WIFI_BAND]);
20504 	if (!tb[EXTSCAN_CONFIG_MAX_CHANNELS]) {
20505 		hdd_err("attr max channels failed");
20506 		return -EINVAL;
20507 	}
20508 	max_channels = nla_get_u32(tb[EXTSCAN_CONFIG_MAX_CHANNELS]);
20509 
20510 	if (max_channels > CFG_VALID_CHANNEL_LIST_LEN) {
20511 		hdd_err("Max channels %d exceeded Valid channel list len %d",
20512 			max_channels, CFG_VALID_CHANNEL_LIST_LEN);
20513 		return -EINVAL;
20514 	}
20515 
20516 	hdd_err("Req Id: %u Wifi band: %d Max channels: %d", request_id,
20517 		wifi_band, max_channels);
20518 	status = sme_get_valid_channels_by_band(hdd_ctx->mac_handle,
20519 						wifi_band, chan_list,
20520 						&num_channels);
20521 	if (QDF_STATUS_SUCCESS != status) {
20522 		hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
20523 		        status);
20524 		return -EINVAL;
20525 	}
20526 
20527 	num_channels = QDF_MIN(num_channels, max_channels);
20528 
20529 	if ((QDF_SAP_MODE == adapter->device_mode) ||
20530 	    !strncmp(hdd_get_fwpath(), "ap", 2))
20531 		hdd_remove_passive_channels(wiphy, chan_list,
20532 					    &num_channels);
20533 
20534 	hdd_debug("Number of channels: %d", num_channels);
20535 	for (i = 0; i < num_channels; i++)
20536 		len += scnprintf(buf + len, sizeof(buf) - len,
20537 				 "%u ", chan_list[i]);
20538 
20539 	hdd_debug("Channels: %s", buf);
20540 
20541 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
20542 							     sizeof(u32) +
20543 							     sizeof(u32) *
20544 							     num_channels +
20545 							     NLMSG_HDRLEN);
20546 
20547 	if (reply_skb) {
20548 		if (nla_put_u32(
20549 			reply_skb,
20550 			EXTSCAN_RESULTS_NUM_CHANNELS,
20551 			num_channels) ||
20552 		    nla_put(
20553 			reply_skb,
20554 			EXTSCAN_RESULTS_CHANNELS,
20555 			sizeof(u32) * num_channels, chan_list)) {
20556 			hdd_err("nla put fail");
20557 			wlan_cfg80211_vendor_free_skb(reply_skb);
20558 			return -EINVAL;
20559 		}
20560 		ret = wlan_cfg80211_vendor_cmd_reply(reply_skb);
20561 		return ret;
20562 	}
20563 
20564 	hdd_err("valid channels: buffer alloc fail");
20565 	return -EINVAL;
20566 }
20567 
20568 #undef EXTSCAN_CONFIG_MAX
20569 #undef EXTSCAN_CONFIG_REQUEST_ID
20570 #undef EXTSCAN_CONFIG_WIFI_BAND
20571 #undef ETCAN_CONFIG_MAX_CHANNELS
20572 #undef EXTSCAN_RESULTS_NUM_CHANNELS
20573 #undef EXTSCAN_RESULTS_CHANNELS
20574 
20575 /**
20576  * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
20577  * @wiphy: Pointer to wireless phy
20578  * @wdev: Pointer to wireless device
20579  * @data: Pointer to data
20580  * @data_len: Data length
20581  *
20582  * Return: 0 on success, negative errno on failure
20583  */
wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)20584 static int wlan_hdd_cfg80211_extscan_get_valid_channels(
20585 					struct wiphy *wiphy,
20586 					struct wireless_dev *wdev,
20587 					const void *data, int data_len)
20588 {
20589 	struct osif_psoc_sync *psoc_sync;
20590 	int errno;
20591 
20592 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
20593 	if (errno)
20594 		return errno;
20595 
20596 	errno = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev,
20597 							       data, data_len);
20598 
20599 	osif_psoc_sync_op_stop(psoc_sync);
20600 
20601 	return errno;
20602 }
20603 
20604 #ifdef FEATURE_RADAR_HISTORY
get_radar_history_evt_len(uint32_t count)20605 static uint32_t get_radar_history_evt_len(uint32_t count)
20606 {
20607 	uint32_t data_len = NLMSG_HDRLEN;
20608 
20609 	data_len +=
20610 	/* nested attribute hdr QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES */
20611 		nla_total_size(count *
20612 			       (nla_total_size(
20613 				     /* channel frequency */
20614 				     nla_total_size(sizeof(uint32_t)) +
20615 				     /* timestamp */
20616 				     nla_total_size(sizeof(uint64_t)) +
20617 				     /* radar detected flag */
20618 				     nla_total_size(0))));
20619 
20620 	return data_len;
20621 }
20622 
20623 /**
20624  * __wlan_hdd_cfg80211_get_radar_history () - Get radar history
20625  * @wiphy: Pointer to wireless phy
20626  * @wdev: Pointer to wireless device
20627  * @data: Pointer to data
20628  * @data_len: Data length
20629  *
20630  * Return: 0 on success, negative errno on failure
20631  */
20632 static int
__wlan_hdd_cfg80211_get_radar_history(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)20633 __wlan_hdd_cfg80211_get_radar_history(struct wiphy *wiphy,
20634 				      struct wireless_dev
20635 				      *wdev, const void *data,
20636 				      int data_len)
20637 {
20638 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
20639 	QDF_STATUS status;
20640 	struct sk_buff *reply_skb = NULL;
20641 	int ret, len;
20642 	struct dfs_radar_history *radar_history = NULL;
20643 	uint32_t hist_count = 0;
20644 	int idx;
20645 	struct nlattr *ch_array, *ch_element;
20646 
20647 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
20648 		hdd_err("Command not allowed in FTM mode");
20649 		return -EPERM;
20650 	}
20651 
20652 	ret = wlan_hdd_validate_context(hdd_ctx);
20653 	if (ret)
20654 		return -EINVAL;
20655 
20656 	status = wlansap_query_radar_history(hdd_ctx->mac_handle,
20657 					     &radar_history, &hist_count);
20658 	if (!QDF_IS_STATUS_SUCCESS(status))
20659 		return -EINVAL;
20660 
20661 	len = get_radar_history_evt_len(hist_count);
20662 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
20663 	if (!reply_skb) {
20664 		ret = -ENOMEM;
20665 		goto err;
20666 	}
20667 
20668 	ch_array = nla_nest_start(
20669 			reply_skb, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES);
20670 	if (!ch_array) {
20671 		ret = -ENOMEM;
20672 		goto err;
20673 	}
20674 
20675 	for (idx = 0; idx < hist_count; idx++) {
20676 		ch_element = nla_nest_start(reply_skb, idx);
20677 		if (!ch_element) {
20678 			ret = -ENOMEM;
20679 			goto err;
20680 		}
20681 
20682 		if (nla_put_u32(reply_skb,
20683 				QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ,
20684 				radar_history[idx].ch_freq)) {
20685 			ret = -ENOMEM;
20686 			goto err;
20687 		}
20688 
20689 		if (wlan_cfg80211_nla_put_u64(
20690 			reply_skb,
20691 			QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP,
20692 			radar_history[idx].time)) {
20693 			ret = -ENOMEM;
20694 			goto err;
20695 		}
20696 
20697 		if (radar_history[idx].radar_found &&
20698 		    nla_put_flag(
20699 			reply_skb,
20700 			QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED)) {
20701 			ret = -ENOMEM;
20702 			goto err;
20703 		}
20704 
20705 		nla_nest_end(reply_skb, ch_element);
20706 	}
20707 	nla_nest_end(reply_skb, ch_array);
20708 	qdf_mem_free(radar_history);
20709 
20710 	ret = wlan_cfg80211_vendor_cmd_reply(reply_skb);
20711 	hdd_debug("get radar history count %d, ret %d", hist_count, ret);
20712 
20713 	return ret;
20714 err:
20715 	qdf_mem_free(radar_history);
20716 	wlan_cfg80211_vendor_free_skb(reply_skb);
20717 	hdd_debug("get radar history error %d", ret);
20718 
20719 	return ret;
20720 }
20721 
20722 /**
20723  * wlan_hdd_cfg80211_get_radar_history() - get radar history
20724  * @wiphy: wiphy pointer
20725  * @wdev: pointer to struct wireless_dev
20726  * @data: pointer to incoming NL vendor data
20727  * @data_len: length of @data
20728  *
20729  * Return: 0 on success; error number otherwise.
20730  */
wlan_hdd_cfg80211_get_radar_history(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)20731 static int wlan_hdd_cfg80211_get_radar_history(struct wiphy *wiphy,
20732 					       struct wireless_dev *wdev,
20733 					       const void *data,
20734 					       int data_len)
20735 {
20736 	int errno;
20737 	struct osif_vdev_sync *vdev_sync;
20738 
20739 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
20740 	if (errno)
20741 		return errno;
20742 
20743 	errno = __wlan_hdd_cfg80211_get_radar_history(wiphy, wdev,
20744 						      data, data_len);
20745 
20746 	osif_vdev_sync_op_stop(vdev_sync);
20747 
20748 	return errno;
20749 }
20750 
20751 #define FEATURE_RADAR_HISTORY_VENDOR_COMMANDS				\
20752 {									\
20753 	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
20754 	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY,	\
20755 	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
20756 		WIPHY_VENDOR_CMD_NEED_NETDEV |				\
20757 		WIPHY_VENDOR_CMD_NEED_RUNNING,				\
20758 	.doit = wlan_hdd_cfg80211_get_radar_history,			\
20759 	vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)			\
20760 },
20761 #else
20762 #define FEATURE_RADAR_HISTORY_VENDOR_COMMANDS
20763 #endif
20764 
20765 const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
20766 	{
20767 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20768 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
20769 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20770 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20771 		.doit = is_driver_dfs_capable,
20772 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20773 	},
20774 	{
20775 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20776 		.info.subcmd =
20777 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
20778 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20779 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20780 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20781 		.doit = wlan_hdd_cfg80211_extscan_get_valid_channels,
20782 		vendor_command_policy(
20783 				wlan_hdd_extscan_get_valid_channels_policy,
20784 				EXTSCAN_PARAM_MAX)
20785 	},
20786 #ifdef WLAN_FEATURE_STATS_EXT
20787 	{
20788 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20789 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
20790 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20791 			 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
20792 		.doit = wlan_hdd_cfg80211_stats_ext_request,
20793 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20794 	},
20795 #endif
20796 
20797 	{
20798 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20799 		.info.subcmd =
20800 			QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS,
20801 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20802 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20803 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20804 		.doit = wlan_hdd_cfg80211_connected_chan_stats_req,
20805 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20806 	},
20807 
20808 	FEATURE_EXTSCAN_VENDOR_COMMANDS
20809 
20810 	FEATURE_LL_STATS_VENDOR_COMMANDS
20811 
20812 	{
20813 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20814 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
20815 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20816 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20817 		.doit = wlan_hdd_cfg80211_get_supported_features,
20818 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20819 	},
20820 	{
20821 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20822 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
20823 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20824 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20825 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20826 		.doit = wlan_hdd_cfg80211_set_scanning_mac_oui,
20827 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20828 	},
20829 
20830 	FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
20831 
20832 	{
20833 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20834 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
20835 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20836 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20837 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20838 		.doit = wlan_hdd_cfg80211_disable_dfs_chan_scan,
20839 		vendor_command_policy(wlan_hdd_set_no_dfs_flag_config_policy,
20840 				      QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX)
20841 	},
20842 	{
20843 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20844 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
20845 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20846 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20847 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20848 		.doit = wlan_hdd_cfg80211_handle_wisa_cmd,
20849 		vendor_command_policy(wlan_hdd_wisa_cmd_policy,
20850 				      QCA_WLAN_VENDOR_ATTR_WISA_MAX)
20851 	},
20852 
20853 	FEATURE_STATION_INFO_VENDOR_COMMANDS
20854 
20855 	{
20856 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20857 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
20858 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20859 				WIPHY_VENDOR_CMD_NEED_NETDEV |
20860 				WIPHY_VENDOR_CMD_NEED_RUNNING,
20861 		.doit = wlan_hdd_cfg80211_do_acs,
20862 		vendor_command_policy(wlan_hdd_cfg80211_do_acs_policy,
20863 				      QCA_WLAN_VENDOR_ATTR_ACS_MAX)
20864 	},
20865 
20866 	{
20867 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20868 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
20869 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20870 			WIPHY_VENDOR_CMD_NEED_NETDEV,
20871 		.doit = wlan_hdd_cfg80211_get_features,
20872 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20873 	},
20874 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
20875 	{
20876 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20877 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
20878 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20879 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20880 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20881 		.doit = wlan_hdd_cfg80211_keymgmt_set_key,
20882 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20883 	},
20884 #endif
20885 	{
20886 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20887 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
20888 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20889 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20890 		.doit = wlan_hdd_cfg80211_get_wifi_info,
20891 		vendor_command_policy(qca_wlan_vendor_get_wifi_info_policy,
20892 				      QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX)
20893 	},
20894 	{
20895 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20896 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
20897 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20898 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20899 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20900 		.doit = wlan_hdd_cfg80211_wifi_configuration_set,
20901 		vendor_command_policy(wlan_hdd_wifi_config_policy,
20902 				      QCA_WLAN_VENDOR_ATTR_CONFIG_MAX)
20903 	},
20904 	{
20905 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20906 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION,
20907 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20908 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20909 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20910 		.doit = wlan_hdd_cfg80211_wifi_configuration_get,
20911 		vendor_command_policy(wlan_hdd_wifi_config_policy,
20912 				      QCA_WLAN_VENDOR_ATTR_CONFIG_MAX)
20913 	},
20914 
20915 	FEATURE_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION
20916 #ifdef WLAN_SUPPORT_TWT
20917 	FEATURE_VENDOR_SUBCMD_WIFI_CONFIG_TWT
20918 #endif
20919 
20920 	{
20921 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20922 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
20923 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20924 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20925 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20926 		.doit = wlan_hdd_cfg80211_set_ext_roam_params,
20927 		vendor_command_policy(wlan_hdd_set_roam_param_policy,
20928 				      QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX)
20929 	},
20930 	{
20931 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20932 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG,
20933 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20934 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20935 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20936 		.doit = wlan_hdd_cfg80211_set_ratemask_config,
20937 		vendor_command_policy(wlan_hdd_set_ratemask_param_policy,
20938 				      QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX)
20939 	},
20940 	{
20941 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20942 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
20943 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20944 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20945 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20946 		.doit = wlan_hdd_cfg80211_wifi_logger_start,
20947 		vendor_command_policy(
20948 				qca_wlan_vendor_wifi_logger_start_policy,
20949 				QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX)
20950 	},
20951 	{
20952 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20953 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
20954 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV,
20955 		.doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data,
20956 		vendor_command_policy(
20957 			qca_wlan_vendor_wifi_logger_get_ring_data_policy,
20958 			QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX)
20959 	},
20960 	{
20961 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20962 		.info.subcmd =
20963 			QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
20964 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20965 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20966 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20967 		.doit = wlan_hdd_cfg80211_get_preferred_freq_list,
20968 		vendor_command_policy(
20969 			get_preferred_freq_list_policy,
20970 			QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX)
20971 	},
20972 	{
20973 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20974 		.info.subcmd =
20975 			QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
20976 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20977 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20978 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20979 		.doit = wlan_hdd_cfg80211_set_probable_oper_channel,
20980 		vendor_command_policy(
20981 				set_probable_oper_channel_policy,
20982 				QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX)
20983 	},
20984 
20985 	FEATURE_HANDLE_TSF_VENDOR_COMMANDS
20986 
20987 #ifdef FEATURE_WLAN_TDLS
20988 	{
20989 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20990 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
20991 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20992 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20993 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20994 		.doit = wlan_hdd_cfg80211_get_tdls_capabilities,
20995 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20996 	},
20997 #endif
20998 #ifdef WLAN_FEATURE_OFFLOAD_PACKETS
20999 	{
21000 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21001 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
21002 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21003 			WIPHY_VENDOR_CMD_NEED_NETDEV |
21004 			WIPHY_VENDOR_CMD_NEED_RUNNING,
21005 		.doit = wlan_hdd_cfg80211_offloaded_packets,
21006 		vendor_command_policy(offloaded_packet_policy,
21007 				      QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX)
21008 	},
21009 #endif
21010 	FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
21011 	FEATURE_OEM_DATA_VENDOR_COMMANDS
21012 	FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS
21013 
21014 #ifdef WLAN_NS_OFFLOAD
21015 	{
21016 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21017 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
21018 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21019 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
21020 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
21021 		.doit = wlan_hdd_cfg80211_set_ns_offload,
21022 		vendor_command_policy(ns_offload_set_policy,
21023 				      QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX)
21024 	},
21025 #endif /* WLAN_NS_OFFLOAD */
21026 	{
21027 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21028 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
21029 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21030 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
21031 		.doit = wlan_hdd_cfg80211_get_logger_supp_feature,
21032 		vendor_command_policy(get_logger_set_policy,
21033 				      QCA_WLAN_VENDOR_ATTR_LOGGER_MAX)
21034 	},
21035 
21036 	FEATURE_TRIGGER_SCAN_VENDOR_COMMANDS
21037 
21038 	/* Vendor abort scan */
21039 	FEATURE_ABORT_SCAN_VENDOR_COMMANDS
21040 
21041 	/* OCB commands */
21042 	FEATURE_OCB_VENDOR_COMMANDS
21043 
21044 	{
21045 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21046 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
21047 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21048 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
21049 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
21050 		.doit = wlan_hdd_cfg80211_get_link_properties,
21051 		vendor_command_policy(wlan_hdd_get_link_properties_policy,
21052 				      QCA_WLAN_VENDOR_ATTR_MAX)
21053 	},
21054 
21055 	FEATURE_OTA_TEST_VENDOR_COMMANDS
21056 
21057 	FEATURE_LFR_SUBNET_DETECT_VENDOR_COMMANDS
21058 
21059 	FEATURE_TX_POWER_VENDOR_COMMANDS
21060 
21061 	FEATURE_APF_OFFLOAD_VENDOR_COMMANDS
21062 
21063 	{
21064 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21065 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
21066 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21067 			WIPHY_VENDOR_CMD_NEED_NETDEV |
21068 			WIPHY_VENDOR_CMD_NEED_RUNNING,
21069 		.doit = wlan_hdd_cfg80211_acs_dfs_mode,
21070 		vendor_command_policy(wlan_hdd_set_acs_dfs_config_policy,
21071 				      QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX)
21072 	},
21073 	{
21074 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21075 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
21076 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21077 			WIPHY_VENDOR_CMD_NEED_NETDEV |
21078 			WIPHY_VENDOR_CMD_NEED_RUNNING,
21079 		.doit = wlan_hdd_cfg80211_sta_roam_policy,
21080 		vendor_command_policy(
21081 			wlan_hdd_set_sta_roam_config_policy,
21082 			QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX)
21083 	},
21084 
21085 	{
21086 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21087 		.info.subcmd =
21088 			QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_POLICY,
21089 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21090 			WIPHY_VENDOR_CMD_NEED_NETDEV |
21091 			WIPHY_VENDOR_CMD_NEED_RUNNING,
21092 		.doit = wlan_hdd_cfg80211_concurrent_session_policy,
21093 		vendor_command_policy(
21094 			wlan_hdd_set_concurrent_session_policy,
21095 			QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX)
21096 	},
21097 
21098 #ifdef FEATURE_WLAN_CH_AVOID
21099 	{
21100 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21101 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
21102 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21103 			WIPHY_VENDOR_CMD_NEED_NETDEV |
21104 			WIPHY_VENDOR_CMD_NEED_RUNNING,
21105 		.doit = wlan_hdd_cfg80211_avoid_freq,
21106 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
21107 	},
21108 #endif
21109 	{
21110 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21111 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
21112 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21113 			WIPHY_VENDOR_CMD_NEED_NETDEV |
21114 			WIPHY_VENDOR_CMD_NEED_RUNNING,
21115 		.doit = wlan_hdd_cfg80211_sap_configuration_set,
21116 		vendor_command_policy(wlan_hdd_sap_config_policy,
21117 				      QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX)
21118 	},
21119 
21120 	FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
21121 
21122 	FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
21123 	{
21124 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21125 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
21126 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21127 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
21128 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
21129 		.doit = wlan_hdd_cfg80211_get_wakelock_stats,
21130 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
21131 	},
21132 	{
21133 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21134 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
21135 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21136 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
21137 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
21138 		.doit = wlan_hdd_cfg80211_get_bus_size,
21139 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
21140 	},
21141 	{
21142 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21143 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
21144 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21145 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
21146 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
21147 		.doit = wlan_hdd_cfg80211_update_vendor_channel,
21148 		vendor_command_policy(acs_chan_config_policy,
21149 				      QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX)
21150 	},
21151 	{
21152 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21153 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
21154 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21155 					WIPHY_VENDOR_CMD_NEED_NETDEV |
21156 					WIPHY_VENDOR_CMD_NEED_RUNNING,
21157 		.doit = wlan_hdd_cfg80211_setband,
21158 		vendor_command_policy(setband_policy, QCA_WLAN_VENDOR_ATTR_MAX)
21159 	},
21160 	{
21161 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21162 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GETBAND,
21163 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21164 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
21165 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
21166 		.doit = wlan_hdd_cfg80211_getband,
21167 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
21168 	},
21169 	{
21170 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21171 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
21172 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21173 			WIPHY_VENDOR_CMD_NEED_NETDEV |
21174 			WIPHY_VENDOR_CMD_NEED_RUNNING,
21175 		.doit = wlan_hdd_cfg80211_set_fast_roaming,
21176 		vendor_command_policy(qca_wlan_vendor_attr,
21177 				      QCA_WLAN_VENDOR_ATTR_MAX)
21178 	},
21179 	FEATURE_DISA_VENDOR_COMMANDS
21180 	FEATURE_TDLS_VENDOR_COMMANDS
21181 	FEATURE_SAR_LIMITS_VENDOR_COMMANDS
21182 	BCN_RECV_FEATURE_VENDOR_COMMANDS
21183 	FEATURE_VENDOR_SUBCMD_SET_TRACE_LEVEL
21184 #ifdef WLAN_FEATURE_LINK_LAYER_STATS
21185 	{
21186 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21187 		.info.subcmd =
21188 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
21189 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21190 				 WIPHY_VENDOR_CMD_NEED_NETDEV |
21191 				 WIPHY_VENDOR_CMD_NEED_RUNNING,
21192 		.doit = wlan_hdd_cfg80211_ll_stats_ext_set_param,
21193 		vendor_command_policy(qca_wlan_vendor_ll_ext_policy,
21194 				      QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX)
21195 	},
21196 #endif
21197 	FEATURE_VENDOR_SUBCMD_NUD_STATS_SET
21198 	{
21199 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21200 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
21201 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21202 			WIPHY_VENDOR_CMD_NEED_NETDEV |
21203 			WIPHY_VENDOR_CMD_NEED_RUNNING,
21204 		.doit = wlan_hdd_cfg80211_get_nud_stats,
21205 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
21206 	},
21207 
21208 	FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
21209 	FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
21210 	FEATURE_CFR_VENDOR_COMMANDS
21211 	FEATURE_11AX_VENDOR_COMMANDS
21212 
21213 	{
21214 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21215 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
21216 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21217 			WIPHY_VENDOR_CMD_NEED_NETDEV |
21218 			WIPHY_VENDOR_CMD_NEED_RUNNING,
21219 		.doit = wlan_hdd_cfg80211_get_chain_rssi,
21220 		vendor_command_policy(get_chain_rssi_policy,
21221 				      QCA_WLAN_VENDOR_ATTR_MAX)
21222 	},
21223 	{
21224 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21225 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS,
21226 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21227 			WIPHY_VENDOR_CMD_NEED_NETDEV,
21228 		.doit = wlan_hdd_cfg80211_get_usable_channel,
21229 		vendor_command_policy(get_usable_channel_policy,
21230 				      QCA_WLAN_VENDOR_ATTR_MAX)
21231 	},
21232 	FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
21233 	FEATURE_NAN_VENDOR_COMMANDS
21234 	FEATURE_FW_STATE_COMMANDS
21235 	FEATURE_COEX_CONFIG_COMMANDS
21236 	FEATURE_MPTA_HELPER_COMMANDS
21237 	FEATURE_HW_CAPABILITY_COMMANDS
21238 	FEATURE_THERMAL_VENDOR_COMMANDS
21239 	FEATURE_BTC_CHAIN_MODE_COMMANDS
21240 	FEATURE_WMM_COMMANDS
21241 	FEATURE_GPIO_CFG_VENDOR_COMMANDS
21242 	FEATURE_MEDIUM_ASSESS_VENDOR_COMMANDS
21243 	FEATURE_RADAR_HISTORY_VENDOR_COMMANDS
21244 	FEATURE_AVOID_FREQ_EXT_VENDOR_COMMANDS
21245 	FEATURE_MDNS_OFFLOAD_VENDOR_COMMANDS
21246 
21247 	FEATURE_GREEN_AP_LOW_LATENCY_PWR_SAVE_COMMANDS
21248 
21249 #if defined(WLAN_FEATURE_PKT_CAPTURE) || defined(WLAN_FEATURE_LOCAL_PKT_CAPTURE)
21250 	FEATURE_MONITOR_MODE_VENDOR_COMMANDS
21251 #endif
21252 
21253 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
21254 	{
21255 	.info.vendor_id = QCA_NL80211_VENDOR_ID,
21256 	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS,
21257 	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21258 		 WIPHY_VENDOR_CMD_NEED_NETDEV |
21259 		 WIPHY_VENDOR_CMD_NEED_RUNNING,
21260 	.doit = wlan_hdd_cfg80211_set_roam_events,
21261 	vendor_command_policy(set_roam_events_policy,
21262 			      QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX)
21263 	},
21264 #endif
21265 	FEATURE_ROAM_STATS_COMMANDS
21266 	FEATURE_WIFI_POS_11AZ_AUTH_COMMANDS
21267 	FEATURE_WIFI_POS_SET_SECURE_RANGING_CONTEXT_COMMANDS
21268 	FEATURE_MCC_QUOTA_VENDOR_COMMANDS
21269 	FEATURE_PEER_FLUSH_VENDOR_COMMANDS
21270 	{
21271 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
21272 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RADIO_COMBINATION_MATRIX,
21273 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
21274 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
21275 		.doit = wlan_hdd_cfg80211_get_radio_combination_matrix,
21276 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
21277 	},
21278 	FEATURE_COAP_OFFLOAD_COMMANDS
21279 	FEATURE_ML_LINK_STATE_COMMANDS
21280 	FEATURE_AFC_VENDOR_COMMANDS
21281 	FEATURE_LL_LT_SAP_VENDOR_COMMANDS
21282 	FEATURE_TX_LATENCY_STATS_COMMANDS
21283 	FEATURE_REGULATORY_TPC_INFO_VENDOR_COMMANDS
21284 };
21285 
hdd_cfg80211_wiphy_alloc(void)21286 struct hdd_context *hdd_cfg80211_wiphy_alloc(void)
21287 {
21288 	struct wiphy *wiphy;
21289 	struct hdd_context *hdd_ctx;
21290 
21291 	hdd_enter();
21292 
21293 	wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, sizeof(*hdd_ctx));
21294 	if (!wiphy) {
21295 		hdd_err("failed to allocate wiphy!");
21296 		return NULL;
21297 	}
21298 
21299 	hdd_ctx = wiphy_priv(wiphy);
21300 	hdd_ctx->wiphy = wiphy;
21301 
21302 	return hdd_ctx;
21303 }
21304 
wlan_hdd_cfg80211_update_band(struct hdd_context * hdd_ctx,struct wiphy * wiphy,enum band_info new_band)21305 int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx,
21306 				  struct wiphy *wiphy,
21307 				  enum band_info new_band)
21308 {
21309 	int i, j;
21310 	enum channel_state channel_state;
21311 
21312 	hdd_enter();
21313 
21314 	for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
21315 
21316 		if (!wiphy->bands[i])
21317 			continue;
21318 
21319 		for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
21320 			struct ieee80211_supported_band *band = wiphy->bands[i];
21321 
21322 			channel_state = wlan_reg_get_channel_state_for_pwrmode(
21323 					hdd_ctx->pdev,
21324 					band->channels[j].center_freq,
21325 					REG_CURRENT_PWR_MODE);
21326 
21327 			if (HDD_NL80211_BAND_2GHZ == i &&
21328 			    BAND_5G == new_band) {
21329 				/* 5G only */
21330 #ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
21331 				/* Enable Social channels for P2P */
21332 				if (WLAN_HDD_IS_SOCIAL_CHANNEL
21333 					    (band->channels[j].center_freq)
21334 				    && CHANNEL_STATE_ENABLE ==
21335 				    channel_state)
21336 					band->channels[j].flags &=
21337 						~IEEE80211_CHAN_DISABLED;
21338 				else
21339 #endif
21340 				band->channels[j].flags |=
21341 					IEEE80211_CHAN_DISABLED;
21342 				continue;
21343 			} else if (HDD_NL80211_BAND_5GHZ == i &&
21344 				   BAND_2G == new_band) {
21345 				/* 2G only */
21346 				band->channels[j].flags |=
21347 					IEEE80211_CHAN_DISABLED;
21348 				continue;
21349 			}
21350 
21351 			if (CHANNEL_STATE_DISABLE != channel_state)
21352 				band->channels[j].flags &=
21353 					~IEEE80211_CHAN_DISABLED;
21354 		}
21355 	}
21356 	return 0;
21357 }
21358 
21359 #if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
21360 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
wlan_hdd_cfg80211_scan_randomization_init(struct wiphy * wiphy)21361 static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
21362 {
21363 	wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
21364 	wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
21365 }
21366 #else
wlan_hdd_cfg80211_scan_randomization_init(struct wiphy * wiphy)21367 static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
21368 {
21369 }
21370 #endif
21371 
21372 #define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
21373 
21374 #if defined(CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME) || \
21375 		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
21376 /**
21377  * wlan_hdd_cfg80211_action_frame_randomization_init() - Randomize SA of MA
21378  * frames
21379  * @wiphy: Pointer to wiphy
21380  *
21381  * This function is used to indicate the support of source mac address
21382  * randomization of management action frames
21383  *
21384  * Return: None
21385  */
21386 static void
wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy * wiphy)21387 wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
21388 {
21389 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA);
21390 }
21391 #else
21392 static void
wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy * wiphy)21393 wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
21394 {
21395 }
21396 #endif
21397 
21398 #if defined(WLAN_FEATURE_FILS_SK) && \
21399 	(defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
21400 		 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy * wiphy)21401 static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
21402 {
21403 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
21404 }
21405 #else
wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy * wiphy)21406 static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
21407 {
21408 }
21409 #endif
21410 
21411 #if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
21412 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy * wiphy)21413 static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
21414 {
21415 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
21416 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
21417 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
21418 }
21419 #else
wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy * wiphy)21420 static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
21421 {
21422 }
21423 #endif
21424 
21425 #if defined(CFG80211_BIGTK_CONFIGURATION_SUPPORT) || \
21426 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
wlan_hdd_cfg80211_set_bigtk_flags(struct wiphy * wiphy)21427 static void wlan_hdd_cfg80211_set_bigtk_flags(struct wiphy *wiphy)
21428 {
21429 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION);
21430 }
21431 #else
wlan_hdd_cfg80211_set_bigtk_flags(struct wiphy * wiphy)21432 static void wlan_hdd_cfg80211_set_bigtk_flags(struct wiphy *wiphy)
21433 {
21434 }
21435 #endif
21436 
21437 #if defined(CFG80211_OCV_CONFIGURATION_SUPPORT) || \
21438 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
wlan_hdd_cfg80211_set_ocv_flags(struct wiphy * wiphy)21439 static void wlan_hdd_cfg80211_set_ocv_flags(struct wiphy *wiphy)
21440 {
21441 	wiphy_ext_feature_set(wiphy,
21442 			      NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION);
21443 }
21444 #else
wlan_hdd_cfg80211_set_ocv_flags(struct wiphy * wiphy)21445 static void wlan_hdd_cfg80211_set_ocv_flags(struct wiphy *wiphy)
21446 {
21447 }
21448 #endif
21449 
21450 #if defined(CFG80211_SCAN_OCE_CAPABILITY_SUPPORT) || \
21451 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy * wiphy)21452 static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
21453 {
21454 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME);
21455 	wiphy_ext_feature_set(wiphy,
21456 			      NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP);
21457 	wiphy_ext_feature_set(wiphy,
21458 			      NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
21459 	wiphy_ext_feature_set(
21460 		wiphy, NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION);
21461 }
21462 #else
wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy * wiphy)21463 static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
21464 {
21465 }
21466 #endif
21467 
21468 #if defined(WLAN_FEATURE_SAE) && \
21469 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
21470 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
21471 /**
21472  * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
21473  * @wiphy: Pointer to wiphy
21474  *
21475  * This function is used to indicate the support of SAE
21476  *
21477  * Return: None
21478  */
wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy * wiphy)21479 static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
21480 {
21481 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
21482 
21483 	if (ucfg_fwol_get_sae_enable(hdd_ctx->psoc))
21484 		wiphy->features |= NL80211_FEATURE_SAE;
21485 }
21486 #else
wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy * wiphy)21487 static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
21488 {
21489 }
21490 #endif
21491 
21492 #if defined(CFG80211_SAE_AUTH_TA_ADDR_SUPPORT)
wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(struct wiphy * wiphy)21493 static void wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(struct wiphy *wiphy)
21494 {
21495 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AUTH_TX_RANDOM_TA);
21496 }
21497 #else
wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(struct wiphy * wiphy)21498 static void wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(struct wiphy *wiphy)
21499 {
21500 }
21501 #endif
21502 
21503 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
21504 	defined(CFG80211_DFS_OFFLOAD_BACKPORT)
wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy * wiphy)21505 static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
21506 {
21507 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
21508 }
21509 #else
wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy * wiphy)21510 static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
21511 {
21512 	wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
21513 }
21514 #endif
21515 
21516 #ifdef WLAN_FEATURE_DSRC
wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config * hdd_cfg,int * num_ch,int * ch_len)21517 static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
21518 					     int *num_ch, int *ch_len)
21519 {
21520 	*num_ch = QDF_ARRAY_SIZE(hdd_channels_dot11p);
21521 	*ch_len = sizeof(hdd_channels_dot11p);
21522 }
21523 
wlan_hdd_copy_dsrc_ch(char * ch_ptr,int ch_arr_len)21524 static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
21525 {
21526 	if (!ch_arr_len)
21527 		return;
21528 	qdf_mem_copy(ch_ptr, &hdd_channels_dot11p[0], ch_arr_len);
21529 }
21530 
wlan_hdd_get_num_srd_ch_and_len(struct hdd_config * hdd_cfg,int * num_ch,int * ch_len)21531 static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
21532 					    int *num_ch, int *ch_len)
21533 {
21534 	*num_ch = 0;
21535 	*ch_len = 0;
21536 }
21537 
wlan_hdd_copy_srd_ch(char * ch_ptr,int ch_arr_len)21538 static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
21539 {
21540 }
21541 
21542 /**
21543  * wlan_hdd_populate_5dot9_chan_info() - Populate 5.9 GHz chan info in hdd
21544  * context
21545  * @hdd_ctx: pointer to hdd context
21546  * @index: 5.9 GHz channel beginning index in chan_info of @hdd_ctx
21547  *
21548  * Return: Number of 5.9 GHz channels populated
21549  */
21550 static uint32_t
wlan_hdd_populate_5dot9_chan_info(struct hdd_context * hdd_ctx,uint32_t index)21551 wlan_hdd_populate_5dot9_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
21552 {
21553 	return 0;
21554 }
21555 
21556 #else
21557 
wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config * hdd_cfg,int * num_ch,int * ch_len)21558 static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
21559 					     int *num_ch, int *ch_len)
21560 {
21561 	*num_ch = 0;
21562 	*ch_len = 0;
21563 }
21564 
wlan_hdd_copy_dsrc_ch(char * ch_ptr,int ch_arr_len)21565 static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
21566 {
21567 }
21568 
wlan_hdd_get_num_srd_ch_and_len(struct hdd_config * hdd_cfg,int * num_ch,int * ch_len)21569 static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
21570 					    int *num_ch, int *ch_len)
21571 {
21572 	*num_ch = QDF_ARRAY_SIZE(hdd_5dot9_ghz_ch);
21573 	*ch_len = sizeof(hdd_5dot9_ghz_ch);
21574 }
21575 
wlan_hdd_copy_srd_ch(char * ch_ptr,int ch_arr_len)21576 static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
21577 {
21578 	if (!ch_arr_len)
21579 		return;
21580 	qdf_mem_copy(ch_ptr, &hdd_5dot9_ghz_ch[0], ch_arr_len);
21581 }
21582 
21583 /**
21584  * wlan_hdd_populate_5dot9_chan_info() - Populate 5.9 GHz chan info in hdd
21585  * context
21586  * @hdd_ctx: pointer to hdd context
21587  * @index: 5.9 GHz channel beginning index in chan_info of @hdd_ctx
21588  *
21589  * Return: Number of 5.9 GHz channels populated
21590  */
21591 static uint32_t
wlan_hdd_populate_5dot9_chan_info(struct hdd_context * hdd_ctx,uint32_t index)21592 wlan_hdd_populate_5dot9_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
21593 {
21594 	uint32_t num_5dot9_ch, i;
21595 	struct scan_chan_info *chan_info;
21596 
21597 	num_5dot9_ch = QDF_ARRAY_SIZE(hdd_5dot9_ghz_ch);
21598 	chan_info = hdd_ctx->chan_info;
21599 
21600 	for (i = 0; i < num_5dot9_ch; i++)
21601 		chan_info[index + i].freq = hdd_5dot9_ghz_ch[i].center_freq;
21602 
21603 	return num_5dot9_ch;
21604 }
21605 
21606 #endif
21607 
21608 #if defined(WLAN_FEATURE_11AX) && \
21609 	(defined(CFG80211_SBAND_IFTYPE_DATA_BACKPORT) || \
21610 	 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)))
21611 #if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
21612 	   (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
21613 static QDF_STATUS
wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context * hdd_ctx)21614 wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
21615 {
21616 	hdd_ctx->iftype_data_6g =
21617 			qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_6g) *
21618 				       EHT_OPMODE_SUPPORTED);
21619 
21620 	if (!hdd_ctx->iftype_data_6g)
21621 		return QDF_STATUS_E_NOMEM;
21622 
21623 	return QDF_STATUS_SUCCESS;
21624 }
21625 
21626 static void
wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context * hdd_ctx)21627 wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
21628 {
21629 	qdf_mem_free(hdd_ctx->iftype_data_6g);
21630 	hdd_ctx->iftype_data_6g = NULL;
21631 }
21632 #else
21633 static inline QDF_STATUS
wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context * hdd_ctx)21634 wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
21635 {
21636 	return QDF_STATUS_SUCCESS;
21637 }
21638 
21639 static inline void
wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context * hdd_ctx)21640 wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
21641 {
21642 }
21643 #endif
21644 
21645 static QDF_STATUS
wlan_hdd_iftype_data_alloc(struct hdd_context * hdd_ctx)21646 wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
21647 {
21648 	hdd_ctx->iftype_data_2g =
21649 			qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_2g) *
21650 				       EHT_OPMODE_SUPPORTED);
21651 
21652 	if (!hdd_ctx->iftype_data_2g)
21653 		return QDF_STATUS_E_NOMEM;
21654 
21655 	hdd_ctx->iftype_data_5g =
21656 			qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_5g) *
21657 				       EHT_OPMODE_SUPPORTED);
21658 	if (!hdd_ctx->iftype_data_5g) {
21659 		qdf_mem_free(hdd_ctx->iftype_data_2g);
21660 		hdd_ctx->iftype_data_2g = NULL;
21661 		return QDF_STATUS_E_NOMEM;
21662 	}
21663 
21664 	if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc_6ghz(hdd_ctx))) {
21665 		qdf_mem_free(hdd_ctx->iftype_data_5g);
21666 		qdf_mem_free(hdd_ctx->iftype_data_2g);
21667 		hdd_ctx->iftype_data_2g = NULL;
21668 		hdd_ctx->iftype_data_5g = NULL;
21669 		return QDF_STATUS_E_NOMEM;
21670 	}
21671 
21672 	return QDF_STATUS_SUCCESS;
21673 }
21674 
21675 static void
wlan_hdd_iftype_data_mem_free(struct hdd_context * hdd_ctx)21676 wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
21677 {
21678 	wlan_hdd_iftype_data_mem_free_6ghz(hdd_ctx);
21679 	qdf_mem_free(hdd_ctx->iftype_data_5g);
21680 	qdf_mem_free(hdd_ctx->iftype_data_2g);
21681 	hdd_ctx->iftype_data_5g = NULL;
21682 	hdd_ctx->iftype_data_2g = NULL;
21683 }
21684 #else
21685 static QDF_STATUS
wlan_hdd_iftype_data_alloc(struct hdd_context * hdd_ctx)21686 wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
21687 
21688 {
21689 	return QDF_STATUS_SUCCESS;
21690 }
21691 
21692 static inline void
wlan_hdd_iftype_data_mem_free(struct hdd_context * hdd_ctx)21693 wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
21694 {
21695 }
21696 #endif
21697 
21698 #if defined(WLAN_FEATURE_NAN) && \
21699 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
wlan_hdd_set_nan_if_mode(struct wiphy * wiphy)21700 static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
21701 {
21702 	wiphy->interface_modes |= BIT(NL80211_IFTYPE_NAN);
21703 }
21704 #else
wlan_hdd_set_nan_if_mode(struct wiphy * wiphy)21705 static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
21706 {
21707 }
21708 #endif
21709 
21710 #if defined(WLAN_FEATURE_NAN) && \
21711 	   (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
wlan_hdd_set_nan_supported_bands(struct wiphy * wiphy)21712 static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
21713 {
21714 	wiphy->nan_supported_bands =
21715 		BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ);
21716 }
21717 #else
wlan_hdd_set_nan_supported_bands(struct wiphy * wiphy)21718 static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
21719 {
21720 }
21721 #endif
21722 
21723 #if defined(WLAN_FEATURE_NAN) && defined(WLAN_EXT_FEATURE_SECURE_NAN)
21724 /**
21725  * wlan_hdd_set_nan_secure_mode - Populate Secure NAN supported by driver
21726  * @wiphy: wiphy
21727  *
21728  * Return: void
21729  */
wlan_hdd_set_nan_secure_mode(struct wiphy * wiphy)21730 static void wlan_hdd_set_nan_secure_mode(struct wiphy *wiphy)
21731 {
21732 	if (sme_is_feature_supported_by_fw(SECURE_NAN))
21733 		wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SECURE_NAN);
21734 }
21735 #else
wlan_hdd_set_nan_secure_mode(struct wiphy * wiphy)21736 static void wlan_hdd_set_nan_secure_mode(struct wiphy *wiphy)
21737 {
21738 }
21739 #endif
21740 
21741 /**
21742  * wlan_hdd_update_akm_suit_info() - Populate akm suits supported by driver
21743  * @wiphy: wiphy
21744  *
21745  * Return: void
21746  */
21747 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) || \
21748 	defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
21749 static void
wlan_hdd_update_akm_suit_info(struct wiphy * wiphy)21750 wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
21751 {
21752 	wiphy->iftype_akm_suites = wlan_hdd_akm_suites;
21753 	wiphy->num_iftype_akm_suites = QDF_ARRAY_SIZE(wlan_hdd_akm_suites);
21754 }
21755 #else
21756 static void
wlan_hdd_update_akm_suit_info(struct wiphy * wiphy)21757 wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
21758 {
21759 }
21760 #endif
21761 
21762 #ifdef CFG80211_CTRL_FRAME_SRC_ADDR_TA_ADDR
wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy * wiphy)21763 static void wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy *wiphy)
21764 {
21765 	wiphy_ext_feature_set(wiphy,
21766 			      NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
21767 	wiphy_ext_feature_set(wiphy,
21768 			      NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH);
21769 }
21770 #else
wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy * wiphy)21771 static void wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy *wiphy)
21772 {
21773 }
21774 #endif
21775 
21776 #ifdef WLAN_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA
21777 /**
21778  * wlan_hdd_set_auth_deauth_random_ta_feature_flag() - set feature flag for
21779  * random address for auth and deauth frames to the kernel.
21780  * @wiphy: wiphy
21781  *
21782  * Return: void
21783  */
wlan_hdd_set_auth_deauth_random_ta_feature_flag(struct wiphy * wiphy)21784 static void wlan_hdd_set_auth_deauth_random_ta_feature_flag(struct wiphy *wiphy)
21785 {
21786 	wiphy_ext_feature_set(wiphy,
21787 			      NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA);
21788 }
21789 #else
wlan_hdd_set_auth_deauth_random_ta_feature_flag(struct wiphy * wiphy)21790 static void wlan_hdd_set_auth_deauth_random_ta_feature_flag(struct wiphy *wiphy)
21791 {
21792 }
21793 #endif
21794 
21795 #ifdef CFG80211_MULTI_AKM_CONNECT_SUPPORT
21796 static void
wlan_hdd_update_max_connect_akm(struct wiphy * wiphy)21797 wlan_hdd_update_max_connect_akm(struct wiphy *wiphy)
21798 {
21799 	wiphy->max_num_akm_suites = WLAN_CM_MAX_CONNECT_AKMS;
21800 }
21801 #else
21802 static void
wlan_hdd_update_max_connect_akm(struct wiphy * wiphy)21803 wlan_hdd_update_max_connect_akm(struct wiphy *wiphy)
21804 {
21805 }
21806 #endif
21807 
21808 #ifdef NL80211_EXT_FEATURE_PUNCT_SUPPORT
21809 /**
21810  * wlan_hdd_set_ext_feature_punct() - set feature flag for puncture
21811  * @wiphy: wiphy
21812  *
21813  * Return: void
21814  */
wlan_hdd_set_ext_feature_punct(struct wiphy * wiphy)21815 static void wlan_hdd_set_ext_feature_punct(struct wiphy *wiphy)
21816 {
21817 	hdd_debug("enable puncture cap");
21818 	wiphy_ext_feature_set(wiphy,
21819 			      NL80211_EXT_FEATURE_PUNCT);
21820 }
21821 #else
wlan_hdd_set_ext_feature_punct(struct wiphy * wiphy)21822 static inline void wlan_hdd_set_ext_feature_punct(struct wiphy *wiphy)
21823 {
21824 }
21825 #endif
21826 
21827 /*
21828  * FUNCTION: wlan_hdd_cfg80211_init
21829  * This function is called by hdd_wlan_startup()
21830  * during initialization.
21831  * This function is used to initialize and register wiphy structure.
21832  */
wlan_hdd_cfg80211_init(struct device * dev,struct wiphy * wiphy,struct hdd_config * config)21833 int wlan_hdd_cfg80211_init(struct device *dev,
21834 			   struct wiphy *wiphy, struct hdd_config *config)
21835 {
21836 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
21837 	uint32_t *cipher_suites;
21838 	hdd_enter();
21839 
21840 	/* Now bind the underlying wlan device with wiphy */
21841 	set_wiphy_dev(wiphy, dev);
21842 
21843 	wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
21844 	wlan_hdd_update_akm_suit_info(wiphy);
21845 	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
21846 			| WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
21847 			| WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
21848 #ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
21849 			| WIPHY_FLAG_4ADDR_STATION
21850 #endif
21851 			| WIPHY_FLAG_OFFCHAN_TX
21852 			| WIPHY_FLAG_NETNS_OK;
21853 
21854 	if (ucfg_pmo_get_suspend_mode(hdd_ctx->psoc) == PMO_SUSPEND_WOW) {
21855 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
21856 		wiphy->wowlan = &wowlan_support_cfg80211_init;
21857 #else
21858 		wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
21859 		wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
21860 		wiphy->wowlan.pattern_min_len = 1;
21861 		wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
21862 #endif
21863 	}
21864 
21865 #ifdef FEATURE_WLAN_TDLS
21866 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
21867 			| WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
21868 #endif
21869 
21870 	wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
21871 
21872 	wlan_scan_cfg80211_add_connected_pno_support(wiphy);
21873 
21874 	wiphy->max_scan_ssids = MAX_SCAN_SSID;
21875 
21876 	wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
21877 
21878 	wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
21879 
21880 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
21881 				 | BIT(NL80211_IFTYPE_P2P_CLIENT)
21882 				 | BIT(NL80211_IFTYPE_P2P_GO)
21883 				 | BIT(NL80211_IFTYPE_AP)
21884 				 | BIT(NL80211_IFTYPE_MONITOR);
21885 
21886 	wlan_hdd_set_nan_if_mode(wiphy);
21887 
21888 	/*
21889 	 * In case of static linked driver at the time of driver unload,
21890 	 * module exit doesn't happens. Module cleanup helps in cleaning
21891 	 * of static memory.
21892 	 * If driver load happens statically, at the time of driver unload,
21893 	 * wiphy flags don't get reset because of static memory.
21894 	 * It's better not to store channel in static memory.
21895 	 * The memory is for channels of struct wiphy and shouldn't be
21896 	 * released during stop modules. So if it's allocated in active
21897 	 * domain, the memory leak detector would catch the leak during
21898 	 * stop modules. To avoid this,alloc in init domain in advance.
21899 	 */
21900 	hdd_ctx->channels_2ghz = qdf_mem_malloc(band_2_ghz_channels_size);
21901 	if (!hdd_ctx->channels_2ghz)
21902 		return -ENOMEM;
21903 
21904 	hdd_ctx->channels_5ghz = qdf_mem_malloc(band_5_ghz_channels_size);
21905 	if (!hdd_ctx->channels_5ghz)
21906 		goto mem_fail_5g;
21907 
21908 	if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc(hdd_ctx)))
21909 		goto mem_fail_iftype_data;
21910 
21911 	/*Initialise the supported cipher suite details */
21912 	if (ucfg_fwol_get_gcmp_enable(hdd_ctx->psoc)) {
21913 		cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
21914 					       sizeof(hdd_gcmp_cipher_suits));
21915 		if (!cipher_suites)
21916 			goto mem_fail_cipher_suites;
21917 		wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
21918 			 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
21919 		qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
21920 			     sizeof(hdd_cipher_suites));
21921 		qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
21922 			     &hdd_gcmp_cipher_suits,
21923 			     sizeof(hdd_gcmp_cipher_suits));
21924 	} else {
21925 		cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
21926 		if (!cipher_suites)
21927 			goto mem_fail_cipher_suites;
21928 		wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
21929 		qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
21930 			     sizeof(hdd_cipher_suites));
21931 	}
21932 	wiphy->cipher_suites = cipher_suites;
21933 	cipher_suites = NULL;
21934 	/*signal strength in mBm (100*dBm) */
21935 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
21936 	wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
21937 
21938 	wiphy->n_vendor_commands = ARRAY_SIZE(hdd_wiphy_vendor_commands);
21939 	wiphy->vendor_commands = hdd_wiphy_vendor_commands;
21940 
21941 	wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
21942 	wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
21943 
21944 #ifdef QCA_HT_2040_COEX
21945 	wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
21946 #endif
21947 	wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
21948 
21949 	wiphy->features |= NL80211_FEATURE_VIF_TXPOWER;
21950 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
21951 	defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
21952 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
21953 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
21954 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
21955 #endif
21956 
21957 	hdd_add_channel_switch_support(&wiphy->flags);
21958 	wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
21959 
21960 	wlan_hdd_update_max_connect_akm(wiphy);
21961 
21962 	wlan_hdd_cfg80211_action_frame_randomization_init(wiphy);
21963 	wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(wiphy);
21964 
21965 	wlan_hdd_set_nan_supported_bands(wiphy);
21966 
21967 	wlan_hdd_update_eapol_over_nl80211_flags(wiphy);
21968 
21969 	wlan_hdd_set_auth_deauth_random_ta_feature_flag(wiphy);
21970 	wlan_hdd_set_ext_feature_punct(wiphy);
21971 
21972 	hdd_exit();
21973 	return 0;
21974 
21975 mem_fail_cipher_suites:
21976 	wlan_hdd_iftype_data_mem_free(hdd_ctx);
21977 mem_fail_iftype_data:
21978 	qdf_mem_free(hdd_ctx->channels_5ghz);
21979 	hdd_ctx->channels_5ghz = NULL;
21980 mem_fail_5g:
21981 	hdd_err("Not enough memory to allocate channels");
21982 	qdf_mem_free(hdd_ctx->channels_2ghz);
21983 	hdd_ctx->channels_2ghz = NULL;
21984 
21985 	return -ENOMEM;
21986 }
21987 
21988 /**
21989  * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
21990  * @wiphy: the wiphy to validate against
21991  *
21992  * this function deinit cfg80211 and cleanup the
21993  * memory allocated in wlan_hdd_cfg80211_init also
21994  * reset the global reg params.
21995  *
21996  * Return: void
21997  */
wlan_hdd_cfg80211_deinit(struct wiphy * wiphy)21998 void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
21999 {
22000 	int i;
22001 	const uint32_t *cipher_suites;
22002 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
22003 
22004 	for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
22005 		if (wiphy->bands[i] &&
22006 		   (wiphy->bands[i]->channels))
22007 			wiphy->bands[i]->channels = NULL;
22008 	}
22009 	wlan_hdd_iftype_data_mem_free(hdd_ctx);
22010 	qdf_mem_free(hdd_ctx->channels_5ghz);
22011 	qdf_mem_free(hdd_ctx->channels_2ghz);
22012 	hdd_ctx->channels_2ghz = NULL;
22013 	hdd_ctx->channels_5ghz = NULL;
22014 
22015 	cipher_suites = wiphy->cipher_suites;
22016 	wiphy->cipher_suites = NULL;
22017 	wiphy->n_cipher_suites = 0;
22018 	qdf_mem_free((uint32_t *)cipher_suites);
22019 	cipher_suites = NULL;
22020 	hdd_reset_global_reg_params();
22021 }
22022 
22023 /**
22024  * wlan_hdd_update_ht_cap() - update HT capabilities for supported bands
22025  * @hdd_ctx: HDD context
22026  *
22027  * this function will update HT capabilities for supported bands
22028  *
22029  * Return: void
22030  */
wlan_hdd_update_ht_cap(struct hdd_context * hdd_ctx)22031 static void wlan_hdd_update_ht_cap(struct hdd_context *hdd_ctx)
22032 {
22033 	struct mlme_ht_capabilities_info ht_cap_info = {0};
22034 	QDF_STATUS status;
22035 	uint32_t channel_bonding_mode;
22036 	struct ieee80211_supported_band *band_2g;
22037 	struct ieee80211_supported_band *band_5g;
22038 	uint8_t i;
22039 
22040 	status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
22041 	if (QDF_STATUS_SUCCESS != status)
22042 		hdd_err("could not get HT capability info");
22043 
22044 	band_2g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ];
22045 	band_5g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ];
22046 
22047 	if (band_2g) {
22048 		if (ht_cap_info.tx_stbc)
22049 			band_2g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
22050 
22051 		if (!sme_is_feature_supported_by_fw(DOT11AC)) {
22052 			band_2g->vht_cap.vht_supported = 0;
22053 			band_2g->vht_cap.cap = 0;
22054 		}
22055 
22056 		if (!ht_cap_info.short_gi_20_mhz)
22057 			band_2g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
22058 
22059 		for (i = 0; i < hdd_ctx->num_rf_chains; i++)
22060 			band_2g->ht_cap.mcs.rx_mask[i] = 0xff;
22061 
22062 		/*
22063 		 * According to mcs_nss HT MCS parameters highest data rate for
22064 		 * Nss = 1 is 150 Mbps
22065 		 */
22066 		band_2g->ht_cap.mcs.rx_highest =
22067 				cpu_to_le16(150 * hdd_ctx->num_rf_chains);
22068 	}
22069 
22070 	if (band_5g) {
22071 		if (ht_cap_info.tx_stbc)
22072 			band_5g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
22073 
22074 		if (!sme_is_feature_supported_by_fw(DOT11AC)) {
22075 			band_5g->vht_cap.vht_supported = 0;
22076 			band_5g->vht_cap.cap = 0;
22077 		}
22078 
22079 		if (!ht_cap_info.short_gi_20_mhz)
22080 			band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
22081 
22082 		if (!ht_cap_info.short_gi_40_mhz)
22083 			band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
22084 
22085 		ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
22086 						   &channel_bonding_mode);
22087 		if (!channel_bonding_mode)
22088 			band_5g->ht_cap.cap &=
22089 					~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
22090 
22091 		for (i = 0; i < hdd_ctx->num_rf_chains; i++)
22092 			band_5g->ht_cap.mcs.rx_mask[i] = 0xff;
22093 		/*
22094 		 * According to mcs_nss HT MCS parameters highest data rate for
22095 		 * Nss = 1 is 150 Mbps
22096 		 */
22097 		band_5g->ht_cap.mcs.rx_highest =
22098 				cpu_to_le16(150 * hdd_ctx->num_rf_chains);
22099 	}
22100 }
22101 
22102 /**
22103  * wlan_hdd_update_band_cap_in_wiphy() - update channel flags based on band cap
22104  * @hdd_ctx: HDD context
22105  *
22106  * This function updates the channel flags based on the band capability set
22107  * in the MLME CFG
22108  *
22109  * Return: void
22110  */
wlan_hdd_update_band_cap_in_wiphy(struct hdd_context * hdd_ctx)22111 static void wlan_hdd_update_band_cap_in_wiphy(struct hdd_context *hdd_ctx)
22112 {
22113 	int i, j;
22114 	uint32_t band_capability;
22115 	QDF_STATUS status;
22116 	struct ieee80211_supported_band *band;
22117 
22118 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
22119 	if (QDF_IS_STATUS_ERROR(status)) {
22120 		hdd_err("Failed to get MLME Band Capability");
22121 		return;
22122 	}
22123 
22124 	for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
22125 		if (!hdd_ctx->wiphy->bands[i])
22126 			continue;
22127 
22128 		for (j = 0; j < hdd_ctx->wiphy->bands[i]->n_channels; j++) {
22129 			band = hdd_ctx->wiphy->bands[i];
22130 
22131 			if (HDD_NL80211_BAND_2GHZ == i &&
22132 			    BIT(REG_BAND_5G) == band_capability) {
22133 				/* 5G only */
22134 #ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
22135 				/* Enable social channels for P2P */
22136 				if (WLAN_HDD_IS_SOCIAL_CHANNEL
22137 				    (band->channels[j].center_freq))
22138 					band->channels[j].flags &=
22139 						~IEEE80211_CHAN_DISABLED;
22140 				else
22141 #endif
22142 				band->channels[j].flags |=
22143 					IEEE80211_CHAN_DISABLED;
22144 				continue;
22145 			} else if (HDD_NL80211_BAND_5GHZ == i &&
22146 				   BIT(REG_BAND_2G) == band_capability) {
22147 				/* 2G only */
22148 				band->channels[j].flags |=
22149 					IEEE80211_CHAN_DISABLED;
22150 				continue;
22151 			}
22152 		}
22153 	}
22154 }
22155 
22156 #ifdef FEATURE_WLAN_ESE
22157 /**
22158  * wlan_hdd_update_lfr_wiphy() - update LFR flag based on configures
22159  * @hdd_ctx: HDD context
22160  *
22161  * This function updates the LFR flag based on LFR configures
22162  *
22163  * Return: void
22164  */
wlan_hdd_update_lfr_wiphy(struct hdd_context * hdd_ctx)22165 static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
22166 {
22167 	bool fast_transition_enabled;
22168 	bool lfr_enabled;
22169 	bool ese_enabled;
22170 	bool roam_offload;
22171 
22172 	ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
22173 					     &fast_transition_enabled);
22174 	ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
22175 	ucfg_mlme_is_ese_enabled(hdd_ctx->psoc, &ese_enabled);
22176 	ucfg_mlme_get_roaming_offload(hdd_ctx->psoc, &roam_offload);
22177 	if (fast_transition_enabled || lfr_enabled || ese_enabled ||
22178 	    roam_offload)
22179 		hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
22180 }
22181 #else
wlan_hdd_update_lfr_wiphy(struct hdd_context * hdd_ctx)22182 static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
22183 {
22184 	bool fast_transition_enabled;
22185 	bool lfr_enabled;
22186 	bool roam_offload;
22187 
22188 	ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
22189 					     &fast_transition_enabled);
22190 	ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
22191 	ucfg_mlme_get_roaming_offload(hdd_ctx->psoc, &roam_offload);
22192 	if (fast_transition_enabled || lfr_enabled || roam_offload)
22193 		hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
22194 }
22195 #endif
22196 
22197 #if defined (CFG80211_SA_QUERY_OFFLOAD_SUPPORT) || \
22198 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
22199 /**
22200  * wlan_hdd_set_sa_query_offload_wiphy() - set sa query offload cap in sme cap
22201  * @hdd_ctx: HDD context
22202  *
22203  * This function set sa query offload cap for ap sme capabilities in wiphy
22204  *
22205  * Return: void
22206  */
wlan_hdd_set_sa_query_offload_wiphy(struct hdd_context * hdd_ctx)22207 static void wlan_hdd_set_sa_query_offload_wiphy(struct hdd_context *hdd_ctx)
22208 {
22209 	hdd_ctx->wiphy->ap_sme_capa |= NL80211_AP_SME_SA_QUERY_OFFLOAD;
22210 }
22211 
22212 /**
22213  * wlan_hdd_update_ap_sme_cap_wiphy() - update ap sme capabilities in wiphy
22214  * @hdd_ctx: HDD context
22215  *
22216  * This function update ap sme capabilities in wiphy
22217  *
22218  * Return: void
22219  */
wlan_hdd_update_ap_sme_cap_wiphy(struct hdd_context * hdd_ctx)22220 static void wlan_hdd_update_ap_sme_cap_wiphy(struct hdd_context *hdd_ctx)
22221 {
22222 	wlan_hdd_set_sa_query_offload_wiphy(hdd_ctx);
22223 }
22224 #else
wlan_hdd_update_ap_sme_cap_wiphy(struct hdd_context * hdd_ctx)22225 static void wlan_hdd_update_ap_sme_cap_wiphy(struct hdd_context *hdd_ctx)
22226 {
22227 }
22228 #endif
22229 
22230 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
22231 static inline
wlan_hdd_set_mlo_wiphy_ext_feature(struct wiphy * wiphy,struct hdd_context * hdd_ctx)22232 void wlan_hdd_set_mlo_wiphy_ext_feature(struct wiphy *wiphy,
22233 					struct hdd_context *hdd_ctx)
22234 {
22235 	bool eht_capab;
22236 
22237 	wlan_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
22238 	if (!eht_capab)
22239 		return;
22240 
22241 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
22242 }
22243 #else
22244 static inline
wlan_hdd_set_mlo_wiphy_ext_feature(struct wiphy * wiphy,struct hdd_context * hdd_ctx)22245 void wlan_hdd_set_mlo_wiphy_ext_feature(struct wiphy *wiphy,
22246 					struct hdd_context *hdd_ctx)
22247 {
22248 }
22249 #endif
22250 
22251 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
22252 static inline
wlan_hdd_set_ext_kek_kck_support(struct wiphy * wiphy)22253 void wlan_hdd_set_ext_kek_kck_support(struct wiphy *wiphy)
22254 {
22255 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK;
22256 }
22257 #else
22258 static inline
wlan_hdd_set_ext_kek_kck_support(struct wiphy * wiphy)22259 void wlan_hdd_set_ext_kek_kck_support(struct wiphy *wiphy)
22260 {
22261 }
22262 #endif
22263 
22264 #ifdef NL80211_KCK_EXT_LEN_32
22265 static inline
wlan_hdd_set_32bytes_kck_support(struct wiphy * wiphy)22266 void wlan_hdd_set_32bytes_kck_support(struct wiphy *wiphy)
22267 {
22268 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_EXT_KCK_32;
22269 }
22270 #else
22271 static inline
wlan_hdd_set_32bytes_kck_support(struct wiphy * wiphy)22272 void wlan_hdd_set_32bytes_kck_support(struct wiphy *wiphy)
22273 {
22274 }
22275 #endif
22276 
22277 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
wlan_hdd_set_vlan_offload(struct hdd_context * hdd_ctx)22278 static void wlan_hdd_set_vlan_offload(struct hdd_context *hdd_ctx)
22279 {
22280 	if (ucfg_mlme_is_multipass_sap(hdd_ctx->psoc))
22281 		wiphy_ext_feature_set(hdd_ctx->wiphy,
22282 				      NL80211_EXT_FEATURE_VLAN_OFFLOAD);
22283 }
22284 #else
wlan_hdd_set_vlan_offload(struct hdd_context * hdd_ctx)22285 static void wlan_hdd_set_vlan_offload(struct hdd_context *hdd_ctx)
22286 {
22287 }
22288 #endif
22289 
22290 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
wlan_hdd_set_mfp_optional(struct wiphy * wiphy)22291 static void wlan_hdd_set_mfp_optional(struct wiphy *wiphy)
22292 {
22293 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MFP_OPTIONAL);
22294 }
22295 #else
wlan_hdd_set_mfp_optional(struct wiphy * wiphy)22296 static void wlan_hdd_set_mfp_optional(struct wiphy *wiphy)
22297 {
22298 }
22299 #endif
22300 
22301 /**
22302  * wlan_hdd_iface_debug_string() - This API converts IFACE type to string
22303  * @iface_type: interface type
22304  *
22305  * Return: name string
22306  */
wlan_hdd_iface_debug_string(uint32_t iface_type)22307 static char *wlan_hdd_iface_debug_string(uint32_t iface_type)
22308 {
22309 	if (iface_type == BIT(NL80211_IFTYPE_STATION))
22310 		return "STA";
22311 	else if (iface_type == BIT(NL80211_IFTYPE_AP))
22312 		return "SAP";
22313 	else if (iface_type == (BIT(NL80211_IFTYPE_P2P_CLIENT) |
22314 		 BIT(NL80211_IFTYPE_P2P_GO)))
22315 		return "(P2P_CLI or P2P_GO)";
22316 	else if (iface_type == BIT(NL80211_IFTYPE_P2P_CLIENT))
22317 		return "P2P_CLIENT";
22318 	else if (iface_type == BIT(NL80211_IFTYPE_P2P_GO))
22319 		return "P2P_GO";
22320 	else if (iface_type == BIT(NL80211_IFTYPE_NAN))
22321 		return "NAN";
22322 	else if (iface_type == BIT(NL80211_IFTYPE_MONITOR))
22323 		return "MONITOR";
22324 
22325 	return "invalid iface";
22326 }
22327 
22328 #define IFACE_DUMP_SIZE 100
22329 /**
22330  * wlan_hdd_dump_iface_combinations() - This API prints the IFACE combinations
22331  * @num: number of combinations
22332  * @combination: pointer to iface combination structure
22333  *
22334  * Return: void
22335  */
wlan_hdd_dump_iface_combinations(uint32_t num,const struct ieee80211_iface_combination * combination)22336 static void wlan_hdd_dump_iface_combinations(uint32_t num,
22337 			const struct ieee80211_iface_combination *combination)
22338 {
22339 	int i, j, k;
22340 	char buf[IFACE_DUMP_SIZE] = {0};
22341 	uint8_t len = 0;
22342 
22343 	hdd_debug("max combinations %d", num);
22344 
22345 	for (i = 0; i < num; i++) {
22346 		for (j = 0; j < combination[i].n_limits; j++) {
22347 			for (k = 0; k < combination[i].limits[j].max; k++) {
22348 				if (combination[i].limits[j].types)
22349 					len += qdf_scnprintf(buf + len,
22350 					       IFACE_DUMP_SIZE - len,
22351 					       k == 0 && j == 0 ? "%s" : "+%s",
22352 					       wlan_hdd_iface_debug_string(
22353 					       combination[i].limits[j].types));
22354 			}
22355 		}
22356 
22357 		hdd_nofl_debug("iface combination[%d]: %s", i, buf);
22358 		len = 0;
22359 	}
22360 }
22361 
22362 /*
22363  * In this function, wiphy structure is updated after QDF
22364  * initialization. In wlan_hdd_cfg80211_init, only the
22365  * default values will be initialized. The final initialization
22366  * of all required members can be done here.
22367  */
wlan_hdd_update_wiphy(struct hdd_context * hdd_ctx)22368 void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
22369 {
22370 	int value = 0;
22371 	bool fils_enabled, mac_spoofing_enabled;
22372 	bool dfs_master_capable = true, is_oce_sta_enabled = false;
22373 	QDF_STATUS status;
22374 	struct wiphy *wiphy = hdd_ctx->wiphy;
22375 	uint8_t allow_mcc_go_diff_bi = 0, enable_mcc = 0;
22376 	bool is_bigtk_supported;
22377 	bool is_ocv_supported;
22378 	uint8_t iface_num;
22379 	bool dbs_one_by_one, dbs_two_by_two;
22380 
22381 	if (!wiphy) {
22382 		hdd_err("Invalid wiphy");
22383 		return;
22384 	}
22385 	ucfg_mlme_get_sap_max_peers(hdd_ctx->psoc, &value);
22386 	hdd_ctx->wiphy->max_ap_assoc_sta = value;
22387 	wlan_hdd_update_ht_cap(hdd_ctx);
22388 	wlan_hdd_update_band_cap_in_wiphy(hdd_ctx);
22389 	wlan_hdd_update_lfr_wiphy(hdd_ctx);
22390 	wlan_hdd_update_ap_sme_cap_wiphy(hdd_ctx);
22391 
22392 	fils_enabled = 0;
22393 	status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc,
22394 						 &fils_enabled);
22395 	if (QDF_IS_STATUS_ERROR(status))
22396 		hdd_err("could not get fils enabled info");
22397 	if (fils_enabled)
22398 		wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy);
22399 
22400 	status = ucfg_mlme_get_dfs_master_capability(hdd_ctx->psoc,
22401 						     &dfs_master_capable);
22402 	if (QDF_IS_STATUS_SUCCESS(status) && dfs_master_capable)
22403 		wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy);
22404 
22405 
22406 	status = ucfg_mlme_get_bigtk_support(hdd_ctx->psoc,
22407 					     &is_bigtk_supported);
22408 
22409 	if (QDF_IS_STATUS_SUCCESS(status) && is_bigtk_supported)
22410 		wlan_hdd_cfg80211_set_bigtk_flags(wiphy);
22411 
22412 	status = ucfg_mlme_get_ocv_support(hdd_ctx->psoc,
22413 					   &is_ocv_supported);
22414 	if (QDF_IS_STATUS_SUCCESS(status) && is_ocv_supported)
22415 		wlan_hdd_cfg80211_set_ocv_flags(wiphy);
22416 
22417 	status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc,
22418 						    &is_oce_sta_enabled);
22419 	if (QDF_IS_STATUS_ERROR(status))
22420 		hdd_err("could not get OCE STA enable info");
22421 	if (is_oce_sta_enabled)
22422 		wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(wiphy);
22423 
22424 	wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy);
22425 
22426 	if (QDF_STATUS_SUCCESS !=
22427 	    ucfg_policy_mgr_get_allow_mcc_go_diff_bi(hdd_ctx->psoc,
22428 						     &allow_mcc_go_diff_bi))
22429 		hdd_err("can't get mcc_go_diff_bi value, use default");
22430 
22431 	if (QDF_STATUS_SUCCESS !=
22432 	    ucfg_mlme_get_mcc_feature(hdd_ctx->psoc, &enable_mcc))
22433 		hdd_err("can't get enable_mcc value, use default");
22434 
22435 	if (hdd_ctx->config->advertise_concurrent_operation) {
22436 		if (enable_mcc) {
22437 			int i;
22438 
22439 			for (i = 0;
22440 			     i < ARRAY_SIZE(wlan_hdd_iface_combination);
22441 			     i++) {
22442 				if (!allow_mcc_go_diff_bi)
22443 					wlan_hdd_iface_combination[i].
22444 					beacon_int_infra_match = true;
22445 			}
22446 		}
22447 
22448 		status = ucfg_policy_mgr_get_dbs_hw_modes(hdd_ctx->psoc,
22449 							  &dbs_one_by_one,
22450 							  &dbs_two_by_two);
22451 
22452 		if (QDF_IS_STATUS_ERROR(status)) {
22453 			hdd_err("HW mode failure");
22454 			return;
22455 		}
22456 
22457 		if (!ucfg_policy_mgr_is_fw_supports_dbs(hdd_ctx->psoc)) {
22458 			/* Update IFACE combination for non-DBS target */
22459 			wiphy->iface_combinations =
22460 					wlan_hdd_non_dbs_iface_combination;
22461 			iface_num =
22462 				ARRAY_SIZE(wlan_hdd_non_dbs_iface_combination);
22463 		} else if (dbs_one_by_one && !dbs_two_by_two) {
22464 			/* Update IFACE combination for 1x1 DBS target */
22465 			wiphy->iface_combinations =
22466 						wlan_hdd_derived_combination;
22467 			iface_num = ARRAY_SIZE(wlan_hdd_derived_combination);
22468 		} else {
22469 			/* Update IFACE combination for DBS target */
22470 			wiphy->iface_combinations = wlan_hdd_iface_combination;
22471 			iface_num = ARRAY_SIZE(wlan_hdd_iface_combination);
22472 		}
22473 
22474 		wiphy->n_iface_combinations = iface_num;
22475 
22476 		wlan_hdd_dump_iface_combinations(wiphy->n_iface_combinations,
22477 						 wiphy->iface_combinations);
22478 	}
22479 
22480 	mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
22481 	if (mac_spoofing_enabled)
22482 		wlan_hdd_cfg80211_scan_randomization_init(wiphy);
22483 
22484 	wlan_wifi_pos_cfg80211_set_wiphy_ext_feature(wiphy, hdd_ctx->psoc);
22485 	wlan_hdd_set_mlo_wiphy_ext_feature(wiphy, hdd_ctx);
22486 	wlan_hdd_set_ext_kek_kck_support(wiphy);
22487 	wlan_hdd_set_32bytes_kck_support(wiphy);
22488 	wlan_hdd_set_nan_secure_mode(wiphy);
22489 	wlan_hdd_set_vlan_offload(hdd_ctx);
22490 	wlan_hdd_set_mfp_optional(wiphy);
22491 }
22492 
22493 /**
22494  * wlan_hdd_update_11n_mode - update 11n mode
22495  * @hdd_ctx: hdd ccontext
22496  *
22497  * this function updated 11n mode in hdd cfg and UMAC
22498  *
22499  * Return: void
22500  */
wlan_hdd_update_11n_mode(struct hdd_context * hdd_ctx)22501 void wlan_hdd_update_11n_mode(struct hdd_context *hdd_ctx)
22502 {
22503 	struct hdd_config *cfg = hdd_ctx->config;
22504 
22505 	if (sme_is_feature_supported_by_fw(DOT11AC)) {
22506 		hdd_debug("support 11ac");
22507 	} else {
22508 		hdd_debug("not support 11ac");
22509 		if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
22510 		    (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
22511 			cfg->dot11Mode = eHDD_DOT11_MODE_11n;
22512 			ucfg_mlme_set_sap_11ac_override(hdd_ctx->psoc, 0);
22513 			ucfg_mlme_set_go_11ac_override(hdd_ctx->psoc, 0);
22514 		}
22515 	}
22516 }
22517 
wlan_hdd_update_wiphy_supported_band(struct hdd_context * hdd_ctx)22518 QDF_STATUS wlan_hdd_update_wiphy_supported_band(struct hdd_context *hdd_ctx)
22519 {
22520 	int len_5g_ch, num_ch;
22521 	int num_dsrc_ch, len_dsrc_ch, num_srd_ch, len_srd_ch;
22522 	bool is_vht_for_24ghz = false;
22523 	QDF_STATUS status;
22524 	struct hdd_config *cfg = hdd_ctx->config;
22525 	struct wiphy *wiphy = hdd_ctx->wiphy;
22526 
22527 	if (wiphy->registered)
22528 		return QDF_STATUS_SUCCESS;
22529 
22530 	if (hdd_is_2g_supported(hdd_ctx)) {
22531 		if (!hdd_ctx->channels_2ghz)
22532 			return QDF_STATUS_E_NOMEM;
22533 		wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
22534 		wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
22535 							hdd_ctx->channels_2ghz;
22536 		qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
22537 			     &hdd_channels_2_4_ghz[0],
22538 			     sizeof(hdd_channels_2_4_ghz));
22539 
22540 		status = ucfg_mlme_get_vht_for_24ghz(hdd_ctx->psoc,
22541 						     &is_vht_for_24ghz);
22542 		if (QDF_IS_STATUS_ERROR(status))
22543 			hdd_err("could not get VHT capability");
22544 
22545 		if (is_vht_for_24ghz &&
22546 		    sme_is_feature_supported_by_fw(DOT11AC) &&
22547 		    (cfg->dot11Mode == eHDD_DOT11_MODE_AUTO ||
22548 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY ||
22549 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ac ||
22550 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ax ||
22551 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY))
22552 			wlan_hdd_band_2_4_ghz.vht_cap.vht_supported = 1;
22553 	}
22554 	if (!hdd_is_5g_supported(hdd_ctx) ||
22555 	    (eHDD_DOT11_MODE_11b == cfg->dot11Mode) ||
22556 	    (eHDD_DOT11_MODE_11g == cfg->dot11Mode) ||
22557 	    (eHDD_DOT11_MODE_11b_ONLY == cfg->dot11Mode) ||
22558 	    (eHDD_DOT11_MODE_11g_ONLY == cfg->dot11Mode))
22559 		return QDF_STATUS_SUCCESS;
22560 
22561 	if (!hdd_ctx->channels_5ghz)
22562 		return QDF_STATUS_E_NOMEM;
22563 	wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
22564 	wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels = hdd_ctx->channels_5ghz;
22565 	wlan_hdd_get_num_dsrc_ch_and_len(cfg, &num_dsrc_ch, &len_dsrc_ch);
22566 	wlan_hdd_get_num_srd_ch_and_len(cfg, &num_srd_ch, &len_srd_ch);
22567 	num_ch = QDF_ARRAY_SIZE(hdd_channels_5_ghz) + num_dsrc_ch + num_srd_ch;
22568 	len_5g_ch = sizeof(hdd_channels_5_ghz);
22569 
22570 	wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels = num_ch;
22571 	qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels,
22572 		     &hdd_channels_5_ghz[0], len_5g_ch);
22573 	if (num_dsrc_ch)
22574 		wlan_hdd_copy_dsrc_ch((char *)wiphy->bands[
22575 				      HDD_NL80211_BAND_5GHZ]->channels +
22576 				      len_5g_ch, len_dsrc_ch);
22577 	if (num_srd_ch)
22578 		wlan_hdd_copy_srd_ch((char *)wiphy->bands[
22579 				     HDD_NL80211_BAND_5GHZ]->channels +
22580 				     len_5g_ch, len_srd_ch);
22581 
22582 	if (cfg->dot11Mode != eHDD_DOT11_MODE_AUTO &&
22583 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ac &&
22584 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ac_ONLY &&
22585 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ax &&
22586 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ax_ONLY)
22587 		 wlan_hdd_band_5_ghz.vht_cap.vht_supported = 0;
22588 
22589 	if (cfg->dot11Mode == eHDD_DOT11_MODE_AUTO ||
22590 	    cfg->dot11Mode == eHDD_DOT11_MODE_11ax ||
22591 	    cfg->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY)
22592 		hdd_init_6ghz(hdd_ctx);
22593 
22594 	return QDF_STATUS_SUCCESS;
22595 }
22596 
22597 /* In this function we are registering wiphy. */
wlan_hdd_cfg80211_register(struct wiphy * wiphy)22598 int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
22599 {
22600 	int ret;
22601 
22602 	hdd_enter();
22603 	ret = wiphy_register(wiphy);
22604 	/* Register our wiphy dev with cfg80211 */
22605 	if (ret < 0) {
22606 		hdd_err("wiphy register failed %d", ret);
22607 		return -EIO;
22608 	}
22609 
22610 	hdd_exit();
22611 	return 0;
22612 }
22613 
22614 /* This function registers for all frame which supplicant is interested in */
wlan_hdd_cfg80211_register_frames(struct hdd_adapter * adapter)22615 int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
22616 {
22617 	mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
22618 	/* Register for all P2P action, public action etc frames */
22619 	uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
22620 	QDF_STATUS status = QDF_STATUS_E_INVAL;
22621 
22622 	hdd_enter();
22623 	if (adapter->device_mode == QDF_FTM_MODE) {
22624 		hdd_info("No need to register frames in FTM mode");
22625 		return 0;
22626 	}
22627 
22628 	if (!mac_handle) {
22629 		hdd_err("mac_handle is NULL, failed to register frames");
22630 		goto ret_status;
22631 	}
22632 
22633 	/* Register frame indication call back */
22634 	status = sme_register_mgmt_frame_ind_callback(mac_handle,
22635 						      hdd_indicate_mgmt_frame);
22636 	if (status != QDF_STATUS_SUCCESS) {
22637 		hdd_err("Failed to register hdd_indicate_mgmt_frame");
22638 		goto ret_status;
22639 	}
22640 
22641 	/* Right now we are registering these frame when driver is getting
22642 	 * initialized. Once we will move to 2.6.37 kernel, in which we have
22643 	 * frame register ops, we will move this code as a part of that
22644 	 */
22645 
22646 	/* GAS Initial Request */
22647 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22648 					 (uint8_t *) GAS_INITIAL_REQ,
22649 					 GAS_INITIAL_REQ_SIZE);
22650 	if (status != QDF_STATUS_SUCCESS) {
22651 		hdd_err("Failed to register GAS_INITIAL_REQ");
22652 		goto ret_status;
22653 	}
22654 
22655 	/* GAS Initial Response */
22656 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22657 					 (uint8_t *) GAS_INITIAL_RSP,
22658 					 GAS_INITIAL_RSP_SIZE);
22659 	if (status != QDF_STATUS_SUCCESS) {
22660 		hdd_err("Failed to register GAS_INITIAL_RSP");
22661 		goto dereg_gas_initial_req;
22662 	}
22663 
22664 	/* GAS Comeback Request */
22665 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22666 					 (uint8_t *) GAS_COMEBACK_REQ,
22667 					 GAS_COMEBACK_REQ_SIZE);
22668 	if (status != QDF_STATUS_SUCCESS) {
22669 		hdd_err("Failed to register GAS_COMEBACK_REQ");
22670 		goto dereg_gas_initial_rsp;
22671 	}
22672 
22673 	/* GAS Comeback Response */
22674 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22675 					 (uint8_t *) GAS_COMEBACK_RSP,
22676 					 GAS_COMEBACK_RSP_SIZE);
22677 	if (status != QDF_STATUS_SUCCESS) {
22678 		hdd_err("Failed to register GAS_COMEBACK_RSP");
22679 		goto dereg_gas_comeback_req;
22680 	}
22681 
22682 	/* WNM BSS Transition Request frame */
22683 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22684 					 (uint8_t *) WNM_BSS_ACTION_FRAME,
22685 					 WNM_BSS_ACTION_FRAME_SIZE);
22686 	if (status != QDF_STATUS_SUCCESS) {
22687 		hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
22688 		goto dereg_gas_comeback_rsp;
22689 	}
22690 
22691 	/* WNM-Notification */
22692 	status = sme_register_mgmt_frame(mac_handle,
22693 					 adapter->deflink->vdev_id, type,
22694 					 (uint8_t *) WNM_NOTIFICATION_FRAME,
22695 					 WNM_NOTIFICATION_FRAME_SIZE);
22696 	if (status != QDF_STATUS_SUCCESS) {
22697 		hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
22698 		goto dereg_wnm_bss_action_frm;
22699 	}
22700 
22701 	return 0;
22702 
22703 dereg_wnm_bss_action_frm:
22704 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22705 				  (uint8_t *) WNM_BSS_ACTION_FRAME,
22706 				  WNM_BSS_ACTION_FRAME_SIZE);
22707 dereg_gas_comeback_rsp:
22708 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22709 				  (uint8_t *) GAS_COMEBACK_RSP,
22710 				  GAS_COMEBACK_RSP_SIZE);
22711 dereg_gas_comeback_req:
22712 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22713 				  (uint8_t *) GAS_COMEBACK_REQ,
22714 				  GAS_COMEBACK_REQ_SIZE);
22715 dereg_gas_initial_rsp:
22716 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22717 				  (uint8_t *) GAS_INITIAL_RSP,
22718 				  GAS_INITIAL_RSP_SIZE);
22719 dereg_gas_initial_req:
22720 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22721 				  (uint8_t *) GAS_INITIAL_REQ,
22722 				  GAS_INITIAL_REQ_SIZE);
22723 ret_status:
22724 	return qdf_status_to_os_return(status);
22725 }
22726 
wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter * adapter)22727 void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
22728 {
22729 	mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
22730 	/* Deregister for all P2P action, public action etc frames */
22731 	uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
22732 
22733 	hdd_enter();
22734 
22735 	if (!mac_handle) {
22736 		hdd_err("mac_handle is NULL, failed to deregister frames");
22737 		return;
22738 	}
22739 
22740 	/* Right now we are registering these frame when driver is getting
22741 	 * initialized. Once we will move to 2.6.37 kernel, in which we have
22742 	 * frame register ops, we will move this code as a part of that
22743 	 */
22744 
22745 	/* GAS Initial Request */
22746 
22747 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22748 				  (uint8_t *) GAS_INITIAL_REQ,
22749 				  GAS_INITIAL_REQ_SIZE);
22750 
22751 	/* GAS Initial Response */
22752 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22753 				  (uint8_t *) GAS_INITIAL_RSP,
22754 				  GAS_INITIAL_RSP_SIZE);
22755 
22756 	/* GAS Comeback Request */
22757 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22758 				  (uint8_t *) GAS_COMEBACK_REQ,
22759 				  GAS_COMEBACK_REQ_SIZE);
22760 
22761 	/* GAS Comeback Response */
22762 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22763 				  (uint8_t *) GAS_COMEBACK_RSP,
22764 				  GAS_COMEBACK_RSP_SIZE);
22765 
22766 	/* P2P Public Action */
22767 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22768 				  (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
22769 				  P2P_PUBLIC_ACTION_FRAME_SIZE);
22770 
22771 	/* P2P Action */
22772 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22773 				  (uint8_t *) P2P_ACTION_FRAME,
22774 				  P2P_ACTION_FRAME_SIZE);
22775 
22776 	/* WNM-Notification */
22777 	sme_deregister_mgmt_frame(mac_handle, adapter->deflink->vdev_id, type,
22778 				  (uint8_t *) WNM_NOTIFICATION_FRAME,
22779 				  WNM_NOTIFICATION_FRAME_SIZE);
22780 }
22781 
wlan_hdd_is_ap_supports_immediate_power_save(uint8_t * ies,int length)22782 bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
22783 {
22784 	const uint8_t *vendor_ie;
22785 
22786 	if (length < 2) {
22787 		hdd_debug("bss size is less than expected");
22788 		return true;
22789 	}
22790 	if (!ies) {
22791 		hdd_debug("invalid IE pointer");
22792 		return true;
22793 	}
22794 	vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
22795 				VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
22796 	if (vendor_ie) {
22797 		hdd_debug("AP can't support immediate powersave. defer it");
22798 		return false;
22799 	}
22800 	return true;
22801 }
22802 
wlan_hdd_validate_operation_channel(struct hdd_context * hdd_ctx,uint32_t ch_freq)22803 QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_context *hdd_ctx,
22804 					       uint32_t ch_freq)
22805 {
22806 	bool value = 0;
22807 	uint32_t i;
22808 	struct regulatory_channel *cur_chan_list;
22809 	QDF_STATUS status;
22810 
22811 	status = ucfg_mlme_get_sap_allow_all_channels(hdd_ctx->psoc, &value);
22812 	if (status != QDF_STATUS_SUCCESS)
22813 		hdd_err("Unable to fetch sap allow all channels");
22814 	status = QDF_STATUS_E_INVAL;
22815 	if (value) {
22816 		/* Validate the channel */
22817 		for (i = CHAN_ENUM_2412; i < NUM_CHANNELS; i++) {
22818 			if (ch_freq == WLAN_REG_CH_TO_FREQ(i)) {
22819 				status = QDF_STATUS_SUCCESS;
22820 				break;
22821 			}
22822 		}
22823 	} else {
22824 		cur_chan_list = qdf_mem_malloc(NUM_CHANNELS *
22825 				sizeof(struct regulatory_channel));
22826 		if (!cur_chan_list)
22827 			return QDF_STATUS_E_NOMEM;
22828 
22829 		if (wlan_reg_get_secondary_current_chan_list(
22830 		    hdd_ctx->pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
22831 			qdf_mem_free(cur_chan_list);
22832 			return QDF_STATUS_E_INVAL;
22833 		}
22834 
22835 		for (i = 0; i < NUM_CHANNELS; i++) {
22836 			if (ch_freq != cur_chan_list[i].center_freq)
22837 				continue;
22838 			if (cur_chan_list[i].state != CHANNEL_STATE_DISABLE &&
22839 			    cur_chan_list[i].state != CHANNEL_STATE_INVALID)
22840 				status = QDF_STATUS_SUCCESS;
22841 			break;
22842 		}
22843 		qdf_mem_free(cur_chan_list);
22844 	}
22845 
22846 	return status;
22847 
22848 }
22849 
__wlan_hdd_cfg80211_change_bss(struct wiphy * wiphy,struct net_device * dev,struct bss_parameters * params)22850 static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
22851 					  struct net_device *dev,
22852 					  struct bss_parameters *params)
22853 {
22854 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22855 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22856 	struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
22857 	int ret = 0;
22858 	QDF_STATUS qdf_ret_status;
22859 	mac_handle_t mac_handle;
22860 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
22861 	cdp_config_param_type vdev_param;
22862 
22863 	hdd_enter();
22864 
22865 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
22866 		hdd_err("Command not allowed in FTM mode");
22867 		return -EINVAL;
22868 	}
22869 
22870 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
22871 		return -EINVAL;
22872 
22873 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22874 		   TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
22875 		   adapter->deflink->vdev_id, params->ap_isolate);
22876 
22877 	hdd_debug("Device_mode %s(%d), ap_isolate = %d",
22878 		  qdf_opmode_str(adapter->device_mode),
22879 		  adapter->device_mode, params->ap_isolate);
22880 
22881 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22882 	ret = wlan_hdd_validate_context(hdd_ctx);
22883 	if (0 != ret)
22884 		return ret;
22885 
22886 	if (!(adapter->device_mode == QDF_SAP_MODE ||
22887 	      adapter->device_mode == QDF_P2P_GO_MODE)) {
22888 		return -EOPNOTSUPP;
22889 	}
22890 
22891 	/* ap_isolate == -1 means that in change bss, upper layer doesn't
22892 	 * want to update this parameter
22893 	 */
22894 	if (-1 != params->ap_isolate) {
22895 		ap_ctx->disable_intrabss_fwd = !!params->ap_isolate;
22896 
22897 		mac_handle = hdd_ctx->mac_handle;
22898 		qdf_ret_status = sme_ap_disable_intra_bss_fwd(
22899 						mac_handle,
22900 						adapter->deflink->vdev_id,
22901 						ap_ctx->disable_intrabss_fwd);
22902 		if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
22903 			ret = -EINVAL;
22904 
22905 		ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->pdev,
22906 					 adapter->deflink->vdev_id,
22907 					 ap_ctx->disable_intrabss_fwd);
22908 
22909 		vdev_param.cdp_vdev_param_ap_brdg_en =
22910 			!ap_ctx->disable_intrabss_fwd;
22911 		cdp_txrx_set_vdev_param(soc, adapter->deflink->vdev_id,
22912 					CDP_ENABLE_AP_BRIDGE, vdev_param);
22913 	}
22914 
22915 	hdd_exit();
22916 	return ret;
22917 }
22918 
22919 /**
22920  * hdd_change_adapter_mode() - change @adapter's operating mode to @new_mode
22921  * @adapter: the adapter to change modes on
22922  * @new_mode: the new operating mode to change to
22923  *
22924  * Return: Errno
22925  */
hdd_change_adapter_mode(struct hdd_adapter * adapter,enum QDF_OPMODE new_mode)22926 static int hdd_change_adapter_mode(struct hdd_adapter *adapter,
22927 				   enum QDF_OPMODE new_mode)
22928 {
22929 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22930 	struct net_device *netdev = adapter->dev;
22931 	QDF_STATUS status = QDF_STATUS_SUCCESS;
22932 
22933 	hdd_enter();
22934 
22935 	hdd_stop_adapter(hdd_ctx, adapter);
22936 	hdd_deinit_adapter(hdd_ctx, adapter, true);
22937 	adapter->device_mode = new_mode;
22938 	memset(&adapter->deflink->session, 0,
22939 	       sizeof(adapter->deflink->session));
22940 	hdd_set_station_ops(netdev);
22941 
22942 	hdd_exit();
22943 
22944 	return qdf_status_to_os_return(status);
22945 }
22946 
wlan_hdd_cfg80211_change_bss(struct wiphy * wiphy,struct net_device * dev,struct bss_parameters * params)22947 static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
22948 					struct net_device *dev,
22949 					struct bss_parameters *params)
22950 {
22951 	int errno;
22952 	struct osif_vdev_sync *vdev_sync;
22953 
22954 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22955 	if (errno)
22956 		return errno;
22957 
22958 	errno = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
22959 
22960 	osif_vdev_sync_op_stop(vdev_sync);
22961 
22962 	return errno;
22963 }
22964 
hdd_is_client_mode(enum QDF_OPMODE mode)22965 static bool hdd_is_client_mode(enum QDF_OPMODE mode)
22966 {
22967 	switch (mode) {
22968 	case QDF_STA_MODE:
22969 	case QDF_P2P_CLIENT_MODE:
22970 	case QDF_P2P_DEVICE_MODE:
22971 		return true;
22972 	default:
22973 		return false;
22974 	}
22975 }
22976 
hdd_is_ap_mode(enum QDF_OPMODE mode)22977 static bool hdd_is_ap_mode(enum QDF_OPMODE mode)
22978 {
22979 	switch (mode) {
22980 	case QDF_SAP_MODE:
22981 	case QDF_P2P_GO_MODE:
22982 		return true;
22983 	default:
22984 		return false;
22985 	}
22986 }
22987 
22988 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
22989 	!defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
22990 static QDF_STATUS
hdd_adapter_update_mac_on_mode_change(struct hdd_adapter * adapter)22991 hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter)
22992 {
22993 	int i;
22994 	QDF_STATUS status;
22995 	struct hdd_adapter *link_adapter;
22996 	struct hdd_mlo_adapter_info *mlo_adapter_info;
22997 	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
22998 	struct qdf_mac_addr link_addr[WLAN_MAX_ML_BSS_LINKS] = {0};
22999 
23000 	status = hdd_derive_link_address_from_mld(hdd_ctx->psoc,
23001 						  &adapter->mld_addr,
23002 						  &link_addr[0],
23003 						  WLAN_MAX_ML_BSS_LINKS);
23004 	if (QDF_IS_STATUS_ERROR(status))
23005 		return status;
23006 
23007 	mlo_adapter_info = &adapter->mlo_adapter_info;
23008 	for (i = 0; i < WLAN_MAX_MLD; i++) {
23009 		link_adapter = mlo_adapter_info->link_adapter[i];
23010 		qdf_copy_macaddr(&adapter->link_info[i].link_addr,
23011 				 &link_addr[i]);
23012 		if (!link_adapter)
23013 			continue;
23014 
23015 		ucfg_dp_update_intf_mac(hdd_ctx->psoc, &link_adapter->mac_addr,
23016 					&link_addr[i],
23017 					link_adapter->deflink->vdev);
23018 		qdf_copy_macaddr(&link_adapter->mac_addr, &link_addr[i]);
23019 	}
23020 	qdf_copy_macaddr(&adapter->link_info[i].link_addr, &link_addr[i]);
23021 
23022 	return QDF_STATUS_SUCCESS;
23023 }
23024 #else
23025 static inline QDF_STATUS
hdd_adapter_update_mac_on_mode_change(struct hdd_adapter * adapter)23026 hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter)
23027 {
23028 	return QDF_STATUS_SUCCESS;
23029 }
23030 #endif
23031 
23032 /**
23033  * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
23034  * @wiphy: Pointer to the wiphy structure
23035  * @ndev: Pointer to the net device
23036  * @type: Interface type
23037  * @flags: Flags for change interface
23038  * @params: Pointer to change interface parameters
23039  *
23040  * Return: 0 for success, error number on failure.
23041  */
__wlan_hdd_cfg80211_change_iface(struct wiphy * wiphy,struct net_device * ndev,enum nl80211_iftype type,u32 * flags,struct vif_params * params)23042 static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
23043 					    struct net_device *ndev,
23044 					    enum nl80211_iftype type,
23045 					    u32 *flags,
23046 					    struct vif_params *params)
23047 {
23048 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
23049 	struct hdd_context *hdd_ctx;
23050 	bool iff_up = ndev->flags & IFF_UP;
23051 	enum QDF_OPMODE new_mode;
23052 	bool ap_random_bssid_enabled;
23053 	QDF_STATUS status;
23054 	int errno;
23055 	uint8_t mac_addr[QDF_MAC_ADDR_SIZE];
23056 	bool eht_capab;
23057 	struct wlan_hdd_link_info *link_info = adapter->deflink;
23058 
23059 	hdd_enter();
23060 
23061 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
23062 		hdd_err("Command not allowed in FTM mode");
23063 		return -EINVAL;
23064 	}
23065 
23066 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23067 	errno = wlan_hdd_validate_context(hdd_ctx);
23068 	if (errno)
23069 		return errno;
23070 
23071 	if (wlan_hdd_is_mon_concurrency())
23072 		return -EINVAL;
23073 
23074 	wlan_hdd_lpc_handle_concurrency(hdd_ctx, false);
23075 
23076 	if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) &&
23077 	    !hdd_lpc_is_work_scheduled(hdd_ctx))
23078 		return -EINVAL;
23079 
23080 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
23081 		   TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
23082 		   link_info->vdev_id, type);
23083 
23084 	status = hdd_nl_to_qdf_iface_type(type, &new_mode);
23085 	if (QDF_IS_STATUS_ERROR(status))
23086 		return qdf_status_to_os_return(status);
23087 
23088 	/* A userspace issue leads to it sending a 'change to station mode'
23089 	 * request on a "p2p" device, expecting the driver do execute a 'change
23090 	 * to p2p-device mode' request instead. The (unfortunate) work around
23091 	 * here is implemented by overriding the new mode if the net_device name
23092 	 * starts with "p2p" and the requested mode was station.
23093 	 */
23094 	if (strnstr(ndev->name, "p2p", 3) && new_mode == QDF_STA_MODE)
23095 		new_mode = QDF_P2P_DEVICE_MODE;
23096 
23097 	hdd_debug("Changing mode for '%s' from %s to %s",
23098 		  ndev->name,
23099 		  qdf_opmode_str(adapter->device_mode),
23100 		  qdf_opmode_str(new_mode));
23101 
23102 	errno = hdd_trigger_psoc_idle_restart(hdd_ctx);
23103 	if (errno) {
23104 		hdd_err("Failed to restart psoc; errno:%d", errno);
23105 		return -EINVAL;
23106 	}
23107 
23108 	/* Reset the current device mode bit mask */
23109 	policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
23110 
23111 	if (hdd_is_client_mode(adapter->device_mode)) {
23112 		if (adapter->device_mode == QDF_STA_MODE)
23113 			hdd_cleanup_conn_info(link_info);
23114 
23115 		if (hdd_is_client_mode(new_mode)) {
23116 			errno = hdd_change_adapter_mode(adapter, new_mode);
23117 			if (errno) {
23118 				hdd_err("change intf mode fail %d", errno);
23119 				goto err;
23120 			}
23121 		} else if (hdd_is_ap_mode(new_mode)) {
23122 			if (new_mode == QDF_P2P_GO_MODE)
23123 				wlan_hdd_cleanup_remain_on_channel_ctx(link_info);
23124 
23125 			hdd_stop_adapter(hdd_ctx, adapter);
23126 			hdd_deinit_adapter(hdd_ctx, adapter, true);
23127 			memset(&link_info->session, 0,
23128 			       sizeof(link_info->session));
23129 			adapter->device_mode = new_mode;
23130 
23131 			status = ucfg_mlme_get_ap_random_bssid_enable(
23132 						hdd_ctx->psoc,
23133 						&ap_random_bssid_enabled);
23134 			if (QDF_IS_STATUS_ERROR(status))
23135 				return qdf_status_to_os_return(status);
23136 
23137 			if (adapter->device_mode == QDF_SAP_MODE &&
23138 			    ap_random_bssid_enabled) {
23139 				/* To meet Android requirements create
23140 				 * a randomized MAC address of the
23141 				 * form 02:1A:11:Fx:xx:xx
23142 				 */
23143 				memcpy(mac_addr, ndev->dev_addr,
23144 				       QDF_MAC_ADDR_SIZE);
23145 
23146 				get_random_bytes(&mac_addr[3], 3);
23147 				mac_addr[0] = 0x02;
23148 				mac_addr[1] = 0x1A;
23149 				mac_addr[2] = 0x11;
23150 				mac_addr[3] |= 0xF0;
23151 				memcpy(adapter->mac_addr.bytes, mac_addr,
23152 				       QDF_MAC_ADDR_SIZE);
23153 				qdf_net_update_net_device_dev_addr(ndev,
23154 								   mac_addr,
23155 								   QDF_MAC_ADDR_SIZE);
23156 
23157 				pr_info("wlan: Generated HotSpot BSSID "
23158 					QDF_MAC_ADDR_FMT "\n",
23159 					QDF_MAC_ADDR_REF(ndev->dev_addr));
23160 			}
23161 			hdd_set_ap_ops(adapter->dev);
23162 		} else {
23163 			hdd_err("Changing to device mode '%s' is not supported",
23164 				qdf_opmode_str(new_mode));
23165 			errno = -EOPNOTSUPP;
23166 			goto err;
23167 		}
23168 	} else if (hdd_is_ap_mode(adapter->device_mode)) {
23169 		if (hdd_is_client_mode(new_mode)) {
23170 			errno = hdd_change_adapter_mode(adapter, new_mode);
23171 			if (errno) {
23172 				hdd_err("change mode fail %d", errno);
23173 				goto err;
23174 			}
23175 		} else if (hdd_is_ap_mode(new_mode)) {
23176 			adapter->device_mode = new_mode;
23177 
23178 			/* avoid starting the adapter, since it never stopped */
23179 			iff_up = false;
23180 		} else {
23181 			hdd_err("Changing to device mode '%s' is not supported",
23182 				qdf_opmode_str(new_mode));
23183 			errno = -EOPNOTSUPP;
23184 			goto err;
23185 		}
23186 	} else {
23187 		hdd_err("Changing from device mode '%s' is not supported",
23188 			qdf_opmode_str(adapter->device_mode));
23189 		errno = -EOPNOTSUPP;
23190 		goto err;
23191 	}
23192 
23193 	ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
23194 	if (eht_capab && hdd_adapter_is_ml_adapter(adapter)) {
23195 		switch (adapter->device_mode) {
23196 		case QDF_SAP_MODE:
23197 			hdd_adapter_set_sl_ml_adapter(adapter);
23198 			adapter->active_links = 0x1;
23199 			break;
23200 		case QDF_STA_MODE:
23201 			hdd_adapter_clear_sl_ml_adapter(adapter);
23202 
23203 			status = hdd_adapter_update_mac_on_mode_change(adapter);
23204 			if (QDF_IS_STATUS_ERROR(status))
23205 				goto err;
23206 
23207 			adapter->active_links =
23208 					(1 << adapter->num_links_on_create) - 1;
23209 			break;
23210 		default:
23211 			hdd_adapter_clear_sl_ml_adapter(adapter);
23212 			adapter->active_links = 0x1;
23213 			break;
23214 		}
23215 	}
23216 
23217 	/* restart the adapter if it was up before the change iface request */
23218 	if (iff_up) {
23219 		errno = hdd_start_adapter(adapter, true);
23220 		if (errno) {
23221 			hdd_err("Failed to start adapter");
23222 			errno = -EINVAL;
23223 			goto err;
23224 		}
23225 	}
23226 
23227 	ndev->ieee80211_ptr->iftype = type;
23228 	hdd_lpass_notify_mode_change(link_info);
23229 err:
23230 	/* Set bitmask based on updated value */
23231 	policy_mgr_set_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
23232 
23233 	hdd_exit();
23234 
23235 	return errno;
23236 }
23237 
_wlan_hdd_cfg80211_change_iface(struct wiphy * wiphy,struct net_device * net_dev,enum nl80211_iftype type,u32 * flags,struct vif_params * params)23238 static int _wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
23239 					   struct net_device *net_dev,
23240 					   enum nl80211_iftype type,
23241 					   u32 *flags,
23242 					   struct vif_params *params)
23243 {
23244 	int errno;
23245 	struct osif_vdev_sync *vdev_sync;
23246 
23247 	errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
23248 	if (errno)
23249 		goto err;
23250 
23251 	errno = __wlan_hdd_cfg80211_change_iface(wiphy, net_dev, type,
23252 						 flags, params);
23253 
23254 	osif_vdev_sync_trans_stop(vdev_sync);
23255 
23256 	return errno;
23257 err:
23258 	/* In the SSR case, errno will be -EINVAL from
23259 	 * __dsc_vdev_can_trans with qdf_is_recovering()
23260 	 * is true, only change -EINVAL to -EBUSY to make
23261 	 * wpa_supplicant has chance to retry mode switch.
23262 	 * Meanwhile do not touch the errno from
23263 	 * __wlan_hdd_cfg80211_change_iface with this
23264 	 * change.
23265 	 */
23266 	if (errno && errno != -EAGAIN && errno != -EBUSY)
23267 		errno = -EBUSY;
23268 	return errno;
23269 }
23270 
23271 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
23272 /**
23273  * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
23274  * @wiphy: Pointer to the wiphy structure
23275  * @ndev: Pointer to the net device
23276  * @type: Interface type
23277  * @flags: Flags for change interface
23278  * @params: Pointer to change interface parameters
23279  *
23280  * Return: 0 for success, error number on failure.
23281  */
wlan_hdd_cfg80211_change_iface(struct wiphy * wiphy,struct net_device * ndev,enum nl80211_iftype type,u32 * flags,struct vif_params * params)23282 static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
23283 					  struct net_device *ndev,
23284 					  enum nl80211_iftype type,
23285 					  u32 *flags,
23286 					  struct vif_params *params)
23287 {
23288 	return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
23289 					       flags, params);
23290 }
23291 #else
wlan_hdd_cfg80211_change_iface(struct wiphy * wiphy,struct net_device * ndev,enum nl80211_iftype type,struct vif_params * params)23292 static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
23293 					  struct net_device *ndev,
23294 					  enum nl80211_iftype type,
23295 					  struct vif_params *params)
23296 {
23297 	return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
23298 					       &params->flags, params);
23299 }
23300 #endif /* KERNEL_VERSION(4, 12, 0) */
23301 
wlan_hdd_send_sta_authorized_event(struct hdd_adapter * adapter,struct hdd_context * hdd_ctx,const struct qdf_mac_addr * mac_addr)23302 QDF_STATUS wlan_hdd_send_sta_authorized_event(
23303 					struct hdd_adapter *adapter,
23304 					struct hdd_context *hdd_ctx,
23305 					const struct qdf_mac_addr *mac_addr)
23306 {
23307 	struct sk_buff *vendor_event;
23308 	QDF_STATUS status;
23309 	struct nl80211_sta_flag_update sta_flags;
23310 
23311 	hdd_enter();
23312 	if (!hdd_ctx) {
23313 		hdd_err("HDD context is null");
23314 		return QDF_STATUS_E_INVAL;
23315 	}
23316 
23317 	vendor_event =
23318 		wlan_cfg80211_vendor_event_alloc(
23319 			hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) +
23320 			QDF_MAC_ADDR_SIZE + NLMSG_HDRLEN,
23321 			QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX,
23322 			GFP_KERNEL);
23323 	if (!vendor_event) {
23324 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
23325 		return QDF_STATUS_E_FAILURE;
23326 	}
23327 
23328 	qdf_mem_zero(&sta_flags, sizeof(sta_flags));
23329 
23330 	sta_flags.mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
23331 	sta_flags.set = true;
23332 
23333 	status = nla_put(vendor_event,
23334 			 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS,
23335 			 sizeof(struct  nl80211_sta_flag_update),
23336 			 &sta_flags);
23337 	if (status) {
23338 		hdd_err("STA flag put fails");
23339 		wlan_cfg80211_vendor_free_skb(vendor_event);
23340 		return QDF_STATUS_E_FAILURE;
23341 	}
23342 	status = nla_put(vendor_event,
23343 			 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR,
23344 			 QDF_MAC_ADDR_SIZE, mac_addr->bytes);
23345 	if (status) {
23346 		hdd_err("STA MAC put fails");
23347 		wlan_cfg80211_vendor_free_skb(vendor_event);
23348 		return QDF_STATUS_E_FAILURE;
23349 	}
23350 
23351 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
23352 
23353 	hdd_exit();
23354 	return QDF_STATUS_SUCCESS;
23355 }
23356 
23357 #ifdef QCA_MULTIPASS_SUPPORT
23358 static int
wlan_hdd_set_peer_vlan_config(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,uint8_t * mac_addr,uint8_t vlan_id)23359 wlan_hdd_set_peer_vlan_config(struct hdd_adapter *adapter,
23360 			      struct wlan_objmgr_vdev *vdev,
23361 			      uint8_t *mac_addr,
23362 			      uint8_t vlan_id)
23363 {
23364 	ol_txrx_soc_handle soc_txrx_handle;
23365 	cdp_config_param_type val;
23366 	QDF_STATUS status;
23367 
23368 	soc_txrx_handle = wlan_psoc_get_dp_handle(wlan_vdev_get_psoc(vdev));
23369 
23370 	cdp_peer_set_vlan_id(soc_txrx_handle,
23371 			     wlan_vdev_get_id(vdev),
23372 			     mac_addr, vlan_id);
23373 
23374 	val.cdp_peer_param_isolation = true;
23375 
23376 	cdp_txrx_set_peer_param(soc_txrx_handle,
23377 				wlan_vdev_get_id(vdev),
23378 				mac_addr,
23379 				CDP_CONFIG_ISOLATION,
23380 				val);
23381 
23382 	status = ucfg_mlme_peer_config_vlan(vdev, mac_addr);
23383 	if (QDF_IS_STATUS_ERROR(status))
23384 		return -EINVAL;
23385 
23386 	return 0;
23387 }
23388 
23389 static void
wlan_hdd_set_vlan_id(struct hdd_sta_info_obj * sta_info_list,uint8_t * mac,struct station_parameters * params)23390 wlan_hdd_set_vlan_id(struct hdd_sta_info_obj *sta_info_list,
23391 		     uint8_t *mac, struct station_parameters *params)
23392 {
23393 	struct hdd_station_info *sta_info;
23394 
23395 	if (!params->vlan_id)
23396 		return;
23397 
23398 	sta_info =
23399 	hdd_get_sta_info_by_mac(sta_info_list,
23400 				mac,
23401 				STA_INFO_SOFTAP_GET_STA_INFO);
23402 	if (!sta_info) {
23403 		hdd_err("Failed to find right station MAC: "
23404 			  QDF_MAC_ADDR_FMT,
23405 			  QDF_MAC_ADDR_REF(mac));
23406 		return;
23407 	}
23408 
23409 	sta_info->vlan_id = params->vlan_id;
23410 
23411 	hdd_put_sta_info_ref(sta_info_list, &sta_info, true,
23412 			     STA_INFO_SOFTAP_GET_STA_INFO);
23413 }
23414 
23415 static QDF_STATUS
wlan_hdd_set_vlan_config(struct hdd_adapter * adapter,uint8_t * mac)23416 wlan_hdd_set_vlan_config(struct hdd_adapter *adapter,
23417 			 uint8_t *mac)
23418 {
23419 	int ret;
23420 	struct hdd_station_info *sta_info;
23421 
23422 	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
23423 					   (uint8_t *)mac,
23424 					   STA_INFO_SOFTAP_GET_STA_INFO);
23425 
23426 	if (!sta_info) {
23427 		hdd_err("Failed to find right station MAC:"
23428 			QDF_MAC_ADDR_FMT,
23429 			QDF_MAC_ADDR_REF((uint8_t *)mac));
23430 			return QDF_STATUS_E_INVAL;
23431 	}
23432 
23433 	if (!sta_info->vlan_id) {
23434 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
23435 				     true,
23436 				     STA_INFO_SOFTAP_GET_STA_INFO);
23437 		return QDF_STATUS_E_INVAL;
23438 	}
23439 
23440 	ret = wlan_hdd_set_peer_vlan_config(adapter,
23441 					    adapter->deflink->vdev,
23442 					    mac,
23443 					    sta_info->vlan_id);
23444 	if (ret < 0) {
23445 		hdd_err("Unable to send peer vlan config");
23446 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
23447 				     true,
23448 				     STA_INFO_SOFTAP_GET_STA_INFO);
23449 		return QDF_STATUS_E_INVAL;
23450 	}
23451 
23452 	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
23453 			     true,  STA_INFO_SOFTAP_GET_STA_INFO);
23454 
23455 	return QDF_STATUS_SUCCESS;
23456 }
23457 #else
23458 static inline void
wlan_hdd_set_vlan_id(struct hdd_sta_info_obj * sta_info_list,uint8_t * mac,struct station_parameters * params)23459 wlan_hdd_set_vlan_id(struct hdd_sta_info_obj *sta_info_list,
23460 		     uint8_t *mac, struct station_parameters *params)
23461 {
23462 }
23463 
23464 static inline QDF_STATUS
wlan_hdd_set_vlan_config(struct hdd_adapter * adapter,uint8_t * mac)23465 wlan_hdd_set_vlan_config(struct hdd_adapter *adapter,
23466 			 uint8_t *mac)
23467 {
23468 	return QDF_STATUS_SUCCESS;
23469 }
23470 #endif
23471 /**
23472  * __wlan_hdd_change_station() - change station
23473  * @wiphy: Pointer to the wiphy structure
23474  * @dev: Pointer to the net device.
23475  * @mac: bssid
23476  * @params: Pointer to station parameters
23477  *
23478  * Return: 0 for success, error number on failure.
23479  */
23480 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
__wlan_hdd_change_station(struct wiphy * wiphy,struct net_device * dev,const uint8_t * mac,struct station_parameters * params)23481 static int __wlan_hdd_change_station(struct wiphy *wiphy,
23482 				   struct net_device *dev,
23483 				   const uint8_t *mac,
23484 				   struct station_parameters *params)
23485 #else
23486 static int __wlan_hdd_change_station(struct wiphy *wiphy,
23487 				   struct net_device *dev,
23488 				   uint8_t *mac,
23489 				   struct station_parameters *params)
23490 #endif
23491 {
23492 	QDF_STATUS status = QDF_STATUS_SUCCESS;
23493 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
23494 	struct hdd_context *hdd_ctx;
23495 	struct hdd_station_ctx *sta_ctx;
23496 	struct hdd_ap_ctx *ap_ctx;
23497 	struct qdf_mac_addr sta_macaddr;
23498 	int ret;
23499 
23500 	hdd_enter();
23501 
23502 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
23503 		hdd_err("Command not allowed in FTM mode");
23504 		return -EINVAL;
23505 	}
23506 
23507 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
23508 		   TRACE_CODE_HDD_CHANGE_STATION,
23509 		   adapter->deflink->vdev_id, params->listen_interval);
23510 
23511 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
23512 		return -EINVAL;
23513 
23514 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23515 	ret = wlan_hdd_validate_context(hdd_ctx);
23516 	if (0 != ret)
23517 		return ret;
23518 
23519 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
23520 
23521 	qdf_mem_copy(sta_macaddr.bytes, mac, QDF_MAC_ADDR_SIZE);
23522 
23523 	wlan_hdd_set_vlan_id(&adapter->sta_info_list, (uint8_t *)mac, params);
23524 
23525 	if ((adapter->device_mode == QDF_SAP_MODE) ||
23526 	    (adapter->device_mode == QDF_P2P_GO_MODE)) {
23527 		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
23528 			ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
23529 			/*
23530 			 * For Encrypted SAP session, this will be done as
23531 			 * part of eSAP_STA_SET_KEY_EVENT
23532 			 */
23533 
23534 			if (ucfg_mlme_is_multipass_sap(hdd_ctx->psoc)) {
23535 				status =
23536 				wlan_hdd_set_vlan_config(adapter,
23537 							 (uint8_t *)mac);
23538 				if (QDF_IS_STATUS_ERROR(status))
23539 					return 0;
23540 			}
23541 
23542 			if (ap_ctx->encryption_type !=
23543 			    eCSR_ENCRYPT_TYPE_NONE) {
23544 				hdd_debug("Encrypt type %d, not setting peer authorized now",
23545 					  ap_ctx->encryption_type);
23546 				return 0;
23547 			}
23548 
23549 			status =
23550 				hdd_softap_change_sta_state(adapter,
23551 							    &sta_macaddr,
23552 							    OL_TXRX_PEER_STATE_AUTH);
23553 
23554 			if (status != QDF_STATUS_SUCCESS) {
23555 				hdd_debug("Not able to change TL state to AUTHENTICATED");
23556 				return -EINVAL;
23557 			}
23558 			status = wlan_hdd_send_sta_authorized_event(
23559 								adapter,
23560 								hdd_ctx,
23561 								&sta_macaddr);
23562 			if (status != QDF_STATUS_SUCCESS) {
23563 				return -EINVAL;
23564 			}
23565 		}
23566 	} else if ((adapter->device_mode == QDF_STA_MODE) ||
23567 		   (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
23568 		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
23569 #if defined(FEATURE_WLAN_TDLS)
23570 			struct wlan_objmgr_vdev *vdev;
23571 
23572 			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
23573 							   WLAN_OSIF_TDLS_ID);
23574 			if (!vdev)
23575 				return -EINVAL;
23576 			ret = wlan_cfg80211_tdls_update_peer(vdev, mac, params);
23577 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
23578 #endif
23579 		}
23580 	}
23581 	hdd_exit();
23582 	return ret;
23583 }
23584 
23585 /**
23586  * wlan_hdd_change_station() - cfg80211 change station handler function
23587  * @wiphy: Pointer to the wiphy structure
23588  * @dev: Pointer to the net device.
23589  * @mac: bssid
23590  * @params: Pointer to station parameters
23591  *
23592  * This is the cfg80211 change station handler function which invokes
23593  * the internal function @__wlan_hdd_change_station with
23594  * SSR protection.
23595  *
23596  * Return: 0 for success, error number on failure.
23597  */
23598 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
wlan_hdd_change_station(struct wiphy * wiphy,struct net_device * dev,const u8 * mac,struct station_parameters * params)23599 static int wlan_hdd_change_station(struct wiphy *wiphy,
23600 				   struct net_device *dev,
23601 				   const u8 *mac,
23602 				   struct station_parameters *params)
23603 #else
23604 static int wlan_hdd_change_station(struct wiphy *wiphy,
23605 				   struct net_device *dev,
23606 				   u8 *mac,
23607 				   struct station_parameters *params)
23608 #endif
23609 {
23610 	int errno;
23611 	struct osif_vdev_sync *vdev_sync;
23612 
23613 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
23614 	if (errno)
23615 		return errno;
23616 
23617 	errno = __wlan_hdd_change_station(wiphy, dev, mac, params);
23618 
23619 	osif_vdev_sync_op_stop(vdev_sync);
23620 
23621 	return errno;
23622 }
23623 
23624 #ifdef FEATURE_WLAN_ESE
hdd_is_krk_enc_type(uint32_t cipher_type)23625 static bool hdd_is_krk_enc_type(uint32_t cipher_type)
23626 {
23627 	if (cipher_type == WLAN_CIPHER_SUITE_KRK)
23628 		return true;
23629 
23630 	return false;
23631 }
23632 #else
hdd_is_krk_enc_type(uint32_t cipher_type)23633 static bool hdd_is_krk_enc_type(uint32_t cipher_type)
23634 {
23635 	return false;
23636 }
23637 #endif
23638 
23639 #if defined(FEATURE_WLAN_ESE) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
hdd_is_btk_enc_type(uint32_t cipher_type)23640 static bool hdd_is_btk_enc_type(uint32_t cipher_type)
23641 {
23642 	if (cipher_type == WLAN_CIPHER_SUITE_BTK)
23643 		return true;
23644 
23645 	return false;
23646 }
23647 #else
hdd_is_btk_enc_type(uint32_t cipher_type)23648 static bool hdd_is_btk_enc_type(uint32_t cipher_type)
23649 {
23650 	return false;
23651 }
23652 #endif
23653 
23654 #ifdef WLAN_FEATURE_11BE_MLO
wlan_key_get_link_vdev(struct hdd_adapter * adapter,wlan_objmgr_ref_dbgid id,int link_id)23655 struct wlan_objmgr_vdev *wlan_key_get_link_vdev(struct hdd_adapter *adapter,
23656 						wlan_objmgr_ref_dbgid id,
23657 						int link_id)
23658 {
23659 	struct wlan_objmgr_vdev *vdev, *link_vdev;
23660 
23661 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, id);
23662 	if (!vdev)
23663 		return NULL;
23664 
23665 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
23666 		return vdev;
23667 
23668 	link_vdev = mlo_get_vdev_by_link_id(vdev, link_id, id);
23669 	hdd_objmgr_put_vdev_by_user(vdev, id);
23670 
23671 	return link_vdev;
23672 }
23673 
wlan_key_put_link_vdev(struct wlan_objmgr_vdev * link_vdev,wlan_objmgr_ref_dbgid id)23674 void wlan_key_put_link_vdev(struct wlan_objmgr_vdev *link_vdev,
23675 			    wlan_objmgr_ref_dbgid id)
23676 {
23677 	if (!wlan_vdev_mlme_is_mlo_vdev(link_vdev)) {
23678 		hdd_objmgr_put_vdev_by_user(link_vdev, id);
23679 		return;
23680 	}
23681 
23682 	wlan_objmgr_vdev_release_ref(link_vdev, id);
23683 }
23684 #else
wlan_key_get_link_vdev(struct hdd_adapter * adapter,wlan_objmgr_ref_dbgid id,int link_id)23685 struct wlan_objmgr_vdev *wlan_key_get_link_vdev(struct hdd_adapter *adapter,
23686 						wlan_objmgr_ref_dbgid id,
23687 						int link_id)
23688 {
23689 	struct wlan_objmgr_vdev *vdev;
23690 
23691 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, id);
23692 	if (!vdev)
23693 		return NULL;
23694 
23695 	return vdev;
23696 }
23697 
wlan_key_put_link_vdev(struct wlan_objmgr_vdev * link_vdev,wlan_objmgr_ref_dbgid id)23698 void wlan_key_put_link_vdev(struct wlan_objmgr_vdev *link_vdev,
23699 			    wlan_objmgr_ref_dbgid id)
23700 {
23701 	hdd_objmgr_put_vdev_by_user(link_vdev, id);
23702 }
23703 #endif
23704 
23705 /*
23706  * FUNCTION: __wlan_hdd_cfg80211_get_key
23707  * This function is used to get the key information
23708  */
23709 
wlan_hdd_add_key_sap(struct wlan_hdd_link_info * link_info,bool pairwise,u8 key_index,enum wlan_crypto_cipher_type cipher)23710 static int wlan_hdd_add_key_sap(struct wlan_hdd_link_info *link_info,
23711 				bool pairwise, u8 key_index,
23712 				enum wlan_crypto_cipher_type cipher)
23713 {
23714 	struct wlan_objmgr_vdev *vdev;
23715 	int errno = 0;
23716 	struct hdd_hostapd_state *hostapd_state =
23717 		WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info);
23718 
23719 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
23720 	if (!vdev)
23721 		return -EINVAL;
23722 
23723 	/* Do not send install key when sap restart is in progress. If there is
23724 	 * critical channel request handling going on, fw will stop that request
23725 	 * and will not send restart response
23726 	 */
23727 	if (wlan_vdev_is_restart_progress(vdev) == QDF_STATUS_SUCCESS) {
23728 		hdd_err("vdev: %d restart in progress", wlan_vdev_get_id(vdev));
23729 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
23730 		return -EINVAL;
23731 	}
23732 
23733 	if (hostapd_state->bss_state == BSS_START) {
23734 		errno =
23735 		wlan_cfg80211_crypto_add_key(vdev,
23736 					     (pairwise ?
23737 					      WLAN_CRYPTO_KEY_TYPE_UNICAST :
23738 					      WLAN_CRYPTO_KEY_TYPE_GROUP),
23739 					     key_index, true);
23740 		if (!errno)
23741 			wma_update_set_key(link_info->vdev_id, pairwise,
23742 					   key_index, cipher);
23743 	}
23744 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
23745 
23746 	return errno;
23747 }
23748 
wlan_hdd_add_key_sta(struct wlan_objmgr_pdev * pdev,struct wlan_hdd_link_info * link_info,bool pairwise,u8 key_index,bool * ft_mode)23749 static int wlan_hdd_add_key_sta(struct wlan_objmgr_pdev *pdev,
23750 				struct wlan_hdd_link_info *link_info,
23751 				bool pairwise, u8 key_index, bool *ft_mode)
23752 {
23753 	struct wlan_objmgr_vdev *vdev;
23754 	int errno;
23755 	QDF_STATUS status;
23756 	struct hdd_adapter *adapter = link_info->adapter;
23757 
23758 	/* The supplicant may attempt to set the PTK once
23759 	 * pre-authentication is done. Save the key in the
23760 	 * UMAC and install it after association
23761 	 */
23762 	status = ucfg_cm_check_ft_status(pdev, link_info->vdev_id);
23763 	if (status == QDF_STATUS_SUCCESS) {
23764 		*ft_mode = true;
23765 		return 0;
23766 	}
23767 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
23768 	if (!vdev)
23769 		return -EINVAL;
23770 	errno = wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
23771 					     WLAN_CRYPTO_KEY_TYPE_UNICAST :
23772 					     WLAN_CRYPTO_KEY_TYPE_GROUP),
23773 					     key_index, true);
23774 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
23775 	if (!errno && adapter->send_mode_change) {
23776 		wlan_hdd_send_mode_change_event();
23777 		adapter->send_mode_change = false;
23778 	}
23779 
23780 	return errno;
23781 }
23782 
23783 #ifdef WLAN_FEATURE_11BE_MLO
23784 static void
wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc * psoc,struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,bool pairwise)23785 wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc *psoc,
23786 			    struct hdd_adapter *adapter,
23787 			    struct wlan_objmgr_vdev *vdev,
23788 			    bool pairwise)
23789 {
23790 	struct qdf_mac_addr *link_addr;
23791 	uint8_t link_id;
23792 
23793 	if (adapter->device_mode != QDF_STA_MODE)
23794 		return;
23795 
23796 	if (pairwise &&
23797 	    wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
23798 	    mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
23799 					      wlan_vdev_get_id(vdev))) {
23800 		link_addr =
23801 		(struct qdf_mac_addr *)wlan_vdev_mlme_get_linkaddr(vdev);
23802 
23803 		if (!link_addr) {
23804 			crypto_err("link_addr NULL");
23805 			return;
23806 		}
23807 		link_id = wlan_vdev_get_link_id(vdev);
23808 		wlan_crypto_free_key_by_link_id(psoc, link_addr, link_id);
23809 	}
23810 }
23811 
23812 #else
23813 
23814 static void
wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc * psoc,struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,bool pairwise)23815 wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc *psoc,
23816 			    struct hdd_adapter *adapter,
23817 			    struct wlan_objmgr_vdev *vdev,
23818 			    bool pairwise)
23819 {
23820 }
23821 #endif
23822 
23823 #ifdef WLAN_FEATURE_11BE_MLO
23824 QDF_STATUS
wlan_hdd_mlo_copy_partner_addr_from_mlie(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * partner_mac)23825 wlan_hdd_mlo_copy_partner_addr_from_mlie(struct wlan_objmgr_vdev *vdev,
23826 					 struct qdf_mac_addr *partner_mac)
23827 {
23828 	int i;
23829 	QDF_STATUS status;
23830 	struct wlan_mlo_dev_context *mlo_dev_ctx;
23831 	struct wlan_mlo_sta *sta_ctx;
23832 	struct mlo_link_info *partner_link_info;
23833 	struct element_info *assoc_rsp;
23834 	const uint8_t *ie_data_ptr;
23835 	size_t ie_data_len, ml_ie_len = 0;
23836 	uint8_t *ml_ie = NULL;
23837 	bool found = false;
23838 	struct mlo_partner_info partner_info = {0};
23839 
23840 	if (!vdev)
23841 		return QDF_STATUS_E_NULL_VALUE;
23842 
23843 	mlo_dev_ctx = vdev->mlo_dev_ctx;
23844 	if (!mlo_dev_ctx)
23845 		return QDF_STATUS_E_INVAL;
23846 
23847 	sta_ctx = mlo_dev_ctx->sta_ctx;
23848 	if (!sta_ctx)
23849 		return QDF_STATUS_E_INVAL;
23850 
23851 	mlo_dev_lock_acquire(mlo_dev_ctx);
23852 	assoc_rsp = &sta_ctx->assoc_rsp;
23853 
23854 	if (!assoc_rsp->len || !assoc_rsp->ptr ||
23855 	    assoc_rsp->len <= WLAN_ASSOC_RSP_IES_OFFSET) {
23856 		mlo_dev_lock_release(mlo_dev_ctx);
23857 		return QDF_STATUS_E_INVAL;
23858 	}
23859 
23860 	ie_data_len = assoc_rsp->len - WLAN_ASSOC_RSP_IES_OFFSET;
23861 	ie_data_ptr = assoc_rsp->ptr + WLAN_ASSOC_RSP_IES_OFFSET;
23862 	status = util_find_mlie((uint8_t *)ie_data_ptr, ie_data_len,
23863 				&ml_ie, &ml_ie_len);
23864 
23865 	if (QDF_IS_STATUS_ERROR(status) || !ml_ie) {
23866 		mlo_dev_lock_release(mlo_dev_ctx);
23867 		hdd_debug("ML IE not found %d", status);
23868 		return status;
23869 	}
23870 
23871 	status = util_get_bvmlie_persta_partner_info(ml_ie, ml_ie_len,
23872 						     &partner_info);
23873 	if (QDF_IS_STATUS_ERROR(status)) {
23874 		mlo_dev_lock_release(mlo_dev_ctx);
23875 		hdd_err("Unable to find per-sta profile in ML IE");
23876 		return status;
23877 	}
23878 	mlo_dev_lock_release(mlo_dev_ctx);
23879 
23880 	for (i = 0; i < partner_info.num_partner_links; i++) {
23881 		partner_link_info = &partner_info.partner_link_info[i];
23882 		if (partner_link_info->link_id == vdev->vdev_mlme.mlo_link_id) {
23883 			qdf_copy_macaddr(partner_mac,
23884 					 &partner_link_info->link_addr);
23885 			found = true;
23886 			break;
23887 		}
23888 	}
23889 
23890 	if (!partner_info.num_partner_links || !found)
23891 		status = QDF_STATUS_E_NOENT;
23892 
23893 	return status;
23894 }
23895 #endif
23896 
23897 #if defined(QCA_MULTIPASS_SUPPORT) && \
23898 	(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
23899 static void
wlan_hdd_set_vlan_groupkey(ol_txrx_soc_handle soc_txrx_handle,uint16_t vdev_id,struct key_params * params,uint8_t key_index)23900 wlan_hdd_set_vlan_groupkey(ol_txrx_soc_handle soc_txrx_handle, uint16_t vdev_id,
23901 			   struct key_params *params, uint8_t key_index)
23902 {
23903 	if (params->vlan_id)
23904 		cdp_set_vlan_groupkey(soc_txrx_handle, vdev_id,
23905 				      params->vlan_id, key_index);
23906 }
23907 
23908 static int
wlan_hdd_add_vlan(struct wlan_objmgr_vdev * vdev,struct sap_context * sap_ctx,struct key_params * params,uint8_t key_index,uint8_t * vlan_key_idx)23909 wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
23910 		  struct key_params *params, uint8_t key_index,
23911 		  uint8_t *vlan_key_idx)
23912 {
23913 	struct wlan_objmgr_psoc *psoc = NULL;
23914 	ol_txrx_soc_handle soc_txrx_handle;
23915 	uint16_t *vlan_map = sap_ctx->vlan_map;
23916 	uint8_t found = 0;
23917 	bool keyindex_valid;
23918 	int i = 0;
23919 
23920 	psoc = wlan_vdev_get_psoc(vdev);
23921 	if (!psoc) {
23922 		hdd_err("Unable to get psoc");
23923 		return -EINVAL;
23924 	}
23925 
23926 	for (i = 0; i < (MAX_VLAN * 2); i += 2) {
23927 		if (!vlan_map[i] || !vlan_map[i + 1]) {
23928 			found = 1;
23929 			break;
23930 		} else if ((vlan_map[i] == params->vlan_id) ||
23931 			   (vlan_map[i + 1] == params->vlan_id)) {
23932 			vlan_map[i] = 0;
23933 			vlan_map[i + 1] = 0;
23934 			found = 1;
23935 			break;
23936 		}
23937 	}
23938 
23939 	keyindex_valid = (i + key_index - 1) < (2 * MAX_VLAN) ? true : false;
23940 
23941 	if (found && keyindex_valid) {
23942 		soc_txrx_handle = wlan_psoc_get_dp_handle(psoc);
23943 		vlan_map[i + key_index - 1] = params->vlan_id;
23944 		wlan_hdd_set_vlan_groupkey(soc_txrx_handle,
23945 					   wlan_vdev_get_id(vdev),
23946 					   params,
23947 					   (i / 2) + 1);
23948 		*vlan_key_idx = (i + key_index - 1 + 8);
23949 		return 0;
23950 	}
23951 
23952 	hdd_err("Unable to find group key mapping for vlan_id: %d",
23953 		params->vlan_id);
23954 	return -EINVAL;
23955 }
23956 #else
23957 static int
wlan_hdd_add_vlan(struct wlan_objmgr_vdev * vdev,struct sap_context * sap_ctx,struct key_params * params,uint8_t key_index,uint8_t * vlan_key_idx)23958 wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
23959 		  struct key_params *params, uint8_t key_index,
23960 		  uint8_t *vlan_key_idx)
23961 {
23962 	return key_index;
23963 }
23964 #endif
23965 
23966 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev * vdev,struct hdd_context * hdd_ctx,u8 key_index,bool pairwise,struct key_params * params)23967 static void wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev *vdev,
23968 					       struct hdd_context *hdd_ctx,
23969 					       u8 key_index, bool pairwise,
23970 					       struct key_params *params)
23971 {
23972 	struct mlo_link_info *mlo_link_info;
23973 	uint8_t link_info_iter = 0;
23974 
23975 	mlo_link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[0];
23976 	for (link_info_iter = 0; link_info_iter < WLAN_MAX_ML_BSS_LINKS;
23977 	     link_info_iter++, mlo_link_info++) {
23978 		if (qdf_is_macaddr_zero(&mlo_link_info->ap_link_addr) ||
23979 		    mlo_link_info->link_id == 0xFF)
23980 			continue;
23981 			hdd_debug(" Add pairwise key link id  %d ",
23982 				  mlo_link_info->link_id);
23983 			wlan_cfg80211_store_link_key(
23984 				hdd_ctx->psoc, key_index,
23985 				(pairwise ? WLAN_CRYPTO_KEY_TYPE_UNICAST :
23986 				WLAN_CRYPTO_KEY_TYPE_GROUP),
23987 				(uint8_t *)mlo_link_info->ap_link_addr.bytes,
23988 				params, &mlo_link_info->link_addr,
23989 				mlo_link_info->link_id);
23990 	}
23991 }
23992 
23993 static bool
wlan_hdd_mlo_defer_set_keys(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mac_address)23994 wlan_hdd_mlo_defer_set_keys(struct hdd_adapter *adapter,
23995 			    struct wlan_objmgr_vdev *vdev,
23996 			    struct qdf_mac_addr *mac_address)
23997 {
23998 	uint8_t link_id;
23999 
24000 	if (!adapter)
24001 		return false;
24002 
24003 	if (!vdev || !vdev->mlo_dev_ctx)
24004 		return false;
24005 
24006 	link_id = wlan_vdev_get_link_id(vdev);
24007 
24008 	if ((adapter->device_mode == QDF_STA_MODE) &&
24009 	    ((!wlan_cm_is_vdev_connected(vdev)) ||
24010 	    (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
24011 	     mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
24012 					       wlan_vdev_get_id(vdev))))) {
24013 		hdd_debug("MLO:Defer set keys for link_id %d", link_id);
24014 		mlo_defer_set_keys(vdev, link_id, true);
24015 		return true;
24016 	}
24017 
24018 	return false;
24019 }
24020 
24021 #else
24022 
wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev * vdev,struct hdd_context * hdd_ctx,u8 key_index,bool pairwise,struct key_params * params)24023 static void wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev *vdev,
24024 					       struct hdd_context *hdd_ctx,
24025 					       u8 key_index, bool pairwise,
24026 					       struct key_params *params)
24027 {
24028 }
24029 
24030 static bool
wlan_hdd_mlo_defer_set_keys(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mac_address)24031 wlan_hdd_mlo_defer_set_keys(struct hdd_adapter *adapter,
24032 			    struct wlan_objmgr_vdev *vdev,
24033 			    struct qdf_mac_addr *mac_address)
24034 {
24035 	return false;
24036 }
24037 
24038 #endif
24039 
wlan_hdd_add_key_vdev(mac_handle_t mac_handle,struct wlan_objmgr_vdev * vdev,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params,int link_id,struct wlan_hdd_link_info * link_info)24040 static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
24041 				 struct wlan_objmgr_vdev *vdev, u8 key_index,
24042 				 bool pairwise, const u8 *mac_addr,
24043 				 struct key_params *params, int link_id,
24044 				 struct wlan_hdd_link_info *link_info)
24045 {
24046 	QDF_STATUS status;
24047 	struct wlan_objmgr_peer *peer;
24048 	struct hdd_context *hdd_ctx;
24049 	struct qdf_mac_addr mac_address;
24050 	int32_t cipher_cap, ucast_cipher = 0;
24051 	int errno = 0;
24052 	enum wlan_crypto_cipher_type cipher;
24053 	bool ft_mode = false;
24054 	uint8_t keyidx;
24055 	struct hdd_ap_ctx *hdd_ap_ctx;
24056 	struct sap_context *sap_ctx;
24057 	struct hdd_adapter *adapter = link_info->adapter;
24058 
24059 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24060 
24061 	if (hdd_is_btk_enc_type(params->cipher))
24062 		return sme_add_key_btk(mac_handle, wlan_vdev_get_id(vdev),
24063 				       params->key, params->key_len);
24064 	if (hdd_is_krk_enc_type(params->cipher))
24065 		return sme_add_key_krk(mac_handle, wlan_vdev_get_id(vdev),
24066 				       params->key, params->key_len);
24067 
24068 	if (!pairwise && ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) ||
24069 	   (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE))) {
24070 		peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_ID);
24071 		if (peer) {
24072 			qdf_mem_copy(mac_address.bytes,
24073 				     wlan_peer_get_macaddr(peer),
24074 				     QDF_MAC_ADDR_SIZE);
24075 			wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
24076 		} else if (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
24077 			   adapter->device_mode == QDF_STA_MODE) {
24078 			status = wlan_objmgr_vdev_try_get_ref(vdev,
24079 							      WLAN_OSIF_ID);
24080 			if (QDF_IS_STATUS_ERROR(status)) {
24081 				hdd_err("Failed to get vdev ref");
24082 				return qdf_status_to_os_return(status);
24083 			}
24084 			status = wlan_hdd_mlo_copy_partner_addr_from_mlie(
24085 							vdev, &mac_address);
24086 			wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
24087 			if (QDF_IS_STATUS_ERROR(status)) {
24088 				hdd_err("Failed to get peer address from ML IEs");
24089 				return qdf_status_to_os_return(status);
24090 			}
24091 			goto done;
24092 		} else {
24093 			hdd_err("Peer is null return");
24094 			return -EINVAL;
24095 		}
24096 
24097 		status = mlo_get_link_mac_addr_from_reassoc_rsp(vdev,
24098 								&mac_address);
24099 		if (QDF_IS_STATUS_ERROR(status)) {
24100 			peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
24101 								WLAN_OSIF_ID);
24102 			if (!peer) {
24103 				hdd_err("Peer is null return");
24104 				return -EINVAL;
24105 			}
24106 			qdf_mem_copy(mac_address.bytes,
24107 				     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
24108 			wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
24109 		}
24110 	} else {
24111 		if (mac_addr)
24112 			qdf_mem_copy(mac_address.bytes,
24113 				     mac_addr,
24114 				     QDF_MAC_ADDR_SIZE);
24115 	}
24116 
24117 done:
24118 	wlan_hdd_mlo_link_free_keys(hdd_ctx->psoc, adapter, vdev, pairwise);
24119 	if (pairwise && adapter->device_mode == QDF_STA_MODE &&
24120 	    wlan_vdev_mlme_is_mlo_vdev(vdev) &&
24121 	    !wlan_vdev_mlme_is_tdls_vdev(vdev)) {
24122 		wlan_hdd_mlo_link_add_pairwise_key(vdev, hdd_ctx, key_index,
24123 						   pairwise, params);
24124 
24125 	} else {
24126 		errno = wlan_cfg80211_store_key(
24127 					vdev, key_index,
24128 					(pairwise ?
24129 					WLAN_CRYPTO_KEY_TYPE_UNICAST :
24130 					WLAN_CRYPTO_KEY_TYPE_GROUP),
24131 					mac_address.bytes, params);
24132 	}
24133 
24134 	if (wlan_hdd_mlo_defer_set_keys(adapter, vdev, &mac_address))
24135 		return 0;
24136 
24137 	cipher_cap = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_CIPHER_CAP);
24138 	if (errno)
24139 		return errno;
24140 	cipher = osif_nl_to_crypto_cipher_type(params->cipher);
24141 	QDF_SET_PARAM(ucast_cipher, cipher);
24142 	if (pairwise)
24143 		wma_set_peer_ucast_cipher(mac_address.bytes,
24144 					  ucast_cipher, cipher_cap);
24145 
24146 	cdp_peer_flush_frags(cds_get_context(QDF_MODULE_ID_SOC),
24147 			     wlan_vdev_get_id(vdev), mac_address.bytes);
24148 
24149 	switch (adapter->device_mode) {
24150 	case QDF_SAP_MODE:
24151 	case QDF_P2P_GO_MODE:
24152 		hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
24153 		if (hdd_ap_ctx->during_auth_offload) {
24154 			hdd_err("don't need install key during auth");
24155 			return -EINVAL;
24156 		}
24157 
24158 		keyidx = key_index;
24159 
24160 		if (ucfg_mlme_is_multipass_sap(hdd_ctx->psoc) &&
24161 		    params->vlan_id) {
24162 			sap_ctx = hdd_ap_ctx->sap_context;
24163 			errno = wlan_hdd_add_vlan(vdev, sap_ctx, params,
24164 						  key_index, &keyidx);
24165 			if (errno < 0)
24166 				return errno;
24167 		}
24168 
24169 		errno = wlan_hdd_add_key_sap(link_info, pairwise,
24170 					     keyidx, cipher);
24171 
24172 		break;
24173 	case QDF_STA_MODE:
24174 	case QDF_P2P_CLIENT_MODE:
24175 	case QDF_NAN_DISC_MODE:
24176 		errno = wlan_hdd_add_key_sta(hdd_ctx->pdev, link_info, pairwise,
24177 					     key_index, &ft_mode);
24178 		if (ft_mode)
24179 			return 0;
24180 		break;
24181 	default:
24182 		break;
24183 	}
24184 	if (!errno && (adapter->device_mode != QDF_SAP_MODE))
24185 		wma_update_set_key(wlan_vdev_get_id(vdev), pairwise, key_index,
24186 				   cipher);
24187 
24188 	hdd_exit();
24189 	return errno;
24190 }
24191 
24192 #ifdef WLAN_FEATURE_11BE_MLO
wlan_hdd_send_key_vdev(struct wlan_objmgr_vdev * vdev,u8 key_index,bool pairwise,enum wlan_crypto_cipher_type cipher_type)24193 QDF_STATUS wlan_hdd_send_key_vdev(struct wlan_objmgr_vdev *vdev,
24194 				  u8 key_index, bool pairwise,
24195 				  enum wlan_crypto_cipher_type cipher_type)
24196 {
24197 	struct wlan_objmgr_peer *peer;
24198 	struct qdf_mac_addr mac_address;
24199 	int32_t cipher_cap, ucast_cipher = 0;
24200 	QDF_STATUS status = QDF_STATUS_SUCCESS;
24201 	int errno;
24202 	bool ft_mode = false;
24203 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
24204 	uint8_t vdev_id;
24205 	struct wlan_hdd_link_info *link_info;
24206 
24207 	if (!hdd_ctx) {
24208 		hdd_err("hdd_ctx is NULL");
24209 		return QDF_STATUS_E_NULL_VALUE;
24210 	}
24211 
24212 	vdev_id = wlan_vdev_get_id(vdev);
24213 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
24214 	if (!link_info) {
24215 		hdd_err("adapter is NULL for vdev %d", vdev_id);
24216 		return QDF_STATUS_E_NULL_VALUE;
24217 	}
24218 
24219 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) {
24220 		hdd_debug("vdev opmode is not STA mode");
24221 		return QDF_STATUS_E_INVAL;
24222 	}
24223 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_ID);
24224 	if (!peer) {
24225 		hdd_err("Peer is null return");
24226 		return QDF_STATUS_E_NULL_VALUE;
24227 	}
24228 	qdf_mem_copy(mac_address.bytes,
24229 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
24230 	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
24231 
24232 	cipher_cap = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_CIPHER_CAP);
24233 	QDF_SET_PARAM(ucast_cipher, cipher_type);
24234 	if (pairwise)
24235 		wma_set_peer_ucast_cipher(mac_address.bytes,
24236 					  ucast_cipher, cipher_cap);
24237 
24238 	cdp_peer_flush_frags(cds_get_context(QDF_MODULE_ID_SOC),
24239 			     vdev_id, mac_address.bytes);
24240 
24241 	errno = wlan_hdd_add_key_sta(hdd_ctx->pdev, link_info,
24242 				     pairwise, key_index, &ft_mode);
24243 	if (ft_mode)
24244 		return QDF_STATUS_SUCCESS;
24245 
24246 	if (!errno)
24247 		wma_update_set_key(vdev_id, pairwise, key_index, cipher_type);
24248 	else
24249 		status = QDF_STATUS_E_FAILURE;
24250 
24251 	return status;
24252 }
24253 #endif
24254 
24255 #if defined(WLAN_FEATURE_11BE_MLO) && \
24256 defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT)
24257 struct wlan_objmgr_peer *
wlan_hdd_ml_sap_get_peer(struct wlan_objmgr_vdev * vdev,const uint8_t * peer_mld)24258 wlan_hdd_ml_sap_get_peer(struct wlan_objmgr_vdev *vdev,
24259 			 const uint8_t *peer_mld)
24260 {
24261 	struct wlan_mlo_dev_context *ap_mlo_dev_ctx;
24262 	struct wlan_mlo_peer_list *mlo_peer_list;
24263 	struct wlan_mlo_peer_context *ml_peer;
24264 	struct wlan_mlo_link_peer_entry *peer_entry;
24265 	int i, pdev_id;
24266 	uint8_t *peer_mac;
24267 	struct wlan_objmgr_pdev *pdev;
24268 	struct wlan_objmgr_psoc *psoc;
24269 	struct wlan_objmgr_peer *peer = NULL;
24270 
24271 	if (!vdev)
24272 		return NULL;
24273 
24274 	pdev = wlan_vdev_get_pdev(vdev);
24275 
24276 	if (!pdev)
24277 		return NULL;
24278 
24279 	psoc = wlan_pdev_get_psoc(pdev);
24280 
24281 	if (!psoc)
24282 		return NULL;
24283 
24284 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
24285 
24286 	ap_mlo_dev_ctx = vdev->mlo_dev_ctx;
24287 	mlo_dev_lock_acquire(ap_mlo_dev_ctx);
24288 	mlo_peer_list = &ap_mlo_dev_ctx->mlo_peer_list;
24289 	ml_peerlist_lock_acquire(mlo_peer_list);
24290 	ml_peer = mlo_get_mlpeer(ap_mlo_dev_ctx,
24291 				 (struct qdf_mac_addr *)peer_mld);
24292 	if (!ml_peer) {
24293 		/* Peer is a legacy STA client, check peer list.
24294 		 * Treat the MLD address as legacy MAC address
24295 		 */
24296 		peer = wlan_objmgr_get_peer(psoc, pdev_id,
24297 					    peer_mld, WLAN_OSIF_ID);
24298 		goto out;
24299 	}
24300 
24301 	mlo_peer_lock_acquire(ml_peer);
24302 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
24303 		peer_entry = &ml_peer->peer_list[i];
24304 		if (!peer_entry)
24305 			continue;
24306 		/* Checking for VDEV match which will
24307 		 * be used for multiple VDEV case.
24308 		 */
24309 		if (vdev == wlan_peer_get_vdev(peer_entry->link_peer)) {
24310 			peer_mac = &peer_entry->link_peer->macaddr[0];
24311 			peer = wlan_objmgr_get_peer(psoc, pdev_id, peer_mac,
24312 						    WLAN_OSIF_ID);
24313 			break;
24314 		}
24315 	}
24316 	mlo_peer_lock_release(ml_peer);
24317 
24318 out:
24319 	ml_peerlist_lock_release(mlo_peer_list);
24320 	mlo_dev_lock_release(ap_mlo_dev_ctx);
24321 
24322 	return peer;
24323 }
24324 
wlan_hdd_add_key_all_mlo_vdev(mac_handle_t mac_handle,struct wlan_objmgr_vdev * vdev,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params,int link_id,struct hdd_adapter * adapter)24325 static int wlan_hdd_add_key_all_mlo_vdev(mac_handle_t mac_handle,
24326 					 struct wlan_objmgr_vdev *vdev,
24327 					 u8 key_index, bool pairwise,
24328 					 const u8 *mac_addr,
24329 					 struct key_params *params, int link_id,
24330 					 struct hdd_adapter *adapter)
24331 {
24332 	QDF_STATUS status;
24333 	struct hdd_context *hdd_ctx;
24334 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
24335 	struct wlan_objmgr_vdev *link_vdev;
24336 	struct qdf_mac_addr peer_mac;
24337 	struct wlan_objmgr_peer *peer = NULL;
24338 	int errno = 0;
24339 	uint16_t link, vdev_count = 0;
24340 	uint8_t vdev_id;
24341 	struct wlan_hdd_link_info *link_info;
24342 
24343 	/* if vdev mlme is mlo & pairwaise is set to true set same info for
24344 	 * both the links.
24345 	 */
24346 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24347 
24348 	mlo_sta_get_vdev_list(vdev, &vdev_count, wlan_vdev_list);
24349 	for (link = 0; link < vdev_count; link++) {
24350 		link_vdev = wlan_vdev_list[link];
24351 		vdev_id = wlan_vdev_get_id(link_vdev);
24352 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
24353 		if (!link_info) {
24354 			mlo_release_vdev_ref(link_vdev);
24355 			continue;
24356 		}
24357 		peer = NULL;
24358 		switch (adapter->device_mode) {
24359 		case QDF_SAP_MODE:
24360 			if (wlan_vdev_mlme_is_mlo_vdev(link_vdev))
24361 				peer = wlan_hdd_ml_sap_get_peer(
24362 						link_vdev,
24363 						mac_addr);
24364 			break;
24365 		case QDF_STA_MODE:
24366 		default:
24367 			status = mlo_get_link_mac_addr_from_reassoc_rsp(link_vdev,
24368 									&peer_mac);
24369 			if (QDF_IS_STATUS_ERROR(status))
24370 				peer = wlan_objmgr_vdev_try_get_bsspeer(link_vdev,
24371 									WLAN_OSIF_ID);
24372 			else
24373 				goto add_key;
24374 			break;
24375 		}
24376 
24377 		if (peer) {
24378 			qdf_mem_copy(peer_mac.bytes,
24379 				     wlan_peer_get_macaddr(peer),
24380 				     QDF_MAC_ADDR_SIZE);
24381 			wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
24382 
24383 		} else if (wlan_vdev_mlme_is_mlo_link_vdev(link_vdev) &&
24384 			   adapter->device_mode == QDF_STA_MODE) {
24385 			status = wlan_hdd_mlo_copy_partner_addr_from_mlie(
24386 							link_vdev, &peer_mac);
24387 			if (QDF_IS_STATUS_ERROR(status)) {
24388 				hdd_err("Failed to get peer address from ML IEs");
24389 				mlo_release_vdev_ref(link_vdev);
24390 				continue;
24391 			}
24392 		} else {
24393 			hdd_err("Peer is null");
24394 			mlo_release_vdev_ref(link_vdev);
24395 			continue;
24396 		}
24397 
24398 add_key:
24399 		errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
24400 					      pairwise, peer_mac.bytes,
24401 					      params, link_id, link_info);
24402 		mlo_release_vdev_ref(link_vdev);
24403 	}
24404 
24405 	return errno;
24406 }
24407 
wlan_add_key_standby_link(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,int link_id,u8 key_index,bool pairwise,struct key_params * params)24408 static int wlan_add_key_standby_link(struct hdd_adapter *adapter,
24409 				     struct wlan_objmgr_vdev *vdev,
24410 				     int link_id, u8 key_index,
24411 				     bool pairwise, struct key_params *params)
24412 {
24413 	int errno = 0;
24414 	struct hdd_context *hdd_ctx;
24415 	struct mlo_link_info *mlo_link_info;
24416 
24417 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24418 
24419 	mlo_link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx,
24420 						       link_id);
24421 	if (!mlo_link_info)
24422 		return QDF_STATUS_E_FAILURE;
24423 
24424 	errno = wlan_cfg80211_store_link_key(
24425 			hdd_ctx->psoc, key_index,
24426 			(pairwise ? WLAN_CRYPTO_KEY_TYPE_UNICAST :
24427 			WLAN_CRYPTO_KEY_TYPE_GROUP),
24428 			(uint8_t *)mlo_link_info->ap_link_addr.bytes,
24429 			params,
24430 			&mlo_link_info->link_addr,
24431 			link_id);
24432 	hdd_debug("ml defer set key link id %d", link_id);
24433 	mlo_defer_set_keys(vdev, link_id, true);
24434 	return errno;
24435 }
24436 
wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,struct wlan_objmgr_vdev * vdev,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params,int link_id,struct hdd_adapter * adapter)24437 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
24438 				     struct wlan_objmgr_vdev *vdev,
24439 				     u8 key_index, bool pairwise,
24440 				     const u8 *mac_addr,
24441 				     struct key_params *params, int link_id,
24442 				     struct hdd_adapter *adapter)
24443 {
24444 	int errno = 0;
24445 	struct wlan_objmgr_vdev *link_vdev;
24446 	struct hdd_context *hdd_ctx;
24447 	uint8_t vdev_id;
24448 	QDF_STATUS status;
24449 	struct wlan_hdd_link_info *link_info;
24450 
24451 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
24452 		return errno;
24453 
24454 	vdev_id = wlan_vdev_get_id(vdev);
24455 	if (pairwise &&
24456 	    mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
24457 					      vdev_id)) {
24458 		status = mlo_roam_link_connect_notify(adapter->hdd_ctx->psoc,
24459 						      vdev_id);
24460 		if (QDF_IS_STATUS_ERROR(status)) {
24461 			hdd_err("Posting of link connect request failed");
24462 			return -EINVAL;
24463 		}
24464 	}
24465 
24466 	link_vdev = ucfg_tdls_get_tdls_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
24467 	if (pairwise && link_id == -1 && !link_vdev)
24468 		return wlan_hdd_add_key_all_mlo_vdev(mac_handle, vdev,
24469 						     key_index, pairwise,
24470 						     mac_addr, params,
24471 						     link_id, adapter);
24472 
24473 	if (pairwise && link_id == -1 && link_vdev) {
24474 		hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24475 		link_info =
24476 		      hdd_get_link_info_by_vdev(hdd_ctx,
24477 						wlan_vdev_get_id(link_vdev));
24478 		link_id = wlan_vdev_get_link_id(link_vdev);
24479 		if (!link_info) {
24480 			ucfg_tdls_put_tdls_link_vdev(link_vdev,
24481 						     WLAN_OSIF_TDLS_ID);
24482 			hdd_err("couldn't set tdls key, link_id %d", link_id);
24483 			return -EINVAL;
24484 		}
24485 
24486 		errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
24487 					      pairwise, mac_addr, params,
24488 					      link_id, link_info);
24489 		ucfg_tdls_put_tdls_link_vdev(link_vdev, WLAN_OSIF_TDLS_ID);
24490 
24491 		return errno;
24492 	}
24493 
24494 	if (link_vdev)
24495 		ucfg_tdls_put_tdls_link_vdev(link_vdev, WLAN_OSIF_TDLS_ID);
24496 
24497 	if (wlan_vdev_get_link_id(adapter->deflink->vdev) == link_id) {
24498 		hdd_debug("add_key for same vdev: %d",
24499 			  adapter->deflink->vdev_id);
24500 		return wlan_hdd_add_key_vdev(mac_handle, vdev, key_index,
24501 					     pairwise, mac_addr, params,
24502 					     link_id, adapter->deflink);
24503 	}
24504 
24505 	link_vdev = wlan_key_get_link_vdev(adapter, WLAN_MLO_MGR_ID, link_id);
24506 	if (!link_vdev) {
24507 		hdd_err("couldn't get vdev for link_id :%d", link_id);
24508 		errno = wlan_add_key_standby_link(adapter, vdev, link_id,
24509 						  key_index, pairwise, params);
24510 		return errno;
24511 	}
24512 
24513 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24514 	link_info = hdd_get_link_info_by_vdev(hdd_ctx,
24515 					      wlan_vdev_get_id(link_vdev));
24516 	if (!link_info) {
24517 		hdd_err("couldn't set key for link_id:%d", link_id);
24518 		goto release_ref;
24519 	}
24520 
24521 	errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
24522 				      pairwise, mac_addr, params,
24523 				      link_id, link_info);
24524 
24525 release_ref:
24526 	wlan_key_put_link_vdev(link_vdev, WLAN_MLO_MGR_ID);
24527 	return errno;
24528 }
24529 #elif defined(CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV)
wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,struct wlan_objmgr_vdev * vdev,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params,int link_id,struct hdd_adapter * adapter)24530 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
24531 				     struct wlan_objmgr_vdev *vdev,
24532 				     u8 key_index, bool pairwise,
24533 				     const u8 *mac_addr,
24534 				     struct key_params *params, int link_id,
24535 				     struct hdd_adapter *adapter)
24536 {
24537 	return wlan_hdd_add_key_vdev(mac_handle, vdev, key_index,
24538 				     pairwise, mac_addr, params,
24539 				     link_id, adapter->deflink);
24540 }
24541 #else
wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,struct wlan_objmgr_vdev * vdev,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params,int link_id,struct hdd_adapter * adapter)24542 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
24543 				     struct wlan_objmgr_vdev *vdev,
24544 				     u8 key_index, bool pairwise,
24545 				     const u8 *mac_addr,
24546 				     struct key_params *params, int link_id,
24547 				     struct hdd_adapter *adapter)
24548 {
24549 	return 0;
24550 }
24551 #endif
24552 
__wlan_hdd_cfg80211_add_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params,int link_id)24553 static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24554 				       struct net_device *ndev,
24555 				       u8 key_index, bool pairwise,
24556 				       const u8 *mac_addr,
24557 				       struct key_params *params, int link_id)
24558 {
24559 	struct hdd_context *hdd_ctx;
24560 	mac_handle_t mac_handle;
24561 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
24562 	struct wlan_objmgr_vdev *vdev;
24563 	int errno;
24564 
24565 	hdd_enter();
24566 
24567 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
24568 		hdd_err("Command not allowed in FTM mode");
24569 		return -EINVAL;
24570 	}
24571 
24572 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24573 		return -EINVAL;
24574 
24575 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
24576 		   TRACE_CODE_HDD_CFG80211_ADD_KEY,
24577 		   adapter->deflink->vdev_id, params->key_len);
24578 
24579 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24580 	errno = wlan_hdd_validate_context(hdd_ctx);
24581 	if (errno)
24582 		return errno;
24583 
24584 	hdd_debug("converged Device_mode %s(%d) index %d, pairwise %d link_id %d",
24585 		  qdf_opmode_str(adapter->device_mode),
24586 		  adapter->device_mode, key_index, pairwise, link_id);
24587 	mac_handle = hdd_ctx->mac_handle;
24588 
24589 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
24590 	if (!vdev)
24591 		return -EINVAL;
24592 
24593 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
24594 		errno = wlan_hdd_add_key_vdev(mac_handle, vdev, key_index,
24595 					      pairwise, mac_addr, params,
24596 					      link_id, adapter->deflink);
24597 	else
24598 		errno = wlan_hdd_add_key_mlo_vdev(mac_handle, vdev, key_index,
24599 						  pairwise, mac_addr, params,
24600 						  link_id, adapter);
24601 
24602 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
24603 
24604 	return errno;
24605 }
24606 
24607 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24608 #ifdef CFG80211_SET_KEY_WITH_SRC_MAC
wlan_hdd_cfg80211_add_key(struct wiphy * wiphy,struct wireless_dev * wdev,u8 key_index,bool pairwise,const u8 * src_addr,const u8 * mac_addr,struct key_params * params)24609 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24610 				     struct wireless_dev *wdev,
24611 				     u8 key_index, bool pairwise,
24612 				     const u8 *src_addr,
24613 				     const u8 *mac_addr,
24614 				     struct key_params *params)
24615 #else
24616 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24617 				     struct wireless_dev *wdev,
24618 				     u8 key_index, bool pairwise,
24619 				     const u8 *mac_addr,
24620 				     struct key_params *params)
24621 #endif
24622 {
24623 	int errno = -EINVAL;
24624 	struct osif_vdev_sync *vdev_sync;
24625 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24626 						   struct hdd_adapter,
24627 						   wdev);
24628 	/* Legacy purposes */
24629 	int link_id = -1;
24630 
24631 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24632 		return errno;
24633 
24634 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24635 	if (errno)
24636 		return errno;
24637 
24638 	errno = __wlan_hdd_cfg80211_add_key(wiphy, adapter->dev, key_index,
24639 					    pairwise, mac_addr, params,
24640 					    link_id);
24641 
24642 	osif_vdev_sync_op_stop(vdev_sync);
24643 
24644 	return errno;
24645 }
24646 #elif defined(CFG80211_SET_KEY_WITH_SRC_MAC)
wlan_hdd_cfg80211_add_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index,bool pairwise,const u8 * src_addr,const u8 * mac_addr,struct key_params * params)24647 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24648 				     struct net_device *ndev,
24649 				     u8 key_index, bool pairwise,
24650 				     const u8 *src_addr,
24651 				     const u8 *mac_addr,
24652 				     struct key_params *params)
24653 {
24654 	int errno;
24655 	int link_id = -1;
24656 	struct osif_vdev_sync *vdev_sync;
24657 
24658 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24659 	if (errno)
24660 		return errno;
24661 
24662 	errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
24663 					    mac_addr, params, link_id);
24664 
24665 	osif_vdev_sync_op_stop(vdev_sync);
24666 
24667 	return errno;
24668 }
24669 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
wlan_hdd_cfg80211_add_key(struct wiphy * wiphy,struct net_device * ndev,int link_id,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params)24670 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24671 				     struct net_device *ndev,
24672 				     int link_id, u8 key_index, bool pairwise,
24673 				     const u8 *mac_addr,
24674 				     struct key_params *params)
24675 {
24676 	int errno;
24677 	struct osif_vdev_sync *vdev_sync;
24678 
24679 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24680 	if (errno)
24681 		return errno;
24682 
24683 	errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
24684 					    mac_addr, params, link_id);
24685 
24686 	osif_vdev_sync_op_stop(vdev_sync);
24687 
24688 	return errno;
24689 }
24690 #else
wlan_hdd_cfg80211_add_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params)24691 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24692 				     struct net_device *ndev,
24693 				     u8 key_index, bool pairwise,
24694 				     const u8 *mac_addr,
24695 				     struct key_params *params)
24696 {
24697 	int errno, link_id = -1;
24698 	struct osif_vdev_sync *vdev_sync;
24699 
24700 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24701 	if (errno)
24702 		return errno;
24703 
24704 	errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
24705 					    mac_addr, params, link_id);
24706 
24707 	osif_vdev_sync_op_stop(vdev_sync);
24708 
24709 	return errno;
24710 }
24711 #endif
24712 
__wlan_hdd_cfg80211_get_key(struct wiphy * wiphy,struct net_device * ndev,int link_id,u8 key_index,bool pairwise,const u8 * mac_addr,void * cookie,void (* callback)(void * cookie,struct key_params *))24713 static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
24714 				       struct net_device *ndev,
24715 				       int link_id,
24716 				       u8 key_index, bool pairwise,
24717 				       const u8 *mac_addr, void *cookie,
24718 				       void (*callback)(void *cookie,
24719 							struct key_params *)
24720 				       )
24721 {
24722 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
24723 	struct key_params params;
24724 	eCsrEncryptionType enc_type;
24725 	int32_t ucast_cipher = 0;
24726 	struct wlan_objmgr_vdev *link_vdev;
24727 
24728 	hdd_enter();
24729 
24730 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
24731 		hdd_err("Command not allowed in FTM mode");
24732 		return -EINVAL;
24733 	}
24734 
24735 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24736 		return -EINVAL;
24737 
24738 	hdd_debug("Device_mode %s(%d)",
24739 		  qdf_opmode_str(adapter->device_mode), adapter->device_mode);
24740 
24741 	memset(&params, 0, sizeof(params));
24742 
24743 	if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX +
24744 			  WLAN_CRYPTO_MAXBIGTKKEYIDX)) {
24745 		hdd_err("Invalid key index: %d", key_index);
24746 		return -EINVAL;
24747 	}
24748 
24749 	link_vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
24750 	if (!link_vdev) {
24751 		hdd_err("Invalid vdev for link_id :%d", link_id);
24752 		return -EINVAL;
24753 	}
24754 
24755 	if (link_vdev)
24756 		ucast_cipher = wlan_crypto_get_param(link_vdev,
24757 						WLAN_CRYPTO_PARAM_UCAST_CIPHER);
24758 
24759 	sme_fill_enc_type(&enc_type, ucast_cipher);
24760 
24761 	switch (enc_type) {
24762 	case eCSR_ENCRYPT_TYPE_NONE:
24763 		params.cipher = IW_AUTH_CIPHER_NONE;
24764 		break;
24765 
24766 	case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
24767 	case eCSR_ENCRYPT_TYPE_WEP40:
24768 		params.cipher = WLAN_CIPHER_SUITE_WEP40;
24769 		break;
24770 
24771 	case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
24772 	case eCSR_ENCRYPT_TYPE_WEP104:
24773 		params.cipher = WLAN_CIPHER_SUITE_WEP104;
24774 		break;
24775 
24776 	case eCSR_ENCRYPT_TYPE_TKIP:
24777 		params.cipher = WLAN_CIPHER_SUITE_TKIP;
24778 		break;
24779 
24780 	case eCSR_ENCRYPT_TYPE_AES:
24781 		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
24782 		break;
24783 	case eCSR_ENCRYPT_TYPE_AES_GCMP:
24784 		params.cipher = WLAN_CIPHER_SUITE_GCMP;
24785 		break;
24786 	case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
24787 		params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
24788 		break;
24789 	default:
24790 		params.cipher = IW_AUTH_CIPHER_NONE;
24791 		break;
24792 	}
24793 
24794 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
24795 		   TRACE_CODE_HDD_CFG80211_GET_KEY,
24796 		   wlan_vdev_get_id(link_vdev), params.cipher);
24797 
24798 	params.key_len = 0;
24799 	params.seq_len = 0;
24800 	params.seq = NULL;
24801 	params.key = NULL;
24802 	callback(cookie, &params);
24803 
24804 	wlan_key_put_link_vdev(link_vdev, WLAN_OSIF_ID);
24805 	hdd_exit();
24806 	return 0;
24807 }
24808 
24809 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
wlan_hdd_cfg80211_get_key(struct wiphy * wiphy,struct wireless_dev * wdev,u8 key_index,bool pairwise,const u8 * mac_addr,void * cookie,void (* callback)(void * cookie,struct key_params *))24810 static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
24811 				     struct wireless_dev *wdev,
24812 				     u8 key_index, bool pairwise,
24813 				     const u8 *mac_addr, void *cookie,
24814 				     void (*callback)(void *cookie,
24815 						      struct key_params *)
24816 				     )
24817 {
24818 	int errno = -EINVAL;
24819 	struct osif_vdev_sync *vdev_sync;
24820 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24821 						   struct hdd_adapter,
24822 						   wdev);
24823 	int link_id = -1;
24824 
24825 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24826 		return errno;
24827 
24828 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24829 	if (errno)
24830 		return errno;
24831 
24832 	errno = __wlan_hdd_cfg80211_get_key(wiphy, adapter->dev, link_id,
24833 					    key_index,
24834 					    pairwise, mac_addr, cookie,
24835 					    callback);
24836 
24837 	osif_vdev_sync_op_stop(vdev_sync);
24838 
24839 	return errno;
24840 }
24841 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
wlan_hdd_cfg80211_get_key(struct wiphy * wiphy,struct net_device * ndev,int link_id,u8 key_index,bool pairwise,const u8 * mac_addr,void * cookie,void (* callback)(void * cookie,struct key_params *))24842 static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
24843 				     struct net_device *ndev,
24844 				     int link_id, u8 key_index, bool pairwise,
24845 				     const u8 *mac_addr, void *cookie,
24846 				     void (*callback)(void *cookie,
24847 						      struct key_params *)
24848 				     )
24849 {
24850 	int errno;
24851 	struct osif_vdev_sync *vdev_sync;
24852 
24853 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24854 	if (errno)
24855 		return errno;
24856 
24857 	errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, link_id, key_index,
24858 					    pairwise, mac_addr, cookie,
24859 					    callback);
24860 
24861 	osif_vdev_sync_op_stop(vdev_sync);
24862 
24863 	return errno;
24864 }
24865 #else
wlan_hdd_cfg80211_get_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index,bool pairwise,const u8 * mac_addr,void * cookie,void (* callback)(void * cookie,struct key_params *))24866 static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
24867 				     struct net_device *ndev,
24868 				     u8 key_index, bool pairwise,
24869 				     const u8 *mac_addr, void *cookie,
24870 				     void (*callback)(void *cookie,
24871 						      struct key_params *)
24872 				     )
24873 {
24874 	int errno;
24875 	int link_id = -1;
24876 	struct osif_vdev_sync *vdev_sync;
24877 
24878 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24879 	if (errno)
24880 		return errno;
24881 
24882 	errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, link_id, key_index,
24883 					    pairwise, mac_addr, cookie,
24884 					    callback);
24885 
24886 	osif_vdev_sync_op_stop(vdev_sync);
24887 
24888 	return errno;
24889 }
24890 #endif
24891 
24892 /**
24893  * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
24894  * @wiphy: wiphy interface context
24895  * @ndev: pointer to net device
24896  * @key_index: Key index used in 802.11 frames
24897  * @pairwise: true if it is pairwise key
24898  * @mac_addr: Peer address
24899  *
24900  * This function is required for cfg80211_ops API.
24901  * It is used to delete the key information
24902  * Underlying hardware implementation does not have API to delete the
24903  * encryption key for normal peers. Currently delete keys are supported
24904  * only for PASN peers.
24905  * For other peers, it is automatically deleted when the peer is
24906  * removed. Hence this function currently does nothing.
24907  * Future implementation may interpret delete key operation to
24908  * replacing the key with a random junk value, effectively making it
24909  * useless.
24910  *
24911  * Return: status code, always 0.
24912  */
24913 
__wlan_hdd_cfg80211_del_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index,bool pairwise,const u8 * mac_addr)24914 static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
24915 				       struct net_device *ndev,
24916 				       u8 key_index,
24917 				       bool pairwise, const u8 *mac_addr)
24918 {
24919 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
24920 	struct wlan_objmgr_peer *peer;
24921 	struct qdf_mac_addr peer_mac;
24922 	enum wlan_peer_type peer_type;
24923 	QDF_STATUS status = QDF_STATUS_SUCCESS;
24924 	int ret;
24925 
24926 	hdd_enter();
24927 
24928 	if (!mac_addr) {
24929 		hdd_debug("Peer mac address is NULL");
24930 		hdd_exit();
24931 		return 0;
24932 	}
24933 
24934 	ret = wlan_hdd_validate_context(hdd_ctx);
24935 	if (ret)
24936 		return ret;
24937 
24938 	qdf_mem_copy(peer_mac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
24939 	if (qdf_is_macaddr_zero(&peer_mac) ||
24940 	    qdf_is_macaddr_broadcast(&peer_mac)) {
24941 		hdd_err("Invalid mac address");
24942 		ret = -EINVAL;
24943 		goto err;
24944 	}
24945 
24946 	peer = wlan_objmgr_get_peer_by_mac(hdd_ctx->psoc, peer_mac.bytes,
24947 					   WLAN_OSIF_ID);
24948 	if (peer) {
24949 		peer_type = wlan_peer_get_peer_type(peer);
24950 		if (peer_type == WLAN_PEER_RTT_PASN) {
24951 			status = wifi_pos_send_pasn_peer_deauth(hdd_ctx->psoc,
24952 								&peer_mac);
24953 			if (QDF_IS_STATUS_ERROR(status))
24954 				hdd_err("send_pasn_peer_deauth failed");
24955 
24956 			ret = qdf_status_to_os_return(status);
24957 		}
24958 		wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
24959 	}
24960 err:
24961 	hdd_exit();
24962 
24963 	return ret;
24964 }
24965 
24966 /**
24967  * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
24968  * @wiphy: Pointer to wiphy structure.
24969  * @wdev: Pointer to wireless_dev structure.
24970  * @key_index: key index
24971  * @pairwise: pairwise
24972  * @mac_addr: mac address
24973  *
24974  * This is the cfg80211 delete key handler function which invokes
24975  * the internal function @__wlan_hdd_cfg80211_del_key with
24976  * SSR protection.
24977  *
24978  * Return: 0 for success, error number on failure.
24979  */
24980 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
wlan_hdd_cfg80211_del_key(struct wiphy * wiphy,struct wireless_dev * wdev,u8 key_index,bool pairwise,const u8 * mac_addr)24981 static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
24982 				     struct wireless_dev *wdev,
24983 				     u8 key_index,
24984 				     bool pairwise, const u8 *mac_addr)
24985 {
24986 	int errno = -EINVAL;
24987 	struct osif_vdev_sync *vdev_sync;
24988 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24989 						   struct hdd_adapter,
24990 						   wdev);
24991 
24992 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24993 		return errno;
24994 
24995 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24996 	if (errno)
24997 		return errno;
24998 
24999 	errno = __wlan_hdd_cfg80211_del_key(wiphy, adapter->dev, key_index,
25000 					    pairwise, mac_addr);
25001 
25002 	osif_vdev_sync_op_stop(vdev_sync);
25003 
25004 	return errno;
25005 }
25006 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
wlan_hdd_cfg80211_del_key(struct wiphy * wiphy,struct net_device * dev,int link_id,u8 key_index,bool pairwise,const u8 * mac_addr)25007 static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
25008 				     struct net_device *dev,
25009 				     int link_id, u8 key_index,
25010 				     bool pairwise, const u8 *mac_addr)
25011 {
25012 	int errno;
25013 	struct osif_vdev_sync *vdev_sync;
25014 
25015 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25016 	if (errno)
25017 		return errno;
25018 
25019 	errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
25020 					    pairwise, mac_addr);
25021 
25022 	osif_vdev_sync_op_stop(vdev_sync);
25023 
25024 	return errno;
25025 }
25026 #else
wlan_hdd_cfg80211_del_key(struct wiphy * wiphy,struct net_device * dev,u8 key_index,bool pairwise,const u8 * mac_addr)25027 static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
25028 				     struct net_device *dev,
25029 				     u8 key_index, bool pairwise,
25030 				     const u8 *mac_addr)
25031 {
25032 	int errno;
25033 	struct osif_vdev_sync *vdev_sync;
25034 
25035 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25036 	if (errno)
25037 		return errno;
25038 
25039 	errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
25040 					    pairwise, mac_addr);
25041 
25042 	osif_vdev_sync_op_stop(vdev_sync);
25043 
25044 	return errno;
25045 }
25046 #endif
__wlan_hdd_cfg80211_set_default_key(struct wiphy * wiphy,struct net_device * ndev,int link_id,u8 key_index,bool unicast,bool multicast)25047 static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
25048 					       struct net_device *ndev,
25049 					       int link_id,
25050 					       u8 key_index,
25051 					       bool unicast, bool multicast)
25052 {
25053 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
25054 	struct hdd_context *hdd_ctx;
25055 	struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
25056 	struct hdd_ap_ctx *ap_ctx;
25057 	struct wlan_crypto_key *crypto_key;
25058 	struct wlan_objmgr_vdev *vdev;
25059 	int ret;
25060 	QDF_STATUS status;
25061 
25062 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25063 		hdd_err("Command not allowed in FTM mode");
25064 		return -EINVAL;
25065 	}
25066 
25067 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25068 		return -EINVAL;
25069 
25070 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25071 		   TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
25072 		   adapter->deflink->vdev_id, key_index);
25073 
25074 	hdd_debug("Device_mode %s(%d) key_index = %d",
25075 		  qdf_opmode_str(adapter->device_mode),
25076 		  adapter->device_mode, key_index);
25077 
25078 	if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX +
25079 			  WLAN_CRYPTO_MAXBIGTKKEYIDX)) {
25080 		hdd_err("Invalid key index: %d", key_index);
25081 		return -EINVAL;
25082 	}
25083 
25084 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25085 	ret = wlan_hdd_validate_context(hdd_ctx);
25086 
25087 	if (0 != ret)
25088 		return ret;
25089 
25090 	vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
25091 	if (!vdev)
25092 		return -EINVAL;
25093 
25094 	crypto_key = wlan_crypto_get_key(vdev, key_index);
25095 	if (!crypto_key) {
25096 		hdd_err("Invalid NULL key info");
25097 		ret = -EINVAL;
25098 		goto out;
25099 	}
25100 	hdd_debug("unicast %d, multicast %d cipher %d",
25101 		  unicast, multicast, crypto_key->cipher_type);
25102 	if (!IS_WEP_CIPHER(crypto_key->cipher_type)) {
25103 		ret = 0;
25104 		goto out;
25105 	}
25106 
25107 	if ((adapter->device_mode == QDF_STA_MODE) ||
25108 	    (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
25109 		ret =
25110 		wlan_cfg80211_crypto_add_key(vdev,
25111 					     (unicast ?
25112 					      WLAN_CRYPTO_KEY_TYPE_UNICAST :
25113 					      WLAN_CRYPTO_KEY_TYPE_GROUP),
25114 					     key_index, true);
25115 		wma_update_set_key(adapter->deflink->vdev_id, unicast,
25116 				   key_index, crypto_key->cipher_type);
25117 	}
25118 
25119 	if (adapter->device_mode == QDF_SAP_MODE ||
25120 	    adapter->device_mode == QDF_P2P_GO_MODE) {
25121 		status = wlan_cfg80211_set_default_key(vdev, key_index,
25122 						       &bssid);
25123 		if (QDF_IS_STATUS_ERROR(status)) {
25124 			hdd_err("ret fail status %d", ret);
25125 			ret = -EINVAL;
25126 			goto out;
25127 		}
25128 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
25129 		ap_ctx->wep_def_key_idx = key_index;
25130 	}
25131 
25132 out:
25133 	wlan_key_put_link_vdev(vdev, WLAN_OSIF_ID);
25134 	return ret;
25135 }
25136 
25137 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
wlan_hdd_cfg80211_set_default_key(struct wiphy * wiphy,struct wireless_dev * wdev,u8 key_index,bool unicast,bool multicast)25138 static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
25139 					     struct wireless_dev *wdev,
25140 					     u8 key_index,
25141 					     bool unicast, bool multicast)
25142 {
25143 	int errno = -EINVAL;
25144 	struct osif_vdev_sync *vdev_sync;
25145 	struct hdd_adapter *adapter = qdf_container_of(wdev,
25146 						   struct hdd_adapter,
25147 						   wdev);
25148 	int link_id = -1;
25149 
25150 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25151 		return errno;
25152 
25153 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
25154 	if (errno)
25155 		return errno;
25156 
25157 	errno = __wlan_hdd_cfg80211_set_default_key(wiphy, adapter->dev,
25158 						    link_id, key_index,
25159 						    unicast, multicast);
25160 
25161 	osif_vdev_sync_op_stop(vdev_sync);
25162 
25163 	return errno;
25164 }
25165 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
wlan_hdd_cfg80211_set_default_key(struct wiphy * wiphy,struct net_device * ndev,int link_id,u8 key_index,bool unicast,bool multicast)25166 static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
25167 					     struct net_device *ndev,
25168 					     int link_id, u8 key_index,
25169 					     bool unicast, bool multicast)
25170 {
25171 	int errno;
25172 	struct osif_vdev_sync *vdev_sync;
25173 
25174 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
25175 	if (errno)
25176 		return errno;
25177 
25178 	errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, link_id,
25179 						    key_index, unicast,
25180 						    multicast);
25181 
25182 	osif_vdev_sync_op_stop(vdev_sync);
25183 
25184 	return errno;
25185 }
25186 #else
wlan_hdd_cfg80211_set_default_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index,bool unicast,bool multicast)25187 static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
25188 					     struct net_device *ndev,
25189 					     u8 key_index,
25190 					     bool unicast, bool multicast)
25191 {
25192 	int errno;
25193 	int link_id = -1;
25194 	struct osif_vdev_sync *vdev_sync;
25195 
25196 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
25197 	if (errno)
25198 		return errno;
25199 
25200 	errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, link_id,
25201 						    key_index, unicast,
25202 						    multicast);
25203 
25204 	osif_vdev_sync_op_stop(vdev_sync);
25205 
25206 	return errno;
25207 }
25208 #endif
25209 
25210 #if defined (CFG80211_BIGTK_CONFIGURATION_SUPPORT) || \
25211 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
_wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index)25212 static int _wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
25213 						     struct net_device *ndev,
25214 						     u8 key_index)
25215 {
25216 	hdd_enter();
25217 	return 0;
25218 }
25219 
25220 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy * wiphy,struct wireless_dev * wdev,u8 key_index)25221 static int wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
25222 						    struct wireless_dev *wdev,
25223 						    u8 key_index)
25224 {
25225 	int errno = -EINVAL;
25226 	struct osif_vdev_sync *vdev_sync;
25227 	struct hdd_adapter *adapter = qdf_container_of(wdev,
25228 						   struct hdd_adapter,
25229 						   wdev);
25230 
25231 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25232 		return errno;
25233 
25234 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
25235 	if (errno)
25236 		return errno;
25237 
25238 	errno = _wlan_hdd_cfg80211_set_default_beacon_key(wiphy, adapter->dev,
25239 							  key_index);
25240 
25241 	osif_vdev_sync_op_stop(vdev_sync);
25242 
25243 	return errno;
25244 }
25245 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy * wiphy,struct net_device * ndev,int link_id,u8 key_index)25246 static int wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
25247 						    struct net_device *ndev,
25248 						    int link_id, u8 key_index)
25249 {
25250 	int errno;
25251 	struct osif_vdev_sync *vdev_sync;
25252 
25253 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
25254 	if (errno)
25255 		return errno;
25256 
25257 	errno = _wlan_hdd_cfg80211_set_default_beacon_key(wiphy, ndev,
25258 							  key_index);
25259 
25260 	osif_vdev_sync_op_stop(vdev_sync);
25261 
25262 	return errno;
25263 }
25264 #else
wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index)25265 static int wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
25266 						    struct net_device *ndev,
25267 						    u8 key_index)
25268 {
25269 	int errno;
25270 	struct osif_vdev_sync *vdev_sync;
25271 
25272 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
25273 	if (errno)
25274 		return errno;
25275 
25276 	errno = _wlan_hdd_cfg80211_set_default_beacon_key(wiphy, ndev,
25277 							  key_index);
25278 
25279 	osif_vdev_sync_op_stop(vdev_sync);
25280 
25281 	return errno;
25282 }
25283 #endif
25284 #endif
25285 
25286 #ifdef FEATURE_MONITOR_MODE_SUPPORT
25287 static
hdd_mon_select_cbmode(struct hdd_adapter * adapter,uint32_t op_freq,struct ch_params * ch_params)25288 void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
25289 			   uint32_t op_freq,
25290 			   struct ch_params *ch_params)
25291 {
25292 	struct hdd_station_ctx *station_ctx =
25293 			 WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
25294 	struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
25295 	enum hdd_dot11_mode hdd_dot11_mode;
25296 	uint8_t ini_dot11_mode =
25297 			(WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
25298 
25299 	hdd_debug("Dot11Mode is %u", ini_dot11_mode);
25300 	switch (ini_dot11_mode) {
25301 	case eHDD_DOT11_MODE_AUTO:
25302 #ifdef WLAN_FEATURE_11BE
25303 	case eHDD_DOT11_MODE_11be:
25304 	case eHDD_DOT11_MODE_11be_ONLY:
25305 		if (sme_is_feature_supported_by_fw(DOT11BE))
25306 			hdd_dot11_mode = eHDD_DOT11_MODE_11be;
25307 		else
25308 #endif
25309 		if (sme_is_feature_supported_by_fw(DOT11AX))
25310 			hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
25311 		else if (sme_is_feature_supported_by_fw(DOT11AC))
25312 			hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
25313 		else
25314 			hdd_dot11_mode = eHDD_DOT11_MODE_11n;
25315 		break;
25316 	case eHDD_DOT11_MODE_11ax:
25317 	case eHDD_DOT11_MODE_11ax_ONLY:
25318 		if (sme_is_feature_supported_by_fw(DOT11AX))
25319 			hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
25320 		else if (sme_is_feature_supported_by_fw(DOT11AC))
25321 			hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
25322 		else
25323 			hdd_dot11_mode = eHDD_DOT11_MODE_11n;
25324 		break;
25325 	case eHDD_DOT11_MODE_11ac:
25326 	case eHDD_DOT11_MODE_11ac_ONLY:
25327 		if (sme_is_feature_supported_by_fw(DOT11AC))
25328 			hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
25329 		else
25330 			hdd_dot11_mode = eHDD_DOT11_MODE_11n;
25331 		break;
25332 	case eHDD_DOT11_MODE_11n:
25333 	case eHDD_DOT11_MODE_11n_ONLY:
25334 		hdd_dot11_mode = eHDD_DOT11_MODE_11n;
25335 		break;
25336 	default:
25337 		hdd_dot11_mode = ini_dot11_mode;
25338 		break;
25339 	}
25340 	ch_info->channel_width = ch_params->ch_width;
25341 	ch_info->phy_mode =
25342 		hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
25343 	ch_info->freq = op_freq;
25344 	ch_info->cb_mode = ch_params->ch_width;
25345 	hdd_debug("ch_info width %d, phymode %d channel freq %d",
25346 		  ch_info->channel_width, ch_info->phy_mode,
25347 		  ch_info->freq);
25348 }
25349 #else
25350 static
hdd_mon_select_cbmode(struct hdd_adapter * adapter,uint32_t op_freq,struct ch_params * ch_params)25351 void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
25352 			   uint32_t op_freq,
25353 			   struct ch_params *ch_params)
25354 {
25355 }
25356 #endif
25357 
hdd_select_cbmode(struct hdd_adapter * adapter,qdf_freq_t oper_freq,qdf_freq_t sec_ch_2g_freq,struct ch_params * ch_params)25358 void hdd_select_cbmode(struct hdd_adapter *adapter, qdf_freq_t oper_freq,
25359 		       qdf_freq_t sec_ch_2g_freq, struct ch_params *ch_params)
25360 {
25361 	uint32_t sec_ch_freq = 0;
25362 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25363 
25364 	/*
25365 	 * CDS api expects secondary channel for calculating
25366 	 * the channel params
25367 	 */
25368 	if (ch_params->ch_width == CH_WIDTH_40MHZ &&
25369 	    WLAN_REG_IS_24GHZ_CH_FREQ(oper_freq)) {
25370 		if (sec_ch_2g_freq) {
25371 			sec_ch_freq = sec_ch_2g_freq;
25372 		} else {
25373 			if (oper_freq >= 2412 && oper_freq <= 2432)
25374 				sec_ch_freq = oper_freq + 20;
25375 			else if (oper_freq >= 2437 && oper_freq <= 2472)
25376 				sec_ch_freq = oper_freq - 20;
25377 		}
25378 	}
25379 
25380 	/* This call decides required channel bonding mode */
25381 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev, oper_freq,
25382 						sec_ch_freq, ch_params,
25383 						REG_CURRENT_PWR_MODE);
25384 
25385 	if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE ||
25386 	    policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
25387 		hdd_mon_select_cbmode(adapter, oper_freq, ch_params);
25388 }
25389 
25390 /**
25391  * wlan_hdd_cfg80211_connect() - cfg80211 connect api
25392  * @wiphy: Pointer to wiphy
25393  * @ndev: Pointer to network device
25394  * @req: Pointer to cfg80211 connect request
25395  *
25396  * Return: 0 for success, non-zero for failure
25397  */
wlan_hdd_cfg80211_connect(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_connect_params * req)25398 static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
25399 				     struct net_device *ndev,
25400 				     struct cfg80211_connect_params *req)
25401 {
25402 	int errno;
25403 	struct osif_vdev_sync *vdev_sync;
25404 
25405 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
25406 	if (errno)
25407 		return errno;
25408 
25409 	errno = wlan_hdd_cm_connect(wiphy, ndev, req);
25410 
25411 	osif_vdev_sync_op_stop(vdev_sync);
25412 
25413 	return errno;
25414 }
25415 
25416 /**
25417  * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
25418  * @wiphy: Pointer to wiphy
25419  * @dev: Pointer to network device
25420  * @reason: Disconnect reason code
25421  *
25422  * Return: 0 for success, non-zero for failure
25423  */
wlan_hdd_cfg80211_disconnect(struct wiphy * wiphy,struct net_device * dev,u16 reason)25424 static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
25425 					struct net_device *dev, u16 reason)
25426 {
25427 	int errno;
25428 	struct osif_vdev_sync *vdev_sync;
25429 
25430 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25431 	if (errno)
25432 		return errno;
25433 
25434 	errno = wlan_hdd_cm_disconnect(wiphy, dev, reason);
25435 
25436 	osif_vdev_sync_op_stop(vdev_sync);
25437 
25438 	return errno;
25439 }
25440 
25441 /**
25442  * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
25443  * @wiphy: Pointer to wiphy
25444  * @changed: Parameters changed
25445  *
25446  * This function is used to set the phy parameters. RTS Threshold/FRAG
25447  * Threshold/Retry Count etc.
25448  *
25449  * Return: 0 for success, non-zero for failure
25450  */
__wlan_hdd_cfg80211_set_wiphy_params(struct wiphy * wiphy,u32 changed)25451 static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
25452 						u32 changed)
25453 {
25454 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
25455 	int status;
25456 
25457 	hdd_enter();
25458 
25459 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25460 		hdd_err("Command not allowed in FTM mode");
25461 		return -EINVAL;
25462 	}
25463 
25464 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25465 		   TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
25466 		   NO_SESSION, wiphy->rts_threshold);
25467 
25468 	status = wlan_hdd_validate_context(hdd_ctx);
25469 
25470 	if (0 != status)
25471 		return status;
25472 
25473 	if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
25474 		u32 rts_threshold = (wiphy->rts_threshold == -1) ?
25475 				     cfg_max(CFG_RTS_THRESHOLD) :
25476 				     wiphy->rts_threshold;
25477 
25478 		if ((cfg_min(CFG_RTS_THRESHOLD) > rts_threshold) ||
25479 		    (cfg_max(CFG_RTS_THRESHOLD) < rts_threshold)) {
25480 			hdd_err("Invalid RTS Threshold value: %u",
25481 				rts_threshold);
25482 			return -EINVAL;
25483 		}
25484 
25485 		if (0 != ucfg_mlme_set_rts_threshold(hdd_ctx->psoc,
25486 		    rts_threshold)) {
25487 			hdd_err("mlme_set_rts_threshold failed for val %u",
25488 				rts_threshold);
25489 			return -EIO;
25490 		}
25491 
25492 		hdd_debug("set rts threshold %u", rts_threshold);
25493 	}
25494 
25495 	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
25496 		u16 frag_threshold = (wiphy->frag_threshold == -1) ?
25497 				     cfg_max(CFG_FRAG_THRESHOLD) :
25498 				     wiphy->frag_threshold;
25499 
25500 		if ((cfg_min(CFG_FRAG_THRESHOLD) > frag_threshold) ||
25501 		    (cfg_max(CFG_FRAG_THRESHOLD) < frag_threshold)) {
25502 			hdd_err("Invalid frag_threshold value %hu",
25503 				frag_threshold);
25504 			return -EINVAL;
25505 		}
25506 
25507 		if (0 != ucfg_mlme_set_frag_threshold(hdd_ctx->psoc,
25508 						      frag_threshold)) {
25509 			hdd_err("mlme_set_frag_threshold failed for val %hu",
25510 				frag_threshold);
25511 			return -EIO;
25512 		}
25513 
25514 		hdd_debug("set frag threshold %hu", frag_threshold);
25515 	}
25516 
25517 	hdd_exit();
25518 	return 0;
25519 }
25520 
25521 /**
25522  * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
25523  * @wiphy: Pointer to wiphy
25524  * @changed: Parameters changed
25525  *
25526  * Return: 0 for success, non-zero for failure
25527  */
wlan_hdd_cfg80211_set_wiphy_params(struct wiphy * wiphy,u32 changed)25528 static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
25529 {
25530 	struct osif_psoc_sync *psoc_sync;
25531 	int errno;
25532 
25533 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
25534 	if (errno)
25535 		return errno;
25536 
25537 	errno = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
25538 
25539 	osif_psoc_sync_op_stop(psoc_sync);
25540 
25541 	return errno;
25542 }
25543 
25544 /**
25545  * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
25546  *				     key
25547  * @wiphy: Pointer to wiphy
25548  * @netdev: Pointer to network device
25549  * @key_index: Key index
25550  *
25551  * Return: 0
25552  */
__wlan_hdd_set_default_mgmt_key(struct wiphy * wiphy,struct net_device * netdev,u8 key_index)25553 static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
25554 					   struct net_device *netdev,
25555 					   u8 key_index)
25556 {
25557 	hdd_enter();
25558 	return 0;
25559 }
25560 
25561 /**
25562  * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
25563  *				wlan_hdd_set_default_mgmt_key
25564  * @wiphy: pointer to wiphy
25565  * @wdev: pointer to wireless_device structure
25566  * @key_index: key index
25567  *
25568  * Return: 0 on success, error number on failure
25569  */
25570 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
wlan_hdd_set_default_mgmt_key(struct wiphy * wiphy,struct wireless_dev * wdev,u8 key_index)25571 static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
25572 					 struct wireless_dev *wdev,
25573 					 u8 key_index)
25574 {
25575 	int errno = -EINVAL;
25576 	struct osif_vdev_sync *vdev_sync;
25577 	struct hdd_adapter *adapter = qdf_container_of(wdev,
25578 						   struct hdd_adapter,
25579 						   wdev);
25580 
25581 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25582 		return errno;
25583 
25584 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
25585 	if (errno)
25586 		return errno;
25587 
25588 	errno = __wlan_hdd_set_default_mgmt_key(wiphy, adapter->dev, key_index);
25589 
25590 	osif_vdev_sync_op_stop(vdev_sync);
25591 
25592 	return errno;
25593 }
25594 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
wlan_hdd_set_default_mgmt_key(struct wiphy * wiphy,struct net_device * netdev,int link_id,u8 key_index)25595 static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
25596 					 struct net_device *netdev,
25597 					 int link_id, u8 key_index)
25598 {
25599 	int errno;
25600 	struct osif_vdev_sync *vdev_sync;
25601 
25602 	errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
25603 	if (errno)
25604 		return errno;
25605 
25606 	errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
25607 
25608 	osif_vdev_sync_op_stop(vdev_sync);
25609 
25610 	return errno;
25611 }
25612 #else
wlan_hdd_set_default_mgmt_key(struct wiphy * wiphy,struct net_device * netdev,u8 key_index)25613 static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
25614 					 struct net_device *netdev,
25615 					 u8 key_index)
25616 {
25617 	int errno;
25618 	struct osif_vdev_sync *vdev_sync;
25619 
25620 	errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
25621 	if (errno)
25622 		return errno;
25623 
25624 	errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
25625 
25626 	osif_vdev_sync_op_stop(vdev_sync);
25627 
25628 	return errno;
25629 }
25630 #endif
25631 
25632 /*
25633  * Default val of cwmin, this value is used to override the
25634  * incorrect user set value
25635  */
25636 #define DEFAULT_CWMIN 15
25637 
25638 /*
25639  * Default val of cwmax, this value is used to override the
25640  * incorrect user set value
25641  */
25642 #define DEFAULT_CWMAX 1023
25643 
25644 /**
25645  * __wlan_hdd_set_txq_params() - implementation of set tx queue params
25646  *				to configure internal EDCA parameters
25647  * @wiphy: Pointer to wiphy
25648  * @dev: Pointer to network device
25649  * @params: Pointer to tx queue parameters
25650  *
25651  * Return: 0
25652  */
__wlan_hdd_set_txq_params(struct wiphy * wiphy,struct net_device * dev,struct ieee80211_txq_params * params)25653 static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
25654 				   struct net_device *dev,
25655 				   struct ieee80211_txq_params *params)
25656 {
25657 	QDF_STATUS status;
25658 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25659 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25660 	mac_handle_t mac_handle;
25661 	tSirMacEdcaParamRecord txq_edca_params;
25662 	static const uint8_t ieee_ac_to_qca_ac[] = {
25663 		[IEEE80211_AC_VO] = QCA_WLAN_AC_VO,
25664 		[IEEE80211_AC_VI] = QCA_WLAN_AC_VI,
25665 		[IEEE80211_AC_BE] = QCA_WLAN_AC_BE,
25666 		[IEEE80211_AC_BK] = QCA_WLAN_AC_BK,
25667 	};
25668 
25669 	hdd_enter();
25670 
25671 	if (wlan_hdd_validate_context(hdd_ctx))
25672 		return -EINVAL;
25673 
25674 	mac_handle = hdd_ctx->mac_handle;
25675 	if (params->cwmin == 0 || params->cwmin > DEFAULT_CWMAX)
25676 		params->cwmin = DEFAULT_CWMIN;
25677 
25678 	if (params->cwmax < params->cwmin || params->cwmax > DEFAULT_CWMAX)
25679 		params->cwmax = DEFAULT_CWMAX;
25680 
25681 	txq_edca_params.cw.min = convert_cw(params->cwmin);
25682 	txq_edca_params.cw.max = convert_cw(params->cwmax);
25683 	txq_edca_params.aci.aifsn = params->aifs;
25684 	/* The txop is multiple of 32us units */
25685 	txq_edca_params.txoplimit = params->txop;
25686 	txq_edca_params.aci.aci =
25687 			ieee_ac_to_qca_ac[params->ac];
25688 
25689 	status = sme_update_session_txq_edca_params(mac_handle,
25690 						    adapter->deflink->vdev_id,
25691 						    &txq_edca_params);
25692 
25693 	hdd_exit();
25694 	return qdf_status_to_os_return(status);
25695 }
25696 
25697 /**
25698  * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
25699  * @wiphy: pointer to wiphy
25700  * @dev: pointer to net_device structure
25701  * @params: pointer to ieee80211_txq_params
25702  *
25703  * Return: 0 on success, error number on failure
25704  */
wlan_hdd_set_txq_params(struct wiphy * wiphy,struct net_device * dev,struct ieee80211_txq_params * params)25705 static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
25706 				   struct net_device *dev,
25707 				   struct ieee80211_txq_params *params)
25708 {
25709 	int errno;
25710 	struct osif_vdev_sync *vdev_sync;
25711 
25712 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25713 	if (errno)
25714 		return errno;
25715 
25716 	errno = __wlan_hdd_set_txq_params(wiphy, dev, params);
25717 
25718 	osif_vdev_sync_op_stop(vdev_sync);
25719 
25720 	return errno;
25721 }
25722 
25723 /**
25724  * hdd_softap_deauth_current_sta() - Deauth current sta
25725  * @adapter: pointer to adapter structure
25726  * @sta_info: pointer to the current station info structure
25727  * @hapd_state: pointer to hostapd state structure
25728  * @param: pointer to del sta params
25729  *
25730  * Return: QDF_STATUS on success, corresponding QDF failure status on failure
25731  */
25732 static
hdd_softap_deauth_current_sta(struct hdd_adapter * adapter,struct hdd_station_info * sta_info,struct hdd_hostapd_state * hapd_state,struct csr_del_sta_params * param)25733 QDF_STATUS hdd_softap_deauth_current_sta(struct hdd_adapter *adapter,
25734 					 struct hdd_station_info *sta_info,
25735 					 struct hdd_hostapd_state *hapd_state,
25736 					 struct csr_del_sta_params *param)
25737 {
25738 	qdf_event_t *disassoc_event = &hapd_state->qdf_sta_disassoc_event;
25739 	struct hdd_context *hdd_ctx;
25740 	QDF_STATUS qdf_status;
25741 	struct hdd_station_info *tmp = NULL;
25742 
25743 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25744 	if (!hdd_ctx) {
25745 		hdd_err("hdd_ctx is NULL");
25746 		return QDF_STATUS_E_INVAL;
25747 	}
25748 
25749 	qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
25750 
25751 	if (!qdf_is_macaddr_broadcast(&param->peerMacAddr))
25752 		sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
25753 					    adapter->deflink->vdev_id,
25754 					    (uint8_t *)&param->peerMacAddr,
25755 					    param->reason_code, 0);
25756 
25757 	qdf_status = hdd_softap_sta_deauth(adapter, param);
25758 
25759 	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
25760 		if (qdf_is_macaddr_broadcast(&sta_info->sta_mac)) {
25761 			hdd_for_each_sta_ref_safe(
25762 					adapter->sta_info_list,
25763 					sta_info, tmp,
25764 					STA_INFO_SOFTAP_DEAUTH_CURRENT_STA) {
25765 				sta_info->is_deauth_in_progress = true;
25766 				hdd_put_sta_info_ref(
25767 					&adapter->sta_info_list,
25768 					&sta_info, true,
25769 					STA_INFO_SOFTAP_DEAUTH_CURRENT_STA);
25770 			}
25771 		} else {
25772 			sta_info->is_deauth_in_progress = true;
25773 		}
25774 		qdf_status = qdf_wait_for_event_completion(
25775 						disassoc_event,
25776 						SME_PEER_DISCONNECT_TIMEOUT);
25777 		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
25778 			hdd_warn("Deauth time expired");
25779 	} else {
25780 		sta_info->is_deauth_in_progress = false;
25781 		hdd_debug("STA removal failed for ::" QDF_MAC_ADDR_FMT,
25782 			  QDF_MAC_ADDR_REF(sta_info->sta_mac.bytes));
25783 		return QDF_STATUS_E_NOENT;
25784 	}
25785 	return QDF_STATUS_SUCCESS;
25786 }
25787 
hdd_softap_deauth_all_sta(struct hdd_adapter * adapter,struct hdd_hostapd_state * hapd_state,struct csr_del_sta_params * param)25788 QDF_STATUS hdd_softap_deauth_all_sta(struct hdd_adapter *adapter,
25789 				     struct hdd_hostapd_state *hapd_state,
25790 				     struct csr_del_sta_params *param)
25791 {
25792 	QDF_STATUS status;
25793 	bool is_sap_bcast_deauth_enabled = false;
25794 	struct hdd_context *hdd_ctx;
25795 	struct hdd_station_info *sta_info, *tmp = NULL;
25796 
25797 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25798 	if (!hdd_ctx) {
25799 		hdd_err("hdd_ctx is NULL");
25800 		return QDF_STATUS_E_INVAL;
25801 	}
25802 
25803 	ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc,
25804 					       &is_sap_bcast_deauth_enabled);
25805 
25806 	hdd_debug("sap_bcast_deauth_enabled %d", is_sap_bcast_deauth_enabled);
25807 
25808 	if (is_sap_bcast_deauth_enabled) {
25809 		struct hdd_station_info bcast_sta_info;
25810 
25811 		qdf_set_macaddr_broadcast(&bcast_sta_info.sta_mac);
25812 		return hdd_softap_deauth_current_sta(adapter, &bcast_sta_info,
25813 						     hapd_state, param);
25814 	}
25815 
25816 	hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp,
25817 				  STA_INFO_SOFTAP_DEAUTH_ALL_STA) {
25818 		if (!sta_info->is_deauth_in_progress) {
25819 			hdd_debug("Delete STA with MAC:" QDF_MAC_ADDR_FMT,
25820 				  QDF_MAC_ADDR_REF(sta_info->sta_mac.bytes));
25821 
25822 			if (QDF_IS_ADDR_BROADCAST(sta_info->sta_mac.bytes)) {
25823 				hdd_put_sta_info_ref(&adapter->sta_info_list,
25824 						&sta_info, true,
25825 						STA_INFO_SOFTAP_DEAUTH_ALL_STA);
25826 				continue;
25827 			}
25828 
25829 			qdf_mem_copy(param->peerMacAddr.bytes,
25830 				     sta_info->sta_mac.bytes,
25831 				     QDF_MAC_ADDR_SIZE);
25832 			status =
25833 			    hdd_softap_deauth_current_sta(adapter, sta_info,
25834 							  hapd_state, param);
25835 			if (QDF_IS_STATUS_ERROR(status)) {
25836 				hdd_put_sta_info_ref(
25837 						&adapter->sta_info_list,
25838 						&sta_info, true,
25839 						STA_INFO_SOFTAP_DEAUTH_ALL_STA);
25840 				if (tmp)
25841 					hdd_put_sta_info_ref(
25842 						&adapter->sta_info_list,
25843 						&tmp, true,
25844 						STA_INFO_SOFTAP_DEAUTH_ALL_STA);
25845 				return status;
25846 			}
25847 		}
25848 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
25849 				     STA_INFO_SOFTAP_DEAUTH_ALL_STA);
25850 	}
25851 
25852 	return QDF_STATUS_SUCCESS;
25853 }
25854 
25855 /**
25856  * __wlan_hdd_cfg80211_del_station() - delete station v2
25857  * @wiphy: Pointer to wiphy
25858  * @dev: Underlying net device
25859  * @param: Pointer to delete station parameter
25860  *
25861  * Return: 0 for success, non-zero for failure
25862  */
25863 static
__wlan_hdd_cfg80211_del_station(struct wiphy * wiphy,struct net_device * dev,struct csr_del_sta_params * param)25864 int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
25865 				    struct net_device *dev,
25866 				    struct csr_del_sta_params *param)
25867 {
25868 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25869 	struct hdd_context *hdd_ctx;
25870 	struct hdd_hostapd_state *hapd_state;
25871 	uint8_t *mac;
25872 	struct hdd_station_info *sta_info;
25873 
25874 	hdd_enter();
25875 
25876 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25877 		hdd_err("Command not allowed in FTM mode");
25878 		return -EINVAL;
25879 	}
25880 
25881 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25882 		return -EINVAL;
25883 
25884 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25885 		   TRACE_CODE_HDD_CFG80211_DEL_STA,
25886 		   adapter->deflink->vdev_id, adapter->device_mode);
25887 
25888 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25889 	if (!hdd_ctx) {
25890 		hdd_err("hdd_ctx is NULL");
25891 		return -EINVAL;
25892 	}
25893 
25894 	mac = (uint8_t *) param->peerMacAddr.bytes;
25895 
25896 	if (QDF_SAP_MODE != adapter->device_mode &&
25897 	    QDF_P2P_GO_MODE != adapter->device_mode)
25898 		goto fn_end;
25899 
25900 	hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
25901 	if (!hapd_state) {
25902 		hdd_err("Hostapd State is Null");
25903 		return 0;
25904 	}
25905 
25906 	if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac)) {
25907 		if (!QDF_IS_STATUS_SUCCESS(hdd_softap_deauth_all_sta(adapter,
25908 								     hapd_state,
25909 								     param)))
25910 			goto fn_end;
25911 	} else {
25912 		if (param->reason_code == REASON_1X_AUTH_FAILURE) {
25913 			struct wlan_objmgr_vdev *vdev;
25914 
25915 			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
25916 							   WLAN_DP_ID);
25917 			if (vdev) {
25918 				ucfg_dp_softap_check_wait_for_tx_eap_pkt(vdev,
25919 						(struct qdf_mac_addr *)mac);
25920 				hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
25921 			}
25922 		}
25923 
25924 		sta_info = hdd_get_sta_info_by_mac(
25925 						&adapter->sta_info_list,
25926 						mac,
25927 						STA_INFO_CFG80211_DEL_STATION);
25928 
25929 		if (!sta_info) {
25930 			hdd_debug("Skip DEL STA as this is not used::"
25931 				  QDF_MAC_ADDR_FMT,
25932 				  QDF_MAC_ADDR_REF(mac));
25933 			return -ENOENT;
25934 		}
25935 
25936 		if (sta_info->is_deauth_in_progress) {
25937 			hdd_debug("Skip DEL STA as deauth is in progress::"
25938 				  QDF_MAC_ADDR_FMT,
25939 				  QDF_MAC_ADDR_REF(mac));
25940 			hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
25941 					     true,
25942 					     STA_INFO_CFG80211_DEL_STATION);
25943 			return -ENOENT;
25944 		}
25945 
25946 		hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_FMT,
25947 			  QDF_MAC_ADDR_REF(mac));
25948 		hdd_softap_deauth_current_sta(adapter, sta_info, hapd_state,
25949 					      param);
25950 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
25951 				     STA_INFO_CFG80211_DEL_STATION);
25952 	}
25953 
25954 fn_end:
25955 	hdd_exit();
25956 	return 0;
25957 }
25958 
25959 #if defined(USE_CFG80211_DEL_STA_V2)
wlan_hdd_del_station(struct hdd_adapter * adapter,const uint8_t * mac)25960 int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac)
25961 {
25962 	struct station_del_parameters del_sta;
25963 
25964 	del_sta.mac = mac;
25965 	del_sta.subtype = IEEE80211_STYPE_DEAUTH >> 4;
25966 	del_sta.reason_code = WLAN_REASON_DEAUTH_LEAVING;
25967 
25968 	return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
25969 					     adapter->dev, &del_sta);
25970 }
25971 #else
wlan_hdd_del_station(struct hdd_adapter * adapter,const uint8_t * mac)25972 int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac)
25973 {
25974 	return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
25975 					     adapter->dev, mac);
25976 }
25977 #endif
25978 
25979 /**
25980  * _wlan_hdd_cfg80211_del_station() - delete station entry handler
25981  * @wiphy: Pointer to wiphy
25982  * @dev: net_device to operate against
25983  * @mac: binary mac address
25984  * @reason_code: reason for the deauthorization/disassociation
25985  * @subtype: management frame subtype to indicate removal
25986  *
25987  * Return: Errno
25988  */
_wlan_hdd_cfg80211_del_station(struct wiphy * wiphy,struct net_device * dev,const uint8_t * mac,uint16_t reason_code,uint8_t subtype)25989 static int _wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
25990 					  struct net_device *dev,
25991 					  const uint8_t *mac,
25992 					  uint16_t reason_code,
25993 					  uint8_t subtype)
25994 {
25995 	int errno;
25996 	struct csr_del_sta_params delStaParams;
25997 	struct osif_vdev_sync *vdev_sync;
25998 
25999 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26000 	if (errno)
26001 		return errno;
26002 
26003 	wlansap_populate_del_sta_params(mac, reason_code, subtype,
26004 					&delStaParams);
26005 	errno = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
26006 
26007 	osif_vdev_sync_op_stop(vdev_sync);
26008 
26009 	return errno;
26010 }
26011 
26012 #ifdef USE_CFG80211_DEL_STA_V2
wlan_hdd_cfg80211_del_station(struct wiphy * wiphy,struct net_device * dev,struct station_del_parameters * param)26013 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
26014 				  struct net_device *dev,
26015 				  struct station_del_parameters *param)
26016 {
26017 	if (!param)
26018 		return -EINVAL;
26019 
26020 	return _wlan_hdd_cfg80211_del_station(wiphy, dev, param->mac,
26021 					      param->reason_code,
26022 					      param->subtype);
26023 }
26024 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
wlan_hdd_cfg80211_del_station(struct wiphy * wiphy,struct net_device * dev,const uint8_t * mac)26025 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
26026 				  const uint8_t *mac)
26027 {
26028 	uint16_t reason = REASON_DEAUTH_NETWORK_LEAVING;
26029 	uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
26030 
26031 	return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
26032 }
26033 #else
wlan_hdd_cfg80211_del_station(struct wiphy * wiphy,struct net_device * dev,uint8_t * mac)26034 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
26035 				  uint8_t *mac)
26036 {
26037 	uint16_t reason = REASON_DEAUTH_NETWORK_LEAVING;
26038 	uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
26039 
26040 	return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
26041 }
26042 #endif
26043 
26044 #ifdef CFG80211_LINK_STA_PARAMS_PRESENT
26045 static inline
wlan_hdd_get_link_id(struct station_parameters * params)26046 uint8_t wlan_hdd_get_link_id(struct station_parameters *params)
26047 {
26048 	return params->link_sta_params.link_id;
26049 }
26050 #else
26051 static inline
wlan_hdd_get_link_id(struct station_parameters * params)26052 uint8_t wlan_hdd_get_link_id(struct station_parameters *params)
26053 {
26054 	return 255;
26055 }
26056 #endif
26057 /**
26058  * __wlan_hdd_cfg80211_add_station() - add station
26059  * @wiphy: Pointer to wiphy
26060  * @dev: Pointer to network device
26061  * @mac: Pointer to station mac address
26062  * @params: Pointer to add station parameter
26063  *
26064  * Return: 0 for success, non-zero for failure
26065  */
__wlan_hdd_cfg80211_add_station(struct wiphy * wiphy,struct net_device * dev,const uint8_t * mac,struct station_parameters * params)26066 static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
26067 					   struct net_device *dev,
26068 					   const uint8_t *mac,
26069 					   struct station_parameters *params)
26070 {
26071 	int status = -EPERM;
26072 #ifdef FEATURE_WLAN_TDLS
26073 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26074 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
26075 	u32 mask, set;
26076 	uint8_t link_id;
26077 
26078 	hdd_enter();
26079 
26080 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26081 		hdd_err("Command not allowed in FTM mode");
26082 		return -EINVAL;
26083 	}
26084 
26085 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26086 		return -EINVAL;
26087 
26088 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26089 		   TRACE_CODE_HDD_CFG80211_ADD_STA,
26090 		   adapter->deflink->vdev_id, params->listen_interval);
26091 
26092 	if (0 != wlan_hdd_validate_context(hdd_ctx))
26093 		return -EINVAL;
26094 
26095 	mask = params->sta_flags_mask;
26096 	set = params->sta_flags_set;
26097 	link_id = wlan_hdd_get_link_id(params);
26098 	hdd_debug("mask 0x%x set 0x%x link_id %d " QDF_MAC_ADDR_FMT, mask, set,
26099 		  link_id, QDF_MAC_ADDR_REF(mac));
26100 
26101 	if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
26102 		if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
26103 			status = wlan_cfg80211_tdls_add_peer_mlo(adapter,
26104 								 mac, link_id);
26105 		}
26106 	}
26107 #endif
26108 	hdd_exit();
26109 	return status;
26110 }
26111 
26112 /**
26113  * wlan_hdd_cfg80211_add_station() - add station
26114  * @wiphy: Pointer to wiphy
26115  * @dev: Pointer to network device
26116  * @mac: Pointer to station mac address
26117  * @params: Pointer to add station parameter
26118  *
26119  * Return: 0 for success, non-zero for failure
26120  */
26121 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
wlan_hdd_cfg80211_add_station(struct wiphy * wiphy,struct net_device * dev,const uint8_t * mac,struct station_parameters * params)26122 static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
26123 					 struct net_device *dev,
26124 					 const uint8_t *mac,
26125 					 struct station_parameters *params)
26126 #else
26127 static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
26128 					 struct net_device *dev, uint8_t *mac,
26129 					 struct station_parameters *params)
26130 #endif
26131 {
26132 	int errno;
26133 	struct osif_vdev_sync *vdev_sync;
26134 
26135 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26136 	if (errno)
26137 		return errno;
26138 
26139 	errno = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
26140 
26141 	osif_vdev_sync_op_stop(vdev_sync);
26142 
26143 	return errno;
26144 }
26145 
26146 #if (defined(CFG80211_CONFIG_PMKSA_TIMER_PARAMS_SUPPORT) || \
26147 	     (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)))
26148 static inline void
hdd_fill_pmksa_lifetime(struct cfg80211_pmksa * pmksa,struct wlan_crypto_pmksa * pmk_cache)26149 hdd_fill_pmksa_lifetime(struct cfg80211_pmksa *pmksa,
26150 			struct wlan_crypto_pmksa *pmk_cache)
26151 {
26152 	pmk_cache->pmk_lifetime = pmksa->pmk_lifetime;
26153 	if (pmk_cache->pmk_lifetime > WLAN_CRYPTO_MAX_PMKID_LIFETIME)
26154 		pmk_cache->pmk_lifetime = WLAN_CRYPTO_MAX_PMKID_LIFETIME;
26155 
26156 	pmk_cache->pmk_lifetime_threshold = pmksa->pmk_reauth_threshold;
26157 	if (pmk_cache->pmk_lifetime_threshold >=
26158 	    WLAN_CRYPTO_MAX_PMKID_LIFETIME_THRESHOLD)
26159 		pmk_cache->pmk_lifetime_threshold =
26160 			WLAN_CRYPTO_MAX_PMKID_LIFETIME_THRESHOLD - 1;
26161 
26162 	hdd_debug("PMKSA: lifetime:%d threshold:%d",  pmk_cache->pmk_lifetime,
26163 		  pmk_cache->pmk_lifetime_threshold);
26164 }
26165 #else
26166 static inline void
hdd_fill_pmksa_lifetime(struct cfg80211_pmksa * pmksa,struct wlan_crypto_pmksa * src_pmk_cache)26167 hdd_fill_pmksa_lifetime(struct cfg80211_pmksa *pmksa,
26168 			struct wlan_crypto_pmksa *src_pmk_cache)
26169 {}
26170 #endif
26171 
wlan_hdd_set_pmksa_cache(struct hdd_adapter * adapter,struct wlan_crypto_pmksa * pmk_cache)26172 static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
26173 					   struct wlan_crypto_pmksa *pmk_cache)
26174 {
26175 	QDF_STATUS result;
26176 	struct wlan_crypto_pmksa *pmksa;
26177 	struct wlan_objmgr_vdev *vdev;
26178 	mac_handle_t mac_handle;
26179 	struct hdd_context *hdd_ctx;
26180 
26181 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26182 	if (!hdd_ctx) {
26183 		hdd_err("HDD context is null");
26184 		return QDF_STATUS_E_INVAL;
26185 	}
26186 
26187 	if (wlan_hdd_validate_context(hdd_ctx))
26188 		return QDF_STATUS_E_INVAL;
26189 	mac_handle = hdd_ctx->mac_handle;
26190 
26191 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
26192 	if (!vdev)
26193 		return QDF_STATUS_E_FAILURE;
26194 
26195 	pmksa = qdf_mem_malloc(sizeof(*pmksa));
26196 	if (!pmksa) {
26197 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
26198 		return QDF_STATUS_E_NOMEM;
26199 	}
26200 
26201 	if (!pmk_cache->ssid_len) {
26202 		qdf_copy_macaddr(&pmksa->bssid, &pmk_cache->bssid);
26203 	} else {
26204 		qdf_mem_copy(pmksa->ssid, pmk_cache->ssid, pmk_cache->ssid_len);
26205 		qdf_mem_copy(pmksa->cache_id, pmk_cache->cache_id,
26206 			     WLAN_CACHE_ID_LEN);
26207 		pmksa->ssid_len = pmk_cache->ssid_len;
26208 	}
26209 	qdf_mem_copy(pmksa->pmkid, pmk_cache->pmkid, PMKID_LEN);
26210 	qdf_mem_copy(pmksa->pmk, pmk_cache->pmk, pmk_cache->pmk_len);
26211 	pmksa->pmk_len = pmk_cache->pmk_len;
26212 	pmksa->pmk_entry_ts = qdf_get_system_timestamp();
26213 	pmksa->pmk_lifetime = pmk_cache->pmk_lifetime;
26214 	pmksa->pmk_lifetime_threshold = pmk_cache->pmk_lifetime_threshold;
26215 
26216 	result = wlan_crypto_set_del_pmksa(vdev, pmksa, true);
26217 	if (result != QDF_STATUS_SUCCESS) {
26218 		qdf_mem_zero(pmksa, sizeof(*pmksa));
26219 		qdf_mem_free(pmksa);
26220 	}
26221 
26222 	if (result == QDF_STATUS_SUCCESS && pmk_cache->pmk_len) {
26223 		sme_roam_set_psk_pmk(mac_handle, pmksa,
26224 				     adapter->deflink->vdev_id, false);
26225 		sme_set_pmk_cache_ft(mac_handle, adapter->deflink->vdev_id,
26226 				     pmk_cache);
26227 	}
26228 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
26229 
26230 	return result;
26231 }
26232 
wlan_hdd_del_pmksa_cache(struct hdd_adapter * adapter,struct wlan_crypto_pmksa * pmk_cache)26233 static QDF_STATUS wlan_hdd_del_pmksa_cache(struct hdd_adapter *adapter,
26234 					   struct wlan_crypto_pmksa *pmk_cache)
26235 {
26236 	QDF_STATUS result;
26237 	struct wlan_crypto_pmksa pmksa;
26238 	struct wlan_objmgr_vdev *vdev;
26239 
26240 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
26241 	if (!vdev)
26242 		return QDF_STATUS_E_FAILURE;
26243 
26244 	qdf_mem_zero(&pmksa, sizeof(pmksa));
26245 	if (!pmk_cache->ssid_len) {
26246 		qdf_copy_macaddr(&pmksa.bssid, &pmk_cache->bssid);
26247 	} else {
26248 		qdf_mem_copy(pmksa.ssid, pmk_cache->ssid, pmk_cache->ssid_len);
26249 		qdf_mem_copy(pmksa.cache_id, pmk_cache->cache_id,
26250 			     WLAN_CACHE_ID_LEN);
26251 		pmksa.ssid_len = pmk_cache->ssid_len;
26252 	}
26253 
26254 	result = wlan_crypto_set_del_pmksa(vdev, &pmksa, false);
26255 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
26256 
26257 	return result;
26258 }
26259 
wlan_hdd_flush_pmksa_cache(struct wlan_hdd_link_info * link_info)26260 QDF_STATUS wlan_hdd_flush_pmksa_cache(struct wlan_hdd_link_info *link_info)
26261 {
26262 	QDF_STATUS result;
26263 	struct wlan_objmgr_vdev *vdev;
26264 
26265 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
26266 	if (!vdev)
26267 		return QDF_STATUS_E_FAILURE;
26268 
26269 	result = wlan_crypto_set_del_pmksa(vdev, NULL, false);
26270 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
26271 
26272 	if (QDF_IS_STATUS_ERROR(result))
26273 		hdd_debug("Cannot flush PMKIDCache");
26274 
26275 	return result;
26276 }
26277 
26278 #if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
26279 	 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
26280 /*
26281  * wlan_hdd_is_pmksa_valid: API to validate pmksa
26282  * @pmksa: pointer to cfg80211_pmksa structure
26283  *
26284  * Return: True if valid else false
26285  */
wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa * pmksa)26286 static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
26287 {
26288 	if (!pmksa->bssid) {
26289 		hdd_warn("bssid is NULL");
26290 		if (!pmksa->ssid || !pmksa->cache_id) {
26291 			hdd_err("either ssid or cache_id are NULL");
26292 			return false;
26293 		}
26294 	}
26295 	return true;
26296 }
26297 
26298 /*
26299  * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
26300  * @adapter: Pointer to hdd adapter
26301  * @pmk_cache: pmk that needs to be updated
26302  * @pmksa: pmk from supplicant
26303  * @is_delete: Bool to decide set or delete PMK
26304  * Return: None
26305  */
hdd_fill_pmksa_info(struct hdd_adapter * adapter,struct wlan_crypto_pmksa * pmk_cache,struct cfg80211_pmksa * pmksa,bool is_delete)26306 static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
26307 				struct wlan_crypto_pmksa *pmk_cache,
26308 				struct cfg80211_pmksa *pmksa, bool is_delete)
26309 {
26310 	if (pmksa->bssid) {
26311 		hdd_debug("%s PMKSA for " QDF_MAC_ADDR_FMT,
26312 			  is_delete ? "Delete" : "Set",
26313 			  QDF_MAC_ADDR_REF(pmksa->bssid));
26314 		qdf_mem_copy(pmk_cache->bssid.bytes,
26315 			     pmksa->bssid, QDF_MAC_ADDR_SIZE);
26316 	} else {
26317 		qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, pmksa->ssid_len);
26318 		qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
26319 			     CACHE_ID_LEN);
26320 		pmk_cache->ssid_len = pmksa->ssid_len;
26321 		hdd_debug("%s PMKSA for ssid " QDF_SSID_FMT " cache_id %x %x",
26322 			  is_delete ? "Delete" : "Set",
26323 			  QDF_SSID_REF(pmk_cache->ssid_len, pmk_cache->ssid),
26324 			  pmk_cache->cache_id[0],
26325 			  pmk_cache->cache_id[1]);
26326 	}
26327 	qdf_mem_copy(pmk_cache->pmkid, pmksa->pmkid, PMKID_LEN);
26328 
26329 	hdd_fill_pmksa_lifetime(pmksa, pmk_cache);
26330 
26331 	if (is_delete)
26332 		return;
26333 
26334 	if (pmksa->pmk_len && (pmksa->pmk_len <= MAX_PMK_LEN)) {
26335 		qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
26336 		pmk_cache->pmk_len = pmksa->pmk_len;
26337 	} else
26338 		hdd_err("Invalid pmk len is %zu", pmksa->pmk_len);
26339 }
26340 #else
26341 /*
26342  * wlan_hdd_is_pmksa_valid: API to validate pmksa
26343  * @pmksa: pointer to cfg80211_pmksa structure
26344  *
26345  * Return: True if valid else false
26346  */
wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa * pmksa)26347 static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
26348 {
26349 	if (!pmksa->bssid) {
26350 		hdd_err("both bssid is NULL %pK", pmksa->bssid);
26351 		return false;
26352 	}
26353 	return true;
26354 }
26355 
26356 /*
26357  * hdd_fill_pmksa_info: API to update struct wlan_crypto_pmksa from
26358  * cfg80211_pmksa
26359  * @adapter: Pointer to hdd adapter
26360  * @pmk_cache: pmk which needs to be updated
26361  * @pmksa: pmk from supplicant
26362  * @is_delete: Bool to decide whether to set or delete PMK
26363  *
26364  * Return: None
26365  */
hdd_fill_pmksa_info(struct hdd_adapter * adapter,struct wlan_crypto_pmksa * pmk_cache,struct cfg80211_pmksa * pmksa,bool is_delete)26366 static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
26367 				struct wlan_crypto_pmksa *pmk_cache,
26368 				struct cfg80211_pmksa *pmksa, bool is_delete)
26369 {
26370 	mac_handle_t mac_handle;
26371 
26372 	hdd_debug("%s PMKSA for " QDF_MAC_ADDR_FMT, is_delete ? "Delete" : "Set",
26373 		  QDF_MAC_ADDR_REF(pmksa->bssid));
26374 	qdf_mem_copy(pmk_cache->bssid.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
26375 
26376 	if (is_delete)
26377 		return;
26378 	mac_handle = hdd_adapter_get_mac_handle(adapter);
26379 	sme_get_pmk_info(mac_handle, adapter->deflink->vdev_id, pmk_cache);
26380 	qdf_mem_copy(pmk_cache->pmkid, pmksa->pmkid, PMKID_LEN);
26381 }
26382 #endif
26383 
26384 /**
26385  * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
26386  * @wiphy: Pointer to wiphy
26387  * @dev: Pointer to network device
26388  * @pmksa: Pointer to set pmksa parameter
26389  *
26390  * Return: 0 for success, non-zero for failure
26391  */
__wlan_hdd_cfg80211_set_pmksa(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_pmksa * pmksa)26392 static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
26393 					 struct net_device *dev,
26394 					 struct cfg80211_pmksa *pmksa)
26395 {
26396 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26397 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26398 	QDF_STATUS result = QDF_STATUS_SUCCESS;
26399 	int status;
26400 	struct wlan_crypto_pmksa *pmk_cache;
26401 
26402 	hdd_enter();
26403 
26404 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26405 		hdd_err("Command not allowed in FTM mode");
26406 		return -EINVAL;
26407 	}
26408 
26409 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26410 		return -EINVAL;
26411 
26412 	if (!pmksa) {
26413 		hdd_err("pmksa is NULL");
26414 		return -EINVAL;
26415 	}
26416 
26417 	if (!pmksa->pmkid) {
26418 		hdd_err("pmksa->pmkid(%pK) is NULL",
26419 		       pmksa->pmkid);
26420 		return -EINVAL;
26421 	}
26422 
26423 	if (!wlan_hdd_is_pmksa_valid(pmksa))
26424 		return -EINVAL;
26425 
26426 	status = wlan_hdd_validate_context(hdd_ctx);
26427 
26428 	if (0 != status)
26429 		return status;
26430 
26431 	pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
26432 	if (!pmk_cache)
26433 		return -ENOMEM;
26434 
26435 	hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, false);
26436 
26437 	/*
26438 	 * Add to the PMKSA Cache in CSR
26439 	 * PMKSA cache will be having following
26440 	 * 1. pmkid id
26441 	 * 2. pmk
26442 	 * 3. bssid or cache identifier
26443 	 */
26444 	result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
26445 
26446 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26447 		   TRACE_CODE_HDD_CFG80211_SET_PMKSA,
26448 		   adapter->deflink->vdev_id, result);
26449 
26450 	if (QDF_IS_STATUS_SUCCESS(result) || result == QDF_STATUS_E_EXISTS)
26451 		sme_set_del_pmkid_cache(hdd_ctx->psoc,
26452 					adapter->deflink->vdev_id,
26453 					pmk_cache, true);
26454 
26455 	qdf_mem_zero(pmk_cache, sizeof(*pmk_cache));
26456 
26457 	qdf_mem_free(pmk_cache);
26458 	hdd_exit();
26459 
26460 	return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
26461 }
26462 
26463 /**
26464  * wlan_hdd_cfg80211_set_pmksa() - set pmksa
26465  * @wiphy: Pointer to wiphy
26466  * @dev: Pointer to network device
26467  * @pmksa: Pointer to set pmksa parameter
26468  *
26469  * Return: 0 for success, non-zero for failure
26470  */
wlan_hdd_cfg80211_set_pmksa(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_pmksa * pmksa)26471 static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
26472 				       struct net_device *dev,
26473 				       struct cfg80211_pmksa *pmksa)
26474 {
26475 	int errno;
26476 	struct osif_vdev_sync *vdev_sync;
26477 
26478 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26479 	if (errno)
26480 		return errno;
26481 
26482 	errno = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
26483 
26484 	osif_vdev_sync_op_stop(vdev_sync);
26485 
26486 	return errno;
26487 }
26488 
26489 /**
26490  * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
26491  * @wiphy: Pointer to wiphy
26492  * @dev: Pointer to network device
26493  * @pmksa: Pointer to pmksa parameter
26494  *
26495  * Return: 0 for success, non-zero for failure
26496  */
__wlan_hdd_cfg80211_del_pmksa(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_pmksa * pmksa)26497 static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
26498 					 struct net_device *dev,
26499 					 struct cfg80211_pmksa *pmksa)
26500 {
26501 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26502 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26503 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
26504 	int status = 0;
26505 	struct wlan_crypto_pmksa *pmk_cache;
26506 
26507 	hdd_enter();
26508 
26509 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26510 		hdd_err("Command not allowed in FTM mode");
26511 		return -EINVAL;
26512 	}
26513 
26514 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26515 		return -EINVAL;
26516 
26517 	if (!pmksa) {
26518 		hdd_err("pmksa is NULL");
26519 		return -EINVAL;
26520 	}
26521 
26522 	if (!wlan_hdd_is_pmksa_valid(pmksa))
26523 		return -EINVAL;
26524 
26525 	status = wlan_hdd_validate_context(hdd_ctx);
26526 
26527 	if (0 != status)
26528 		return status;
26529 
26530 	pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
26531 	if (!pmk_cache)
26532 		return -ENOMEM;
26533 
26534 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26535 		   TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
26536 		   adapter->deflink->vdev_id, 0);
26537 
26538 	hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, true);
26539 
26540 	qdf_status = wlan_hdd_del_pmksa_cache(adapter, pmk_cache);
26541 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
26542 		if (!pmksa->bssid)
26543 			hdd_err("Failed to delete PMKSA for null bssid");
26544 		else
26545 			hdd_err("Failed to delete PMKSA for " QDF_MAC_ADDR_FMT,
26546 				QDF_MAC_ADDR_REF(pmksa->bssid));
26547 		status = -EINVAL;
26548 	} else {
26549 		/* clear single_pmk_info information */
26550 		sme_clear_sae_single_pmk_info(hdd_ctx->psoc,
26551 					      adapter->deflink->vdev_id,
26552 					      pmk_cache);
26553 
26554 		/* Send the delete pmkid command to firmware */
26555 		sme_set_del_pmkid_cache(hdd_ctx->psoc,
26556 					adapter->deflink->vdev_id,
26557 					pmk_cache, false);
26558 	}
26559 
26560 	qdf_mem_zero(pmk_cache, sizeof(*pmk_cache));
26561 	qdf_mem_free(pmk_cache);
26562 
26563 	hdd_exit();
26564 
26565 	return status;
26566 }
26567 
26568 /**
26569  * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
26570  * @wiphy: Pointer to wiphy
26571  * @dev: Pointer to network device
26572  * @pmksa: Pointer to pmksa parameter
26573  *
26574  * Return: 0 for success, non-zero for failure
26575  */
wlan_hdd_cfg80211_del_pmksa(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_pmksa * pmksa)26576 static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
26577 				       struct net_device *dev,
26578 				       struct cfg80211_pmksa *pmksa)
26579 {
26580 	int errno;
26581 	struct osif_vdev_sync *vdev_sync;
26582 
26583 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26584 	if (errno)
26585 		return errno;
26586 
26587 	errno = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
26588 
26589 	osif_vdev_sync_op_stop(vdev_sync);
26590 
26591 	return errno;
26592 
26593 }
26594 
26595 /**
26596  * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
26597  * @wiphy: Pointer to wiphy
26598  * @dev: Pointer to network device
26599  *
26600  * Return: 0 for success, non-zero for failure
26601  */
__wlan_hdd_cfg80211_flush_pmksa(struct wiphy * wiphy,struct net_device * dev)26602 static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
26603 					   struct net_device *dev)
26604 {
26605 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26606 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26607 	int errno;
26608 	QDF_STATUS status;
26609 
26610 	hdd_enter();
26611 
26612 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26613 		hdd_err("Command not allowed in FTM mode");
26614 		return -EINVAL;
26615 	}
26616 
26617 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26618 		return -EINVAL;
26619 
26620 	hdd_debug("Flushing PMKSA");
26621 
26622 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26623 	errno  = wlan_hdd_validate_context(hdd_ctx);
26624 	if (errno)
26625 		return errno;
26626 
26627 	status = wlan_hdd_flush_pmksa_cache(adapter->deflink);
26628 	if (status == QDF_STATUS_E_NOSUPPORT)
26629 		errno = -EOPNOTSUPP;
26630 	else if (QDF_IS_STATUS_ERROR(status))
26631 		errno = -EINVAL;
26632 
26633 	sme_set_del_pmkid_cache(hdd_ctx->psoc, adapter->deflink->vdev_id,
26634 				NULL, false);
26635 	hdd_exit();
26636 	return errno;
26637 }
26638 
26639 /**
26640  * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
26641  * @wiphy: Pointer to wiphy
26642  * @dev: Pointer to network device
26643  *
26644  * Return: 0 for success, non-zero for failure
26645  */
wlan_hdd_cfg80211_flush_pmksa(struct wiphy * wiphy,struct net_device * dev)26646 static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
26647 					 struct net_device *dev)
26648 {
26649 	int errno;
26650 	struct osif_vdev_sync *vdev_sync;
26651 
26652 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26653 	if (errno)
26654 		return errno;
26655 
26656 	errno = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
26657 
26658 	osif_vdev_sync_op_stop(vdev_sync);
26659 
26660 	return errno;
26661 }
26662 
26663 #if defined(KERNEL_SUPPORT_11R_CFG80211)
26664 /**
26665  * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
26666  * @wiphy: Pointer to wiphy
26667  * @dev: Pointer to network device
26668  * @ftie: Pointer to fast transition ie parameter
26669  *
26670  * Return: 0 for success, non-zero for failure
26671  */
26672 static int
__wlan_hdd_cfg80211_update_ft_ies(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_update_ft_ies_params * ftie)26673 __wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
26674 				  struct net_device *dev,
26675 				  struct cfg80211_update_ft_ies_params *ftie)
26676 {
26677 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
26678 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26679 	int status;
26680 
26681 	hdd_enter();
26682 
26683 	status = wlan_hdd_validate_context(hdd_ctx);
26684 	if (status)
26685 		return status;
26686 
26687 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26688 		hdd_err("Command not allowed in FTM mode");
26689 		return -EINVAL;
26690 	}
26691 
26692 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26693 		return -EINVAL;
26694 
26695 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26696 		   TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
26697 		   adapter->deflink->vdev_id, 0);
26698 
26699 	/* Added for debug on reception of Re-assoc Req. */
26700 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
26701 		hdd_err("Called with Ie of length = %zu when not associated",
26702 		       ftie->ie_len);
26703 		hdd_err("Should be Re-assoc Req IEs");
26704 	}
26705 	hdd_debug("called with Ie of length = %zu", ftie->ie_len);
26706 
26707 	ucfg_cm_set_ft_ies(hdd_ctx->pdev, adapter->deflink->vdev_id,
26708 			   (const u8 *)ftie->ie, ftie->ie_len);
26709 	hdd_exit();
26710 	return 0;
26711 }
26712 
26713 /**
26714  * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
26715  * @wiphy: Pointer to wiphy
26716  * @dev: Pointer to network device
26717  * @ftie: Pointer to fast transition ie parameter
26718  *
26719  * Return: 0 for success, non-zero for failure
26720  */
26721 static int
wlan_hdd_cfg80211_update_ft_ies(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_update_ft_ies_params * ftie)26722 wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
26723 				struct net_device *dev,
26724 				struct cfg80211_update_ft_ies_params *ftie)
26725 {
26726 	int errno;
26727 	struct osif_vdev_sync *vdev_sync;
26728 
26729 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26730 	if (errno)
26731 		return errno;
26732 
26733 	errno = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
26734 
26735 	osif_vdev_sync_op_stop(vdev_sync);
26736 
26737 	return errno;
26738 }
26739 #endif
26740 
26741 #if defined(CFG80211_EXTERNAL_DH_UPDATE_SUPPORT) || \
26742 (LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0))
26743 /**
26744  * __wlan_hdd_cfg80211_update_owe_info() - update OWE info
26745  * @wiphy: Pointer to wiphy
26746  * @dev: Pointer to network device
26747  * @owe_info: Pointer to OWE info
26748  *
26749  * Return: 0 for success, non-zero for failure
26750  */
26751 static int
__wlan_hdd_cfg80211_update_owe_info(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_update_owe_info * owe_info)26752 __wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
26753 				    struct net_device *dev,
26754 				    struct cfg80211_update_owe_info *owe_info)
26755 {
26756 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
26757 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26758 	QDF_STATUS status;
26759 	int errno;
26760 	struct sap_context *sap_ctx;
26761 
26762 	hdd_enter_dev(dev);
26763 
26764 	errno = wlan_hdd_validate_context(hdd_ctx);
26765 	if (errno)
26766 		return errno;
26767 
26768 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26769 		hdd_err("Command not allowed in FTM mode");
26770 		return -EINVAL;
26771 	}
26772 
26773 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26774 		return -EINVAL;
26775 
26776 	hdd_debug("owe_status %d", owe_info->status);
26777 
26778 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink);
26779 	status = wlansap_update_owe_info(sap_ctx, owe_info->peer, owe_info->ie,
26780 					 owe_info->ie_len, owe_info->status);
26781 	if (QDF_IS_STATUS_ERROR(status)) {
26782 		hdd_err("Failed to update OWE info");
26783 		errno = qdf_status_to_os_return(status);
26784 	}
26785 
26786 	hdd_exit();
26787 	return errno;
26788 }
26789 
26790 /**
26791  * wlan_hdd_cfg80211_update_owe_info() - update OWE info
26792  * @wiphy: Pointer to wiphy
26793  * @net_dev: Pointer to network device
26794  * @owe_info: Pointer to OWE info
26795  *
26796  * Return: 0 for success, non-zero for failure
26797  */
26798 static int
wlan_hdd_cfg80211_update_owe_info(struct wiphy * wiphy,struct net_device * net_dev,struct cfg80211_update_owe_info * owe_info)26799 wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
26800 				  struct net_device *net_dev,
26801 				  struct cfg80211_update_owe_info *owe_info)
26802 {
26803 	struct osif_vdev_sync *vdev_sync;
26804 	int errno;
26805 
26806 	errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
26807 	if (errno)
26808 		return errno;
26809 
26810 	errno = __wlan_hdd_cfg80211_update_owe_info(wiphy, net_dev, owe_info);
26811 
26812 	osif_vdev_sync_op_stop(vdev_sync);
26813 
26814 	return errno;
26815 }
26816 #endif
26817 
wlan_hdd_cfg80211_update_replay_counter_cb(void * cb_ctx,struct pmo_gtk_rsp_params * gtk_rsp_param)26818 void wlan_hdd_cfg80211_update_replay_counter_cb(
26819 		void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
26820 
26821 {
26822 	struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
26823 	uint8_t temp_replay_counter[8];
26824 	int i;
26825 	uint8_t *p;
26826 
26827 	hdd_enter();
26828 
26829 	if (!adapter) {
26830 		hdd_err("HDD adapter is Null");
26831 		goto out;
26832 	}
26833 
26834 	if (!gtk_rsp_param) {
26835 		hdd_err("gtk_rsp_param is Null");
26836 		goto out;
26837 	}
26838 
26839 	if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
26840 		hdd_err("wlan Failed to get replay counter value");
26841 		goto out;
26842 	}
26843 
26844 	hdd_debug("updated replay counter: %llu from fwr",
26845 		gtk_rsp_param->replay_counter);
26846 	/* convert little to big endian since supplicant works on big endian */
26847 	p = (uint8_t *)&gtk_rsp_param->replay_counter;
26848 	for (i = 0; i < 8; i++)
26849 		temp_replay_counter[7 - i] = (uint8_t) p[i];
26850 
26851 	hdd_debug("gtk_rsp_param bssid "QDF_MAC_ADDR_FMT,
26852 		  QDF_MAC_ADDR_REF(gtk_rsp_param->bssid.bytes));
26853 	/* Update replay counter to NL */
26854 	cfg80211_gtk_rekey_notify(adapter->dev,
26855 					gtk_rsp_param->bssid.bytes,
26856 					temp_replay_counter, GFP_KERNEL);
26857 out:
26858 	hdd_exit();
26859 
26860 }
26861 
26862 #ifdef WLAN_FEATURE_GTK_OFFLOAD
26863 /**
26864  * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
26865  * @gtk_req: Pointer to GTK request
26866  * @data: Pointer to rekey data
26867  *
26868  * Return: none
26869  */
26870 #if (defined(CFG80211_REKEY_DATA_KEK_LEN) || \
26871 	LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
26872 static
wlan_hdd_copy_gtk_kek(struct pmo_gtk_req * gtk_req,struct cfg80211_gtk_rekey_data * data)26873 void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
26874 			   struct cfg80211_gtk_rekey_data *data)
26875 {
26876 	qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
26877 	gtk_req->kek_len = data->kek_len;
26878 }
26879 #else
26880 static
wlan_hdd_copy_gtk_kek(struct pmo_gtk_req * gtk_req,struct cfg80211_gtk_rekey_data * data)26881 void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
26882 			   struct cfg80211_gtk_rekey_data *data)
26883 {
26884 	qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
26885 	gtk_req->kek_len = NL80211_KEK_LEN;
26886 }
26887 #endif
26888 
26889 /**
26890  * wlan_hdd_copy_gtk_kck - Copy the KCK from GTK rekey data to GTK request
26891  * @gtk_req: Pointer to GTK request
26892  * @data: Pointer to rekey data
26893  *
26894  * Return: None
26895  */
26896 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
26897 static
wlan_hdd_copy_gtk_kck(struct pmo_gtk_req * gtk_req,struct cfg80211_gtk_rekey_data * data)26898 void wlan_hdd_copy_gtk_kck(struct pmo_gtk_req *gtk_req,
26899 			   struct cfg80211_gtk_rekey_data *data)
26900 {
26901 	qdf_mem_copy(gtk_req->kck, data->kck, data->kck_len);
26902 	gtk_req->kck_len = data->kck_len;
26903 }
26904 #else
26905 static
wlan_hdd_copy_gtk_kck(struct pmo_gtk_req * gtk_req,struct cfg80211_gtk_rekey_data * data)26906 void wlan_hdd_copy_gtk_kck(struct pmo_gtk_req *gtk_req,
26907 			   struct cfg80211_gtk_rekey_data *data)
26908 {
26909 	qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
26910 	gtk_req->kck_len = NL80211_KCK_LEN;
26911 }
26912 #endif
26913 /**
26914  * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
26915  * @wiphy: Pointer to wiphy
26916  * @dev: Pointer to network device
26917  * @data: Pointer to rekey data
26918  *
26919  * This function is used to offload GTK rekeying job to the firmware.
26920  *
26921  * Return: 0 for success, non-zero for failure
26922  */
26923 static
__wlan_hdd_cfg80211_set_rekey_data(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_gtk_rekey_data * data)26924 int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
26925 		struct net_device *dev,
26926 		struct cfg80211_gtk_rekey_data *data)
26927 {
26928 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26929 	int result, i;
26930 	struct pmo_gtk_req *gtk_req = NULL;
26931 	struct hdd_context *hdd_ctx =  WLAN_HDD_GET_CTX(adapter);
26932 	uint8_t *buf;
26933 	struct wlan_objmgr_vdev *vdev;
26934 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
26935 
26936 	hdd_enter();
26937 
26938 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26939 		hdd_err("Command not allowed in FTM mode");
26940 		result = -EINVAL;
26941 		goto out;
26942 	}
26943 
26944 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) {
26945 		result = -EINVAL;
26946 		goto out;
26947 	}
26948 
26949 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26950 		   TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
26951 		   adapter->deflink->vdev_id, adapter->device_mode);
26952 
26953 	result = wlan_hdd_validate_context(hdd_ctx);
26954 	if (0 != result)
26955 		goto out;
26956 
26957 	gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
26958 	if (!gtk_req) {
26959 		result = -ENOMEM;
26960 		goto out;
26961 	}
26962 
26963 	/* convert big to little endian since driver work on little endian */
26964 	buf = (uint8_t *)&gtk_req->replay_counter;
26965 	for (i = 0; i < 8; i++)
26966 		buf[7 - i] = data->replay_ctr[i];
26967 
26968 	hdd_debug("current replay counter: %llu in user space",
26969 		gtk_req->replay_counter);
26970 
26971 	wlan_hdd_copy_gtk_kek(gtk_req, data);
26972 	wlan_hdd_copy_gtk_kck(gtk_req, data);
26973 
26974 	gtk_req->is_fils_connection = hdd_is_fils_connection(hdd_ctx, adapter);
26975 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
26976 					   WLAN_OSIF_POWER_ID);
26977 	if (!vdev) {
26978 		result = -EINVAL;
26979 		goto out;
26980 	}
26981 	status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
26982 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
26983 	if (status != QDF_STATUS_SUCCESS) {
26984 		hdd_err("Failed to cache GTK Offload");
26985 		result = qdf_status_to_os_return(status);
26986 	}
26987 out:
26988 	if (gtk_req)
26989 		qdf_mem_free(gtk_req);
26990 	hdd_exit();
26991 
26992 	return result;
26993 }
26994 
26995 /**
26996  * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
26997  * @wiphy: Pointer to wiphy
26998  * @dev: Pointer to network device
26999  * @data: Pointer to rekey data
27000  *
27001  * This function is used to offload GTK rekeying job to the firmware.
27002  *
27003  * Return: 0 for success, non-zero for failure
27004  */
27005 static
wlan_hdd_cfg80211_set_rekey_data(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_gtk_rekey_data * data)27006 int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
27007 				     struct net_device *dev,
27008 				     struct cfg80211_gtk_rekey_data *data)
27009 {
27010 	int errno;
27011 	struct osif_vdev_sync *vdev_sync;
27012 
27013 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27014 	if (errno)
27015 		return errno;
27016 
27017 	errno = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
27018 
27019 	osif_vdev_sync_op_stop(vdev_sync);
27020 
27021 	return errno;
27022 }
27023 #endif /* WLAN_FEATURE_GTK_OFFLOAD */
27024 
27025 /**
27026  * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
27027  * @wiphy: Pointer to wiphy
27028  * @dev: Pointer to network device
27029  * @params: Pointer to access control parameter
27030  *
27031  * Return: 0 for success, non-zero for failure
27032  */
__wlan_hdd_cfg80211_set_mac_acl(struct wiphy * wiphy,struct net_device * dev,const struct cfg80211_acl_data * params)27033 static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
27034 					 struct net_device *dev,
27035 					 const struct cfg80211_acl_data *params)
27036 {
27037 	int i;
27038 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
27039 	struct hdd_hostapd_state *hostapd_state;
27040 	struct sap_config *config;
27041 	struct hdd_context *hdd_ctx;
27042 	int status;
27043 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
27044 
27045 	hdd_enter();
27046 
27047 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
27048 		hdd_err("Command not allowed in FTM mode");
27049 		return -EINVAL;
27050 	}
27051 
27052 	if (!params) {
27053 		hdd_err("params is Null");
27054 		return -EINVAL;
27055 	}
27056 
27057 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
27058 	status = wlan_hdd_validate_context(hdd_ctx);
27059 
27060 	if (0 != status)
27061 		return status;
27062 
27063 	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
27064 
27065 	if (!hostapd_state) {
27066 		hdd_err("hostapd_state is Null");
27067 		return -EINVAL;
27068 	}
27069 
27070 	hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
27071 		params->n_acl_entries);
27072 
27073 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
27074 		   TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
27075 		   adapter->deflink->vdev_id, adapter->device_mode);
27076 
27077 	if (QDF_SAP_MODE == adapter->device_mode) {
27078 		config = &adapter->deflink->session.ap.sap_config;
27079 
27080 		/* default value */
27081 		config->num_accept_mac = 0;
27082 		config->num_deny_mac = 0;
27083 
27084 		/**
27085 		 * access control policy
27086 		 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
27087 		 *   listed in hostapd.deny file.
27088 		 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
27089 		 *   listed in hostapd.accept file.
27090 		 */
27091 		if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
27092 			config->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
27093 		} else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
27094 			   params->acl_policy) {
27095 			config->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
27096 		} else {
27097 			hdd_warn("Acl Policy : %d is not supported",
27098 				params->acl_policy);
27099 			return -ENOTSUPP;
27100 		}
27101 
27102 		if (eSAP_DENY_UNLESS_ACCEPTED == config->SapMacaddr_acl) {
27103 			config->num_accept_mac = params->n_acl_entries;
27104 			for (i = 0; i < params->n_acl_entries; i++) {
27105 				hdd_debug("** Add ACL MAC entry %i in WhiletList :"
27106 					QDF_MAC_ADDR_FMT, i,
27107 					QDF_MAC_ADDR_REF(
27108 						params->mac_addrs[i].addr));
27109 
27110 				qdf_mem_copy(&config->accept_mac[i],
27111 					     params->mac_addrs[i].addr,
27112 					     QDF_MAC_ADDR_SIZE);
27113 			}
27114 		} else if (eSAP_ACCEPT_UNLESS_DENIED == config->SapMacaddr_acl) {
27115 			config->num_deny_mac = params->n_acl_entries;
27116 			for (i = 0; i < params->n_acl_entries; i++) {
27117 				hdd_debug("** Add ACL MAC entry %i in DenyList :"
27118 					QDF_MAC_ADDR_FMT, i,
27119 					QDF_MAC_ADDR_REF(
27120 						params->mac_addrs[i].addr));
27121 
27122 				qdf_mem_copy(&config->deny_mac[i],
27123 					     params->mac_addrs[i].addr,
27124 					     QDF_MAC_ADDR_SIZE);
27125 			}
27126 		}
27127 		qdf_status = wlansap_set_mac_acl(
27128 			WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink), config);
27129 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
27130 			hdd_err("SAP Set Mac Acl fail");
27131 			return -EINVAL;
27132 		}
27133 	} else {
27134 		hdd_debug("Invalid device_mode %s(%d)",
27135 			  qdf_opmode_str(adapter->device_mode),
27136 			  adapter->device_mode);
27137 		return -EINVAL;
27138 	}
27139 	hdd_exit();
27140 	return 0;
27141 }
27142 
27143 /**
27144  * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
27145  *				__wlan_hdd_cfg80211_set_mac_acl
27146  * @wiphy: pointer to wiphy structure
27147  * @dev: pointer to net_device
27148  * @params: pointer to cfg80211_acl_data
27149  *
27150  * Return; 0 on success, error number otherwise
27151  */
27152 static int
wlan_hdd_cfg80211_set_mac_acl(struct wiphy * wiphy,struct net_device * dev,const struct cfg80211_acl_data * params)27153 wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
27154 			      struct net_device *dev,
27155 			      const struct cfg80211_acl_data *params)
27156 {
27157 	int errno;
27158 	struct osif_vdev_sync *vdev_sync;
27159 
27160 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27161 	if (errno)
27162 		return errno;
27163 
27164 	errno = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
27165 
27166 	osif_vdev_sync_op_stop(vdev_sync);
27167 
27168 	return errno;
27169 }
27170 
27171 #ifdef WLAN_NL80211_TESTMODE
27172 #ifdef FEATURE_WLAN_LPHB
27173 /**
27174  * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
27175  * @hdd_ctx: Pointer to hdd context
27176  * @lphb_ind: Pointer to low power heart beat indication parameter
27177  *
27178  * Return: none
27179  */
wlan_hdd_cfg80211_lphb_ind_handler(void * hdd_ctx,struct pmo_lphb_rsp * lphb_ind)27180 static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
27181 		struct pmo_lphb_rsp *lphb_ind)
27182 {
27183 	struct sk_buff *skb;
27184 
27185 	hdd_debug("LPHB indication arrived");
27186 
27187 	if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
27188 		return;
27189 
27190 	if (!lphb_ind) {
27191 		hdd_err("invalid argument lphbInd");
27192 		return;
27193 	}
27194 
27195 	skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
27196 			wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
27197 	if (!skb) {
27198 		hdd_err("LPHB timeout, NL buffer alloc fail");
27199 		return;
27200 	}
27201 
27202 	if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
27203 		hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
27204 		goto nla_put_failure;
27205 	}
27206 	if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
27207 		hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
27208 		goto nla_put_failure;
27209 	}
27210 	if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
27211 			lphb_ind)) {
27212 		hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
27213 		goto nla_put_failure;
27214 	}
27215 	cfg80211_testmode_event(skb, GFP_ATOMIC);
27216 	return;
27217 
27218 nla_put_failure:
27219 	hdd_err("NLA Put fail");
27220 	kfree_skb(skb);
27221 }
27222 #endif /* FEATURE_WLAN_LPHB */
27223 
27224 /**
27225  * __wlan_hdd_cfg80211_testmode() - test mode
27226  * @wiphy: Pointer to wiphy
27227  * @data: Data pointer
27228  * @len: Data length
27229  *
27230  * Return: 0 for success, non-zero for failure
27231  */
__wlan_hdd_cfg80211_testmode(struct wiphy * wiphy,void * data,int len)27232 static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
27233 					void *data, int len)
27234 {
27235 	struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
27236 	int err;
27237 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
27238 
27239 	hdd_enter();
27240 
27241 	err = wlan_hdd_validate_context(hdd_ctx);
27242 	if (err)
27243 		return err;
27244 
27245 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
27246 		hdd_err("Driver Modules are closed");
27247 		return -EINVAL;
27248 	}
27249 
27250 	err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
27251 				      len, wlan_hdd_tm_policy);
27252 	if (err) {
27253 		hdd_err("Testmode INV ATTR");
27254 		return err;
27255 	}
27256 
27257 	if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
27258 		hdd_err("Testmode INV CMD");
27259 		return -EINVAL;
27260 	}
27261 
27262 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
27263 		   TRACE_CODE_HDD_CFG80211_TESTMODE,
27264 		   NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
27265 
27266 	switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
27267 #ifdef FEATURE_WLAN_LPHB
27268 	/* Low Power Heartbeat configuration request */
27269 	case WLAN_HDD_TM_CMD_WLAN_HB:
27270 	{
27271 		int buf_len;
27272 		void *buf;
27273 		struct pmo_lphb_req *hb_params = NULL;
27274 		struct pmo_lphb_req *hb_params_temp = NULL;
27275 		QDF_STATUS status;
27276 
27277 		if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
27278 			hdd_err("Testmode INV DATA");
27279 			return -EINVAL;
27280 		}
27281 
27282 		buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
27283 		buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
27284 		if (buf_len < sizeof(*hb_params_temp)) {
27285 			hdd_err("Invalid buffer length for TM_ATTR_DATA");
27286 			return -EINVAL;
27287 		}
27288 
27289 		hb_params_temp = (struct pmo_lphb_req *) buf;
27290 		if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
27291 		    && (hb_params_temp->params.lphb_tcp_params.
27292 			time_period_sec == 0))
27293 			return -EINVAL;
27294 
27295 		if (buf_len > sizeof(*hb_params)) {
27296 			hdd_err("buf_len=%d exceeded hb_params size limit",
27297 				buf_len);
27298 			return -ERANGE;
27299 		}
27300 
27301 		hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
27302 				sizeof(*hb_params));
27303 		if (!hb_params)
27304 			return -ENOMEM;
27305 
27306 		qdf_mem_zero(hb_params, sizeof(*hb_params));
27307 		qdf_mem_copy(hb_params, buf, buf_len);
27308 		status = ucfg_pmo_lphb_config_req(
27309 					hdd_ctx->psoc,
27310 					hb_params, (void *)hdd_ctx,
27311 					wlan_hdd_cfg80211_lphb_ind_handler);
27312 		if (status != QDF_STATUS_SUCCESS)
27313 			hdd_err("LPHB Config Fail, disable");
27314 
27315 		qdf_mem_free(hb_params);
27316 		return 0;
27317 	}
27318 #endif /* FEATURE_WLAN_LPHB */
27319 
27320 #if  defined(QCA_WIFI_FTM)
27321 	case WLAN_HDD_TM_CMD_WLAN_FTM:
27322 	{
27323 		if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) {
27324 			hdd_err("FTM Command not allowed in mission mode, mode %d",
27325 				hdd_get_conparam());
27326 			return -EINVAL;
27327 		}
27328 
27329 		err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->pdev,
27330 						     data, len);
27331 		break;
27332 	}
27333 #endif
27334 	default:
27335 		hdd_err("command: %d not supported",
27336 			nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
27337 		return -EOPNOTSUPP;
27338 	}
27339 
27340 	hdd_exit();
27341 	return err;
27342 }
27343 
27344 /**
27345  * wlan_hdd_cfg80211_testmode() - test mode
27346  * @wiphy: Pointer to wiphy
27347  * @wdev: Pointer to wireless device
27348  * @data: Data pointer
27349  * @len: Data length
27350  *
27351  * Return: 0 for success, non-zero for failure
27352  */
wlan_hdd_cfg80211_testmode(struct wiphy * wiphy,struct wireless_dev * wdev,void * data,int len)27353 static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
27354 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
27355 				      struct wireless_dev *wdev,
27356 #endif
27357 				      void *data, int len)
27358 {
27359 	struct osif_psoc_sync *psoc_sync;
27360 	int errno;
27361 
27362 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
27363 	if (errno)
27364 		return errno;
27365 
27366 	errno = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
27367 
27368 	osif_psoc_sync_op_stop(psoc_sync);
27369 
27370 	return errno;
27371 }
27372 
27373 #endif /* CONFIG_NL80211_TESTMODE */
27374 
27375 #ifdef QCA_HT_2040_COEX
27376 /**
27377  * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
27378  * @wiphy: Pointer to wiphy
27379  * @dev: Pointer to network device
27380  * @chandef: Pointer to channel definition parameter
27381  *
27382  * Return: 0 for success, non-zero for failure
27383  */
27384 static int
__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_chan_def * chandef)27385 __wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
27386 					 struct net_device *dev,
27387 					 struct cfg80211_chan_def *chandef)
27388 {
27389 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
27390 	struct hdd_context *hdd_ctx;
27391 	QDF_STATUS status;
27392 	int retval = 0;
27393 	enum nl80211_channel_type channel_type;
27394 
27395 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
27396 		hdd_err("Command not allowed in FTM mode");
27397 		return -EINVAL;
27398 	}
27399 
27400 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
27401 		return -EINVAL;
27402 
27403 	if (!(adapter->device_mode == QDF_SAP_MODE ||
27404 	      adapter->device_mode == QDF_P2P_GO_MODE))
27405 		return -EOPNOTSUPP;
27406 
27407 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
27408 	status = wlan_hdd_validate_context(hdd_ctx);
27409 	if (status)
27410 		return status;
27411 
27412 	if (chandef->width < NL80211_CHAN_WIDTH_80)
27413 		channel_type = cfg80211_get_chandef_type(chandef);
27414 	else
27415 		channel_type = NL80211_CHAN_HT40PLUS;
27416 	hdd_debug("Channel width changed to %d ", channel_type);
27417 
27418 	/* Change SAP ht2040 mode */
27419 	status = hdd_set_sap_ht2040_mode(adapter, channel_type);
27420 	if (status != QDF_STATUS_SUCCESS) {
27421 		hdd_err("Cannot set SAP HT20/40 mode!");
27422 		retval = -EINVAL;
27423 	}
27424 
27425 	return retval;
27426 }
27427 
27428 /**
27429  * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
27430  * @wiphy: Pointer to wiphy
27431  * @dev: Pointer to network device
27432  * @link_id: Link id for which channel width has to be applied
27433  * @chandef: Pointer to channel definition parameter
27434  *
27435  * Return: 0 for success, non-zero for failure
27436  */
27437 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
27438 static int
wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy * wiphy,struct net_device * dev,unsigned int link_id,struct cfg80211_chan_def * chandef)27439 wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
27440 				       struct net_device *dev,
27441 				       unsigned int link_id,
27442 				       struct cfg80211_chan_def *chandef)
27443 #else
27444 static int
27445 wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
27446 				       struct net_device *dev,
27447 				       struct cfg80211_chan_def *chandef)
27448 #endif
27449 {
27450 	int errno;
27451 	struct osif_vdev_sync *vdev_sync;
27452 
27453 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27454 	if (errno)
27455 		return errno;
27456 
27457 	errno = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
27458 
27459 	osif_vdev_sync_op_stop(vdev_sync);
27460 
27461 	return errno;
27462 }
27463 #endif
27464 
27465 #ifdef CHANNEL_SWITCH_SUPPORTED
27466 /**
27467  * __wlan_hdd_cfg80211_channel_switch()- function to switch
27468  * channel in SAP/GO
27469  * @wiphy:  wiphy pointer
27470  * @dev: dev pointer.
27471  * @csa_params: Change channel params
27472  *
27473  * This function is called to switch channel in SAP/GO
27474  *
27475  * Return: 0 if success else return non zero
27476  */
__wlan_hdd_cfg80211_channel_switch(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_csa_settings * csa_params)27477 static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
27478 				struct net_device *dev,
27479 				struct cfg80211_csa_settings *csa_params)
27480 {
27481 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
27482 	struct hdd_context *hdd_ctx;
27483 	int ret;
27484 	enum phy_ch_width ch_width;
27485 	bool status;
27486 	struct hdd_hostapd_state *hostapd_state;
27487 
27488 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
27489 		return -EINVAL;
27490 
27491 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
27492 	ret = wlan_hdd_validate_context(hdd_ctx);
27493 
27494 	if (0 != ret)
27495 		return ret;
27496 
27497 	if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
27498 		(QDF_SAP_MODE != adapter->device_mode))
27499 		return -ENOTSUPP;
27500 
27501 	status = policy_mgr_is_sap_allowed_on_dfs_freq(
27502 					hdd_ctx->pdev,
27503 					adapter->deflink->vdev_id,
27504 					csa_params->chandef.chan->center_freq);
27505 	if (!status)
27506 		return -EINVAL;
27507 
27508 	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->deflink->vdev_id,
27509 				    CSA_REASON_USER_INITIATED);
27510 
27511 	ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
27512 	hdd_debug("Freq %d width %d ch_width %d",
27513 		  csa_params->chandef.chan->center_freq,
27514 		  csa_params->chandef.width, ch_width);
27515 	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
27516 	qdf_event_reset(&hostapd_state->qdf_event);
27517 
27518 	ret =
27519 	    hdd_softap_set_channel_change(dev,
27520 					  csa_params->chandef.chan->center_freq,
27521 					  ch_width, false);
27522 	if (ret) {
27523 		hdd_err("CSA failed to %d, ret %d",
27524 			csa_params->chandef.chan->center_freq, ret);
27525 		return ret;
27526 	}
27527 
27528 	status = qdf_wait_for_event_completion(&hostapd_state->qdf_event,
27529 					       SME_CMD_START_BSS_TIMEOUT);
27530 	if (QDF_IS_STATUS_ERROR(status))
27531 		hdd_err("wait for qdf_event failed!!");
27532 	else
27533 		hdd_debug("csa done");
27534 
27535 	return ret;
27536 }
27537 
27538 /**
27539  * wlan_hdd_cfg80211_channel_switch()- function to switch
27540  * channel in SAP/GO
27541  * @wiphy:  wiphy pointer
27542  * @dev: dev pointer.
27543  * @csa_params: Change channel params
27544  *
27545  * This function is called to switch channel in SAP/GO
27546  *
27547  * Return: 0 if success else return non zero
27548  */
wlan_hdd_cfg80211_channel_switch(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_csa_settings * csa_params)27549 static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
27550 				struct net_device *dev,
27551 				struct cfg80211_csa_settings *csa_params)
27552 {
27553 	int errno;
27554 	struct osif_vdev_sync *vdev_sync;
27555 
27556 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27557 	if (errno)
27558 		return errno;
27559 
27560 	errno = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
27561 
27562 	osif_vdev_sync_op_stop(vdev_sync);
27563 
27564 	return errno;
27565 }
27566 #endif
27567 
wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter * adapter,uint32_t chan_freq,enum policy_mgr_conn_update_reason reason)27568 int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
27569 					   uint32_t chan_freq,
27570 					   enum policy_mgr_conn_update_reason reason)
27571 {
27572 	QDF_STATUS status;
27573 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
27574 
27575 	hdd_enter();
27576 
27577 	status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
27578 	if (!QDF_IS_STATUS_SUCCESS(status))
27579 		hdd_err("clearing event failed");
27580 
27581 	status = policy_mgr_current_connections_update(
27582 			hdd_ctx->psoc, adapter->deflink->vdev_id,
27583 			chan_freq, reason, POLICY_MGR_DEF_REQ_ID);
27584 	switch (status) {
27585 	case QDF_STATUS_E_FAILURE:
27586 		/*
27587 		 * QDF_STATUS_E_FAILURE indicates that some error has occurred
27588 		 * while changing the hw mode
27589 		 */
27590 		hdd_err("ERROR: connections update failed!!");
27591 		return -EINVAL;
27592 
27593 	case QDF_STATUS_SUCCESS:
27594 		/*
27595 		 * QDF_STATUS_SUCCESS indicates that HW mode change has been
27596 		 * triggered and wait for it to finish.
27597 		 */
27598 		status = policy_mgr_wait_for_connection_update(
27599 						hdd_ctx->psoc);
27600 		if (!QDF_IS_STATUS_SUCCESS(status)) {
27601 			hdd_err("ERROR: qdf wait for event failed!!");
27602 			return -EINVAL;
27603 		}
27604 		if (QDF_MONITOR_MODE == adapter->device_mode)
27605 			hdd_info("Monitor mode:channel freq:%d (SMM->DBS)", chan_freq);
27606 		break;
27607 
27608 	default:
27609 		/*
27610 		 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
27611 		 * required, so caller can proceed further.
27612 		 */
27613 		break;
27614 
27615 	}
27616 	hdd_exit();
27617 
27618 	return 0;
27619 }
27620 
27621 #ifdef FEATURE_MONITOR_MODE_SUPPORT
27622 /**
27623  * __wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
27624  * @wiphy: Handle to struct wiphy to get handle to module context.
27625  * @chandef: Contains information about the capture channel to be set.
27626  *
27627  * This interface is called if and only if monitor mode interface alone is
27628  * active.
27629  *
27630  * Return: 0 success or error code on failure.
27631  */
__wlan_hdd_cfg80211_set_mon_ch(struct wiphy * wiphy,struct cfg80211_chan_def * chandef)27632 static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
27633 				       struct cfg80211_chan_def *chandef)
27634 {
27635 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
27636 	struct hdd_adapter *adapter;
27637 	struct hdd_station_ctx *sta_ctx;
27638 	struct hdd_mon_set_ch_info *ch_info;
27639 	QDF_STATUS status;
27640 	mac_handle_t mac_handle;
27641 	struct qdf_mac_addr bssid;
27642 	struct channel_change_req *req;
27643 	struct ch_params ch_params = {0};
27644 	int ret;
27645 	enum channel_state chan_freq_state;
27646 	uint8_t max_fw_bw;
27647 	enum phy_ch_width ch_width;
27648 	qdf_freq_t sec_ch_2g_freq = 0;
27649 
27650 	hdd_enter();
27651 
27652 	ret = wlan_hdd_validate_context(hdd_ctx);
27653 	if (ret)
27654 		return ret;
27655 
27656 	mac_handle = hdd_ctx->mac_handle;
27657 
27658 	adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
27659 	if (!adapter)
27660 		return -EIO;
27661 
27662 	hdd_debug("%s: set monitor mode freq %d",
27663 		  adapter->dev->name, chandef->chan->center_freq);
27664 
27665 	/* Verify channel state before accepting this request */
27666 	chan_freq_state =
27667 		wlan_reg_get_channel_state_for_pwrmode(
27668 						hdd_ctx->pdev,
27669 						chandef->chan->center_freq,
27670 						REG_CURRENT_PWR_MODE);
27671 	if (chan_freq_state == CHANNEL_STATE_DISABLE ||
27672 	    chan_freq_state == CHANNEL_STATE_INVALID) {
27673 		hdd_err("Invalid chan freq received for monitor mode aborting");
27674 		return -EINVAL;
27675 	}
27676 
27677 	/* Verify the BW before accepting this request */
27678 	ch_width = hdd_map_nl_chan_width(chandef->width);
27679 
27680 	if (ch_width > CH_WIDTH_10MHZ ||
27681 	   (!cds_is_sub_20_mhz_enabled() && ch_width > CH_WIDTH_160MHZ)) {
27682 		hdd_err("invalid BW received %d", ch_width);
27683 		return -EINVAL;
27684 	}
27685 
27686 	max_fw_bw = sme_get_vht_ch_width();
27687 
27688 	if ((ch_width == CH_WIDTH_160MHZ &&
27689 	    max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) ||
27690 	    (ch_width == CH_WIDTH_80P80MHZ &&
27691 	    max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)) {
27692 		hdd_err("FW does not support this BW %d max BW supported %d",
27693 			ch_width, max_fw_bw);
27694 		return -EINVAL;
27695 	}
27696 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
27697 	ch_info = &sta_ctx->ch_info;
27698 
27699 	if (WLAN_REG_IS_24GHZ_CH_FREQ(chandef->chan->center_freq) &&
27700 	    chandef->width == NL80211_CHAN_WIDTH_40 &&
27701 	    chandef->center_freq1) {
27702 		if (chandef->center_freq1 > chandef->chan->center_freq)
27703 			sec_ch_2g_freq = chandef->chan->center_freq + 20;
27704 		else if (chandef->center_freq1 < chandef->chan->center_freq)
27705 			sec_ch_2g_freq = chandef->chan->center_freq - 20;
27706 	}
27707 	hdd_debug("set mon ch:width=%d, freq %d sec_ch_2g_freq=%d",
27708 		  chandef->width, chandef->chan->center_freq, sec_ch_2g_freq);
27709 	qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
27710 		     QDF_MAC_ADDR_SIZE);
27711 
27712 	ch_params.ch_width = ch_width;
27713 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
27714 						chandef->chan->center_freq,
27715 						sec_ch_2g_freq, &ch_params,
27716 						REG_CURRENT_PWR_MODE);
27717 	if (wlan_hdd_change_hw_mode_for_given_chnl(adapter,
27718 						   chandef->chan->center_freq,
27719 						   POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
27720 		hdd_err("Failed to change hw mode");
27721 		return -EINVAL;
27722 	}
27723 
27724 	if (adapter->monitor_mode_vdev_up_in_progress) {
27725 		hdd_err_rl("monitor mode vdev up in progress");
27726 		return -EBUSY;
27727 	}
27728 
27729 	status = qdf_event_reset(&adapter->qdf_monitor_mode_vdev_up_event);
27730 	if (QDF_IS_STATUS_ERROR(status)) {
27731 		hdd_err_rl("failed to reinit monitor mode vdev up event");
27732 		return qdf_status_to_os_return(status);
27733 	}
27734 	adapter->monitor_mode_vdev_up_in_progress = true;
27735 
27736 	qdf_mem_zero(&ch_params, sizeof(struct ch_params));
27737 
27738 	req = qdf_mem_malloc(sizeof(struct channel_change_req));
27739 	if (!req)
27740 		return -ENOMEM;
27741 
27742 	req->vdev_id = adapter->deflink->vdev_id;
27743 	req->target_chan_freq = chandef->chan->center_freq;
27744 	req->ch_width = ch_width;
27745 
27746 	ch_params.ch_width = ch_width;
27747 	hdd_select_cbmode(adapter, chandef->chan->center_freq, sec_ch_2g_freq,
27748 			  &ch_params);
27749 
27750 	req->sec_ch_offset = ch_params.sec_ch_offset;
27751 	req->center_freq_seg0 = ch_params.center_freq_seg0;
27752 	req->center_freq_seg1 = ch_params.center_freq_seg1;
27753 
27754 	sme_fill_channel_change_request(mac_handle, req, ch_info->phy_mode);
27755 	status = sme_send_channel_change_req(mac_handle, req);
27756 	qdf_mem_free(req);
27757 
27758 	if (status) {
27759 		hdd_err_rl("Failed to set sme_RoamChannel for monitor mode status: %d",
27760 			   status);
27761 		adapter->monitor_mode_vdev_up_in_progress = false;
27762 		ret = qdf_status_to_os_return(status);
27763 		return ret;
27764 	}
27765 
27766 	/* block on a completion variable until vdev up success*/
27767 	status = qdf_wait_for_event_completion(
27768 				       &adapter->qdf_monitor_mode_vdev_up_event,
27769 					WLAN_MONITOR_MODE_VDEV_UP_EVT);
27770 	if (QDF_IS_STATUS_ERROR(status)) {
27771 		hdd_err_rl("monitor vdev up event time out vdev id: %d",
27772 			  adapter->deflink->vdev_id);
27773 		if (adapter->qdf_monitor_mode_vdev_up_event.force_set)
27774 			/*
27775 			 * SSR/PDR has caused shutdown, which has
27776 			 * forcefully set the event.
27777 			 */
27778 			hdd_err_rl("monitor mode vdev up event forcefully set");
27779 		else if (status == QDF_STATUS_E_TIMEOUT)
27780 			hdd_err_rl("monitor mode vdev up timed out");
27781 		else
27782 			hdd_err_rl("Failed monitor mode vdev up(status-%d)",
27783 				  status);
27784 
27785 		adapter->monitor_mode_vdev_up_in_progress = false;
27786 		return qdf_status_to_os_return(status);
27787 	}
27788 
27789 	hdd_exit();
27790 
27791 	return 0;
27792 }
27793 
27794 /**
27795  * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
27796  * @wiphy: Handle to struct wiphy to get handle to module context.
27797  * @chandef: Contains information about the capture channel to be set.
27798  *
27799  * This interface is called if and only if monitor mode interface alone is
27800  * active.
27801  *
27802  * Return: 0 success or error code on failure.
27803  */
wlan_hdd_cfg80211_set_mon_ch(struct wiphy * wiphy,struct cfg80211_chan_def * chandef)27804 static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
27805 				       struct cfg80211_chan_def *chandef)
27806 {
27807 	struct osif_psoc_sync *psoc_sync;
27808 	int errno;
27809 
27810 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
27811 	if (errno)
27812 		return errno;
27813 
27814 	errno = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
27815 
27816 	osif_psoc_sync_op_stop(psoc_sync);
27817 
27818 	return errno;
27819 }
27820 #endif
27821 
27822 #define CNT_DIFF(cur, prev) \
27823 	((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
27824 #define MAX_COUNT 0xffffffff
hdd_update_chan_info(struct hdd_context * hdd_ctx,struct scan_chan_info * chan,struct scan_chan_info * info,uint32_t cmd_flag)27825 static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
27826 			struct scan_chan_info *chan,
27827 			struct scan_chan_info *info, uint32_t cmd_flag)
27828 {
27829 	if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
27830 	   (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
27831 		hdd_err("cmd flag is invalid: %d", info->cmd_flag);
27832 
27833 	mutex_lock(&hdd_ctx->chan_info_lock);
27834 
27835 	if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
27836 		qdf_mem_zero(chan, sizeof(*chan));
27837 
27838 	chan->freq = info->freq;
27839 	chan->noise_floor = info->noise_floor;
27840 	chan->clock_freq = info->clock_freq;
27841 	chan->cmd_flag = info->cmd_flag;
27842 	chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
27843 
27844 	chan->rx_clear_count =
27845 			CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
27846 
27847 	chan->tx_frame_count =
27848 			CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
27849 
27850 	mutex_unlock(&hdd_ctx->chan_info_lock);
27851 
27852 }
27853 #undef CNT_DIFF
27854 #undef MAX_COUNT
27855 
27856 #ifndef UPDATE_ASSOC_IE
27857 #define UPDATE_ASSOC_IE BIT(0)
27858 #endif
27859 
27860 #ifndef UPDATE_FILS_ERP_INFO
27861 #define UPDATE_FILS_ERP_INFO BIT(1)
27862 #endif
27863 
27864 #ifndef UPDATE_FILS_AUTH_TYPE
27865 #define UPDATE_FILS_AUTH_TYPE BIT(2)
27866 #endif
27867 
27868 #if defined(WLAN_FEATURE_FILS_SK) &&\
27869 	(defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) ||\
27870 		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))) &&\
27871 	(defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
27872 		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
27873 static inline int
hdd_update_connect_params_fils_info(struct hdd_adapter * adapter,struct hdd_context * hdd_ctx,struct cfg80211_connect_params * req,uint32_t changed)27874 hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
27875 				    struct hdd_context *hdd_ctx,
27876 				    struct cfg80211_connect_params *req,
27877 				    uint32_t changed)
27878 {
27879 	uint8_t *buf;
27880 	QDF_STATUS status;
27881 	enum wlan_fils_auth_type auth_type;
27882 	struct wlan_fils_con_info *fils_info;
27883 	int ret = 0;
27884 
27885 	fils_info = qdf_mem_malloc(sizeof(*fils_info));
27886 	if (!fils_info)
27887 		return -EINVAL;
27888 
27889 	fils_info->is_fils_connection = true;
27890 	if (changed & UPDATE_FILS_ERP_INFO) {
27891 		fils_info->username_len = req->fils_erp_username_len +
27892 					    sizeof(char) +
27893 					    req->fils_erp_realm_len;
27894 		if (fils_info->username_len >
27895 		    WLAN_CM_FILS_MAX_KEYNAME_NAI_LENGTH) {
27896 			hdd_err("Key NAI Length %d",
27897 				fils_info->username_len);
27898 			ret = -EINVAL;
27899 			goto free_mem;
27900 		}
27901 		if (req->fils_erp_username_len && req->fils_erp_username) {
27902 			buf = fils_info->username;
27903 			qdf_mem_copy(buf, req->fils_erp_username,
27904 				     req->fils_erp_username_len);
27905 			buf += req->fils_erp_username_len;
27906 			*buf++ = '@';
27907 			qdf_mem_copy(buf, req->fils_erp_realm,
27908 				     req->fils_erp_realm_len);
27909 		}
27910 
27911 		fils_info->next_seq_num = req->fils_erp_next_seq_num + 1;
27912 		fils_info->rrk_len = req->fils_erp_rrk_len;
27913 
27914 		if (fils_info->rrk_len > WLAN_CM_FILS_MAX_RRK_LENGTH) {
27915 			hdd_err("r_rk_length is invalid %d",
27916 				fils_info->rrk_len);
27917 			ret = -EINVAL;
27918 			goto free_mem;
27919 		}
27920 
27921 		if (req->fils_erp_rrk_len && req->fils_erp_rrk)
27922 			qdf_mem_copy(fils_info->rrk, req->fils_erp_rrk,
27923 				     fils_info->rrk_len);
27924 
27925 		fils_info->realm_len = req->fils_erp_realm_len;
27926 		if (fils_info->realm_len > WLAN_CM_FILS_MAX_REALM_LEN) {
27927 			hdd_err("Invalid fils realm len %d",
27928 				fils_info->realm_len);
27929 			ret = -EINVAL;
27930 			goto free_mem;
27931 		}
27932 		if (req->fils_erp_realm_len && req->fils_erp_realm)
27933 			qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
27934 				     fils_info->realm_len);
27935 	}
27936 
27937 	if (changed & UPDATE_FILS_AUTH_TYPE) {
27938 		auth_type = osif_cm_get_fils_auth_type(req->auth_type);
27939 		if (auth_type == FILS_PK_MAX) {
27940 			hdd_err("invalid auth type for fils %d",
27941 				req->auth_type);
27942 			ret = -EINVAL;
27943 			goto free_mem;
27944 		}
27945 
27946 		fils_info->auth_type = auth_type;
27947 	}
27948 
27949 	hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
27950 		  changed, fils_info->is_fils_connection,
27951 		  fils_info->username_len);
27952 	/*
27953 	 * Update the FILS config from adapter->roam_profile to
27954 	 * csr_session
27955 	 */
27956 	status = ucfg_cm_update_fils_config(hdd_ctx->psoc,
27957 					    adapter->deflink->vdev_id,
27958 					    fils_info);
27959 	if (QDF_IS_STATUS_ERROR(status))
27960 		hdd_err("Update FILS connect params failed %d", status);
27961 free_mem:
27962 	qdf_mem_free(fils_info);
27963 
27964 	return ret;
27965 }
27966 #else
27967 static inline int
hdd_update_connect_params_fils_info(struct hdd_adapter * adapter,struct hdd_context * hdd_ctx,struct cfg80211_connect_params * req,uint32_t changed)27968 hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
27969 				    struct hdd_context *hdd_ctx,
27970 				    struct cfg80211_connect_params *req,
27971 				    uint32_t changed)
27972 {
27973 	return -EINVAL;
27974 }
27975 #endif
27976 
27977 #if defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
27978 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
27979 
27980 /**
27981  * __wlan_hdd_cfg80211_update_connect_params - update connect params
27982  * @wiphy: Handle to struct wiphy to get handle to module context.
27983  * @dev: Pointer to network device
27984  * @req: Pointer to connect params
27985  * @changed: Bitmap used to indicate the changed params
27986  *
27987  * Update the connect parameters while connected to a BSS. The updated
27988  * parameters can be used by driver/firmware for subsequent BSS selection
27989  * (roaming) decisions and to form the Authentication/(Re)Association
27990  * Request frames. This call does not request an immediate disassociation
27991  * or reassociation with the current BSS, i.e., this impacts only
27992  * subsequent (re)associations. The bits in changed are defined in enum
27993  * cfg80211_connect_params_changed
27994  *
27995  * Return: zero for success, non-zero for failure
27996  */
27997 static int
__wlan_hdd_cfg80211_update_connect_params(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_connect_params * req,uint32_t changed)27998 __wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
27999 					  struct net_device *dev,
28000 					  struct cfg80211_connect_params *req,
28001 					  uint32_t changed)
28002 {
28003 	int ret;
28004 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
28005 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
28006 	QDF_STATUS status;
28007 	mac_handle_t mac_handle;
28008 	struct element_info assoc_ie;
28009 
28010 	hdd_enter_dev(dev);
28011 
28012 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
28013 		return -EINVAL;
28014 
28015 	ret = wlan_hdd_validate_context(hdd_ctx);
28016 	if (ret)
28017 		return -EINVAL;
28018 
28019 	mac_handle = hdd_ctx->mac_handle;
28020 
28021 	if (changed & UPDATE_ASSOC_IE) {
28022 		assoc_ie.len = req->ie_len;
28023 		assoc_ie.ptr = (uint8_t *)req->ie;
28024 		/*
28025 		 * Update this assoc IE received from user space to
28026 		 * umac. RSO command will pick up the assoc
28027 		 * IEs to be sent to firmware from the umac.
28028 		 */
28029 		ucfg_cm_update_session_assoc_ie(hdd_ctx->psoc,
28030 						adapter->deflink->vdev_id,
28031 						&assoc_ie);
28032 	}
28033 
28034 	if ((changed & UPDATE_FILS_ERP_INFO) ||
28035 	    (changed & UPDATE_FILS_AUTH_TYPE)) {
28036 		ret = hdd_update_connect_params_fils_info(adapter, hdd_ctx,
28037 							  req, changed);
28038 		if (ret)
28039 			return -EINVAL;
28040 
28041 		if (!hdd_ctx->is_fils_roaming_supported) {
28042 			hdd_debug("FILS roaming support %d",
28043 				  hdd_ctx->is_fils_roaming_supported);
28044 			return 0;
28045 		}
28046 	}
28047 
28048 	if (changed) {
28049 		status = sme_send_rso_connect_params(mac_handle,
28050 						     adapter->deflink->vdev_id);
28051 		if (QDF_IS_STATUS_ERROR(status))
28052 			hdd_err("Update connect params to fw failed %d",
28053 				status);
28054 	}
28055 
28056 	return 0;
28057 }
28058 
28059 /**
28060  * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
28061  *                __wlan_hdd_cfg80211_update_connect_params
28062  * @wiphy: Pointer to wiphy structure
28063  * @dev: Pointer to net_device
28064  * @req: Pointer to connect params
28065  * @changed: flags used to indicate the changed params
28066  *
28067  * Return: zero for success, non-zero for failure
28068  */
28069 static int
wlan_hdd_cfg80211_update_connect_params(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_connect_params * req,uint32_t changed)28070 wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
28071 					struct net_device *dev,
28072 					struct cfg80211_connect_params *req,
28073 					uint32_t changed)
28074 {
28075 	int errno;
28076 	struct osif_vdev_sync *vdev_sync;
28077 
28078 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
28079 	if (errno)
28080 		return errno;
28081 
28082 	errno = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
28083 							  req, changed);
28084 
28085 	osif_vdev_sync_op_stop(vdev_sync);
28086 
28087 	return errno;
28088 }
28089 #endif
28090 
28091 #if defined(WLAN_FEATURE_SAE) && \
28092 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
28093 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
28094 #if (defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT) || \
28095 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
28096 /**
28097  * wlan_hdd_extauth_cache_pmkid() - Extract and cache pmkid
28098  * @adapter: hdd vdev/net_device context
28099  * @mac_handle: Handle to the MAC
28100  * @params: Pointer to external auth params.
28101  *
28102  * Extract the PMKID and BSS from external auth params and add to the
28103  * PMKSA Cache in CSR.
28104  */
28105 static void
wlan_hdd_extauth_cache_pmkid(struct hdd_adapter * adapter,mac_handle_t mac_handle,struct cfg80211_external_auth_params * params)28106 wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
28107 			     mac_handle_t mac_handle,
28108 			     struct cfg80211_external_auth_params *params)
28109 {
28110 	struct wlan_crypto_pmksa *pmk_cache;
28111 	QDF_STATUS result;
28112 
28113 	if (params->pmkid) {
28114 		pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
28115 		if (!pmk_cache)
28116 			return;
28117 
28118 		qdf_mem_copy(pmk_cache->bssid.bytes, params->bssid,
28119 			     QDF_MAC_ADDR_SIZE);
28120 		qdf_mem_copy(pmk_cache->pmkid, params->pmkid,
28121 			     PMKID_LEN);
28122 		result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
28123 		if (!QDF_IS_STATUS_SUCCESS(result))
28124 			hdd_debug("external_auth: Failed to cache PMKID");
28125 
28126 		qdf_mem_free(pmk_cache);
28127 	}
28128 
28129 }
28130 
28131 /**
28132  * wlan_hdd_extauth_copy_pmkid() - Copy the pmkid received from the
28133  * external authentication command received from the userspace.
28134  * @params: pointer to auth params
28135  * @pmkid: Pointer to destination pmkid buffer to be filled
28136  *
28137  * The caller should ensure that destination pmkid buffer is not NULL.
28138  *
28139  * Return: None
28140  */
28141 static void
wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params * params,uint8_t * pmkid)28142 wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
28143 			    uint8_t *pmkid)
28144 {
28145 	if (params->pmkid)
28146 		qdf_mem_copy(pmkid, params->pmkid, PMKID_LEN);
28147 }
28148 
28149 #else
28150 static void
wlan_hdd_extauth_cache_pmkid(struct hdd_adapter * adapter,mac_handle_t mac_handle,struct cfg80211_external_auth_params * params)28151 wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
28152 			     mac_handle_t mac_handle,
28153 			     struct cfg80211_external_auth_params *params)
28154 {}
28155 
28156 static void
wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params * params,uint8_t * pmkid)28157 wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
28158 			    uint8_t *pmkid)
28159 {}
28160 #endif
28161 /**
28162  * __wlan_hdd_cfg80211_external_auth() - Handle external auth
28163  *
28164  * @wiphy: Pointer to wireless phy
28165  * @dev: net device
28166  * @params: Pointer to external auth params.
28167  * Return: 0 on success, negative errno on failure
28168  *
28169  * Userspace sends status of the external authentication(e.g., SAE) with a peer.
28170  * The message carries BSSID of the peer and auth status (WLAN_STATUS_SUCCESS/
28171  * WLAN_STATUS_UNSPECIFIED_FAILURE) in params.
28172  * Userspace may send PMKID in params, which can be used for
28173  * further connections.
28174  */
28175 static int
__wlan_hdd_cfg80211_external_auth(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_external_auth_params * params)28176 __wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
28177 				  struct net_device *dev,
28178 				  struct cfg80211_external_auth_params *params)
28179 {
28180 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
28181 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
28182 	int ret;
28183 	mac_handle_t mac_handle;
28184 	struct qdf_mac_addr peer_mac_addr;
28185 	uint8_t pmkid[PMKID_LEN] = {0};
28186 
28187 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
28188 		hdd_err("Command not allowed in FTM mode");
28189 		return -EPERM;
28190 	}
28191 
28192 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
28193 		return -EINVAL;
28194 
28195 	ret = wlan_hdd_validate_context(hdd_ctx);
28196 	if (ret)
28197 		return ret;
28198 
28199 	hdd_debug("external_auth status: %d peer mac: " QDF_MAC_ADDR_FMT,
28200 		  params->status, QDF_MAC_ADDR_REF(params->bssid));
28201 	mac_handle = hdd_ctx->mac_handle;
28202 	qdf_mem_copy(peer_mac_addr.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
28203 
28204 	wlan_hdd_extauth_cache_pmkid(adapter, mac_handle, params);
28205 
28206 	wlan_hdd_extauth_copy_pmkid(params, pmkid);
28207 	sme_handle_sae_msg(mac_handle, adapter->deflink->vdev_id,
28208 			   params->status, peer_mac_addr, pmkid);
28209 
28210 	return ret;
28211 }
28212 
28213 /**
28214  * wlan_hdd_cfg80211_external_auth() - Handle external auth
28215  * @wiphy: Pointer to wireless phy
28216  * @dev: net device
28217  * @params: Pointer to external auth params
28218  *
28219  * Return: 0 on success, negative errno on failure
28220  */
28221 static int
wlan_hdd_cfg80211_external_auth(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_external_auth_params * params)28222 wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
28223 				struct net_device *dev,
28224 				struct cfg80211_external_auth_params *params)
28225 {
28226 	int errno;
28227 	struct osif_vdev_sync *vdev_sync;
28228 
28229 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
28230 	if (errno)
28231 		return errno;
28232 
28233 	errno = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
28234 
28235 	osif_vdev_sync_op_stop(vdev_sync);
28236 
28237 	return errno;
28238 }
28239 #endif
28240 
28241 #if defined(WLAN_FEATURE_NAN) && \
28242 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
28243 static int
wlan_hdd_cfg80211_start_nan(struct wiphy * wiphy,struct wireless_dev * wdev,struct cfg80211_nan_conf * conf)28244 wlan_hdd_cfg80211_start_nan(struct wiphy *wiphy, struct wireless_dev *wdev,
28245 			    struct cfg80211_nan_conf *conf)
28246 {
28247 	return -EOPNOTSUPP;
28248 }
28249 
28250 static void
wlan_hdd_cfg80211_stop_nan(struct wiphy * wiphy,struct wireless_dev * wdev)28251 wlan_hdd_cfg80211_stop_nan(struct wiphy *wiphy, struct wireless_dev *wdev)
28252 {
28253 }
28254 
wlan_hdd_cfg80211_add_nan_func(struct wiphy * wiphy,struct wireless_dev * wdev,struct cfg80211_nan_func * nan_func)28255 static int wlan_hdd_cfg80211_add_nan_func(struct wiphy *wiphy,
28256 					  struct wireless_dev *wdev,
28257 					  struct cfg80211_nan_func *nan_func)
28258 {
28259 	return -EOPNOTSUPP;
28260 }
28261 
wlan_hdd_cfg80211_del_nan_func(struct wiphy * wiphy,struct wireless_dev * wdev,u64 cookie)28262 static void wlan_hdd_cfg80211_del_nan_func(struct wiphy *wiphy,
28263 					   struct wireless_dev *wdev,
28264 					   u64 cookie)
28265 {
28266 }
28267 
wlan_hdd_cfg80211_nan_change_conf(struct wiphy * wiphy,struct wireless_dev * wdev,struct cfg80211_nan_conf * conf,u32 changes)28268 static int wlan_hdd_cfg80211_nan_change_conf(struct wiphy *wiphy,
28269 					     struct wireless_dev *wdev,
28270 					     struct cfg80211_nan_conf *conf,
28271 					     u32 changes)
28272 {
28273 	return -EOPNOTSUPP;
28274 }
28275 #endif
28276 
28277 /**
28278  * wlan_hdd_get_ch_width_from_chan_info - get ch_width as per num channel
28279  * present in scan event
28280  * @info: struct scan_chan_info
28281  *
28282  * Return: phy_ch_width.
28283  */
28284 static enum phy_ch_width
wlan_hdd_get_ch_width_from_chan_info(struct scan_chan_info * info)28285 wlan_hdd_get_ch_width_from_chan_info(struct scan_chan_info *info)
28286 {
28287 	enum phy_ch_width scanned_ch_width;
28288 
28289 	switch (info->subband_info.num_chan) {
28290 	case 1:
28291 		scanned_ch_width = CH_WIDTH_20MHZ;
28292 		break;
28293 	case 2:
28294 		scanned_ch_width = CH_WIDTH_40MHZ;
28295 		break;
28296 	case 4:
28297 		scanned_ch_width = CH_WIDTH_80MHZ;
28298 		break;
28299 	case 8:
28300 		scanned_ch_width = CH_WIDTH_160MHZ;
28301 		break;
28302 	default:
28303 		scanned_ch_width = CH_WIDTH_INVALID;
28304 		break;
28305 	}
28306 
28307 	return scanned_ch_width;
28308 }
28309 
28310 /**
28311  * wlan_hdd_fill_subband_scan_info - Fill subband channel info
28312  * @hdd_ctx: hdd context
28313  * @info: struct scan_chan_info
28314  * @chan: scan channel info
28315  *
28316  * update channel info into HDD context on scan done
28317  *
28318  * Return: None.
28319  */
wlan_hdd_fill_subband_scan_info(struct hdd_context * hdd_ctx,struct scan_chan_info * info,struct scan_chan_info * chan)28320 static void wlan_hdd_fill_subband_scan_info(struct hdd_context *hdd_ctx,
28321 					    struct scan_chan_info *info,
28322 					    struct scan_chan_info *chan)
28323 {
28324 	uint8_t idx, info_index, freq_info_num;
28325 	enum phy_ch_width scanned_ch_width;
28326 	const struct bonded_channel_freq *range = NULL;
28327 	qdf_freq_t start_freq, end_freq, sec_2g_freq;
28328 	uint8_t vdev_id = info->subband_info.vdev_id;
28329 	struct assoc_channel_info assoc_chan_info;
28330 
28331 	scanned_ch_width = wlan_hdd_get_ch_width_from_chan_info(info);
28332 	if (scanned_ch_width == CH_WIDTH_INVALID) {
28333 		hdd_debug("vdev %d: Invalid scanned_ch_width", vdev_id);
28334 		return;
28335 	}
28336 
28337 	if (scanned_ch_width == CH_WIDTH_20MHZ) {
28338 		start_freq = info->freq;
28339 		end_freq = info->freq;
28340 	} else if (wlan_reg_is_24ghz_ch_freq(info->freq) &&
28341 		   scanned_ch_width == CH_WIDTH_40MHZ) {
28342 		ucfg_cm_get_associated_ch_info(hdd_ctx->psoc, vdev_id,
28343 					       scanned_ch_width,
28344 					       &assoc_chan_info);
28345 		sec_2g_freq = assoc_chan_info.sec_2g_freq;
28346 		if (!sec_2g_freq) {
28347 			mlme_debug("vdev %d : Invalid sec 2g freq for freq:%d",
28348 				   info->subband_info.vdev_id, info->freq);
28349 			return;
28350 		}
28351 
28352 		hdd_debug("vdev %d :assoc freq %d sec_2g_freq:%d, bw %d",
28353 			  info->subband_info.vdev_id, info->freq,
28354 			  sec_2g_freq, scanned_ch_width);
28355 		if (info->freq > sec_2g_freq) {
28356 			start_freq = sec_2g_freq;
28357 			end_freq = info->freq;
28358 		} else {
28359 			start_freq = info->freq;
28360 			end_freq = sec_2g_freq;
28361 		}
28362 	} else {
28363 		range = wlan_reg_get_bonded_chan_entry(info->freq,
28364 						       scanned_ch_width, 0);
28365 		if (!range) {
28366 			hdd_err("vdev %d: bonded_chan_array is NULL for freq %d, ch_width %d",
28367 				vdev_id, info->freq, scanned_ch_width);
28368 			return;
28369 		}
28370 		start_freq = range->start_freq;
28371 		end_freq = range->end_freq;
28372 	}
28373 
28374 	freq_info_num = info->subband_info.num_chan;
28375 	info_index = 0;
28376 
28377 	hdd_debug("vdev %d: freq :%d bw %d, range [%d-%d], num_freq:%d",
28378 		  vdev_id, info->freq, scanned_ch_width, start_freq,
28379 		  end_freq, freq_info_num);
28380 
28381 	for (idx = 0; idx < NUM_CHANNELS; idx++) {
28382 		if (chan[idx].freq == 0)
28383 			continue;
28384 
28385 		if (start_freq > end_freq || info_index >= freq_info_num ||
28386 		    info_index >= MAX_WIDE_BAND_SCAN_CHAN)
28387 			break;
28388 
28389 		if (chan[idx].freq == start_freq) {
28390 			/*update channel info as per cca busy info */
28391 			info->freq = start_freq;
28392 			info->rx_clear_count =
28393 			   info->subband_info.cca_busy_subband_info[info_index];
28394 
28395 			hdd_update_chan_info(hdd_ctx, &chan[idx], info,
28396 					     info->cmd_flag);
28397 
28398 			hdd_debug("updated info for freq:%u rcc:%d at index:%d",
28399 				  chan[idx].freq, chan[idx].rx_clear_count,
28400 				  idx);
28401 			start_freq += BW_20_MHZ;
28402 			info_index++;
28403 		}
28404 	}
28405 }
28406 
28407 /**
28408  * wlan_hdd_chan_info_cb() - channel info callback
28409  * @info: struct scan_chan_info
28410  *
28411  * Store channel info into HDD context
28412  *
28413  * Return: None.
28414  */
wlan_hdd_chan_info_cb(struct scan_chan_info * info)28415 static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
28416 {
28417 	struct hdd_context *hdd_ctx;
28418 	struct scan_chan_info *chan;
28419 	uint8_t idx;
28420 
28421 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
28422 	if (wlan_hdd_validate_context(hdd_ctx) != 0)
28423 		return;
28424 
28425 	if (!hdd_ctx->chan_info) {
28426 		hdd_err("chan_info is NULL");
28427 		return;
28428 	}
28429 
28430 	chan = hdd_ctx->chan_info;
28431 
28432 	if (info->subband_info.is_wide_band_scan) {
28433 		wlan_hdd_fill_subband_scan_info(hdd_ctx, info, chan);
28434 		return;
28435 	}
28436 
28437 	for (idx = 0; idx < NUM_CHANNELS; idx++) {
28438 		if (chan[idx].freq == info->freq) {
28439 			hdd_update_chan_info(hdd_ctx, &chan[idx], info,
28440 				info->cmd_flag);
28441 			hdd_debug("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
28442 				  chan[idx].cmd_flag, chan[idx].freq,
28443 				  chan[idx].noise_floor,
28444 				  chan[idx].cycle_count,
28445 				  chan[idx].rx_clear_count,
28446 				  chan[idx].clock_freq, chan[idx].cmd_flag,
28447 				  chan[idx].tx_frame_count, idx);
28448 			if (chan[idx].freq == 0)
28449 				break;
28450 
28451 		}
28452 	}
28453 }
28454 
28455 /**
28456  * wlan_hdd_init_chan_info() - init chan info in hdd context
28457  * @hdd_ctx: HDD context pointer
28458  *
28459  * Return: none
28460  */
wlan_hdd_init_chan_info(struct hdd_context * hdd_ctx)28461 void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
28462 {
28463 	uint32_t num_2g, num_5g, index = 0;
28464 	mac_handle_t mac_handle;
28465 
28466 	hdd_ctx->chan_info = NULL;
28467 	if (!ucfg_scan_is_snr_monitor_enabled(hdd_ctx->psoc)) {
28468 		hdd_debug("SNR monitoring is disabled");
28469 		return;
28470 	}
28471 
28472 	hdd_ctx->chan_info =
28473 		qdf_mem_malloc(sizeof(struct scan_chan_info)
28474 					* NUM_CHANNELS);
28475 	if (!hdd_ctx->chan_info)
28476 		return;
28477 	mutex_init(&hdd_ctx->chan_info_lock);
28478 
28479 	num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
28480 	for (; index < num_2g; index++) {
28481 		hdd_ctx->chan_info[index].freq =
28482 			hdd_channels_2_4_ghz[index].center_freq;
28483 	}
28484 
28485 	num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
28486 	for (; (index - num_2g) < num_5g; index++)
28487 		hdd_ctx->chan_info[index].freq =
28488 			hdd_channels_5_ghz[index - num_2g].center_freq;
28489 
28490 	index = num_2g + num_5g;
28491 	index += wlan_hdd_populate_5dot9_chan_info(hdd_ctx, index);
28492 	index += wlan_hdd_populate_6g_chan_info(hdd_ctx, index);
28493 	hdd_debug("Number of channels populated : %d", index);
28494 
28495 	mac_handle = hdd_ctx->mac_handle;
28496 	sme_set_chan_info_callback(mac_handle, &wlan_hdd_chan_info_cb);
28497 }
28498 
28499 /**
28500  * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
28501  * @hdd_ctx: hdd context pointer
28502  *
28503  * Return: none
28504  */
wlan_hdd_deinit_chan_info(struct hdd_context * hdd_ctx)28505 void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
28506 {
28507 	struct scan_chan_info *chan;
28508 
28509 	chan = hdd_ctx->chan_info;
28510 	hdd_ctx->chan_info = NULL;
28511 	if (chan)
28512 		qdf_mem_free(chan);
28513 }
28514 
28515 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) || defined(CFG80211_11BE_BASIC)
28516 #define SET_RATE_INFO_BW_320 RATE_INFO_BW_320
28517 #else
28518 #define SET_RATE_INFO_BW_320 RATE_INFO_BW_160
28519 #endif
28520 
28521 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)28522 static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
28523 {
28524 	switch (hdd_bw) {
28525 	case HDD_RATE_BW_5:
28526 		return RATE_INFO_BW_5;
28527 	case HDD_RATE_BW_10:
28528 		return RATE_INFO_BW_10;
28529 	case HDD_RATE_BW_20:
28530 		return RATE_INFO_BW_20;
28531 	case HDD_RATE_BW_40:
28532 		return RATE_INFO_BW_40;
28533 	case HDD_RATE_BW_80:
28534 		return RATE_INFO_BW_80;
28535 	case HDD_RATE_BW_160:
28536 		return RATE_INFO_BW_160;
28537 	case HDD_RATE_BW_320:
28538 		return SET_RATE_INFO_BW_320;
28539 	}
28540 
28541 	hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
28542 
28543 	return RATE_INFO_BW_20;
28544 }
28545 
hdd_set_rate_bw(struct rate_info * info,enum hdd_rate_info_bw hdd_bw)28546 void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
28547 {
28548 	info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
28549 }
28550 #else
hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)28551 static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
28552 {
28553 	switch (hdd_bw) {
28554 	case HDD_RATE_BW_5:
28555 	case HDD_RATE_BW_10:
28556 	case HDD_RATE_BW_20:
28557 		return (enum rate_info_flags)0;
28558 	case HDD_RATE_BW_40:
28559 		return RATE_INFO_FLAGS_40_MHZ_WIDTH;
28560 	case HDD_RATE_BW_80:
28561 		return RATE_INFO_FLAGS_80_MHZ_WIDTH;
28562 	case HDD_RATE_BW_160:
28563 		return RATE_INFO_FLAGS_160_MHZ_WIDTH;
28564 	}
28565 
28566 	hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
28567 
28568 	return (enum rate_info_flags)0;
28569 }
28570 
hdd_set_rate_bw(struct rate_info * info,enum hdd_rate_info_bw hdd_bw)28571 void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
28572 {
28573 	const enum rate_info_flags all_bws =
28574 		RATE_INFO_FLAGS_40_MHZ_WIDTH |
28575 		RATE_INFO_FLAGS_80_MHZ_WIDTH |
28576 		RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
28577 		RATE_INFO_FLAGS_160_MHZ_WIDTH;
28578 
28579 	info->flags &= ~all_bws;
28580 	info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
28581 }
28582 #endif
28583 
28584 #if defined(CFG80211_EXTERNAL_DH_UPDATE_SUPPORT) || \
28585 (LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0))
28586 
28587 #ifdef WLAN_MLD_AP_OWE_INFO_SUPPORT
28588 static void
hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter * adapter,struct cfg80211_update_owe_info * owe_info,uint8_t * peer_mac)28589 hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter *adapter,
28590 			    struct cfg80211_update_owe_info *owe_info,
28591 			    uint8_t *peer_mac)
28592 {
28593 	bool is_mlo_vdev;
28594 	struct wlan_objmgr_peer *peer;
28595 	struct wlan_objmgr_vdev *vdev;
28596 	uint8_t *peer_mld_addr;
28597 
28598 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
28599 	if (!vdev)
28600 		return;
28601 
28602 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
28603 	if (is_mlo_vdev)
28604 		owe_info->link_id = wlan_vdev_get_link_id(vdev);
28605 	else
28606 		owe_info->link_id = -1;
28607 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
28608 
28609 	if (!is_mlo_vdev)
28610 		return;
28611 
28612 	peer = wlan_objmgr_get_peer_by_mac(adapter->hdd_ctx->psoc,
28613 					   peer_mac, WLAN_OSIF_ID);
28614 	if (!peer) {
28615 		hdd_err("Peer not found with MAC " QDF_MAC_ADDR_FMT,
28616 			QDF_MAC_ADDR_REF(peer_mac));
28617 		return;
28618 	}
28619 
28620 	peer_mld_addr = wlan_peer_mlme_get_mldaddr(peer);
28621 	qdf_mem_copy(&owe_info->peer_mld_addr[0], peer_mld_addr, ETH_ALEN);
28622 	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
28623 }
28624 #elif defined(CFG80211_MLD_AP_STA_CONNECT_UPSTREAM_SUPPORT)
28625 static void
hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter * adapter,struct cfg80211_update_owe_info * owe_info,uint8_t * peer_mac)28626 hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter *adapter,
28627 			    struct cfg80211_update_owe_info *owe_info,
28628 			    uint8_t *peer_mac)
28629 {
28630 	bool is_mlo_vdev;
28631 	struct wlan_objmgr_peer *peer;
28632 	struct wlan_objmgr_vdev *vdev;
28633 	uint8_t *peer_mld_addr;
28634 
28635 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
28636 					   WLAN_HDD_ID_OBJ_MGR);
28637 	if (!vdev)
28638 		return;
28639 
28640 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
28641 	if (!is_mlo_vdev) {
28642 		owe_info->assoc_link_id = -1;
28643 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
28644 		return;
28645 	}
28646 
28647 	owe_info->assoc_link_id = wlan_vdev_get_link_id(vdev);
28648 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
28649 
28650 	peer = wlan_objmgr_get_peer_by_mac(adapter->hdd_ctx->psoc,
28651 					   peer_mac, WLAN_HDD_ID_OBJ_MGR);
28652 	if (!peer) {
28653 		hdd_err("Peer not found with MAC " QDF_MAC_ADDR_FMT,
28654 			QDF_MAC_ADDR_REF(peer_mac));
28655 		return;
28656 	}
28657 
28658 	peer_mld_addr = wlan_peer_mlme_get_mldaddr(peer);
28659 	qdf_mem_copy(&owe_info->peer_mld_addr[0], peer_mld_addr, ETH_ALEN);
28660 	wlan_objmgr_peer_release_ref(peer, WLAN_HDD_ID_OBJ_MGR);
28661 }
28662 #else
28663 static void
hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter * adapter,struct cfg80211_update_owe_info * owe_info,uint8_t * peer_mac)28664 hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter *adapter,
28665 			    struct cfg80211_update_owe_info *owe_info,
28666 			    uint8_t *peer_mac)
28667 {
28668 }
28669 #endif
28670 
hdd_send_update_owe_info_event(struct hdd_adapter * adapter,uint8_t sta_addr[],uint8_t * owe_ie,uint32_t owe_ie_len)28671 void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
28672 				    uint8_t sta_addr[],
28673 				    uint8_t *owe_ie,
28674 				    uint32_t owe_ie_len)
28675 {
28676 	struct cfg80211_update_owe_info owe_info;
28677 	struct net_device *dev = adapter->dev;
28678 
28679 	hdd_enter_dev(dev);
28680 
28681 	qdf_mem_zero(&owe_info, sizeof(owe_info));
28682 	qdf_mem_copy(owe_info.peer, sta_addr, ETH_ALEN);
28683 	hdd_ml_sap_owe_fill_ml_info(adapter, &owe_info, sta_addr);
28684 	owe_info.ie = owe_ie;
28685 	owe_info.ie_len = owe_ie_len;
28686 
28687 	cfg80211_update_owe_info_event(dev, &owe_info, GFP_KERNEL);
28688 
28689 	hdd_exit();
28690 }
28691 #endif
28692 
28693 #define MAX_PDEV_TXRX_PARAMS 2
28694 /* params being sent:
28695  * 1.wmi_pdev_param_tx_chain_mask
28696  * 2.wmi_pdev_param_rx_chain_mask
28697  */
__wlan_hdd_cfg80211_set_chainmask(struct wiphy * wiphy,uint32_t tx_mask,uint32_t rx_mask)28698 static int __wlan_hdd_cfg80211_set_chainmask(struct wiphy *wiphy,
28699 					     uint32_t tx_mask,
28700 					     uint32_t rx_mask)
28701 {
28702 	int ret;
28703 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
28704 	enum hdd_chain_mode chains;
28705 	struct dev_set_param setparam[MAX_PDEV_TXRX_PARAMS] = {};
28706 	uint8_t index = 0;
28707 	uint8_t ll_lt_sap_vdev_id;
28708 
28709 	ret = wlan_hdd_validate_context(hdd_ctx);
28710 	if (ret)
28711 		return -EINVAL;
28712 
28713 	if (hdd_ctx->num_rf_chains != HDD_ANTENNA_MODE_2X2 ||
28714 	    !ucfg_mlme_is_chain_mask_supported(hdd_ctx->psoc)) {
28715 		hdd_info_rl("Chainmask can't be configured, num of rf chain %d",
28716 			    hdd_ctx->num_rf_chains);
28717 		return -ENOTSUPP;
28718 	}
28719 	chains = HDD_CHAIN_MODE_2X2;
28720 	if (!tx_mask || tx_mask > chains || !rx_mask || rx_mask > chains) {
28721 		hdd_err_rl("Invalid masks. txMask: %d rxMask: %d num_rf_chains: %d",
28722 			   tx_mask, rx_mask, hdd_ctx->num_rf_chains);
28723 
28724 		return -EINVAL;
28725 	}
28726 
28727 	ll_lt_sap_vdev_id =
28728 			wlan_policy_mgr_get_ll_lt_sap_vdev_id(hdd_ctx->psoc);
28729 	if (ll_lt_sap_vdev_id != WLAN_INVALID_VDEV_ID) {
28730 		hdd_info_rl("LL_LT_SAP vdev %d present, chainmask config not allowed",
28731 			    ll_lt_sap_vdev_id);
28732 		return -ENOTSUPP;
28733 	}
28734 
28735 	if (sme_validate_txrx_chain_mask(wmi_pdev_param_tx_chain_mask, tx_mask))
28736 		return -EINVAL;
28737 
28738 	ret = mlme_check_index_setparam(
28739 				setparam, wmi_pdev_param_tx_chain_mask,
28740 				tx_mask, index++, MAX_PDEV_TXRX_PARAMS);
28741 	if (QDF_IS_STATUS_ERROR(ret)) {
28742 		hdd_err("failed at wmi_pdev_param_tx_chain_mask");
28743 		return -EINVAL;
28744 	}
28745 
28746 	if (sme_validate_txrx_chain_mask(wmi_pdev_param_rx_chain_mask, rx_mask))
28747 		return -EINVAL;
28748 
28749 	ret = mlme_check_index_setparam(
28750 				setparam, wmi_pdev_param_rx_chain_mask,
28751 				rx_mask, index++, MAX_PDEV_TXRX_PARAMS);
28752 	if (QDF_IS_STATUS_ERROR(ret)) {
28753 		hdd_err("failed at wmi_pdev_param_rx_chain_mask");
28754 		return -EINVAL;
28755 	}
28756 
28757 	ret = wma_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
28758 						  WMI_PDEV_ID_SOC, setparam,
28759 						  index);
28760 	if (QDF_IS_STATUS_ERROR(ret))
28761 		hdd_err("failed to send TX, RX chain mask params");
28762 
28763 	return ret;
28764 }
28765 
wlan_hdd_cfg80211_set_chainmask(struct wiphy * wiphy,uint32_t tx_mask,uint32_t rx_mask)28766 static int wlan_hdd_cfg80211_set_chainmask(struct wiphy *wiphy,
28767 					   uint32_t tx_mask,
28768 					   uint32_t rx_mask)
28769 {
28770 	struct osif_psoc_sync *psoc_sync;
28771 	int errno;
28772 
28773 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
28774 	if (errno)
28775 		return errno;
28776 
28777 	errno = __wlan_hdd_cfg80211_set_chainmask(wiphy, tx_mask, rx_mask);
28778 	osif_psoc_sync_op_stop(psoc_sync);
28779 
28780 	return errno;
28781 }
28782 
__wlan_hdd_cfg80211_get_chainmask(struct wiphy * wiphy,uint32_t * tx_mask,uint32_t * rx_mask)28783 static int __wlan_hdd_cfg80211_get_chainmask(struct wiphy *wiphy,
28784 					     uint32_t *tx_mask,
28785 					     uint32_t *rx_mask)
28786 
28787 {
28788 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
28789 	int ret;
28790 
28791 	ret = wlan_hdd_validate_context(hdd_ctx);
28792 	if (ret)
28793 		return -EINVAL;
28794 
28795 	*tx_mask = wma_cli_get_command(0, wmi_pdev_param_tx_chain_mask,
28796 				       PDEV_CMD);
28797 	*rx_mask = wma_cli_get_command(0, wmi_pdev_param_rx_chain_mask,
28798 				       PDEV_CMD);
28799 
28800 	/* if 0 return max value as 0 mean no set cmnd received yet */
28801 	if (!*tx_mask)
28802 		*tx_mask = hdd_ctx->num_rf_chains == HDD_ANTENNA_MODE_2X2 ?
28803 				HDD_CHAIN_MODE_2X2 : HDD_CHAIN_MODE_1X1;
28804 	if (!*rx_mask)
28805 		*rx_mask = hdd_ctx->num_rf_chains == HDD_ANTENNA_MODE_2X2 ?
28806 				HDD_CHAIN_MODE_2X2 : HDD_CHAIN_MODE_1X1;
28807 	hdd_debug("tx_mask: %d rx_mask: %d", *tx_mask, *rx_mask);
28808 
28809 	return 0;
28810 }
28811 
wlan_hdd_cfg80211_get_chainmask(struct wiphy * wiphy,uint32_t * tx_mask,uint32_t * rx_mask)28812 static int wlan_hdd_cfg80211_get_chainmask(struct wiphy *wiphy,
28813 					   uint32_t *tx_mask,
28814 					   uint32_t *rx_mask)
28815 {
28816 	struct osif_psoc_sync *psoc_sync;
28817 	int errno;
28818 
28819 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
28820 	if (errno)
28821 		return errno;
28822 
28823 	errno = __wlan_hdd_cfg80211_get_chainmask(wiphy, tx_mask, rx_mask);
28824 	osif_psoc_sync_op_stop(psoc_sync);
28825 
28826 	return errno;
28827 }
28828 
28829 enum qca_wlan_802_11_mode
hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode)28830 hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode)
28831 {
28832 	switch (mode) {
28833 	case eCSR_CFG_DOT11_MODE_11A:
28834 		return QCA_WLAN_802_11_MODE_11A;
28835 	case eCSR_CFG_DOT11_MODE_11B:
28836 		return QCA_WLAN_802_11_MODE_11B;
28837 	case eCSR_CFG_DOT11_MODE_11G:
28838 		return QCA_WLAN_802_11_MODE_11G;
28839 	case eCSR_CFG_DOT11_MODE_11N:
28840 		return QCA_WLAN_802_11_MODE_11N;
28841 	case eCSR_CFG_DOT11_MODE_11AC:
28842 		return QCA_WLAN_802_11_MODE_11AC;
28843 	case eCSR_CFG_DOT11_MODE_11G_ONLY:
28844 		return QCA_WLAN_802_11_MODE_11G;
28845 	case eCSR_CFG_DOT11_MODE_11N_ONLY:
28846 		return QCA_WLAN_802_11_MODE_11N;
28847 	case eCSR_CFG_DOT11_MODE_11AC_ONLY:
28848 		return QCA_WLAN_802_11_MODE_11AC;
28849 	case eCSR_CFG_DOT11_MODE_11AX:
28850 		return QCA_WLAN_802_11_MODE_11AX;
28851 	case eCSR_CFG_DOT11_MODE_11AX_ONLY:
28852 		return QCA_WLAN_802_11_MODE_11AX;
28853 	case eCSR_CFG_DOT11_MODE_11BE:
28854 	case eCSR_CFG_DOT11_MODE_11BE_ONLY:
28855 		return QCA_WLAN_802_11_MODE_11BE;
28856 	case eCSR_CFG_DOT11_MODE_ABG:
28857 	case eCSR_CFG_DOT11_MODE_AUTO:
28858 	default:
28859 		return QCA_WLAN_802_11_MODE_INVALID;
28860 	}
28861 }
28862 
28863 enum qca_wlan_802_11_mode
hdd_convert_phymode_to_80211mode(eCsrPhyMode mode)28864 hdd_convert_phymode_to_80211mode(eCsrPhyMode mode)
28865 {
28866 	switch (mode) {
28867 	case eCSR_DOT11_MODE_11a:
28868 		return QCA_WLAN_802_11_MODE_11A;
28869 	case eCSR_DOT11_MODE_11b:
28870 		return QCA_WLAN_802_11_MODE_11B;
28871 	case eCSR_DOT11_MODE_11g:
28872 	case eCSR_DOT11_MODE_11g_ONLY:
28873 		return QCA_WLAN_802_11_MODE_11G;
28874 	case eCSR_DOT11_MODE_11n:
28875 	case eCSR_DOT11_MODE_11n_ONLY:
28876 		return QCA_WLAN_802_11_MODE_11N;
28877 	case eCSR_DOT11_MODE_11ac:
28878 	case eCSR_DOT11_MODE_11ac_ONLY:
28879 		return QCA_WLAN_802_11_MODE_11AC;
28880 	case eCSR_DOT11_MODE_11ax:
28881 	case eCSR_DOT11_MODE_11ax_ONLY:
28882 		return QCA_WLAN_802_11_MODE_11AX;
28883 	case eCSR_DOT11_MODE_11be:
28884 	case eCSR_DOT11_MODE_11be_ONLY:
28885 		return QCA_WLAN_802_11_MODE_11BE;
28886 	case eCSR_DOT11_MODE_abg:
28887 	case eCSR_DOT11_MODE_AUTO:
28888 	default:
28889 		return QCA_WLAN_802_11_MODE_INVALID;
28890 	}
28891 }
28892 
hdd_is_legacy_connection(struct wlan_hdd_link_info * link_info)28893 bool hdd_is_legacy_connection(struct wlan_hdd_link_info *link_info)
28894 {
28895 	struct hdd_station_ctx *sta_ctx;
28896 	int connection_mode = QCA_WLAN_802_11_MODE_INVALID;
28897 	enum csr_cfgdot11mode cfgmode;
28898 	uint16_t tdls_connected_peer;
28899 
28900 	tdls_connected_peer = hdd_get_tdls_connected_peer_count(link_info);
28901 	if (tdls_connected_peer)
28902 		return false;
28903 
28904 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
28905 	cfgmode = sta_ctx->conn_info.dot11mode;
28906 	connection_mode = hdd_convert_cfgdot11mode_to_80211mode(cfgmode);
28907 	if (connection_mode == QCA_WLAN_802_11_MODE_11A ||
28908 	    connection_mode == QCA_WLAN_802_11_MODE_11B ||
28909 	    connection_mode == QCA_WLAN_802_11_MODE_11G)
28910 		return true;
28911 	else
28912 		return false;
28913 }
28914 
28915 static void
wlan_hdd_update_chandef(struct cfg80211_chan_def * chandef,enum phy_ch_width ch_width,uint32_t ch_cfreq2,bool is_legacy_phymode)28916 wlan_hdd_update_chandef(struct cfg80211_chan_def *chandef,
28917 			enum phy_ch_width ch_width, uint32_t ch_cfreq2,
28918 			bool is_legacy_phymode)
28919 {
28920 	switch (ch_width) {
28921 	case CH_WIDTH_20MHZ:
28922 		if (is_legacy_phymode)
28923 			chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
28924 		else
28925 			chandef->width = NL80211_CHAN_WIDTH_20;
28926 		break;
28927 	case CH_WIDTH_40MHZ:
28928 		chandef->width = NL80211_CHAN_WIDTH_40;
28929 		break;
28930 	case CH_WIDTH_80MHZ:
28931 		chandef->width = NL80211_CHAN_WIDTH_80;
28932 		break;
28933 	case CH_WIDTH_160MHZ:
28934 		chandef->width = NL80211_CHAN_WIDTH_160;
28935 		/* Set center_freq1 to center frequency of complete 160MHz */
28936 		chandef->center_freq1 = ch_cfreq2;
28937 		break;
28938 	case CH_WIDTH_80P80MHZ:
28939 		chandef->width = NL80211_CHAN_WIDTH_80P80;
28940 		chandef->center_freq2 = ch_cfreq2;
28941 		break;
28942 	case CH_WIDTH_5MHZ:
28943 		chandef->width = NL80211_CHAN_WIDTH_5;
28944 		break;
28945 	case CH_WIDTH_10MHZ:
28946 		chandef->width = NL80211_CHAN_WIDTH_10;
28947 		break;
28948 	default:
28949 		chandef->width = NL80211_CHAN_WIDTH_20;
28950 		break;
28951 	}
28952 }
28953 
28954 static int
wlan_hdd_cfg80211_get_channel_sap(struct wiphy * wiphy,struct cfg80211_chan_def * chandef,struct hdd_adapter * adapter,int link_id)28955 wlan_hdd_cfg80211_get_channel_sap(struct wiphy *wiphy,
28956 				  struct cfg80211_chan_def *chandef,
28957 				  struct hdd_adapter *adapter, int link_id)
28958 {
28959 	struct hdd_ap_ctx *ap_ctx;
28960 	struct wlan_objmgr_vdev *vdev;
28961 	bool is_legacy_phymode = false;
28962 	uint32_t chan_freq;
28963 	struct wlan_channel *des_chan;
28964 
28965 	if (!test_bit(SOFTAP_BSS_STARTED, &adapter->deflink->link_flags))
28966 		return -EINVAL;
28967 
28968 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
28969 	switch (ap_ctx->sap_config.SapHw_mode) {
28970 	case eCSR_DOT11_MODE_11n:
28971 	case eCSR_DOT11_MODE_11n_ONLY:
28972 	case eCSR_DOT11_MODE_11ac:
28973 	case eCSR_DOT11_MODE_11ac_ONLY:
28974 	case eCSR_DOT11_MODE_11ax:
28975 	case eCSR_DOT11_MODE_11ax_ONLY:
28976 		is_legacy_phymode = false;
28977 		break;
28978 	default:
28979 		is_legacy_phymode = true;
28980 		break;
28981 	}
28982 
28983 	vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
28984 	if (!vdev)
28985 		return -EINVAL;
28986 
28987 	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
28988 	chan_freq = des_chan->ch_freq;
28989 	chandef->center_freq1 = des_chan->ch_cfreq1;
28990 	chandef->center_freq2 = 0;
28991 	chandef->chan = ieee80211_get_channel(wiphy, chan_freq);
28992 
28993 	wlan_hdd_update_chandef(chandef, des_chan->ch_width,
28994 				des_chan->ch_cfreq2, is_legacy_phymode);
28995 
28996 	wlan_hdd_set_chandef_for_11be(chandef, des_chan);
28997 
28998 	wlan_key_put_link_vdev(vdev, WLAN_OSIF_ID);
28999 
29000 	hdd_debug("vdev: %d, freq:%d, ch_width:%d, c_freq1:%d, c_freq2:%d",
29001 		  wlan_vdev_get_id(vdev), chan_freq, chandef->width,
29002 		  chandef->center_freq1, chandef->center_freq2);
29003 	return 0;
29004 }
29005 
hdd_get_sec_2ghz_freq(qdf_freq_t freq,enum phy_ch_width ch_width,qdf_freq_t freq_seg_1)29006 static qdf_freq_t hdd_get_sec_2ghz_freq(qdf_freq_t freq,
29007 					enum phy_ch_width ch_width,
29008 					qdf_freq_t freq_seg_1)
29009 {
29010 	/*
29011 	 * In case of 2.4 GHz + 40 MHz, use the secondary channel
29012 	 * to determine the exact ccfs1
29013 	 */
29014 	if (wlan_reg_is_24ghz_ch_freq(freq) && ch_width == CH_WIDTH_40MHZ) {
29015 		if (freq < freq_seg_1)
29016 			return freq + HT40_SEC_OFFSET;
29017 		else
29018 			return freq - HT40_SEC_OFFSET;
29019 	}
29020 
29021 	return 0;
29022 }
29023 
wlan_hdd_cfg80211_get_vdev_chan_info(struct hdd_context * hdd_ctx,struct wlan_objmgr_vdev * vdev,int link_id,struct wlan_channel * chan_info)29024 static int wlan_hdd_cfg80211_get_vdev_chan_info(struct hdd_context *hdd_ctx,
29025 						struct wlan_objmgr_vdev *vdev,
29026 						int link_id,
29027 						struct wlan_channel *chan_info)
29028 {
29029 	struct hdd_station_ctx *sta_ctx = NULL;
29030 	struct ch_params ch_params = {0};
29031 	struct wlan_hdd_link_info *link_info;
29032 	enum wlan_phymode peer_phymode;
29033 	uint8_t vdev_id;
29034 	struct wlan_channel *des_chan;
29035 	qdf_freq_t sec_2g_freq = 0;
29036 
29037 	vdev_id = wlan_vdev_get_id(vdev);
29038 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
29039 	if (!link_info) {
29040 		hdd_debug("link_info is null");
29041 		return -EBUSY;
29042 	}
29043 
29044 	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
29045 	chan_info->ch_freq = des_chan->ch_freq;
29046 	chan_info->ch_cfreq1 = des_chan->ch_cfreq1;
29047 	chan_info->ch_cfreq2 = des_chan->ch_cfreq2;
29048 	chan_info->ch_width = des_chan->ch_width;
29049 
29050 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
29051 	/* For STA/P2P CLI get the peer pymode as, in some IOT
29052 	 * cases VDEV BW will not be same as peer BW
29053 	 */
29054 	mlme_get_peer_phymode(hdd_ctx->psoc, sta_ctx->conn_info.bssid.bytes,
29055 			      &peer_phymode);
29056 	chan_info->ch_width =
29057 			wlan_mlme_get_ch_width_from_phymode(peer_phymode);
29058 	ch_params.ch_width = chan_info->ch_width;
29059 
29060 	sec_2g_freq = hdd_get_sec_2ghz_freq(chan_info->ch_freq,
29061 					    chan_info->ch_width,
29062 					    chan_info->ch_cfreq1);
29063 
29064 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
29065 						chan_info->ch_freq, sec_2g_freq,
29066 						&ch_params,
29067 						REG_CURRENT_PWR_MODE);
29068 
29069 	if (chan_info->ch_cfreq1 != ch_params.mhz_freq_seg0 ||
29070 	    chan_info->ch_cfreq2 != ch_params.mhz_freq_seg1)
29071 		hdd_debug("Old ccfs1 %d ccfs2 %d - New ccfs1 %d ccfs2 %d",
29072 			  chan_info->ch_cfreq1, chan_info->ch_cfreq2,
29073 			  ch_params.mhz_freq_seg0, ch_params.mhz_freq_seg1);
29074 
29075 	chan_info->ch_cfreq1 = ch_params.mhz_freq_seg0;
29076 	chan_info->ch_cfreq2 = ch_params.mhz_freq_seg1;
29077 
29078 	hdd_debug("vdev: %d, freq: %d, freq1: %d, freq2: %d, ch_width: %d, max_ch_width:%d",
29079 		  vdev_id, chan_info->ch_freq, chan_info->ch_cfreq1,
29080 		  chan_info->ch_cfreq2, chan_info->ch_width,
29081 		  ch_params.ch_width);
29082 
29083 	return 0;
29084 }
29085 
29086 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
29087 static int
wlan_hdd_get_standby_link_chan_info(struct hdd_adapter * adapter,int link_id,struct wlan_channel * chan_info)29088 wlan_hdd_get_standby_link_chan_info(struct hdd_adapter *adapter, int link_id,
29089 				    struct wlan_channel *chan_info)
29090 {
29091 	struct wlan_objmgr_vdev *vdev;
29092 	int ret;
29093 
29094 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
29095 	if (!vdev)
29096 		return -EINVAL;
29097 
29098 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
29099 		hdd_debug("not a mlo vdev");
29100 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
29101 		return -EINVAL;
29102 	}
29103 
29104 	ret = mlo_mgr_get_per_link_chan_info(vdev, link_id, chan_info);
29105 
29106 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
29107 
29108 	return ret;
29109 }
29110 #else
29111 static inline int
wlan_hdd_get_standby_link_chan_info(struct hdd_adapter * adapter,int link_id,struct wlan_channel * chan_info)29112 wlan_hdd_get_standby_link_chan_info(struct hdd_adapter *adapter, int link_id,
29113 				    struct wlan_channel *chan_info)
29114 {
29115 	return -EINVAL;
29116 }
29117 #endif
29118 
29119 static int
wlan_hdd_cfg80211_get_channel_sta(struct wiphy * wiphy,struct cfg80211_chan_def * chandef,struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,int link_id)29120 wlan_hdd_cfg80211_get_channel_sta(struct wiphy *wiphy,
29121 				  struct cfg80211_chan_def *chandef,
29122 				  struct hdd_context *hdd_ctx,
29123 				  struct hdd_adapter *adapter, int link_id)
29124 {
29125 	struct hdd_station_ctx *sta_ctx = NULL;
29126 	struct wlan_objmgr_vdev *link_vdev;
29127 	bool is_legacy_phymode = false;
29128 	struct wlan_channel chan_info;
29129 	int ret = 0;
29130 	struct ch_params ch_params = {0};
29131 	qdf_freq_t sec_2g_freq = 0;
29132 
29133 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
29134 		hdd_debug("vdev not associated");
29135 		return -EINVAL;
29136 	}
29137 
29138 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
29139 	if (sta_ctx->conn_info.dot11mode < eCSR_CFG_DOT11_MODE_11N)
29140 		is_legacy_phymode = true;
29141 
29142 	link_vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
29143 	if (!link_vdev) {
29144 		/* request is for standby link */
29145 		ret =  wlan_hdd_get_standby_link_chan_info(adapter, link_id,
29146 							   &chan_info);
29147 		if (ret)
29148 			return ret;
29149 
29150 		ch_params.ch_width = chan_info.ch_width;
29151 		ch_params.center_freq_seg1 = chan_info.ch_cfreq2;
29152 		sec_2g_freq = hdd_get_sec_2ghz_freq(chan_info.ch_freq,
29153 						    chan_info.ch_width,
29154 						    chan_info.ch_cfreq1);
29155 
29156 		wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
29157 							chan_info.ch_freq,
29158 							sec_2g_freq,
29159 							&ch_params,
29160 							REG_CURRENT_PWR_MODE);
29161 		chan_info.ch_cfreq1 = ch_params.mhz_freq_seg0;
29162 		chan_info.ch_cfreq2 = ch_params.mhz_freq_seg1;
29163 		hdd_debug("max allowed ch_width:%d, ap ch_width: %d",
29164 			  ch_params.ch_width, chan_info.ch_width);
29165 		/*
29166 		 * To take care scenarios when AP channel width and max
29167 		 * supported ch_width for connection in STA may different.
29168 		 * For example, a case where AP advertise beacon/probe response
29169 		 * in 320 MHz and STA (configured with country code = KR)
29170 		 * supports max ch_width 160 MHz.
29171 		 */
29172 		if (ch_params.ch_width < chan_info.ch_width)
29173 			chan_info.ch_width = ch_params.ch_width;
29174 	} else {
29175 		ret = wlan_hdd_cfg80211_get_vdev_chan_info(hdd_ctx, link_vdev,
29176 							   link_id, &chan_info);
29177 		wlan_key_put_link_vdev(link_vdev, WLAN_OSIF_ID);
29178 		if (ret)
29179 			return ret;
29180 	}
29181 
29182 	chandef->chan = ieee80211_get_channel(wiphy, chan_info.ch_freq);
29183 	chandef->center_freq1 = chan_info.ch_cfreq1;
29184 	chandef->center_freq2 = 0;
29185 
29186 	wlan_hdd_update_chandef(chandef, chan_info.ch_width,
29187 				chan_info.ch_cfreq2, is_legacy_phymode);
29188 
29189 	wlan_hdd_set_chandef_for_11be(chandef, &chan_info);
29190 
29191 	hdd_debug("freq:%d, ch_width:%d, c_freq1:%d, c_freq2:%d",
29192 		  chan_info.ch_freq, chandef->width, chandef->center_freq1,
29193 		  chandef->center_freq2);
29194 
29195 	return ret;
29196 }
29197 
__wlan_hdd_cfg80211_get_channel(struct wiphy * wiphy,struct wireless_dev * wdev,struct cfg80211_chan_def * chandef,int link_id)29198 static int __wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
29199 					   struct wireless_dev *wdev,
29200 					   struct cfg80211_chan_def *chandef,
29201 					   int link_id)
29202 {
29203 	struct net_device *dev = wdev->netdev;
29204 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
29205 	struct hdd_context *hdd_ctx;
29206 	int ret = 0;
29207 
29208 	if (hdd_validate_adapter(adapter))
29209 		return -EINVAL;
29210 
29211 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
29212 	if (wlan_hdd_validate_context(hdd_ctx))
29213 		return -EINVAL;
29214 
29215 	hdd_debug("get channel for link id: %d, device mode: %d", link_id,
29216 		  adapter->device_mode);
29217 
29218 	switch (adapter->device_mode) {
29219 	case QDF_SAP_MODE:
29220 	case QDF_P2P_GO_MODE:
29221 		ret = wlan_hdd_cfg80211_get_channel_sap(wiphy, chandef,
29222 							adapter, link_id);
29223 		break;
29224 	case QDF_STA_MODE:
29225 	case QDF_P2P_CLIENT_MODE:
29226 		ret = wlan_hdd_cfg80211_get_channel_sta(wiphy, chandef, hdd_ctx,
29227 							adapter, link_id);
29228 		break;
29229 	default:
29230 		return -EINVAL;
29231 	}
29232 
29233 	return ret;
29234 }
29235 
29236 /**
29237  * wlan_hdd_cfg80211_get_channel() - API to process cfg80211 get_channel request
29238  * @wiphy: Pointer to wiphy
29239  * @wdev: Pointer to wireless device
29240  * @link_id: Channel link ID
29241  * @chandef: Pointer to channel definition
29242  *
29243  * Return: 0 for success, non zero for failure
29244  */
29245 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
wlan_hdd_cfg80211_get_channel(struct wiphy * wiphy,struct wireless_dev * wdev,unsigned int link_id,struct cfg80211_chan_def * chandef)29246 static int wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
29247 					 struct wireless_dev *wdev,
29248 					 unsigned int link_id,
29249 					 struct cfg80211_chan_def *chandef)
29250 {
29251 	int errno;
29252 	struct osif_vdev_sync *vdev_sync;
29253 
29254 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
29255 	if (errno)
29256 		return errno;
29257 
29258 	errno = __wlan_hdd_cfg80211_get_channel(wiphy, wdev, chandef, link_id);
29259 
29260 	osif_vdev_sync_op_stop(vdev_sync);
29261 
29262 	return errno;
29263 }
29264 #else
wlan_hdd_cfg80211_get_channel(struct wiphy * wiphy,struct wireless_dev * wdev,struct cfg80211_chan_def * chandef)29265 static int wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
29266 					 struct wireless_dev *wdev,
29267 					 struct cfg80211_chan_def *chandef)
29268 {
29269 	int errno;
29270 	struct osif_vdev_sync *vdev_sync;
29271 	/* Legacy purposes */
29272 	int link_id = -1;
29273 
29274 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
29275 	if (errno)
29276 		return errno;
29277 
29278 	errno = __wlan_hdd_cfg80211_get_channel(wiphy, wdev, chandef, link_id);
29279 
29280 	osif_vdev_sync_op_stop(vdev_sync);
29281 
29282 	return errno;
29283 }
29284 #endif
29285 
29286 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
29287 static int
hdd_check_he_bitmask_for_single_rate(enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)29288 hdd_check_he_bitmask_for_single_rate(enum nl80211_band band,
29289 				     const struct cfg80211_bitrate_mask *mask)
29290 {
29291 	int he_rates = 0, i;
29292 
29293 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].he_mcs); i++)
29294 		he_rates += qdf_get_hweight16(mask->control[band].he_mcs[i]);
29295 
29296 	return he_rates;
29297 }
29298 
29299 static void
hdd_get_he_bitrate_params_for_band(enum nl80211_band band,const struct cfg80211_bitrate_mask * mask,uint8_t * nss,uint8_t * rate_index,int * bit_rate)29300 hdd_get_he_bitrate_params_for_band(enum nl80211_band band,
29301 				   const struct cfg80211_bitrate_mask *mask,
29302 				   uint8_t *nss, uint8_t *rate_index,
29303 				   int *bit_rate)
29304 {
29305 	int i;
29306 
29307 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].he_mcs); i++) {
29308 		if (qdf_get_hweight16(mask->control[band].he_mcs[i]) == 1) {
29309 			*nss = i;
29310 			*rate_index = (ffs(mask->control[band].he_mcs[i]) - 1);
29311 			*bit_rate = hdd_assemble_rate_code(WMI_RATE_PREAMBLE_HE,
29312 							   *nss, *rate_index);
29313 			break;
29314 		}
29315 	}
29316 }
29317 #else
29318 static inline int
hdd_check_he_bitmask_for_single_rate(enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)29319 hdd_check_he_bitmask_for_single_rate(enum nl80211_band band,
29320 				     const struct cfg80211_bitrate_mask *mask)
29321 {
29322 	return 0;
29323 }
29324 
29325 static inline void
hdd_get_he_bitrate_params_for_band(enum nl80211_band band,const struct cfg80211_bitrate_mask * mask,uint8_t * nss,uint8_t * rate_index,int * bit_rate)29326 hdd_get_he_bitrate_params_for_band(enum nl80211_band band,
29327 				   const struct cfg80211_bitrate_mask *mask,
29328 				   uint8_t *nss, uint8_t *rate_index,
29329 				   int *bit_rate)
29330 
29331 {
29332 }
29333 #endif
29334 
hdd_check_bitmask_for_single_rate(enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)29335 static bool hdd_check_bitmask_for_single_rate(enum nl80211_band band,
29336 				const struct cfg80211_bitrate_mask *mask)
29337 {
29338 	int num_rates = 0, i;
29339 
29340 	num_rates += qdf_get_hweight32(mask->control[band].legacy);
29341 
29342 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].ht_mcs); i++)
29343 		num_rates += qdf_get_hweight8(mask->control[band].ht_mcs[i]);
29344 
29345 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].vht_mcs); i++)
29346 		num_rates += qdf_get_hweight16(mask->control[band].vht_mcs[i]);
29347 
29348 	num_rates += hdd_check_he_bitmask_for_single_rate(band, mask);
29349 
29350 	return num_rates ? true : false;
29351 }
29352 
__wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy * wiphy,struct net_device * dev,const u8 * peer,const struct cfg80211_bitrate_mask * mask)29353 static int __wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
29354 						struct net_device *dev,
29355 						const u8 *peer,
29356 				       const struct cfg80211_bitrate_mask *mask)
29357 {
29358 	enum nl80211_band band;
29359 	int errno;
29360 	struct hdd_adapter *adapter = netdev_priv(dev);
29361 	uint8_t nss, i;
29362 	int bit_rate = -1;
29363 	uint8_t rate_index;
29364 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
29365 	uint8_t vdev_id;
29366 	u8 gi_val = 0;
29367 #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
29368 	uint8_t auto_rate_he_gi = 0;
29369 #endif
29370 
29371 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
29372 	    QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
29373 		hdd_err("Command not allowed in mode");
29374 		return -EINVAL;
29375 	}
29376 
29377 	errno = hdd_validate_adapter(adapter);
29378 	if (errno)
29379 		return errno;
29380 
29381 	errno = wlan_hdd_validate_context(hdd_ctx);
29382 	if (errno)
29383 		return errno;
29384 
29385 	vdev_id = adapter->deflink->vdev_id;
29386 
29387 	for (band = NL80211_BAND_2GHZ; band <= NL80211_BAND_5GHZ; band++) {
29388 		/* Support configuring only one bitrate */
29389 		if (!hdd_check_bitmask_for_single_rate(band, mask)) {
29390 			hdd_err("Multiple bitrate set not supported for band %u",
29391 				band);
29392 			errno = -EINVAL;
29393 			continue;
29394 		}
29395 
29396 		if (!qdf_get_hweight32(mask->control[band].legacy)) {
29397 			hdd_err("Legacy bit rate setting not supported for band %u",
29398 				band);
29399 			errno = -EINVAL;
29400 			continue;
29401 		}
29402 
29403 		for (i = 0;
29404 			i < QDF_ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
29405 			if (qdf_get_hweight8(mask->control[band].ht_mcs[i])
29406 									== 1) {
29407 				nss = i;
29408 				rate_index =
29409 				      (ffs(mask->control[band].ht_mcs[i]) - 1);
29410 				bit_rate = hdd_assemble_rate_code(
29411 						WMI_RATE_PREAMBLE_HT,
29412 						nss, rate_index);
29413 				goto configure_fw;
29414 			}
29415 		}
29416 
29417 		for (i = 0;
29418 			i < QDF_ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
29419 			if (qdf_get_hweight16(mask->control[band].vht_mcs[i])
29420 									== 1) {
29421 				nss = i;
29422 				rate_index =
29423 				     (ffs(mask->control[band].vht_mcs[i]) - 1);
29424 				bit_rate = hdd_assemble_rate_code(
29425 						WMI_RATE_PREAMBLE_VHT,
29426 						nss, rate_index);
29427 				goto configure_fw;
29428 			}
29429 		}
29430 
29431 		if (qdf_get_hweight32(mask->control[band].legacy) == 1) {
29432 			rate_index = (ffs(mask->control[band].legacy) - 1);
29433 			nss = 0;
29434 			if (band == NL80211_BAND_5GHZ)
29435 				rate_index += 4;
29436 			if (rate_index < 4)
29437 				bit_rate = hdd_assemble_rate_code(
29438 					WMI_RATE_PREAMBLE_CCK, nss,
29439 					hdd_legacy_rates[rate_index].hw_value);
29440 			else if (rate_index >= 4 && rate_index < 12)
29441 				bit_rate = hdd_assemble_rate_code(
29442 					WMI_RATE_PREAMBLE_OFDM, nss,
29443 					hdd_legacy_rates[rate_index].hw_value);
29444 		}
29445 
29446 		hdd_get_he_bitrate_params_for_band(band, mask, &nss,
29447 						   &rate_index, &bit_rate);
29448 
29449 configure_fw:
29450 		if (bit_rate != -1) {
29451 			hdd_debug("wmi_vdev_param_fixed_rate val %d", bit_rate);
29452 
29453 			errno = wma_cli_set_command(adapter->deflink->vdev_id,
29454 						    wmi_vdev_param_fixed_rate,
29455 						    bit_rate, VDEV_CMD);
29456 
29457 			if (errno)
29458 				hdd_err("Failed to set firmware, errno %d",
29459 					errno);
29460 		}
29461 
29462 
29463 #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
29464 		if (NL80211_RATE_INFO_HE_GI_0_8 == mask->control[band].he_gi) {
29465 			auto_rate_he_gi = AUTO_RATE_GI_800NS;
29466 			gi_val = 1;
29467 		} else if (NL80211_RATE_INFO_HE_GI_1_6 ==
29468 			   mask->control[band].he_gi) {
29469 			auto_rate_he_gi = AUTO_RATE_GI_1600NS;
29470 			gi_val = 2;
29471 		} else if (NL80211_RATE_INFO_HE_GI_3_2 ==
29472 			   mask->control[band].he_gi) {
29473 			auto_rate_he_gi = AUTO_RATE_GI_3200NS;
29474 			gi_val = 3;
29475 		}
29476 		if (auto_rate_he_gi) {
29477 			errno = sme_set_auto_rate_he_sgi(
29478 						hdd_ctx->mac_handle,
29479 						adapter->deflink->vdev_id,
29480 						auto_rate_he_gi);
29481 			if (errno)
29482 				hdd_err("auto rate GI %d set fail, status %d",
29483 					auto_rate_he_gi, errno);
29484 
29485 			errno = sme_update_ht_config(
29486 					hdd_ctx->mac_handle,
29487 					adapter->deflink->vdev_id,
29488 					WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ,
29489 					gi_val);
29490 
29491 			if (errno) {
29492 				hdd_err("cfg set failed, value %d status %d",
29493 					gi_val, errno);
29494 			}
29495 		} else
29496 #endif
29497 		if (mask->control[band].gi) {
29498 			if (NL80211_TXRATE_FORCE_SGI == mask->control[band].gi)
29499 				gi_val = 0;
29500 			else
29501 				gi_val = 1;
29502 
29503 			errno = sme_update_ht_config(
29504 					hdd_ctx->mac_handle,
29505 					adapter->deflink->vdev_id,
29506 					WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ,
29507 					gi_val);
29508 
29509 			if (errno)
29510 				hdd_err("cfg set failed, value %d status %d",
29511 					mask->control[band].gi, errno);
29512 		}
29513 	}
29514 
29515 	return errno;
29516 }
29517 
29518 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy * wiphy,struct net_device * netdev,unsigned int link_id,const u8 * peer,const struct cfg80211_bitrate_mask * mask)29519 static int wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
29520 					      struct net_device *netdev,
29521 					      unsigned int link_id,
29522 					      const u8 *peer,
29523 				       const struct cfg80211_bitrate_mask *mask)
29524 #else
29525 static int wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
29526 					      struct net_device *netdev,
29527 					      const u8 *peer,
29528 				       const struct cfg80211_bitrate_mask *mask)
29529 #endif
29530 {
29531 	int errno;
29532 	struct osif_vdev_sync *vdev_sync;
29533 
29534 	errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
29535 	if (errno) {
29536 		hdd_err("vdev_sync_op_start failure");
29537 		return errno;
29538 	}
29539 
29540 	errno = __wlan_hdd_cfg80211_set_bitrate_mask(wiphy, netdev, peer,
29541 						     mask);
29542 
29543 	osif_vdev_sync_op_stop(vdev_sync);
29544 
29545 	return errno;
29546 }
29547 
__wlan_hdd_cfg80211_tx_control_port(struct wiphy * wiphy,struct net_device * dev,const u8 * buf,size_t len,const u8 * src,const u8 * dest,__be16 proto,bool unencrypted,int link_id)29548 static int __wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
29549 					       struct net_device *dev,
29550 					       const u8 *buf, size_t len,
29551 					       const u8 *src, const u8 *dest,
29552 						__be16 proto, bool unencrypted,
29553 						int link_id)
29554 {
29555 	qdf_nbuf_t nbuf;
29556 	struct ethhdr *ehdr;
29557 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
29558 
29559 	hdd_enter();
29560 
29561 	nbuf = dev_alloc_skb(len + sizeof(struct ethhdr));
29562 	if (!nbuf)
29563 		return -ENOMEM;
29564 
29565 	skb_reserve(nbuf, sizeof(struct ethhdr));
29566 	skb_put_data(nbuf, buf, len);
29567 	ehdr = skb_push(nbuf, sizeof(struct ethhdr));
29568 	qdf_mem_copy(ehdr->h_dest, dest, ETH_ALEN);
29569 
29570 	if (!src || qdf_is_macaddr_zero((struct qdf_mac_addr *)src))
29571 		qdf_mem_copy(ehdr->h_source, adapter->mac_addr.bytes, ETH_ALEN);
29572 	else
29573 		qdf_mem_copy(ehdr->h_source, src, ETH_ALEN);
29574 
29575 	ehdr->h_proto = proto;
29576 
29577 	nbuf->dev = dev;
29578 	nbuf->protocol = htons(ETH_P_PAE);
29579 	skb_reset_network_header(nbuf);
29580 	skb_reset_mac_header(nbuf);
29581 
29582 	netif_tx_lock(dev);
29583 	skb_set_queue_mapping(nbuf, hdd_wmm_select_queue(dev, nbuf));
29584 	dev->netdev_ops->ndo_start_xmit(nbuf, dev);
29585 	netif_tx_unlock(dev);
29586 
29587 	hdd_exit();
29588 	return 0;
29589 }
29590 
_wlan_hdd_cfg80211_tx_control_port(struct wiphy * wiphy,struct net_device * dev,const u8 * buf,size_t len,const u8 * src,const u8 * dest,__be16 proto,bool unencrypted,int link_id)29591 static int _wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
29592 					      struct net_device *dev,
29593 					      const u8 *buf, size_t len,
29594 					      const u8 *src, const u8 *dest,
29595 					      __be16 proto, bool unencrypted,
29596 					      int link_id)
29597 {
29598 	int errno;
29599 	struct osif_vdev_sync *vdev_sync;
29600 
29601 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
29602 	if (errno)
29603 		return errno;
29604 
29605 	errno = __wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len, src,
29606 						    dest, proto, unencrypted,
29607 						    link_id);
29608 
29609 	osif_vdev_sync_op_stop(vdev_sync);
29610 
29611 	return errno;
29612 }
29613 
29614 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 41) || \
29615 	defined(CFG80211_TX_CONTROL_PORT_LINK_SUPPORT))
wlan_hdd_cfg80211_tx_control_port(struct wiphy * wiphy,struct net_device * dev,const u8 * buf,size_t len,const u8 * dest,const __be16 proto,bool unencrypted,int link_id,u64 * cookie)29616 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
29617 					     struct net_device *dev,
29618 					     const u8 *buf,
29619 					     size_t len,
29620 					     const u8 *dest, const __be16 proto,
29621 					     bool unencrypted, int link_id,
29622 					     u64 *cookie)
29623 {
29624 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
29625 
29626 	return _wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len,
29627 						  adapter->mac_addr.bytes,
29628 						  dest, proto, unencrypted,
29629 						  link_id);
29630 }
29631 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
wlan_hdd_cfg80211_tx_control_port(struct wiphy * wiphy,struct net_device * dev,const u8 * buf,size_t len,const u8 * dest,__be16 proto,bool unencrypted,u64 * cookie)29632 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
29633 					     struct net_device *dev,
29634 					     const u8 *buf, size_t len,
29635 					     const u8 *dest, __be16 proto,
29636 					     bool unencrypted, u64 *cookie)
29637 {
29638 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
29639 
29640 	return _wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len,
29641 						  adapter->mac_addr.bytes,
29642 						  dest, proto, unencrypted, -1);
29643 }
29644 #else
wlan_hdd_cfg80211_tx_control_port(struct wiphy * wiphy,struct net_device * dev,const u8 * buf,size_t len,const u8 * dest,__be16 proto,bool unencrypted)29645 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
29646 					     struct net_device *dev,
29647 					     const u8 *buf, size_t len,
29648 					     const u8 *dest, __be16 proto,
29649 					     bool unencrypted)
29650 {
29651 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
29652 
29653 	return _wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len,
29654 						  adapter->mac_addr.bytes,
29655 						  dest, proto, unencrypted, -1);
29656 }
29657 #endif
29658 
29659 #if defined(CFG80211_CTRL_FRAME_SRC_ADDR_TA_ADDR)
29660 
29661 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 41))
wlan_hdd_cfg80211_rx_control_port(struct net_device * dev,u8 * ta_addr,struct sk_buff * skb,bool unencrypted)29662 bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
29663 				       u8 *ta_addr,
29664 				       struct sk_buff *skb,
29665 				       bool unencrypted)
29666 {
29667 	return cfg80211_rx_control_port(dev, skb, unencrypted, -1);
29668 }
29669 
29670 #else
wlan_hdd_cfg80211_rx_control_port(struct net_device * dev,u8 * ta_addr,struct sk_buff * skb,bool unencrypted)29671 bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
29672 				       u8 *ta_addr,
29673 				       struct sk_buff *skb,
29674 				       bool unencrypted)
29675 {
29676 	return cfg80211_rx_control_port(dev, ta_addr, skb, unencrypted);
29677 }
29678 #endif
29679 
29680 #else
wlan_hdd_cfg80211_rx_control_port(struct net_device * dev,u8 * ta_addr,struct sk_buff * skb,bool unencrypted)29681 bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
29682 				       u8 *ta_addr,
29683 				       struct sk_buff *skb,
29684 				       bool unencrypted)
29685 {
29686 	return false;
29687 }
29688 #endif
29689 
29690 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
29691 static int
wlan_hdd_cfg80211_add_intf_link(struct wiphy * wiphy,struct wireless_dev * wdev,unsigned int link_id)29692 wlan_hdd_cfg80211_add_intf_link(struct wiphy *wiphy, struct wireless_dev *wdev,
29693 				unsigned int link_id)
29694 {
29695 	return 0;
29696 }
29697 
29698 static void
wlan_hdd_cfg80211_del_intf_link(struct wiphy * wiphy,struct wireless_dev * wdev,unsigned int link_id)29699 wlan_hdd_cfg80211_del_intf_link(struct wiphy *wiphy, struct wireless_dev *wdev,
29700 				unsigned int link_id)
29701 {
29702 }
29703 #endif
29704 
29705 #if defined(WLAN_FEATURE_11BE_MLO)
29706 #if defined(WLAN_TID_LINK_MAP_SUPPORT)
29707 #define MAX_T2LM_INFO 2
29708 
wlan_hdd_print_t2lm_info(struct cfg80211_mlo_tid_map * map)29709 static void wlan_hdd_print_t2lm_info(struct cfg80211_mlo_tid_map *map)
29710 {
29711 	int i;
29712 
29713 	hdd_debug("T2LM info send to userspace");
29714 	hdd_debug("default mapping: %d", map->default_map);
29715 	for (i = 0; i < T2LM_MAX_NUM_TIDS; i++)
29716 		hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
29717 			  i, map->t2lmap[i].downlink, map->t2lmap[i].uplink);
29718 }
29719 
wlan_hdd_fill_bidir_t2lm(struct wlan_t2lm_info * t2lm,struct tid_link_map * t2lmap)29720 static void wlan_hdd_fill_bidir_t2lm(struct wlan_t2lm_info *t2lm,
29721 				     struct tid_link_map *t2lmap)
29722 {
29723 	uint8_t tid;
29724 
29725 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
29726 		t2lmap[tid].downlink = t2lm->ieee_link_map_tid[tid];
29727 		t2lmap[tid].uplink = t2lm->ieee_link_map_tid[tid];
29728 	}
29729 }
29730 
wlan_hdd_fill_dldir_t2lm(struct wlan_t2lm_info * t2lm,struct tid_link_map * t2lmap)29731 static void wlan_hdd_fill_dldir_t2lm(struct wlan_t2lm_info *t2lm,
29732 				     struct tid_link_map *t2lmap)
29733 {
29734 	uint8_t tid;
29735 
29736 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++)
29737 		t2lmap[tid].downlink = t2lm->ieee_link_map_tid[tid];
29738 }
29739 
wlan_hdd_fill_uldir_t2lm(struct wlan_t2lm_info * t2lm,struct tid_link_map * t2lmap)29740 static void wlan_hdd_fill_uldir_t2lm(struct wlan_t2lm_info *t2lm,
29741 				     struct tid_link_map *t2lmap)
29742 {
29743 	uint8_t tid;
29744 
29745 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++)
29746 		t2lmap[tid].uplink = t2lm->ieee_link_map_tid[tid];
29747 }
29748 
wlan_hdd_fill_map(struct wlan_t2lm_info * t2lm,struct cfg80211_mlo_tid_map * map,bool * found)29749 static void wlan_hdd_fill_map(struct wlan_t2lm_info *t2lm,
29750 			      struct cfg80211_mlo_tid_map *map, bool *found)
29751 {
29752 	if (t2lm->direction == WLAN_T2LM_INVALID_DIRECTION)
29753 		return;
29754 
29755 	map->default_map = t2lm->default_link_mapping;
29756 
29757 	switch (t2lm->direction) {
29758 	case WLAN_T2LM_BIDI_DIRECTION:
29759 		wlan_hdd_fill_bidir_t2lm(t2lm, map->t2lmap);
29760 		*found = true;
29761 		break;
29762 	case WLAN_T2LM_DL_DIRECTION:
29763 		wlan_hdd_fill_dldir_t2lm(t2lm, map->t2lmap);
29764 		*found = true;
29765 		break;
29766 	case WLAN_T2LM_UL_DIRECTION:
29767 		wlan_hdd_fill_uldir_t2lm(t2lm, map->t2lmap);
29768 		*found = true;
29769 		break;
29770 	default:
29771 		return;
29772 	}
29773 }
29774 
wlan_hdd_fill_t2lm_response(struct wlan_t2lm_info * t2lm,struct cfg80211_mlo_tid_map * map)29775 static int wlan_hdd_fill_t2lm_response(struct wlan_t2lm_info *t2lm,
29776 				       struct cfg80211_mlo_tid_map *map)
29777 {
29778 	uint8_t i;
29779 	bool found = false;
29780 
29781 	for (i = 0; i < MAX_T2LM_INFO; i++)
29782 		wlan_hdd_fill_map(&t2lm[i], map, &found);
29783 
29784 	if (!found) {
29785 		hdd_err("T2LM info not found");
29786 		return -EINVAL;
29787 	}
29788 
29789 	wlan_hdd_print_t2lm_info(map);
29790 
29791 	return 0;
29792 }
29793 
29794 static int
__wlan_hdd_cfg80211_get_t2lm_mapping_status(struct wiphy * wiphy,struct net_device * net_dev,struct cfg80211_mlo_tid_map * map)29795 __wlan_hdd_cfg80211_get_t2lm_mapping_status(struct wiphy *wiphy,
29796 					    struct net_device *net_dev,
29797 					    struct cfg80211_mlo_tid_map *map)
29798 {
29799 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
29800 	struct wlan_objmgr_vdev *vdev;
29801 	struct wlan_t2lm_info *t2lm = NULL;
29802 	int ret, i;
29803 
29804 	hdd_enter();
29805 
29806 	if (hdd_validate_adapter(adapter))
29807 		return -EINVAL;
29808 
29809 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
29810 	if (!vdev) {
29811 		hdd_err("Vdev is null return");
29812 		return -EINVAL;
29813 	}
29814 
29815 	if (!wlan_cm_is_vdev_connected(vdev)) {
29816 		hdd_err("Not associated!, vdev %d", wlan_vdev_get_id(vdev));
29817 		ret = -EAGAIN;
29818 		goto vdev_release;
29819 	}
29820 
29821 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
29822 		hdd_err("failed due to non-ML connection");
29823 		ret = -EINVAL;
29824 		goto vdev_release;
29825 	}
29826 
29827 	t2lm = qdf_mem_malloc(sizeof(*t2lm) * MAX_T2LM_INFO);
29828 	if (!t2lm) {
29829 		hdd_err("mem alloc failed for t2lm");
29830 		ret = -ENOMEM;
29831 		goto vdev_release;
29832 	}
29833 
29834 	for (i = 0; i < MAX_T2LM_INFO; i++)
29835 		t2lm[i].direction = WLAN_T2LM_INVALID_DIRECTION;
29836 
29837 	ret = wlan_get_t2lm_mapping_status(vdev, t2lm);
29838 	if (ret != 0)
29839 		goto t2lm_free;
29840 
29841 	ret = wlan_hdd_fill_t2lm_response(t2lm, map);
29842 
29843 t2lm_free:
29844 	qdf_mem_free(t2lm);
29845 vdev_release:
29846 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
29847 
29848 	hdd_exit();
29849 
29850 	return ret;
29851 }
29852 
29853 static int
wlan_hdd_cfg80211_get_t2lm_mapping_status(struct wiphy * wiphy,struct net_device * net_dev,struct cfg80211_mlo_tid_map * map)29854 wlan_hdd_cfg80211_get_t2lm_mapping_status(struct wiphy *wiphy,
29855 					  struct net_device *net_dev,
29856 					  struct cfg80211_mlo_tid_map *map)
29857 {
29858 	int errno;
29859 	struct osif_vdev_sync *vdev_sync;
29860 
29861 	errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
29862 	if (errno)
29863 		return errno;
29864 
29865 	errno = __wlan_hdd_cfg80211_get_t2lm_mapping_status(wiphy, net_dev, map);
29866 
29867 	osif_vdev_sync_op_stop(vdev_sync);
29868 
29869 	return errno;
29870 }
29871 
hdd_tid_to_link_map(struct wlan_objmgr_vdev * vdev,struct wlan_t2lm_info * t2lm,struct net_device * dev)29872 QDF_STATUS hdd_tid_to_link_map(struct wlan_objmgr_vdev *vdev,
29873 			       struct wlan_t2lm_info *t2lm,
29874 			       struct net_device *dev)
29875 {
29876 	struct cfg80211_mlo_tid_map map;
29877 	bool found = false;
29878 
29879 	qdf_mem_zero(&map, sizeof(map));
29880 	wlan_hdd_fill_map(t2lm, &map, &found);
29881 	if (!found) {
29882 		hdd_debug("Failed to get t2lm info");
29883 		return QDF_STATUS_E_FAILURE;
29884 	}
29885 
29886 	wlan_hdd_print_t2lm_info(&map);
29887 	cfg80211_tid_to_link_map_change(dev, &map);
29888 	return QDF_STATUS_SUCCESS;
29889 }
29890 
29891 #else
wlan_hdd_print_vendor_t2lm_info(struct wlan_t2lm_info * t2lm)29892 static void wlan_hdd_print_vendor_t2lm_info(struct wlan_t2lm_info *t2lm)
29893 {
29894 	int tid, value = 0;
29895 
29896 	hdd_debug("default mapping: %d", t2lm->default_link_mapping);
29897 
29898 	if (t2lm->direction == WLAN_T2LM_INVALID_DIRECTION)
29899 		return;
29900 
29901 	switch (t2lm->direction) {
29902 	case WLAN_T2LM_BIDI_DIRECTION:
29903 		for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
29904 			hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
29905 				  tid, t2lm->ieee_link_map_tid[tid],
29906 				  t2lm->ieee_link_map_tid[tid]);
29907 		}
29908 		break;
29909 	case WLAN_T2LM_DL_DIRECTION:
29910 		for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
29911 			/* Keep uplink info as 0 for downlink direction */
29912 			hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
29913 				  tid, t2lm->ieee_link_map_tid[tid], value);
29914 		}
29915 		break;
29916 	case WLAN_T2LM_UL_DIRECTION:
29917 		for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
29918 			/* Keep downlinklink info as 0 for downlink direction */
29919 			hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
29920 				  tid, value, t2lm->ieee_link_map_tid[tid]);
29921 		}
29922 		break;
29923 	default:
29924 		return;
29925 	}
29926 }
29927 
hdd_tid_to_link_map(struct wlan_objmgr_vdev * vdev,struct wlan_t2lm_info * t2lm,struct net_device * dev)29928 QDF_STATUS hdd_tid_to_link_map(struct wlan_objmgr_vdev *vdev,
29929 			       struct wlan_t2lm_info *t2lm,
29930 			       struct net_device *dev)
29931 {
29932 	uint8_t ret;
29933 
29934 	wlan_hdd_print_vendor_t2lm_info(t2lm);
29935 	ret = wlan_hdd_send_t2lm_event(vdev, t2lm);
29936 	if (QDF_IS_STATUS_ERROR(ret)) {
29937 		hdd_debug("failed to send t2lm info to userspace");
29938 		return QDF_STATUS_E_FAILURE;
29939 	}
29940 	return QDF_STATUS_SUCCESS;
29941 }
29942 #endif
29943 
hdd_mlo_dev_t2lm_notify_link_update(struct wlan_objmgr_vdev * vdev,struct wlan_t2lm_info * t2lm)29944 QDF_STATUS hdd_mlo_dev_t2lm_notify_link_update(struct wlan_objmgr_vdev *vdev,
29945 					       struct wlan_t2lm_info *t2lm)
29946 {
29947 	struct wlan_hdd_link_info *link_info;
29948 	struct net_device *dev;
29949 	uint8_t ret;
29950 
29951 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
29952 	if (!link_info) {
29953 		hdd_err("Invalid VDEV");
29954 		return QDF_STATUS_E_FAILURE;
29955 	}
29956 
29957 	dev = link_info->adapter->dev;
29958 	hdd_enter_dev(dev);
29959 
29960 	ret = hdd_tid_to_link_map(vdev, t2lm, dev);
29961 	if (QDF_IS_STATUS_ERROR(ret)) {
29962 		hdd_debug("tid to link map change failed ");
29963 		return QDF_STATUS_E_FAILURE;
29964 	}
29965 
29966 	hdd_exit();
29967 
29968 	return QDF_STATUS_SUCCESS;
29969 }
29970 #endif
29971 
29972 static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
29973 	.add_virtual_intf = wlan_hdd_add_virtual_intf,
29974 	.del_virtual_intf = wlan_hdd_del_virtual_intf,
29975 	.change_virtual_intf = wlan_hdd_cfg80211_change_iface,
29976 	.change_station = wlan_hdd_change_station,
29977 	.start_ap = wlan_hdd_cfg80211_start_ap,
29978 	.change_beacon = wlan_hdd_cfg80211_change_beacon,
29979 	.stop_ap = wlan_hdd_cfg80211_stop_ap,
29980 	.change_bss = wlan_hdd_cfg80211_change_bss,
29981 	.add_key = wlan_hdd_cfg80211_add_key,
29982 	.get_key = wlan_hdd_cfg80211_get_key,
29983 	.del_key = wlan_hdd_cfg80211_del_key,
29984 	.set_default_key = wlan_hdd_cfg80211_set_default_key,
29985 	.scan = wlan_hdd_cfg80211_scan,
29986 	.connect = wlan_hdd_cfg80211_connect,
29987 	.disconnect = wlan_hdd_cfg80211_disconnect,
29988 	.set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
29989 	.set_tx_power = wlan_hdd_cfg80211_set_txpower,
29990 	.get_tx_power = wlan_hdd_cfg80211_get_txpower,
29991 	.remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
29992 	.cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
29993 	.mgmt_tx = wlan_hdd_mgmt_tx,
29994 	.mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
29995 	.set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
29996 #if defined (CFG80211_BIGTK_CONFIGURATION_SUPPORT) || \
29997 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
29998 	.set_default_beacon_key = wlan_hdd_cfg80211_set_default_beacon_key,
29999 #endif
30000 	.set_txq_params = wlan_hdd_set_txq_params,
30001 	.dump_station = wlan_hdd_cfg80211_dump_station,
30002 	.get_station = wlan_hdd_cfg80211_get_station,
30003 	.set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
30004 	.del_station = wlan_hdd_cfg80211_del_station,
30005 	.add_station = wlan_hdd_cfg80211_add_station,
30006 	.set_pmksa = wlan_hdd_cfg80211_set_pmksa,
30007 	.del_pmksa = wlan_hdd_cfg80211_del_pmksa,
30008 	.flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
30009 #if defined(KERNEL_SUPPORT_11R_CFG80211)
30010 	.update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
30011 #endif
30012 #if defined(CFG80211_EXTERNAL_DH_UPDATE_SUPPORT) || \
30013 (LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0))
30014 	.update_owe_info = wlan_hdd_cfg80211_update_owe_info,
30015 #endif
30016 #ifdef FEATURE_WLAN_TDLS
30017 	.tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
30018 	.tdls_oper = wlan_hdd_cfg80211_tdls_oper,
30019 #endif
30020 #ifdef WLAN_FEATURE_GTK_OFFLOAD
30021 	.set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
30022 #endif /* WLAN_FEATURE_GTK_OFFLOAD */
30023 #ifdef FEATURE_WLAN_SCAN_PNO
30024 	.sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
30025 	.sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
30026 #endif /*FEATURE_WLAN_SCAN_PNO */
30027 	.resume = wlan_hdd_cfg80211_resume_wlan,
30028 	.suspend = wlan_hdd_cfg80211_suspend_wlan,
30029 	.set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
30030 #ifdef WLAN_NL80211_TESTMODE
30031 	.testmode_cmd = wlan_hdd_cfg80211_testmode,
30032 #endif
30033 #ifdef QCA_HT_2040_COEX
30034 	.set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
30035 #endif
30036 	.dump_survey = wlan_hdd_cfg80211_dump_survey,
30037 #ifdef CHANNEL_SWITCH_SUPPORTED
30038 	.channel_switch = wlan_hdd_cfg80211_channel_switch,
30039 #endif
30040 #ifdef FEATURE_MONITOR_MODE_SUPPORT
30041 	.set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
30042 #endif
30043 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
30044 	defined(CFG80211_ABORT_SCAN)
30045 	.abort_scan = wlan_hdd_cfg80211_abort_scan,
30046 #endif
30047 #if defined(CFG80211_UPDATE_CONNECT_PARAMS) || \
30048 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
30049 	.update_connect_params = wlan_hdd_cfg80211_update_connect_params,
30050 #endif
30051 #if defined(WLAN_FEATURE_SAE) && \
30052 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
30053 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
30054 	.external_auth = wlan_hdd_cfg80211_external_auth,
30055 #endif
30056 #if defined(WLAN_FEATURE_NAN) && \
30057 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
30058 	.start_nan = wlan_hdd_cfg80211_start_nan,
30059 	.stop_nan = wlan_hdd_cfg80211_stop_nan,
30060 	.add_nan_func = wlan_hdd_cfg80211_add_nan_func,
30061 	.del_nan_func = wlan_hdd_cfg80211_del_nan_func,
30062 	.nan_change_conf = wlan_hdd_cfg80211_nan_change_conf,
30063 #endif
30064 	.set_antenna = wlan_hdd_cfg80211_set_chainmask,
30065 	.get_antenna = wlan_hdd_cfg80211_get_chainmask,
30066 	.get_channel = wlan_hdd_cfg80211_get_channel,
30067 	.set_bitrate_mask = wlan_hdd_cfg80211_set_bitrate_mask,
30068 	.tx_control_port = wlan_hdd_cfg80211_tx_control_port,
30069 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
30070 	.add_intf_link = wlan_hdd_cfg80211_add_intf_link,
30071 	.del_intf_link = wlan_hdd_cfg80211_del_intf_link,
30072 #endif
30073 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_TID_LINK_MAP_SUPPORT)
30074 	.get_link_tid_map_status = wlan_hdd_cfg80211_get_t2lm_mapping_status,
30075 #endif
30076 };
30077