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, ¶m);
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(>k_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 *)>k_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(¶ms);
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(¶ms);
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], ð_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, ®_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(¶ms);
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 ¶ms->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(¶ms, 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, ¶ms);
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(¶m->peerMacAddr))
25752 sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
25753 adapter->deflink->vdev_id,
25754 (uint8_t *)¶m->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 *)>k_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 *)>k_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