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_main.c
22 *
23 * WLAN Host Device Driver implementation
24 *
25 */
26
27 /* Include Files */
28 #include <wbuff.h>
29 #include "cfg_ucfg_api.h"
30 #include <wlan_hdd_includes.h>
31 #include <cds_api.h>
32 #include <cds_sched.h>
33 #include <linux/cpu.h>
34 #include <linux/etherdevice.h>
35 #include <linux/firmware.h>
36 #include <linux/kernel.h>
37 #include <wlan_hdd_tx_rx.h>
38 #include <wni_api.h>
39 #include <wlan_hdd_cfg.h>
40 #include <wlan_ptt_sock_svc.h>
41 #include <dbglog_host.h>
42 #include <wlan_logging_sock_svc.h>
43 #include <wlan_roam_debug.h>
44 #include <wlan_hdd_connectivity_logging.h>
45 #include "osif_sync.h"
46 #include <wlan_hdd_wowl.h>
47 #include <wlan_hdd_misc.h>
48 #include <wlan_hdd_wext.h>
49 #include "wlan_hdd_trace.h"
50 #include "wlan_hdd_ioctl.h"
51 #include "wlan_hdd_ftm.h"
52 #include "wlan_hdd_power.h"
53 #include "wlan_hdd_stats.h"
54 #include "wlan_hdd_scan.h"
55 #include "wlan_policy_mgr_ucfg.h"
56 #include "wlan_osif_priv.h"
57 #include <wlan_osif_request_manager.h>
58 #ifdef CONFIG_LEAK_DETECTION
59 #include "qdf_debug_domain.h"
60 #endif
61 #include "qdf_delayed_work.h"
62 #include "qdf_periodic_work.h"
63 #include "qdf_str.h"
64 #include "qdf_talloc.h"
65 #include "qdf_trace.h"
66 #include "qdf_types.h"
67 #include "qdf_net_if.h"
68 #include <cdp_txrx_peer_ops.h>
69 #include <cdp_txrx_misc.h>
70 #include <cdp_txrx_stats.h>
71 #include "cdp_txrx_flow_ctrl_legacy.h"
72 #include "qdf_ssr_driver_dump.h"
73
74 #include <net/addrconf.h>
75 #include <linux/wireless.h>
76 #include <net/cfg80211.h>
77 #include <linux/inetdevice.h>
78 #include <net/addrconf.h>
79 #include "wlan_hdd_cfg80211.h"
80 #include "wlan_hdd_ext_scan.h"
81 #include "wlan_hdd_p2p.h"
82 #include <linux/rtnetlink.h>
83 #include "sap_api.h"
84 #include <sap_internal.h>
85 #include <linux/semaphore.h>
86 #include <linux/ctype.h>
87 #include <linux/compat.h>
88 #include <linux/ethtool.h>
89 #include <linux/suspend.h>
90
91 #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH
92 #include "qdf_periodic_work.h"
93 #endif
94
95 #include <wlan_hdd_hostapd.h>
96 #include <wlan_hdd_softap_tx_rx.h>
97 #include <wlan_hdd_green_ap.h>
98 #include "qwlan_version.h"
99 #include "wma_types.h"
100 #include "wlan_hdd_tdls.h"
101 #ifdef FEATURE_WLAN_CH_AVOID
102 #include "cds_regdomain.h"
103 #endif /* FEATURE_WLAN_CH_AVOID */
104 #include "cdp_txrx_flow_ctrl_v2.h"
105 #include "pld_common.h"
106 #include "wlan_hdd_ocb.h"
107 #include "wlan_hdd_nan.h"
108 #include "wlan_hdd_debugfs.h"
109 #include "wlan_hdd_debugfs_csr.h"
110 #include "wlan_hdd_driver_ops.h"
111 #include "epping_main.h"
112 #include "wlan_hdd_data_stall_detection.h"
113 #include "wlan_hdd_mpta_helper.h"
114
115 #include <wlan_hdd_ipa.h>
116 #include "hif.h"
117 #include "wma.h"
118 #include "wlan_policy_mgr_api.h"
119 #include "wlan_hdd_tsf.h"
120 #include "bmi.h"
121 #include <wlan_hdd_regulatory.h>
122 #include "wlan_hdd_lpass.h"
123 #include "wlan_nan_api.h"
124 #include <wlan_hdd_napi.h>
125 #include "wlan_hdd_disa.h"
126 #include <dispatcher_init_deinit.h>
127 #include "wlan_hdd_object_manager.h"
128 #include "cds_utils.h"
129 #include <cdp_txrx_handle.h>
130 #include <qca_vendor.h>
131 #include "wlan_pmo_ucfg_api.h"
132 #include "sir_api.h"
133 #include "os_if_wifi_pos.h"
134 #include "wifi_pos_api.h"
135 #include "wlan_hdd_oemdata.h"
136 #include "wlan_hdd_he.h"
137 #include "os_if_nan.h"
138 #include "nan_public_structs.h"
139 #include "nan_ucfg_api.h"
140 #include "wlan_reg_ucfg_api.h"
141 #include "wlan_hdd_afc.h"
142 #include "wlan_afc_ucfg_api.h"
143 #include "wlan_dfs_ucfg_api.h"
144 #include "wlan_hdd_rx_monitor.h"
145 #include "sme_power_save_api.h"
146 #include "enet.h"
147 #include <cdp_txrx_cmn_struct.h>
148 #include "wlan_hdd_sysfs.h"
149 #include "wlan_disa_ucfg_api.h"
150 #include "wlan_disa_obj_mgmt_api.h"
151 #include "wlan_action_oui_ucfg_api.h"
152 #include "wlan_ipa_ucfg_api.h"
153 #include <target_if.h>
154 #include "wlan_hdd_nud_tracking.h"
155 #include "wlan_hdd_apf.h"
156 #include "wlan_hdd_twt.h"
157 #include "qc_sap_ioctl.h"
158 #include "wlan_mlme_main.h"
159 #include "wlan_p2p_cfg_api.h"
160 #include "wlan_cfg80211_p2p.h"
161 #include "wlan_cfg80211_interop_issues_ap.h"
162 #include "wlan_tdls_cfg_api.h"
163 #include <wlan_hdd_rssi_monitor.h>
164 #include "wlan_mlme_ucfg_api.h"
165 #include "wlan_mlme_twt_ucfg_api.h"
166 #include "wlan_fwol_ucfg_api.h"
167 #include "wlan_policy_mgr_ucfg.h"
168 #include "qdf_func_tracker.h"
169 #include "pld_common.h"
170 #include "wlan_hdd_pre_cac.h"
171
172 #include "sme_api.h"
173
174 #ifdef CNSS_GENL
175 #ifdef CONFIG_CNSS_OUT_OF_TREE
176 #include "cnss_nl.h"
177 #else
178 #include <net/cnss_nl.h>
179 #endif
180 #endif
181 #include "wlan_reg_ucfg_api.h"
182 #include "wlan_ocb_ucfg_api.h"
183 #include <wlan_hdd_spectralscan.h>
184 #include "wlan_green_ap_ucfg_api.h"
185 #include <wlan_p2p_ucfg_api.h>
186 #include <wlan_interop_issues_ap_ucfg_api.h>
187 #include <target_type.h>
188 #include <wlan_hdd_debugfs_coex.h>
189 #include <wlan_hdd_debugfs_config.h>
190 #include "wlan_dlm_ucfg_api.h"
191 #include "ftm_time_sync_ucfg_api.h"
192 #include "wlan_pre_cac_ucfg_api.h"
193 #include "ol_txrx.h"
194 #include "wlan_hdd_sta_info.h"
195 #include "mac_init_api.h"
196 #include "wlan_pkt_capture_ucfg_api.h"
197 #include <wlan_hdd_sar_limits.h>
198 #include "cfg_nan_api.h"
199 #include "wlan_hdd_btc_chain_mode.h"
200 #include <wlan_hdd_dcs.h>
201 #include "wlan_hdd_debugfs_unit_test.h"
202 #include "wlan_hdd_debugfs_mibstat.h"
203 #include <wlan_hdd_hang_event.h>
204 #include "wlan_global_lmac_if_api.h"
205 #include "wlan_coex_ucfg_api.h"
206 #include "wlan_cm_roam_api.h"
207 #include "wlan_cm_roam_ucfg_api.h"
208 #include <cdp_txrx_ctrl.h>
209 #include "qdf_lock.h"
210 #include "wlan_hdd_thermal.h"
211 #include "osif_cm_util.h"
212 #include "wlan_hdd_gpio_wakeup.h"
213 #include "wlan_hdd_bootup_marker.h"
214 #include "wlan_dp_ucfg_api.h"
215 #include "wlan_hdd_medium_assess.h"
216 #include "wlan_hdd_eht.h"
217 #include <linux/bitfield.h>
218 #include "wlan_hdd_mlo.h"
219 #include <wlan_hdd_son.h>
220 #ifdef WLAN_FEATURE_11BE_MLO
221 #include <wlan_mlo_mgr_ap.h>
222 #endif
223 #include "wlan_osif_features.h"
224 #include "wlan_vdev_mgr_ucfg_api.h"
225 #include <wlan_objmgr_psoc_obj_i.h>
226 #include <wlan_objmgr_vdev_obj_i.h>
227 #include "wifi_pos_ucfg_api.h"
228 #include "osif_vdev_mgr_util.h"
229 #include <son_ucfg_api.h>
230 #include "osif_twt_util.h"
231 #include "wlan_twt_ucfg_ext_api.h"
232 #include "wlan_hdd_mcc_quota.h"
233 #include "osif_pre_cac.h"
234 #include "wlan_hdd_pre_cac.h"
235 #include "wlan_osif_features.h"
236 #ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
237 #include <net/pkt_cls.h>
238 #endif
239 #include "wlan_dp_public_struct.h"
240 #include "os_if_dp.h"
241 #include <wlan_dp_ucfg_api.h>
242 #include "wlan_psoc_mlme_ucfg_api.h"
243 #include "os_if_qmi.h"
244 #include "wlan_qmi_ucfg_api.h"
245 #include "wlan_psoc_mlme_ucfg_api.h"
246 #include "wlan_ll_sap_ucfg_api.h"
247
248 #include "os_if_dp_local_pkt_capture.h"
249 #include <wlan_mlo_mgr_link_switch.h>
250 #include "cdp_txrx_mon.h"
251 #include "os_if_ll_sap.h"
252 #include "wlan_p2p_ucfg_api.h"
253 #include "wlan_crypto_obj_mgr_i.h"
254
255 #ifdef MULTI_CLIENT_LL_SUPPORT
256 #define WLAM_WLM_HOST_DRIVER_PORT_ID 0xFFFFFF
257 #endif
258
259 #ifdef MODULE
260 #ifdef WLAN_WEAR_CHIPSET
261 #define WLAN_MODULE_NAME "wlan"
262 #else
263 #define WLAN_MODULE_NAME module_name(THIS_MODULE)
264 #endif
265 #else
266 #define WLAN_MODULE_NAME "wlan"
267 #endif
268
269 #ifdef TIMER_MANAGER
270 #define TIMER_MANAGER_STR " +TIMER_MANAGER"
271 #else
272 #define TIMER_MANAGER_STR ""
273 #endif
274
275 #ifdef MEMORY_DEBUG
276 #define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
277 #else
278 #define MEMORY_DEBUG_STR ""
279 #endif
280
281 #ifdef PANIC_ON_BUG
282 #define PANIC_ON_BUG_STR " +PANIC_ON_BUG"
283 #else
284 #define PANIC_ON_BUG_STR ""
285 #endif
286
287 /* PCIe gen speed change idle shutdown timer 100 milliseconds */
288 #define HDD_PCIE_GEN_SPEED_CHANGE_TIMEOUT_MS (100)
289
290 #define MAX_NET_DEV_REF_LEAK_ITERATIONS 10
291 #define NET_DEV_REF_LEAK_ITERATION_SLEEP_TIME_MS 10
292
293 #ifdef FEATURE_TSO
294 #define TSO_FEATURE_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG)
295 #else
296 #define TSO_FEATURE_FLAGS 0
297 #endif
298
299 int wlan_start_ret_val;
300 static DECLARE_COMPLETION(wlan_start_comp);
301 static qdf_atomic_t wlan_hdd_state_fops_ref;
302 #ifndef MODULE
303 static struct gwlan_loader *wlan_loader;
304 static ssize_t wlan_boot_cb(struct kobject *kobj,
305 struct kobj_attribute *attr,
306 const char *buf, size_t count);
307 struct gwlan_loader {
308 bool loaded_state;
309 struct kobject *boot_wlan_obj;
310 struct attribute_group *attr_group;
311 };
312
313 static struct kobj_attribute wlan_boot_attribute =
314 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
315
316 static struct attribute *attrs[] = {
317 &wlan_boot_attribute.attr,
318 NULL,
319 };
320 #define MODULE_INITIALIZED 1
321
322 #ifdef MULTI_IF_NAME
323 #define WLAN_LOADER_NAME "boot_" MULTI_IF_NAME
324 #else
325 #define WLAN_LOADER_NAME "boot_wlan"
326 #endif
327 #endif
328
329 /* the Android framework expects this param even though we don't use it */
330 #define BUF_LEN 20
331 static char fwpath_buffer[BUF_LEN];
332 static struct kparam_string fwpath = {
333 .string = fwpath_buffer,
334 .maxlen = BUF_LEN,
335 };
336
337 char *country_code;
338 #ifdef FEATURE_WLAN_RESIDENT_DRIVER
339 EXPORT_SYMBOL(country_code);
340 #endif
341 static int enable_11d = -1;
342 static int enable_dfs_chan_scan = -1;
343 static bool is_mode_change_psoc_idle_shutdown;
344
345 #define WLAN_NLINK_CESIUM 30
346
347 static qdf_wake_lock_t wlan_wake_lock;
348
349 /* The valid PCIe gen speeds are 1, 2, 3 */
350 #define HDD_INVALID_MIN_PCIE_GEN_SPEED (0)
351 #define HDD_INVALID_MAX_PCIE_GEN_SPEED (4)
352
353 #define MAX_PDEV_PRE_ENABLE_PARAMS 8
354 #define FTM_MAX_PDEV_PARAMS 1
355
356 #define WOW_MAX_FILTER_LISTS 1
357 #define WOW_MAX_FILTERS_PER_LIST 4
358 #define WOW_MIN_PATTERN_SIZE 6
359 #define WOW_MAX_PATTERN_SIZE 64
360 #define MGMT_DEFAULT_DATA_RATE_6GHZ 0x400 /* This maps to 8.6Mbps data rate */
361
362 #define IS_IDLE_STOP (!cds_is_driver_unloading() && \
363 !cds_is_driver_recovering() && !cds_is_driver_loading())
364
365 #define HDD_FW_VER_MAJOR_SPID(tgt_fw_ver) ((tgt_fw_ver & 0xf0000000) >> 28)
366 #define HDD_FW_VER_MINOR_SPID(tgt_fw_ver) ((tgt_fw_ver & 0xf000000) >> 24)
367 #define HDD_FW_VER_SIID(tgt_fw_ver) ((tgt_fw_ver & 0xf00000) >> 20)
368 #define HDD_FW_VER_CRM_ID(tgt_fw_ver) (tgt_fw_ver & 0x7fff)
369 #define HDD_FW_VER_SUB_ID(tgt_fw_ver_ext) \
370 (((tgt_fw_ver_ext & 0x1c00) >> 6) | ((tgt_fw_ver_ext & 0xf0000000) >> 28))
371 #define HDD_FW_VER_REL_ID(tgt_fw_ver_ext) \
372 ((tgt_fw_ver_ext & 0xf800000) >> 23)
373
374 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
375 static const struct wiphy_wowlan_support wowlan_support_reg_init = {
376 .flags = WIPHY_WOWLAN_ANY |
377 WIPHY_WOWLAN_MAGIC_PKT |
378 WIPHY_WOWLAN_DISCONNECT |
379 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
380 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
381 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
382 WIPHY_WOWLAN_4WAY_HANDSHAKE |
383 WIPHY_WOWLAN_RFKILL_RELEASE,
384 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
385 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
386 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
387 };
388 #endif
389
390 static const struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
391 [QDF_MODULE_ID_TLSHIM] = {QDF_TRACE_LEVEL_ALL},
392 [QDF_MODULE_ID_WMI] = {QDF_TRACE_LEVEL_ALL},
393 [QDF_MODULE_ID_HTT] = {QDF_TRACE_LEVEL_ALL},
394 [QDF_MODULE_ID_HDD] = {QDF_TRACE_LEVEL_ALL},
395 [QDF_MODULE_ID_SME] = {QDF_TRACE_LEVEL_ALL},
396 [QDF_MODULE_ID_PE] = {QDF_TRACE_LEVEL_ALL},
397 [QDF_MODULE_ID_WMA] = {QDF_TRACE_LEVEL_ALL},
398 [QDF_MODULE_ID_SYS] = {QDF_TRACE_LEVEL_ALL},
399 [QDF_MODULE_ID_QDF] = {QDF_TRACE_LEVEL_ALL},
400 [QDF_MODULE_ID_SAP] = {QDF_TRACE_LEVEL_ALL},
401 [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_TRACE_LEVEL_ALL},
402 [QDF_MODULE_ID_HDD_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
403 [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
404 [QDF_MODULE_ID_HIF] = {QDF_DATA_PATH_TRACE_LEVEL},
405 [QDF_MODULE_ID_HTC] = {QDF_DATA_PATH_TRACE_LEVEL},
406 [QDF_MODULE_ID_TXRX] = {QDF_DATA_PATH_TRACE_LEVEL},
407 [QDF_MODULE_ID_HAL] = {QDF_DATA_PATH_TRACE_LEVEL},
408 [QDF_MODULE_ID_QDF_DEVICE] = {QDF_TRACE_LEVEL_ALL},
409 [QDF_MODULE_ID_CFG] = {QDF_TRACE_LEVEL_ALL},
410 [QDF_MODULE_ID_BMI] = {QDF_TRACE_LEVEL_ALL},
411 [QDF_MODULE_ID_EPPING] = {QDF_TRACE_LEVEL_ALL},
412 [QDF_MODULE_ID_QVIT] = {QDF_TRACE_LEVEL_ALL},
413 [QDF_MODULE_ID_DP] = {QDF_DATA_PATH_TRACE_LEVEL},
414 [QDF_MODULE_ID_DP_TX_CAPTURE] = {QDF_DATA_PATH_TRACE_LEVEL},
415 [QDF_MODULE_ID_DP_INIT] = {QDF_DATA_PATH_TRACE_LEVEL},
416 [QDF_MODULE_ID_DP_STATS] = {QDF_DATA_PATH_TRACE_LEVEL},
417 [QDF_MODULE_ID_DP_HTT] = {QDF_DATA_PATH_TRACE_LEVEL},
418 [QDF_MODULE_ID_DP_PEER] = {QDF_DATA_PATH_TRACE_LEVEL},
419 [QDF_MODULE_ID_DP_HTT_TX_STATS] = {QDF_DATA_PATH_TRACE_LEVEL},
420 [QDF_MODULE_ID_DP_REO] = {QDF_DATA_PATH_TRACE_LEVEL},
421 [QDF_MODULE_ID_DP_VDEV] = {QDF_DATA_PATH_TRACE_LEVEL},
422 [QDF_MODULE_ID_DP_CDP] = {QDF_DATA_PATH_TRACE_LEVEL},
423 [QDF_MODULE_ID_DP_UMAC_RESET] = {QDF_DATA_PATH_TRACE_LEVEL},
424 [QDF_MODULE_ID_DP_SAWF] = {QDF_DATA_PATH_TRACE_LEVEL},
425 [QDF_MODULE_ID_SOC] = {QDF_TRACE_LEVEL_ALL},
426 [QDF_MODULE_ID_OS_IF] = {QDF_TRACE_LEVEL_ALL},
427 [QDF_MODULE_ID_TARGET_IF] = {QDF_TRACE_LEVEL_ALL},
428 [QDF_MODULE_ID_SCHEDULER] = {QDF_TRACE_LEVEL_ALL},
429 [QDF_MODULE_ID_MGMT_TXRX] = {QDF_TRACE_LEVEL_ALL},
430 [QDF_MODULE_ID_PMO] = {QDF_TRACE_LEVEL_ALL},
431 [QDF_MODULE_ID_SCAN] = {QDF_TRACE_LEVEL_ALL},
432 [QDF_MODULE_ID_POLICY_MGR] = {QDF_TRACE_LEVEL_ALL},
433 [QDF_MODULE_ID_P2P] = {QDF_TRACE_LEVEL_ALL},
434 [QDF_MODULE_ID_TDLS] = {QDF_TRACE_LEVEL_ALL},
435 [QDF_MODULE_ID_REGULATORY] = {QDF_TRACE_LEVEL_ALL},
436 [QDF_MODULE_ID_SERIALIZATION] = {QDF_TRACE_LEVEL_ALL},
437 [QDF_MODULE_ID_DFS] = {QDF_TRACE_LEVEL_ALL},
438 [QDF_MODULE_ID_OBJ_MGR] = {QDF_TRACE_LEVEL_ALL},
439 [QDF_MODULE_ID_ROAM_DEBUG] = {QDF_TRACE_LEVEL_ALL},
440 [QDF_MODULE_ID_GREEN_AP] = {QDF_TRACE_LEVEL_ALL},
441 [QDF_MODULE_ID_OCB] = {QDF_TRACE_LEVEL_ALL},
442 [QDF_MODULE_ID_IPA] = {QDF_TRACE_LEVEL_ALL},
443 [QDF_MODULE_ID_ACTION_OUI] = {QDF_TRACE_LEVEL_ALL},
444 [QDF_MODULE_ID_CONFIG] = {QDF_TRACE_LEVEL_ALL},
445 [QDF_MODULE_ID_MLME] = {QDF_TRACE_LEVEL_ALL},
446 [QDF_MODULE_ID_TARGET] = {QDF_TRACE_LEVEL_ALL},
447 [QDF_MODULE_ID_CRYPTO] = {QDF_TRACE_LEVEL_ALL},
448 [QDF_MODULE_ID_FWOL] = {QDF_TRACE_LEVEL_ALL},
449 [QDF_MODULE_ID_SM_ENGINE] = {QDF_TRACE_LEVEL_ALL},
450 [QDF_MODULE_ID_CMN_MLME] = {QDF_TRACE_LEVEL_ALL},
451 [QDF_MODULE_ID_NAN] = {QDF_TRACE_LEVEL_ALL},
452 [QDF_MODULE_ID_CP_STATS] = {QDF_TRACE_LEVEL_ALL},
453 [QDF_MODULE_ID_DCS] = {QDF_TRACE_LEVEL_ALL},
454 [QDF_MODULE_ID_INTEROP_ISSUES_AP] = {QDF_TRACE_LEVEL_ALL},
455 [QDF_MODULE_ID_DENYLIST_MGR] = {QDF_TRACE_LEVEL_ALL},
456 [QDF_MODULE_ID_DIRECT_BUF_RX] = {QDF_TRACE_LEVEL_ALL},
457 [QDF_MODULE_ID_SPECTRAL] = {QDF_TRACE_LEVEL_ALL},
458 [QDF_MODULE_ID_WIFIPOS] = {QDF_TRACE_LEVEL_ALL},
459 [QDF_MODULE_ID_PKT_CAPTURE] = {QDF_TRACE_LEVEL_ALL},
460 [QDF_MODULE_ID_FTM_TIME_SYNC] = {QDF_TRACE_LEVEL_ALL},
461 [QDF_MODULE_ID_CFR] = {QDF_TRACE_LEVEL_ALL},
462 [QDF_MODULE_ID_IFMGR] = {QDF_TRACE_LEVEL_ALL},
463 [QDF_MODULE_ID_GPIO] = {QDF_TRACE_LEVEL_ALL},
464 [QDF_MODULE_ID_T2LM] = {QDF_TRACE_LEVEL_ALL},
465 [QDF_MODULE_ID_MLO] = {QDF_TRACE_LEVEL_ALL},
466 [QDF_MODULE_ID_SON] = {QDF_TRACE_LEVEL_ALL},
467 [QDF_MODULE_ID_TWT] = {QDF_TRACE_LEVEL_ALL},
468 [QDF_MODULE_ID_WLAN_PRE_CAC] = {QDF_TRACE_LEVEL_ALL},
469 [QDF_MODULE_ID_COAP] = {QDF_TRACE_LEVEL_ALL},
470 [QDF_MODULE_ID_MON_FILTER] = {QDF_DATA_PATH_TRACE_LEVEL},
471 [QDF_MODULE_ID_LL_SAP] = {QDF_TRACE_LEVEL_ALL},
472 };
473
474 struct notifier_block hdd_netdev_notifier;
475
476 struct sock *cesium_nl_srv_sock;
477 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
478 static void wlan_hdd_auto_shutdown_cb(void);
479 #endif
480
481 static void hdd_dp_register_callbacks(struct hdd_context *hdd_ctx);
482
hdd_adapter_is_ap(struct hdd_adapter * adapter)483 bool hdd_adapter_is_ap(struct hdd_adapter *adapter)
484 {
485 if (!adapter) {
486 hdd_err("null adapter");
487 return false;
488 }
489
490 return adapter->device_mode == QDF_SAP_MODE ||
491 adapter->device_mode == QDF_P2P_GO_MODE;
492 }
493
hdd_common_roam_callback(struct wlan_objmgr_psoc * psoc,uint8_t session_id,struct csr_roam_info * roam_info,eRoamCmdStatus roam_status,eCsrRoamResult roam_result)494 QDF_STATUS hdd_common_roam_callback(struct wlan_objmgr_psoc *psoc,
495 uint8_t session_id,
496 struct csr_roam_info *roam_info,
497 eRoamCmdStatus roam_status,
498 eCsrRoamResult roam_result)
499 {
500 struct hdd_context *hdd_ctx;
501 struct hdd_adapter *adapter;
502 struct wlan_hdd_link_info *link_info;
503 QDF_STATUS status = QDF_STATUS_SUCCESS;
504
505 link_info = wlan_hdd_get_link_info_from_vdev(psoc, session_id);
506 if (!link_info)
507 return QDF_STATUS_E_INVAL;
508
509 adapter = link_info->adapter;
510 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
511 if (!hdd_ctx)
512 return QDF_STATUS_E_INVAL;
513
514 switch (adapter->device_mode) {
515 case QDF_STA_MODE:
516 case QDF_NDI_MODE:
517 case QDF_P2P_CLIENT_MODE:
518 case QDF_P2P_DEVICE_MODE:
519 status = hdd_sme_roam_callback(link_info, roam_info,
520 roam_status, roam_result);
521 break;
522 case QDF_SAP_MODE:
523 case QDF_P2P_GO_MODE:
524 status =
525 wlansap_roam_callback(link_info->session.ap.sap_context,
526 roam_info, roam_status,
527 roam_result);
528 break;
529 default:
530 hdd_err("Wrong device mode");
531 break;
532 }
533
534 return status;
535 }
536
hdd_start_complete(int ret)537 void hdd_start_complete(int ret)
538 {
539 wlan_start_ret_val = ret;
540 complete_all(&wlan_start_comp);
541 }
542
543 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
544 /**
545 * wlan_hdd_lpc_del_monitor_interface() - Delete monitor interface
546 * @hdd_ctx: hdd_ctx
547 * @is_virtual_iface: Is virtual interface
548 *
549 * This function takes care of deleting monitor interface
550 *
551 * Return: none
552 */
553 static void
wlan_hdd_lpc_del_monitor_interface(struct hdd_context * hdd_ctx,bool is_virtual_iface)554 wlan_hdd_lpc_del_monitor_interface(struct hdd_context *hdd_ctx,
555 bool is_virtual_iface)
556 {
557 struct hdd_adapter *adapter;
558 void *soc;
559 bool running;
560
561 if (!hdd_ctx)
562 return;
563
564 if (!ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc))
565 return;
566
567 soc = cds_get_context(QDF_MODULE_ID_SOC);
568 if (!soc)
569 return;
570
571 running = cdp_is_local_pkt_capture_running(soc, OL_TXRX_PDEV_ID);
572 if (!running)
573 return;
574
575 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
576 if (!adapter) {
577 hdd_debug("There is no monitor adapter");
578 return;
579 }
580
581 hdd_debug("lpc: Delete monitor interface");
582
583 wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes);
584 qdf_zero_macaddr(&adapter->mac_addr);
585 hdd_stop_adapter(hdd_ctx, adapter);
586 hdd_deinit_adapter(hdd_ctx, adapter, true);
587 adapter->is_virtual_iface = is_virtual_iface;
588 hdd_ctx->lpc_info.mon_adapter = adapter;
589
590 hdd_ctx->lpc_info.lpc_wk_scheduled = true;
591 qdf_sched_work(0, &hdd_ctx->lpc_info.lpc_wk);
592 }
593
wlan_hdd_lpc_handle_concurrency(struct hdd_context * hdd_ctx,bool is_virtual_iface)594 void wlan_hdd_lpc_handle_concurrency(struct hdd_context *hdd_ctx,
595 bool is_virtual_iface)
596 {
597 wlan_hdd_lpc_del_monitor_interface(hdd_ctx, is_virtual_iface);
598 }
599
hdd_lpc_is_work_scheduled(struct hdd_context * hdd_ctx)600 bool hdd_lpc_is_work_scheduled(struct hdd_context *hdd_ctx)
601 {
602 return hdd_ctx->lpc_info.lpc_wk_scheduled;
603 }
604
hdd_lpc_work_handler(void * arg)605 static void hdd_lpc_work_handler(void *arg)
606 {
607 struct hdd_context *hdd_ctx = (struct hdd_context *)arg;
608 struct hdd_adapter *adapter;
609 struct osif_vdev_sync *vdev_sync;
610 int errno;
611
612 if (!hdd_ctx)
613 return;
614
615 adapter = hdd_ctx->lpc_info.mon_adapter;
616 if (!adapter) {
617 hdd_err("There is no monitor adapter");
618 return;
619 }
620
621 errno = osif_vdev_sync_trans_start_wait(adapter->dev, &vdev_sync);
622 if (errno)
623 return;
624
625 osif_vdev_sync_unregister(adapter->dev);
626 osif_vdev_sync_wait_for_ops(vdev_sync);
627
628 hdd_close_adapter(hdd_ctx, adapter, true);
629 hdd_ctx->lpc_info.lpc_wk_scheduled = false;
630
631 osif_vdev_sync_trans_stop(vdev_sync);
632 osif_vdev_sync_destroy(vdev_sync);
633 }
634
635 static inline
hdd_lp_create_work(struct hdd_context * hdd_ctx)636 void hdd_lp_create_work(struct hdd_context *hdd_ctx)
637 {
638 hdd_ctx->lpc_info.lpc_wk_scheduled = false;
639 qdf_create_work(0, &hdd_ctx->lpc_info.lpc_wk, hdd_lpc_work_handler,
640 hdd_ctx);
641 }
642
643 static inline
hdd_lpc_delete_work(struct hdd_context * hdd_ctx)644 void hdd_lpc_delete_work(struct hdd_context *hdd_ctx)
645 {
646 qdf_flush_work(&hdd_ctx->lpc_info.lpc_wk);
647 hdd_ctx->lpc_info.lpc_wk_scheduled = false;
648 qdf_destroy_work(NULL, &hdd_ctx->lpc_info.lpc_wk);
649 }
650
651 #else
652 static inline
hdd_lp_create_work(struct hdd_context * hdd_ctx)653 void hdd_lp_create_work(struct hdd_context *hdd_ctx)
654 {
655 }
656
657 static inline
hdd_lpc_delete_work(struct hdd_context * hdd_ctx)658 void hdd_lpc_delete_work(struct hdd_context *hdd_ctx)
659 {
660 }
661
662 static inline
wlan_hdd_lpc_del_monitor_interface(struct hdd_context * hdd_ctx,bool is_virtual_iface)663 void wlan_hdd_lpc_del_monitor_interface(struct hdd_context *hdd_ctx,
664 bool is_virtual_iface)
665 {
666 }
667 #endif
668
669 #ifdef QCA_HL_NETDEV_FLOW_CONTROL
wlan_hdd_mod_fc_timer(struct hdd_adapter * adapter,enum netif_action_type action)670 void wlan_hdd_mod_fc_timer(struct hdd_adapter *adapter,
671 enum netif_action_type action)
672 {
673 struct hdd_stats *hdd_stats;
674
675 if (!adapter->tx_flow_timer_initialized)
676 return;
677
678 hdd_stats = &adapter->deflink->hdd_stats;
679 if (action == WLAN_WAKE_NON_PRIORITY_QUEUE) {
680 qdf_mc_timer_stop(&adapter->tx_flow_control_timer);
681 hdd_stats->tx_rx_stats.is_txflow_paused = false;
682 hdd_stats->tx_rx_stats.txflow_unpause_cnt++;
683 } else if (action == WLAN_STOP_NON_PRIORITY_QUEUE) {
684 QDF_STATUS status =
685 qdf_mc_timer_start(&adapter->tx_flow_control_timer,
686 WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
687
688 if (!QDF_IS_STATUS_SUCCESS(status))
689 hdd_err("Failed to start tx_flow_control_timer");
690 else
691 hdd_stats->tx_rx_stats.txflow_timer_cnt++;
692
693 hdd_stats->tx_rx_stats.txflow_pause_cnt++;
694 hdd_stats->tx_rx_stats.is_txflow_paused = true;
695 }
696 }
697 #endif /* QCA_HL_NETDEV_FLOW_CONTROL */
698
699 /**
700 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
701 * @vdev_id: vdev_id
702 * @action: action type
703 * @reason: reason type
704 *
705 * Return: none
706 */
wlan_hdd_txrx_pause_cb(uint8_t vdev_id,enum netif_action_type action,enum netif_reason_type reason)707 void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
708 enum netif_action_type action, enum netif_reason_type reason)
709 {
710 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
711 struct hdd_adapter *adapter;
712 struct wlan_hdd_link_info *link_info;
713
714 if (!hdd_ctx)
715 return;
716
717 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
718 if (!link_info)
719 return;
720
721 adapter = link_info->adapter;
722 wlan_hdd_mod_fc_timer(adapter, action);
723 wlan_hdd_netif_queue_control(adapter, action, reason);
724 }
725
726 /*
727 * Store WLAN driver version and timestamp info in global variables such that
728 * crash debugger can extract them from driver debug symbol and crashdump for
729 * post processing
730 */
731 #ifdef BUILD_TAG
732 uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR PANIC_ON_BUG_STR "; " BUILD_TAG;
733 #else
734 uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR PANIC_ON_BUG_STR;
735 #endif
736
hdd_validate_channel_and_bandwidth(struct hdd_adapter * adapter,qdf_freq_t chan_freq,enum phy_ch_width chan_bw)737 int hdd_validate_channel_and_bandwidth(struct hdd_adapter *adapter,
738 qdf_freq_t chan_freq,
739 enum phy_ch_width chan_bw)
740 {
741 struct ch_params ch_params = {0};
742 struct hdd_context *hdd_ctx;
743
744 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
745 if (!hdd_ctx) {
746 hdd_err("hdd context is NULL");
747 return -EINVAL;
748 }
749
750 if (reg_is_chan_enum_invalid(
751 wlan_reg_get_chan_enum_for_freq(chan_freq))) {
752 hdd_err("Channel freq %d not in driver's valid channel list", chan_freq);
753 return -EOPNOTSUPP;
754 }
755
756 if ((!WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) &&
757 (!WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq)) &&
758 (!WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq))) {
759 hdd_err("CH %d is not in 2.4GHz or 5GHz or 6GHz", chan_freq);
760 return -EINVAL;
761 }
762 ch_params.ch_width = CH_WIDTH_MAX;
763 wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev, chan_freq,
764 0, &ch_params,
765 REG_CURRENT_PWR_MODE);
766 if (ch_params.ch_width == CH_WIDTH_MAX) {
767 hdd_err("failed to get max bandwdith for %d", chan_freq);
768 return -EINVAL;
769 }
770 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) {
771 if (chan_bw == CH_WIDTH_80MHZ) {
772 hdd_err("BW80 not possible in 2.4GHz band");
773 return -EINVAL;
774 }
775 if ((chan_bw != CH_WIDTH_20MHZ) &&
776 (chan_freq == wlan_reg_ch_to_freq(CHAN_ENUM_2484)) &&
777 (chan_bw != CH_WIDTH_MAX) &&
778 (ch_params.ch_width == CH_WIDTH_20MHZ)) {
779 hdd_err("Only BW20 possible on channel freq 2484");
780 return -EINVAL;
781 }
782 }
783
784 if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq)) {
785 if ((chan_bw != CH_WIDTH_20MHZ) &&
786 (chan_freq == wlan_reg_ch_to_freq(CHAN_ENUM_5825)) &&
787 (chan_bw != CH_WIDTH_MAX) &&
788 (ch_params.ch_width == CH_WIDTH_20MHZ)) {
789 hdd_err("Only BW20 possible on channel freq 5825");
790 return -EINVAL;
791 }
792 }
793
794 return 0;
795 }
796
hdd_get_link_info_home_channel(struct wlan_hdd_link_info * link_info)797 uint32_t hdd_get_link_info_home_channel(struct wlan_hdd_link_info *link_info)
798 {
799 uint32_t home_chan_freq = 0;
800 enum QDF_OPMODE opmode = link_info->adapter->device_mode;
801
802 switch (opmode) {
803 case QDF_SAP_MODE:
804 case QDF_P2P_GO_MODE:
805 if (test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
806 home_chan_freq =
807 link_info->session.ap.operating_chan_freq;
808 }
809 break;
810 case QDF_STA_MODE:
811 case QDF_P2P_CLIENT_MODE:
812 if (hdd_cm_is_vdev_associated(link_info)) {
813 home_chan_freq =
814 link_info->session.station.conn_info.chan_freq;
815 }
816 break;
817 default:
818 break;
819 }
820
821 return home_chan_freq;
822 }
823
hdd_get_link_info_width(struct wlan_hdd_link_info * link_info)824 enum phy_ch_width hdd_get_link_info_width(struct wlan_hdd_link_info *link_info)
825 {
826 enum phy_ch_width width = CH_WIDTH_20MHZ;
827 enum QDF_OPMODE opmode = link_info->adapter->device_mode;
828
829 switch (opmode) {
830 case QDF_SAP_MODE:
831 case QDF_P2P_GO_MODE:
832 if (test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
833 struct hdd_ap_ctx *ap_ctx =
834 WLAN_HDD_GET_AP_CTX_PTR(link_info);
835
836 width = ap_ctx->sap_config.ch_params.ch_width;
837 }
838 break;
839 case QDF_STA_MODE:
840 case QDF_P2P_CLIENT_MODE:
841 if (hdd_cm_is_vdev_associated(link_info))
842 width = link_info->session.station.conn_info.ch_width;
843 break;
844 default:
845 break;
846 }
847
848 return width;
849 }
850
851 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
hdd_net_dev_from_notifier(void * context)852 static inline struct net_device *hdd_net_dev_from_notifier(void *context)
853 {
854 struct netdev_notifier_info *info = context;
855
856 return info->dev;
857 }
858 #else
hdd_net_dev_from_notifier(void * context)859 static inline struct net_device *hdd_net_dev_from_notifier(void *context)
860 {
861 return context;
862 }
863 #endif
864
__hdd_netdev_notifier_call(struct net_device * net_dev,unsigned long state)865 static int __hdd_netdev_notifier_call(struct net_device *net_dev,
866 unsigned long state)
867 {
868 struct hdd_adapter *adapter;
869 struct hdd_context *hdd_ctx;
870 struct wlan_objmgr_vdev *vdev;
871
872 hdd_enter_dev(net_dev);
873
874 if (!net_dev->ieee80211_ptr) {
875 hdd_debug("ieee80211_ptr is null");
876 return NOTIFY_DONE;
877 }
878
879 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
880 if (!hdd_ctx)
881 return NOTIFY_DONE;
882
883 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
884 hdd_debug("Driver module is closed");
885 return NOTIFY_DONE;
886 }
887
888 /* Make sure that this callback corresponds to our device. */
889 adapter = hdd_get_adapter_by_iface_name(hdd_ctx, net_dev->name);
890 if (!adapter) {
891 hdd_debug("failed to look up adapter for '%s'", net_dev->name);
892 return NOTIFY_DONE;
893 }
894
895 if (adapter != WLAN_HDD_GET_PRIV_PTR(net_dev)) {
896 hdd_err("HDD adapter mismatch!");
897 return NOTIFY_DONE;
898 }
899
900 if (cds_is_driver_recovering()) {
901 hdd_debug("Driver is recovering");
902 return NOTIFY_DONE;
903 }
904
905 if (cds_is_driver_in_bad_state()) {
906 hdd_debug("Driver is in failed recovery state");
907 return NOTIFY_DONE;
908 }
909
910 hdd_debug("%s New Net Device State = %lu, flags 0x%x",
911 net_dev->name, state, net_dev->flags);
912
913 switch (state) {
914 case NETDEV_REGISTER:
915 break;
916
917 case NETDEV_UNREGISTER:
918 break;
919
920 case NETDEV_UP:
921 sme_ch_avoid_update_req(hdd_ctx->mac_handle);
922 break;
923
924 case NETDEV_DOWN:
925 break;
926
927 case NETDEV_CHANGE:
928 if (adapter->is_link_up_service_needed)
929 complete(&adapter->linkup_event_var);
930 break;
931
932 case NETDEV_GOING_DOWN:
933 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
934 WLAN_OSIF_SCAN_ID);
935 if (!vdev)
936 break;
937 if (ucfg_scan_get_vdev_status(vdev) !=
938 SCAN_NOT_IN_PROGRESS) {
939 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
940 adapter->deflink->vdev_id,
941 INVALID_SCAN_ID, true);
942 }
943 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SCAN_ID);
944 cds_flush_work(&adapter->scan_block_work);
945 /* Need to clean up blocked scan request */
946 wlan_hdd_cfg80211_scan_block(adapter);
947 hdd_debug("Scan is not Pending from user");
948 /*
949 * After NETDEV_GOING_DOWN, kernel calls hdd_stop.Irrespective
950 * of return status of hdd_stop call, kernel resets the IFF_UP
951 * flag after which driver does not send the cfg80211_scan_done.
952 * Ensure to cleanup the scan queue in NETDEV_GOING_DOWN
953 */
954 wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, net_dev);
955 break;
956 case NETDEV_FEAT_CHANGE:
957 hdd_debug("vdev %d netdev Feature 0x%llx\n",
958 adapter->deflink->vdev_id, net_dev->features);
959 break;
960 default:
961 break;
962 }
963
964 return NOTIFY_DONE;
965 }
966
hdd_netdev_notifier_bridge_intf(struct net_device * net_dev,unsigned long state)967 static int hdd_netdev_notifier_bridge_intf(struct net_device *net_dev,
968 unsigned long state)
969 {
970 struct hdd_adapter *adapter, *next_adapter = NULL;
971 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER;
972 struct hdd_context *hdd_ctx;
973 QDF_STATUS status;
974
975 hdd_enter_dev(net_dev);
976
977 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
978 if (wlan_hdd_validate_context(hdd_ctx))
979 return NOTIFY_DONE;
980
981 hdd_debug("%s New Net Device State = %lu, flags 0x%x bridge mac address: "QDF_MAC_ADDR_FMT,
982 net_dev->name, state, net_dev->flags, QDF_MAC_ADDR_REF(net_dev->dev_addr));
983
984 if (!qdf_mem_cmp(hdd_ctx->bridgeaddr, net_dev->dev_addr,
985 QDF_MAC_ADDR_SIZE))
986 return NOTIFY_DONE;
987
988 switch (state) {
989 case NETDEV_REGISTER:
990 case NETDEV_CHANGEADDR:
991 /* Update FW WoW pattern with new MAC address */
992 qdf_mem_copy(hdd_ctx->bridgeaddr, net_dev->dev_addr,
993 QDF_MAC_ADDR_SIZE);
994
995 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
996 dbgid) {
997 if (adapter->device_mode != QDF_SAP_MODE)
998 goto loop_next;
999
1000 if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
1001 goto loop_next;
1002
1003 status = wlan_objmgr_vdev_try_get_ref(adapter->deflink->vdev,
1004 WLAN_HDD_ID_OBJ_MGR);
1005 if (QDF_IS_STATUS_ERROR(status))
1006 goto loop_next;
1007
1008 ucfg_pmo_set_vdev_bridge_addr(adapter->deflink->vdev,
1009 (struct qdf_mac_addr *)hdd_ctx->bridgeaddr);
1010 ucfg_pmo_del_wow_pattern(adapter->deflink->vdev);
1011 ucfg_pmo_register_wow_default_patterns(adapter->deflink->vdev);
1012
1013 wlan_objmgr_vdev_release_ref(adapter->deflink->vdev,
1014 WLAN_HDD_ID_OBJ_MGR);
1015
1016 loop_next:
1017 hdd_adapter_dev_put_debug(adapter, dbgid);
1018 }
1019
1020 break;
1021 case NETDEV_UNREGISTER:
1022 qdf_zero_macaddr((struct qdf_mac_addr *)hdd_ctx->bridgeaddr);
1023 break;
1024 default:
1025 break;
1026 }
1027
1028 return NOTIFY_DONE;
1029 }
1030
1031 /**
1032 * hdd_netdev_notifier_call() - netdev notifier callback function
1033 * @nb: pointer to notifier block
1034 * @state: state
1035 * @context: notifier callback context pointer
1036 *
1037 * Return: 0 on success, error number otherwise.
1038 */
hdd_netdev_notifier_call(struct notifier_block * nb,unsigned long state,void * context)1039 static int hdd_netdev_notifier_call(struct notifier_block *nb,
1040 unsigned long state,
1041 void *context)
1042 {
1043 struct net_device *net_dev = hdd_net_dev_from_notifier(context);
1044 struct osif_vdev_sync *vdev_sync;
1045 int errno;
1046
1047 if (net_dev->priv_flags & IFF_EBRIDGE) {
1048 errno = hdd_netdev_notifier_bridge_intf(net_dev, state);
1049 if (errno)
1050 return NOTIFY_DONE;
1051 }
1052
1053 errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
1054 if (errno) {
1055 hdd_debug("%s New Net Device State = %lu, flags 0x%x NOTIFY_DONE",
1056 net_dev->name, state, net_dev->flags);
1057 return NOTIFY_DONE;
1058 }
1059
1060 errno = __hdd_netdev_notifier_call(net_dev, state);
1061
1062 osif_vdev_sync_op_stop(vdev_sync);
1063
1064 return NOTIFY_DONE;
1065 }
1066
1067 struct notifier_block hdd_netdev_notifier = {
1068 .notifier_call = hdd_netdev_notifier_call,
1069 };
1070
1071 /* variable to hold the insmod parameters */
1072 int con_mode;
1073 #ifdef FEATURE_WLAN_RESIDENT_DRIVER
1074 EXPORT_SYMBOL(con_mode);
1075 #endif
1076
1077 int con_mode_ftm;
1078 #ifdef FEATURE_WLAN_RESIDENT_DRIVER
1079 EXPORT_SYMBOL(con_mode_ftm);
1080 #endif
1081 int con_mode_epping;
1082
1083 static int pcie_gen_speed;
1084
1085 /* Variable to hold connection mode including module parameter con_mode */
1086 static int curr_con_mode;
1087
1088 #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC)
hdd_get_eht_phy_ch_width_from_target(void)1089 static enum phy_ch_width hdd_get_eht_phy_ch_width_from_target(void)
1090 {
1091 uint32_t max_fw_bw = sme_get_eht_ch_width();
1092
1093 if (max_fw_bw == WNI_CFG_EHT_CHANNEL_WIDTH_320MHZ)
1094 return CH_WIDTH_320MHZ;
1095 else if (max_fw_bw == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
1096 return CH_WIDTH_160MHZ;
1097 else
1098 return CH_WIDTH_80MHZ;
1099 }
1100
hdd_is_target_eht_phy_ch_width_supported(enum phy_ch_width width)1101 static bool hdd_is_target_eht_phy_ch_width_supported(enum phy_ch_width width)
1102 {
1103 enum phy_ch_width max_fw_bw = hdd_get_eht_phy_ch_width_from_target();
1104
1105 if (width <= max_fw_bw)
1106 return true;
1107
1108 hdd_err("FW does not support this BW %d max BW supported %d",
1109 width, max_fw_bw);
1110 return false;
1111 }
1112
hdd_is_target_eht_160mhz_capable(void)1113 static bool hdd_is_target_eht_160mhz_capable(void)
1114 {
1115 return hdd_is_target_eht_phy_ch_width_supported(CH_WIDTH_160MHZ);
1116 }
1117
1118 static enum phy_ch_width
wlan_hdd_map_nl_chan_width(enum nl80211_chan_width width)1119 wlan_hdd_map_nl_chan_width(enum nl80211_chan_width width)
1120 {
1121 if (width == NL80211_CHAN_WIDTH_320) {
1122 return hdd_get_eht_phy_ch_width_from_target();
1123 } else {
1124 hdd_err("Invalid channel width %d, setting to default", width);
1125 return CH_WIDTH_INVALID;
1126 }
1127 }
1128
1129 #else /* !WLAN_FEATURE_11BE */
1130 static inline bool
hdd_is_target_eht_phy_ch_width_supported(enum phy_ch_width width)1131 hdd_is_target_eht_phy_ch_width_supported(enum phy_ch_width width)
1132 {
1133 return true;
1134 }
1135
hdd_is_target_eht_160mhz_capable(void)1136 static inline bool hdd_is_target_eht_160mhz_capable(void)
1137 {
1138 return false;
1139 }
1140
1141 static enum phy_ch_width
wlan_hdd_map_nl_chan_width(enum nl80211_chan_width width)1142 wlan_hdd_map_nl_chan_width(enum nl80211_chan_width width)
1143 {
1144 hdd_err("Invalid channel width %d, setting to default", width);
1145 return CH_WIDTH_INVALID;
1146 }
1147 #endif /* WLAN_FEATURE_11BE */
1148
1149 /**
1150 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
1151 * @ch_width: NL channel width
1152 *
1153 * Converts the NL channel width to the driver's internal representation
1154 *
1155 * Return: Converted channel width. In case of non matching NL channel width,
1156 * CH_WIDTH_MAX will be returned.
1157 */
hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)1158 enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
1159 {
1160 uint8_t fw_ch_bw;
1161
1162 fw_ch_bw = wma_get_vht_ch_width();
1163 switch (ch_width) {
1164 case NL80211_CHAN_WIDTH_20_NOHT:
1165 case NL80211_CHAN_WIDTH_20:
1166 return CH_WIDTH_20MHZ;
1167 case NL80211_CHAN_WIDTH_40:
1168 return CH_WIDTH_40MHZ;
1169 case NL80211_CHAN_WIDTH_80:
1170 return CH_WIDTH_80MHZ;
1171 case NL80211_CHAN_WIDTH_80P80:
1172 if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
1173 return CH_WIDTH_80P80MHZ;
1174 else if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
1175 return CH_WIDTH_160MHZ;
1176 else
1177 return CH_WIDTH_80MHZ;
1178 case NL80211_CHAN_WIDTH_160:
1179 if (hdd_is_target_eht_160mhz_capable())
1180 return CH_WIDTH_160MHZ;
1181
1182 if (fw_ch_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
1183 return CH_WIDTH_160MHZ;
1184 else
1185 return CH_WIDTH_80MHZ;
1186 case NL80211_CHAN_WIDTH_5:
1187 return CH_WIDTH_5MHZ;
1188 case NL80211_CHAN_WIDTH_10:
1189 return CH_WIDTH_10MHZ;
1190 default:
1191 return wlan_hdd_map_nl_chan_width(ch_width);
1192 }
1193 }
1194
1195 #if defined(WLAN_FEATURE_NAN) && \
1196 (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
1197 /**
1198 * wlan_hdd_convert_nan_type() - Convert nl type to qdf type
1199 * @nl_type: NL80211 interface type
1200 * @out_qdf_type: QDF type for the given nl_type
1201 *
1202 * Convert nl type to QDF type
1203 *
1204 * Return: QDF_STATUS_SUCCESS if converted, failure otherwise.
1205 */
wlan_hdd_convert_nan_type(enum nl80211_iftype nl_type,enum QDF_OPMODE * out_qdf_type)1206 static QDF_STATUS wlan_hdd_convert_nan_type(enum nl80211_iftype nl_type,
1207 enum QDF_OPMODE *out_qdf_type)
1208 {
1209 if (nl_type == NL80211_IFTYPE_NAN) {
1210 *out_qdf_type = QDF_NAN_DISC_MODE;
1211 return QDF_STATUS_SUCCESS;
1212 }
1213 return QDF_STATUS_E_INVAL;
1214 }
1215
1216 /**
1217 * wlan_hdd_set_nan_if_type() - Set the NAN iftype
1218 * @adapter: pointer to HDD adapter
1219 *
1220 * Set the NL80211_IFTYPE_NAN to wdev iftype.
1221 *
1222 * Return: None
1223 */
wlan_hdd_set_nan_if_type(struct hdd_adapter * adapter)1224 static void wlan_hdd_set_nan_if_type(struct hdd_adapter *adapter)
1225 {
1226 adapter->wdev.iftype = NL80211_IFTYPE_NAN;
1227 }
1228
wlan_hdd_is_vdev_creation_allowed(struct wlan_objmgr_psoc * psoc)1229 static bool wlan_hdd_is_vdev_creation_allowed(struct wlan_objmgr_psoc *psoc)
1230 {
1231 return ucfg_nan_is_vdev_creation_allowed(psoc);
1232 }
1233 #else
wlan_hdd_convert_nan_type(enum nl80211_iftype nl_type,enum QDF_OPMODE * out_qdf_type)1234 static QDF_STATUS wlan_hdd_convert_nan_type(enum nl80211_iftype nl_type,
1235 enum QDF_OPMODE *out_qdf_type)
1236 {
1237 return QDF_STATUS_E_INVAL;
1238 }
1239
wlan_hdd_set_nan_if_type(struct hdd_adapter * adapter)1240 static void wlan_hdd_set_nan_if_type(struct hdd_adapter *adapter)
1241 {
1242 }
1243
wlan_hdd_is_vdev_creation_allowed(struct wlan_objmgr_psoc * psoc)1244 static bool wlan_hdd_is_vdev_creation_allowed(struct wlan_objmgr_psoc *psoc)
1245 {
1246 return false;
1247 }
1248 #endif
1249
hdd_nl_to_qdf_iface_type(enum nl80211_iftype nl_type,enum QDF_OPMODE * out_qdf_type)1250 QDF_STATUS hdd_nl_to_qdf_iface_type(enum nl80211_iftype nl_type,
1251 enum QDF_OPMODE *out_qdf_type)
1252 {
1253 QDF_STATUS status = QDF_STATUS_SUCCESS;
1254
1255 switch (nl_type) {
1256 case NL80211_IFTYPE_AP:
1257 *out_qdf_type = QDF_SAP_MODE;
1258 break;
1259 case NL80211_IFTYPE_MONITOR:
1260 *out_qdf_type = QDF_MONITOR_MODE;
1261 break;
1262 case NL80211_IFTYPE_OCB:
1263 *out_qdf_type = QDF_OCB_MODE;
1264 break;
1265 case NL80211_IFTYPE_P2P_CLIENT:
1266 *out_qdf_type = QDF_P2P_CLIENT_MODE;
1267 break;
1268 case NL80211_IFTYPE_P2P_DEVICE:
1269 *out_qdf_type = QDF_P2P_DEVICE_MODE;
1270 break;
1271 case NL80211_IFTYPE_P2P_GO:
1272 *out_qdf_type = QDF_P2P_GO_MODE;
1273 break;
1274 case NL80211_IFTYPE_STATION:
1275 *out_qdf_type = QDF_STA_MODE;
1276 break;
1277 case NL80211_IFTYPE_WDS:
1278 *out_qdf_type = QDF_WDS_MODE;
1279 break;
1280 default:
1281 status = wlan_hdd_convert_nan_type(nl_type, out_qdf_type);
1282 if (QDF_IS_STATUS_SUCCESS(status))
1283 break;
1284 hdd_err("Invalid nl80211 interface type %d", nl_type);
1285 return QDF_STATUS_E_INVAL;
1286 }
1287
1288 return QDF_STATUS_SUCCESS;
1289 }
1290
wlan_hdd_find_opclass(mac_handle_t mac_handle,uint8_t channel,uint8_t bw_offset)1291 uint8_t wlan_hdd_find_opclass(mac_handle_t mac_handle, uint8_t channel,
1292 uint8_t bw_offset)
1293 {
1294 uint8_t opclass = 0;
1295
1296 sme_get_opclass(mac_handle, channel, bw_offset, &opclass);
1297 return opclass;
1298 }
1299
1300 /**
1301 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
1302 * @module_id: Module whose trace level is being configured
1303 * @bitmask: Bitmask of log levels to be enabled
1304 *
1305 * Called immediately after the cfg.ini is read in order to configure
1306 * the desired trace levels.
1307 *
1308 * Return: None
1309 */
hdd_qdf_trace_enable(QDF_MODULE_ID module_id,uint32_t bitmask)1310 int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask)
1311 {
1312 QDF_TRACE_LEVEL level;
1313 int qdf_print_idx = -1;
1314 int status = -1;
1315 /*
1316 * if the bitmask is the default value, then a bitmask was not
1317 * specified in cfg.ini, so leave the logging level alone (it
1318 * will remain at the "compiled in" default value)
1319 */
1320 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask)
1321 return 0;
1322
1323 qdf_print_idx = qdf_get_pidx();
1324
1325 /* a mask was specified. start by disabling all logging */
1326 status = qdf_print_set_category_verbose(qdf_print_idx, module_id,
1327 QDF_TRACE_LEVEL_NONE, 0);
1328
1329 if (QDF_STATUS_SUCCESS != status)
1330 return -EINVAL;
1331 /* now cycle through the bitmask until all "set" bits are serviced */
1332 level = QDF_TRACE_LEVEL_NONE;
1333 while (0 != bitmask) {
1334 if (bitmask & 1) {
1335 status = qdf_print_set_category_verbose(qdf_print_idx,
1336 module_id, level, 1);
1337 if (QDF_STATUS_SUCCESS != status)
1338 return -EINVAL;
1339 }
1340
1341 level++;
1342 bitmask >>= 1;
1343 }
1344 return 0;
1345 }
1346
__wlan_hdd_validate_context(struct hdd_context * hdd_ctx,const char * func)1347 int __wlan_hdd_validate_context(struct hdd_context *hdd_ctx, const char *func)
1348 {
1349 if (!hdd_ctx) {
1350 hdd_err("HDD context is null (via %s)", func);
1351 return -ENODEV;
1352 }
1353
1354 if (!hdd_ctx->config) {
1355 hdd_err("HDD config is null (via %s)", func);
1356 return -ENODEV;
1357 }
1358
1359 if (cds_is_driver_recovering()) {
1360 hdd_debug("Recovery in progress (via %s); state:0x%x",
1361 func, cds_get_driver_state());
1362 return -EAGAIN;
1363 }
1364
1365 if (cds_is_load_or_unload_in_progress()) {
1366 hdd_debug("Load/unload in progress (via %s); state:0x%x",
1367 func, cds_get_driver_state());
1368 return -EAGAIN;
1369 }
1370
1371 if (cds_is_driver_in_bad_state()) {
1372 hdd_debug("Driver in bad state (via %s); state:0x%x",
1373 func, cds_get_driver_state());
1374 return -EAGAIN;
1375 }
1376
1377 if (cds_is_fw_down()) {
1378 hdd_debug("FW is down (via %s); state:0x%x",
1379 func, cds_get_driver_state());
1380 return -EAGAIN;
1381 }
1382
1383 if (hdd_ctx->is_wlan_disabled) {
1384 hdd_debug("WLAN is disabled by user space");
1385 return -EAGAIN;
1386 }
1387
1388 return 0;
1389 }
1390
__hdd_validate_adapter(struct hdd_adapter * adapter,const char * func)1391 int __hdd_validate_adapter(struct hdd_adapter *adapter, const char *func)
1392 {
1393 if (!adapter) {
1394 hdd_err("adapter is null (via %s)", func);
1395 return -EINVAL;
1396 }
1397
1398 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
1399 hdd_err("bad adapter magic (via %s)", func);
1400 return -EINVAL;
1401 }
1402
1403 if (!adapter->dev) {
1404 hdd_err("adapter net_device is null (via %s)", func);
1405 return -EINVAL;
1406 }
1407
1408 if (!(adapter->dev->flags & IFF_UP)) {
1409 hdd_debug_rl("adapter '%s' is not up (via %s)",
1410 adapter->dev->name, func);
1411 return -EAGAIN;
1412 }
1413
1414 return __wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id, func);
1415 }
1416
__wlan_hdd_validate_vdev_id(uint8_t vdev_id,const char * func)1417 int __wlan_hdd_validate_vdev_id(uint8_t vdev_id, const char *func)
1418 {
1419 if (vdev_id == WLAN_UMAC_VDEV_ID_MAX) {
1420 hdd_debug_rl("adapter is not up (via %s)", func);
1421 return -EINVAL;
1422 }
1423
1424 if (vdev_id >= WLAN_MAX_VDEVS) {
1425 hdd_err("bad vdev Id:%u (via %s)", vdev_id, func);
1426 return -EINVAL;
1427 }
1428
1429 return 0;
1430 }
1431
__wlan_hdd_validate_mac_address(struct qdf_mac_addr * mac_addr,const char * func)1432 QDF_STATUS __wlan_hdd_validate_mac_address(struct qdf_mac_addr *mac_addr,
1433 const char *func)
1434 {
1435 if (!mac_addr) {
1436 hdd_err("Received NULL mac address (via %s)", func);
1437 return QDF_STATUS_E_INVAL;
1438 }
1439
1440 if (qdf_is_macaddr_zero(mac_addr)) {
1441 hdd_err("MAC is all zero (via %s)", func);
1442 return QDF_STATUS_E_INVAL;
1443 }
1444
1445 if (qdf_is_macaddr_broadcast(mac_addr)) {
1446 hdd_err("MAC is Broadcast (via %s)", func);
1447 return QDF_STATUS_E_INVAL;
1448 }
1449
1450 if (QDF_NET_IS_MAC_MULTICAST(mac_addr->bytes)) {
1451 hdd_err("MAC is Multicast (via %s)", func);
1452 return QDF_STATUS_E_INVAL;
1453 }
1454
1455 return QDF_STATUS_SUCCESS;
1456 }
1457
1458 /**
1459 * wlan_hdd_validate_modules_state() - Check modules status
1460 * @hdd_ctx: HDD context pointer
1461 *
1462 * Check's the driver module's state and returns true if the
1463 * modules are enabled returns false if modules are closed.
1464 *
1465 * Return: True if modules are enabled or false.
1466 */
wlan_hdd_validate_modules_state(struct hdd_context * hdd_ctx)1467 bool wlan_hdd_validate_modules_state(struct hdd_context *hdd_ctx)
1468 {
1469 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
1470 hdd_info("Modules not enabled, Present status: %d",
1471 hdd_ctx->driver_status);
1472 return false;
1473 }
1474
1475 return true;
1476 }
1477
1478 #ifdef FEATURE_RUNTIME_PM
1479 /**
1480 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
1481 * @hdd_ctx: HDD context
1482 *
1483 * Return: None
1484 */
hdd_runtime_suspend_context_init(struct hdd_context * hdd_ctx)1485 static void hdd_runtime_suspend_context_init(struct hdd_context *hdd_ctx)
1486 {
1487 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
1488
1489 qdf_runtime_lock_init(&ctx->dfs);
1490 qdf_runtime_lock_init(&ctx->connect);
1491 qdf_runtime_lock_init(&ctx->user);
1492 qdf_runtime_lock_init(&ctx->monitor_mode);
1493 qdf_runtime_lock_init(&ctx->wow_unit_test);
1494 qdf_runtime_lock_init(&ctx->system_suspend);
1495 qdf_runtime_lock_init(&ctx->dyn_mac_addr_update);
1496 qdf_runtime_lock_init(&ctx->vdev_destroy);
1497 qdf_runtime_lock_init(&ctx->oem_data_cmd);
1498
1499 qdf_rtpm_register(QDF_RTPM_ID_WIPHY_SUSPEND, NULL);
1500 qdf_rtpm_register(QDF_RTPM_ID_PM_QOS_NOTIFY, NULL);
1501
1502 ctx->is_user_wakelock_acquired = false;
1503
1504 wlan_scan_runtime_pm_init(hdd_ctx->pdev);
1505 }
1506
1507 /**
1508 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
1509 * @hdd_ctx: HDD Context
1510 *
1511 * Return: None
1512 */
hdd_runtime_suspend_context_deinit(struct hdd_context * hdd_ctx)1513 static void hdd_runtime_suspend_context_deinit(struct hdd_context *hdd_ctx)
1514 {
1515 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
1516
1517 if (ctx->is_user_wakelock_acquired)
1518 qdf_runtime_pm_allow_suspend(&ctx->user);
1519
1520 qdf_runtime_lock_deinit(&ctx->oem_data_cmd);
1521 qdf_runtime_lock_deinit(&ctx->dyn_mac_addr_update);
1522 qdf_runtime_lock_deinit(&ctx->wow_unit_test);
1523 qdf_runtime_lock_deinit(&ctx->monitor_mode);
1524 qdf_runtime_lock_deinit(&ctx->user);
1525 qdf_runtime_lock_deinit(&ctx->connect);
1526 qdf_runtime_lock_deinit(&ctx->dfs);
1527 qdf_runtime_lock_deinit(&ctx->system_suspend);
1528 qdf_runtime_lock_deinit(&ctx->vdev_destroy);
1529
1530 qdf_rtpm_deregister(QDF_RTPM_ID_WIPHY_SUSPEND);
1531 qdf_rtpm_deregister(QDF_RTPM_ID_PM_QOS_NOTIFY);
1532
1533 wlan_scan_runtime_pm_deinit(hdd_ctx->pdev);
1534 }
1535
1536 #else /* FEATURE_RUNTIME_PM */
hdd_runtime_suspend_context_init(struct hdd_context * hdd_ctx)1537 static void hdd_runtime_suspend_context_init(struct hdd_context *hdd_ctx) {}
hdd_runtime_suspend_context_deinit(struct hdd_context * hdd_ctx)1538 static void hdd_runtime_suspend_context_deinit(struct hdd_context *hdd_ctx) {}
1539 #endif /* FEATURE_RUNTIME_PM */
1540
hdd_update_macaddr(struct hdd_context * hdd_ctx,struct qdf_mac_addr hw_macaddr,bool generate_mac_auto)1541 void hdd_update_macaddr(struct hdd_context *hdd_ctx,
1542 struct qdf_mac_addr hw_macaddr, bool generate_mac_auto)
1543 {
1544 int8_t i;
1545 uint8_t macaddr_b3, tmp_br3;
1546
1547 /*
1548 * If "generate_mac_auto" is true, it indicates that all the
1549 * addresses are derived addresses, else the first addresses
1550 * is not derived address (It is provided by fw).
1551 */
1552 if (!generate_mac_auto) {
1553 qdf_mem_copy(hdd_ctx->provisioned_mac_addr[0].bytes,
1554 hw_macaddr.bytes, QDF_MAC_ADDR_SIZE);
1555 hdd_ctx->num_provisioned_addr++;
1556 hdd_debug("hdd_ctx->provisioned_mac_addr[0]: "
1557 QDF_MAC_ADDR_FMT,
1558 QDF_MAC_ADDR_REF(hdd_ctx->
1559 provisioned_mac_addr[0].bytes));
1560 } else {
1561 qdf_mem_copy(hdd_ctx->derived_mac_addr[0].bytes,
1562 hw_macaddr.bytes,
1563 QDF_MAC_ADDR_SIZE);
1564 hdd_ctx->num_derived_addr++;
1565 hdd_debug("hdd_ctx->derived_mac_addr[0]: "
1566 QDF_MAC_ADDR_FMT,
1567 QDF_MAC_ADDR_REF(hdd_ctx->derived_mac_addr[0].bytes));
1568 }
1569 for (i = hdd_ctx->num_derived_addr; i < (QDF_MAX_CONCURRENCY_PERSONA -
1570 hdd_ctx->num_provisioned_addr);
1571 i++) {
1572 qdf_mem_copy(hdd_ctx->derived_mac_addr[i].bytes,
1573 hw_macaddr.bytes,
1574 QDF_MAC_ADDR_SIZE);
1575 macaddr_b3 = hdd_ctx->derived_mac_addr[i].bytes[3];
1576 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
1577 INTF_MACADDR_MASK;
1578 macaddr_b3 += tmp_br3;
1579
1580 /* XOR-ing bit-24 of the mac address. This will give enough
1581 * mac address range before collision
1582 */
1583 macaddr_b3 ^= (1 << 7);
1584
1585 /* Set locally administered bit */
1586 hdd_ctx->derived_mac_addr[i].bytes[0] |= 0x02;
1587 hdd_ctx->derived_mac_addr[i].bytes[3] = macaddr_b3;
1588 hdd_debug("hdd_ctx->derived_mac_addr[%d]: "
1589 QDF_MAC_ADDR_FMT, i,
1590 QDF_MAC_ADDR_REF(hdd_ctx->derived_mac_addr[i].bytes));
1591 hdd_ctx->num_derived_addr++;
1592 }
1593 }
1594
1595 #ifdef FEATURE_WLAN_TDLS
hdd_update_tdls_config(struct hdd_context * hdd_ctx)1596 static int hdd_update_tdls_config(struct hdd_context *hdd_ctx)
1597 {
1598 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
1599 struct tdls_start_params tdls_cfg;
1600 QDF_STATUS status;
1601 struct wlan_mlme_nss_chains vdev_ini_cfg;
1602
1603 /* Populate the nss chain params from ini for this vdev type */
1604 sme_populate_nss_chain_params(hdd_ctx->mac_handle, &vdev_ini_cfg,
1605 QDF_TDLS_MODE,
1606 hdd_ctx->num_rf_chains);
1607
1608 cfg_tdls_set_vdev_nss_2g(hdd_ctx->psoc,
1609 vdev_ini_cfg.rx_nss[NSS_CHAINS_BAND_2GHZ]);
1610 cfg_tdls_set_vdev_nss_5g(hdd_ctx->psoc,
1611 vdev_ini_cfg.rx_nss[NSS_CHAINS_BAND_5GHZ]);
1612 hdd_init_tdls_config(&tdls_cfg);
1613 tdls_cfg.tdls_del_all_peers = eWNI_SME_DEL_ALL_TDLS_PEERS;
1614 tdls_cfg.tdls_update_dp_vdev_flags = CDP_UPDATE_TDLS_FLAGS;
1615 tdls_cfg.tdls_event_cb = wlan_cfg80211_tdls_event_callback;
1616 tdls_cfg.tdls_evt_cb_data = psoc;
1617 tdls_cfg.tdls_peer_context = hdd_ctx;
1618 tdls_cfg.tdls_reg_peer = hdd_tdls_register_peer;
1619 tdls_cfg.tdls_wmm_cb = hdd_wmm_is_acm_allowed;
1620 tdls_cfg.tdls_wmm_cb_data = psoc;
1621 tdls_cfg.tdls_rx_cb = wlan_cfg80211_tdls_rx_callback;
1622 tdls_cfg.tdls_rx_cb_data = psoc;
1623 tdls_cfg.tdls_dp_vdev_update = hdd_update_dp_vdev_flags;
1624 tdls_cfg.tdls_osif_init_cb = wlan_cfg80211_tdls_osif_priv_init;
1625 tdls_cfg.tdls_osif_deinit_cb = wlan_cfg80211_tdls_osif_priv_deinit;
1626 tdls_cfg.tdls_osif_update_cb.tdls_osif_conn_update =
1627 hdd_check_and_set_tdls_conn_params;
1628 tdls_cfg.tdls_osif_update_cb.tdls_osif_disconn_update =
1629 hdd_check_and_set_tdls_disconn_params;
1630
1631 status = ucfg_tdls_update_config(psoc, &tdls_cfg);
1632 if (status != QDF_STATUS_SUCCESS) {
1633 hdd_err("failed pmo psoc configuration");
1634 return -EINVAL;
1635 }
1636
1637 hdd_ctx->tdls_umac_comp_active = true;
1638 /* enable napier specific tdls data path */
1639 hdd_ctx->tdls_nap_active = true;
1640
1641 return 0;
1642 }
1643 #else
hdd_update_tdls_config(struct hdd_context * hdd_ctx)1644 static int hdd_update_tdls_config(struct hdd_context *hdd_ctx)
1645 {
1646 return 0;
1647 }
1648 #endif
1649
hdd_indicate_active_ndp_cnt(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,uint8_t cnt)1650 void hdd_indicate_active_ndp_cnt(struct wlan_objmgr_psoc *psoc,
1651 uint8_t vdev_id, uint8_t cnt)
1652 {
1653 struct wlan_hdd_link_info *link_info;
1654
1655 link_info = wlan_hdd_get_link_info_from_vdev(psoc, vdev_id);
1656 if (!link_info || !cfg_nan_is_roam_config_disabled(psoc))
1657 return;
1658
1659 hdd_debug("vdev_id:%d%s active ndp sessions present", vdev_id,
1660 cnt ? "" : " no more");
1661 if (!cnt)
1662 wlan_hdd_set_roaming_state(link_info, RSO_NDP_CON_ON_NDI, true);
1663 else
1664 wlan_hdd_set_roaming_state(link_info, RSO_NDP_CON_ON_NDI,
1665 false);
1666 }
1667
1668 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
hdd_update_roam_offload(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1669 static void hdd_update_roam_offload(struct hdd_context *hdd_ctx,
1670 struct wma_tgt_services *cfg)
1671 {
1672 bool roam_offload_enable;
1673
1674 ucfg_mlme_get_roaming_offload(hdd_ctx->psoc, &roam_offload_enable);
1675 ucfg_mlme_set_roaming_offload(hdd_ctx->psoc,
1676 roam_offload_enable &
1677 cfg->en_roam_offload);
1678 }
1679 #else
hdd_update_roam_offload(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1680 static inline void hdd_update_roam_offload(struct hdd_context *hdd_ctx,
1681 struct wma_tgt_services *cfg)
1682 {
1683 }
1684 #endif
1685
1686 #ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION
1687 static void
hdd_club_ll_stats_in_get_sta_cfg_update(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)1688 hdd_club_ll_stats_in_get_sta_cfg_update(struct hdd_config *config,
1689 struct wlan_objmgr_psoc *psoc)
1690 {
1691 config->sta_stats_cache_expiry_time =
1692 cfg_get(psoc, CFG_STA_STATS_CACHE_EXPIRY);
1693 }
1694
1695 static void
hdd_update_feature_cfg_club_get_sta_in_ll_stats_req(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1696 hdd_update_feature_cfg_club_get_sta_in_ll_stats_req(
1697 struct hdd_context *hdd_ctx,
1698 struct wma_tgt_services *cfg)
1699 {
1700 hdd_ctx->is_get_station_clubbed_in_ll_stats_req =
1701 cfg->is_get_station_clubbed_in_ll_stats_req &&
1702 cfg_get(hdd_ctx->psoc,
1703 CFG_CLUB_LL_STA_AND_GET_STATION);
1704 }
1705
1706 static void
hdd_init_get_sta_in_ll_stats_config(struct hdd_adapter * adapter)1707 hdd_init_get_sta_in_ll_stats_config(struct hdd_adapter *adapter)
1708 {
1709 adapter->sta_stats_cached_timestamp = 0;
1710 }
1711 #else
1712 static void
hdd_club_ll_stats_in_get_sta_cfg_update(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)1713 hdd_club_ll_stats_in_get_sta_cfg_update(struct hdd_config *config,
1714 struct wlan_objmgr_psoc *psoc)
1715 {
1716 }
1717
1718 static void
hdd_update_feature_cfg_club_get_sta_in_ll_stats_req(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1719 hdd_update_feature_cfg_club_get_sta_in_ll_stats_req(
1720 struct hdd_context *hdd_ctx,
1721 struct wma_tgt_services *cfg)
1722 {
1723 }
1724
1725 static void
hdd_init_get_sta_in_ll_stats_config(struct hdd_adapter * adapter)1726 hdd_init_get_sta_in_ll_stats_config(struct hdd_adapter *adapter)
1727 {
1728 }
1729 #endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */
1730
1731 #ifdef WLAN_FEATURE_11BE_MLO
1732
1733 static void
hdd_init_link_state_cfg(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)1734 hdd_init_link_state_cfg(struct hdd_config *config,
1735 struct wlan_objmgr_psoc *psoc)
1736 {
1737 config->link_state_cache_expiry_time =
1738 cfg_get(psoc, CFG_LINK_STATE_CACHE_EXPIRY);
1739 }
1740
1741 static void
hdd_init_link_state_config(struct hdd_adapter * adapter)1742 hdd_init_link_state_config(struct hdd_adapter *adapter)
1743 {
1744 adapter->link_state_cached_timestamp = 0;
1745 }
1746
1747 #else
1748 static void
hdd_init_link_state_cfg(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)1749 hdd_init_link_state_cfg(struct hdd_config *config,
1750 struct wlan_objmgr_psoc *psoc)
1751 {
1752 }
1753
1754 static void
hdd_init_link_state_config(struct hdd_adapter * adapter)1755 hdd_init_link_state_config(struct hdd_adapter *adapter)
1756 {
1757 }
1758 #endif /* WLAN_FEATURE_11BE_MLO */
1759
1760 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
1761 static void
hdd_intersect_igmp_offload_setting(struct wlan_objmgr_psoc * psoc,struct wma_tgt_services * cfg)1762 hdd_intersect_igmp_offload_setting(struct wlan_objmgr_psoc *psoc,
1763 struct wma_tgt_services *cfg)
1764 {
1765 bool igmp_offload_enable;
1766
1767 igmp_offload_enable =
1768 ucfg_pmo_is_igmp_offload_enabled(psoc);
1769 ucfg_pmo_set_igmp_offload_enabled(psoc,
1770 igmp_offload_enable &
1771 cfg->igmp_offload_enable);
1772 hdd_info("fw cap to handle igmp %d igmp_offload_enable ini %d",
1773 cfg->igmp_offload_enable, igmp_offload_enable);
1774 }
1775 #else
1776 static inline void
hdd_intersect_igmp_offload_setting(struct wlan_objmgr_psoc * psoc,struct wma_tgt_services * cfg)1777 hdd_intersect_igmp_offload_setting(struct wlan_objmgr_psoc *psoc,
1778 struct wma_tgt_services *cfg)
1779 {}
1780 #endif
1781
1782 #ifdef FEATURE_WLAN_TDLS
hdd_update_fw_tdls_wideband_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1783 static void hdd_update_fw_tdls_wideband_capability(struct hdd_context *hdd_ctx,
1784 struct wma_tgt_services *cfg)
1785 {
1786 ucfg_tdls_update_fw_wideband_capability(hdd_ctx->psoc,
1787 cfg->en_tdls_wideband_support);
1788 }
1789
1790 #ifdef WLAN_FEATURE_11BE
hdd_update_fw_tdls_mlo_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1791 static void hdd_update_fw_tdls_mlo_capability(struct hdd_context *hdd_ctx,
1792 struct wma_tgt_services *cfg)
1793 {
1794 ucfg_tdls_update_fw_mlo_capability(hdd_ctx->psoc,
1795 cfg->en_tdls_mlo_support);
1796 }
1797 #else
1798 static inline
hdd_update_fw_tdls_mlo_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1799 void hdd_update_fw_tdls_mlo_capability(struct hdd_context *hdd_ctx,
1800 struct wma_tgt_services *cfg)
1801 {}
1802 #endif
1803
1804 #ifdef WLAN_FEATURE_11AX
hdd_update_fw_tdls_11ax_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1805 static void hdd_update_fw_tdls_11ax_capability(struct hdd_context *hdd_ctx,
1806 struct wma_tgt_services *cfg)
1807 {
1808 ucfg_tdls_update_fw_11ax_capability(hdd_ctx->psoc,
1809 cfg->en_tdls_11ax_support);
1810 }
1811
hdd_update_fw_tdls_6g_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1812 static void hdd_update_fw_tdls_6g_capability(struct hdd_context *hdd_ctx,
1813 struct wma_tgt_services *cfg)
1814 {
1815 ucfg_update_fw_tdls_6g_capability(hdd_ctx->psoc,
1816 cfg->en_tdls_6g_support);
1817 }
1818
1819 #else
1820 static inline
hdd_update_fw_tdls_11ax_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1821 void hdd_update_fw_tdls_11ax_capability(struct hdd_context *hdd_ctx,
1822 struct wma_tgt_services *cfg)
1823 {}
1824 static inline
hdd_update_fw_tdls_6g_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1825 void hdd_update_fw_tdls_6g_capability(struct hdd_context *hdd_ctx,
1826 struct wma_tgt_services *cfg)
1827 {}
1828 #endif
1829 #else
1830 static inline
hdd_update_fw_tdls_mlo_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1831 void hdd_update_fw_tdls_mlo_capability(struct hdd_context *hdd_ctx,
1832 struct wma_tgt_services *cfg)
1833 {}
1834
1835 static inline
hdd_update_fw_tdls_11ax_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1836 void hdd_update_fw_tdls_11ax_capability(struct hdd_context *hdd_ctx,
1837 struct wma_tgt_services *cfg)
1838 {}
1839
1840 static inline
hdd_update_fw_tdls_6g_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1841 void hdd_update_fw_tdls_6g_capability(struct hdd_context *hdd_ctx,
1842 struct wma_tgt_services *cfg)
1843 {}
1844
1845 static inline
hdd_update_fw_tdls_wideband_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1846 void hdd_update_fw_tdls_wideband_capability(struct hdd_context *hdd_ctx,
1847 struct wma_tgt_services *cfg)
1848 {}
1849 #endif
1850
1851 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
1852 static inline void
hdd_set_dynamic_macaddr_update_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1853 hdd_set_dynamic_macaddr_update_capability(struct hdd_context *hdd_ctx,
1854 struct wma_tgt_services *cfg)
1855 {
1856 hdd_ctx->is_vdev_macaddr_dynamic_update_supported =
1857 cfg->dynamic_vdev_macaddr_support &&
1858 cfg_get(hdd_ctx->psoc,
1859 CFG_DYNAMIC_MAC_ADDR_UPDATE_SUPPORTED);
1860 }
1861 #else
1862 static inline void
hdd_set_dynamic_macaddr_update_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1863 hdd_set_dynamic_macaddr_update_capability(struct hdd_context *hdd_ctx,
1864 struct wma_tgt_services *cfg)
1865 {
1866 }
1867 #endif
1868
1869 #ifdef WLAN_FEATURE_11BE
hdd_dot11Mode_support_11be(enum hdd_dot11_mode dot11Mode)1870 static bool hdd_dot11Mode_support_11be(enum hdd_dot11_mode dot11Mode)
1871 {
1872 if (dot11Mode != eHDD_DOT11_MODE_AUTO &&
1873 dot11Mode < eHDD_DOT11_MODE_11be)
1874 return false;
1875
1876 return true;
1877 }
1878
1879 static void
hdd_update_tid_to_link_supported(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1880 hdd_update_tid_to_link_supported(struct hdd_context *hdd_ctx,
1881 struct wma_tgt_services *cfg)
1882 {
1883 if (!cfg->en_mlo_tid_to_link_support)
1884 ucfg_mlme_set_t2lm_negotiation_supported(hdd_ctx->psoc,
1885 T2LM_NEGOTIATION_DISABLED);
1886 }
1887
1888 #else
hdd_dot11Mode_support_11be(enum hdd_dot11_mode dot11Mode)1889 static bool hdd_dot11Mode_support_11be(enum hdd_dot11_mode dot11Mode)
1890 {
1891 return false;
1892 }
1893
1894 static inline void
hdd_update_tid_to_link_supported(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1895 hdd_update_tid_to_link_supported(struct hdd_context *hdd_ctx,
1896 struct wma_tgt_services *cfg)
1897 {
1898 }
1899 #endif
1900
1901 #ifdef WLAN_FEATURE_11BE_MLO
1902 static void
hdd_update_mlo_per_link_stats_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1903 hdd_update_mlo_per_link_stats_capability(struct hdd_context *hdd_ctx,
1904 struct wma_tgt_services *cfg)
1905 {
1906 hdd_ctx->is_mlo_per_link_stats_supported =
1907 cfg->is_mlo_per_link_stats_supported;
1908 }
1909 #else
1910 static void
hdd_update_mlo_per_link_stats_capability(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1911 hdd_update_mlo_per_link_stats_capability(struct hdd_context *hdd_ctx,
1912 struct wma_tgt_services *cfg)
1913 {
1914 }
1915 #endif
1916
hdd_update_tgt_services(struct hdd_context * hdd_ctx,struct wma_tgt_services * cfg)1917 static void hdd_update_tgt_services(struct hdd_context *hdd_ctx,
1918 struct wma_tgt_services *cfg)
1919 {
1920 struct hdd_config *config = hdd_ctx->config;
1921 bool arp_offload_enable;
1922 bool mawc_enabled;
1923 #ifdef FEATURE_WLAN_TDLS
1924 bool tdls_support;
1925 bool tdls_off_channel;
1926 bool tdls_buffer_sta;
1927 uint32_t tdls_uapsd_mask;
1928 #endif
1929 bool get_peer_info_enable;
1930
1931 /* Set up UAPSD */
1932 ucfg_mlme_set_sap_uapsd_flag(hdd_ctx->psoc, cfg->uapsd);
1933
1934 /* 11AX mode support */
1935 if ((config->dot11Mode == eHDD_DOT11_MODE_11ax ||
1936 config->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY) && !cfg->en_11ax)
1937 config->dot11Mode = eHDD_DOT11_MODE_11ac;
1938
1939 /* 11AC mode support */
1940 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
1941 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
1942 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
1943
1944 /* 11BE mode support */
1945 if (cfg->en_11be &&
1946 (!hdd_dot11Mode_support_11be(config->dot11Mode) ||
1947 !wlan_reg_phybitmap_support_11be(hdd_ctx->pdev))) {
1948 hdd_debug("dot11Mode %d override target en_11be to false",
1949 config->dot11Mode);
1950 cfg->en_11be = false;
1951 }
1952
1953 /* ARP offload: override user setting if invalid */
1954 arp_offload_enable =
1955 ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc);
1956 ucfg_pmo_set_arp_offload_enabled(hdd_ctx->psoc,
1957 arp_offload_enable & cfg->arp_offload);
1958
1959 /* Intersect igmp offload ini configuration and fw cap*/
1960 hdd_intersect_igmp_offload_setting(hdd_ctx->psoc, cfg);
1961
1962 #ifdef FEATURE_WLAN_SCAN_PNO
1963 /* PNO offload */
1964 hdd_debug("PNO Capability in f/w = %d", cfg->pno_offload);
1965 if (cfg->pno_offload)
1966 ucfg_scan_set_pno_offload(hdd_ctx->psoc, true);
1967 #endif
1968 #ifdef FEATURE_WLAN_TDLS
1969 cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support);
1970 cfg_tdls_set_support_enable(hdd_ctx->psoc,
1971 tdls_support & cfg->en_tdls);
1972
1973 cfg_tdls_get_off_channel_enable(hdd_ctx->psoc, &tdls_off_channel);
1974 cfg_tdls_set_off_channel_enable(hdd_ctx->psoc,
1975 tdls_off_channel &&
1976 cfg->en_tdls_offchan);
1977
1978 cfg_tdls_get_buffer_sta_enable(hdd_ctx->psoc, &tdls_buffer_sta);
1979 cfg_tdls_set_buffer_sta_enable(hdd_ctx->psoc,
1980 tdls_buffer_sta &&
1981 cfg->en_tdls_uapsd_buf_sta);
1982
1983 cfg_tdls_get_uapsd_mask(hdd_ctx->psoc, &tdls_uapsd_mask);
1984 if (tdls_uapsd_mask && cfg->en_tdls_uapsd_sleep_sta)
1985 cfg_tdls_set_sleep_sta_enable(hdd_ctx->psoc, true);
1986 else
1987 cfg_tdls_set_sleep_sta_enable(hdd_ctx->psoc, false);
1988 #endif
1989 hdd_update_roam_offload(hdd_ctx, cfg);
1990
1991 if (ucfg_mlme_get_sap_get_peer_info(
1992 hdd_ctx->psoc, &get_peer_info_enable) == QDF_STATUS_SUCCESS) {
1993 get_peer_info_enable &= cfg->get_peer_info_enabled;
1994 ucfg_mlme_set_sap_get_peer_info(hdd_ctx->psoc,
1995 get_peer_info_enable);
1996 }
1997
1998 ucfg_mlme_is_mawc_enabled(hdd_ctx->psoc, &mawc_enabled);
1999 ucfg_mlme_set_mawc_enabled(hdd_ctx->psoc,
2000 mawc_enabled & cfg->is_fw_mawc_capable);
2001 hdd_update_tdls_config(hdd_ctx);
2002 sme_update_tgt_services(hdd_ctx->mac_handle, cfg);
2003 hdd_ctx->roam_ch_from_fw_supported = cfg->is_roam_scan_ch_to_host;
2004 hdd_ctx->ll_stats_per_chan_rx_tx_time =
2005 cfg->ll_stats_per_chan_rx_tx_time;
2006
2007 hdd_update_feature_cfg_club_get_sta_in_ll_stats_req(hdd_ctx, cfg);
2008 hdd_ctx->is_therm_cmd_supp =
2009 cfg->is_fw_therm_throt_supp &&
2010 cfg_get(hdd_ctx->psoc,
2011 CFG_THERMAL_MITIGATION_ENABLE);
2012 hdd_update_fw_tdls_11ax_capability(hdd_ctx, cfg);
2013 hdd_update_fw_tdls_mlo_capability(hdd_ctx, cfg);
2014 hdd_set_dynamic_macaddr_update_capability(hdd_ctx, cfg);
2015 hdd_update_fw_tdls_6g_capability(hdd_ctx, cfg);
2016 hdd_update_fw_tdls_wideband_capability(hdd_ctx, cfg);
2017 ucfg_psoc_mlme_set_11be_capab(hdd_ctx->psoc, cfg->en_11be);
2018 hdd_update_mlo_per_link_stats_capability(hdd_ctx, cfg);
2019 }
2020
2021 /**
2022 * hdd_update_vdev_nss() - sets the vdev nss
2023 * @hdd_ctx: HDD context
2024 *
2025 * Sets the Nss per vdev type based on INI
2026 *
2027 * Return: None
2028 */
hdd_update_vdev_nss(struct hdd_context * hdd_ctx)2029 static void hdd_update_vdev_nss(struct hdd_context *hdd_ctx)
2030 {
2031 uint8_t max_supp_nss = 1;
2032 mac_handle_t mac_handle;
2033 QDF_STATUS status;
2034 bool bval;
2035
2036 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval);
2037 if (!QDF_IS_STATUS_SUCCESS(status))
2038 hdd_err("unable to get vht_enable2x2");
2039
2040 if (bval && !cds_is_sub_20_mhz_enabled())
2041 max_supp_nss = 2;
2042
2043 hdd_debug("max nss %d", max_supp_nss);
2044
2045 mac_handle = hdd_ctx->mac_handle;
2046 sme_update_vdev_type_nss(mac_handle, max_supp_nss,
2047 NSS_CHAINS_BAND_2GHZ);
2048
2049 sme_update_vdev_type_nss(mac_handle, max_supp_nss,
2050 NSS_CHAINS_BAND_5GHZ);
2051 }
2052
2053 /**
2054 * hdd_update_2g_wiphy_vhtcap() - Updates 2G wiphy vhtcap fields
2055 * @hdd_ctx: HDD context
2056 *
2057 * Updates 2G wiphy vhtcap fields
2058 *
2059 * Return: None
2060 */
hdd_update_2g_wiphy_vhtcap(struct hdd_context * hdd_ctx)2061 static void hdd_update_2g_wiphy_vhtcap(struct hdd_context *hdd_ctx)
2062 {
2063 struct ieee80211_supported_band *band_2g =
2064 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ];
2065 uint32_t value;
2066 bool is_vht_24ghz;
2067
2068 if (!band_2g) {
2069 hdd_debug("2GHz band disabled, skipping capability population");
2070 return;
2071 }
2072
2073 ucfg_mlme_get_vht_for_24ghz(hdd_ctx->psoc, &is_vht_24ghz);
2074
2075 if (is_vht_24ghz) {
2076 ucfg_mlme_cfg_get_vht_tx_mcs_map(hdd_ctx->psoc, &value);
2077 band_2g->vht_cap.vht_mcs.tx_mcs_map = value;
2078 }
2079 }
2080
2081 /**
2082 * hdd_update_5g_wiphy_vhtcap() - Updates 5G wiphy vhtcap fields
2083 * @hdd_ctx: HDD context
2084 *
2085 * Updates 5G wiphy vhtcap fields
2086 *
2087 * Return: None
2088 */
hdd_update_5g_wiphy_vhtcap(struct hdd_context * hdd_ctx)2089 static void hdd_update_5g_wiphy_vhtcap(struct hdd_context *hdd_ctx)
2090 {
2091 struct ieee80211_supported_band *band_5g =
2092 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ];
2093 QDF_STATUS status;
2094 uint8_t value = 0, value1 = 0;
2095 uint32_t value2;
2096
2097 if (!band_5g) {
2098 hdd_debug("5GHz band disabled, skipping capability population");
2099 return;
2100 }
2101
2102 status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
2103 &value);
2104 if (!QDF_IS_STATUS_SUCCESS(status))
2105 hdd_err("unable to get tx_bfee_ant_supp");
2106
2107 band_5g->vht_cap.cap |=
2108 (value << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
2109
2110 value1 = NUM_OF_SOUNDING_DIMENSIONS;
2111 band_5g->vht_cap.cap |=
2112 (value1 << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT);
2113
2114 hdd_debug("Updated wiphy vhtcap:0x%x, CSNAntSupp:%d, NumSoundDim:%d",
2115 band_5g->vht_cap.cap, value, value1);
2116
2117 ucfg_mlme_cfg_get_vht_rx_mcs_map(hdd_ctx->psoc, &value2);
2118 band_5g->vht_cap.vht_mcs.rx_mcs_map = value2;
2119
2120 ucfg_mlme_cfg_get_vht_tx_mcs_map(hdd_ctx->psoc, &value2);
2121 band_5g->vht_cap.vht_mcs.tx_mcs_map = value2;
2122 }
2123
2124 /**
2125 * hdd_update_wiphy_vhtcap() - Updates wiphy vhtcap fields
2126 * @hdd_ctx: HDD context
2127 *
2128 * Updates wiphy vhtcap fields
2129 *
2130 * Return: None
2131 */
hdd_update_wiphy_vhtcap(struct hdd_context * hdd_ctx)2132 static void hdd_update_wiphy_vhtcap(struct hdd_context *hdd_ctx)
2133 {
2134 hdd_update_2g_wiphy_vhtcap(hdd_ctx);
2135 hdd_update_5g_wiphy_vhtcap(hdd_ctx);
2136 }
2137
hdd_update_tgt_ht_cap(struct hdd_context * hdd_ctx,struct wma_tgt_ht_cap * cfg)2138 static void hdd_update_tgt_ht_cap(struct hdd_context *hdd_ctx,
2139 struct wma_tgt_ht_cap *cfg)
2140 {
2141 QDF_STATUS status;
2142 qdf_size_t value_len;
2143 uint32_t value;
2144 uint8_t mpdu_density;
2145 struct mlme_ht_capabilities_info ht_cap_info;
2146 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
2147 bool b_enable1x1;
2148
2149 /* get the MPDU density */
2150 status = ucfg_mlme_get_ht_mpdu_density(hdd_ctx->psoc, &mpdu_density);
2151 if (QDF_IS_STATUS_ERROR(status)) {
2152 hdd_err("could not get HT MPDU Density");
2153 return;
2154 }
2155
2156 /*
2157 * MPDU density:
2158 * override user's setting if value is larger
2159 * than the one supported by target,
2160 * if target value is 0, then follow user's setting.
2161 */
2162 if (cfg->mpdu_density && mpdu_density > cfg->mpdu_density) {
2163 status = ucfg_mlme_set_ht_mpdu_density(hdd_ctx->psoc,
2164 cfg->mpdu_density);
2165 if (QDF_IS_STATUS_ERROR(status))
2166 hdd_err("could not set HT capability to CCM");
2167 }
2168
2169 /* get the HT capability info */
2170 status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
2171 if (QDF_STATUS_SUCCESS != status) {
2172 hdd_err("could not get HT capability info");
2173 return;
2174 }
2175
2176 /* check and update RX STBC */
2177 if (ht_cap_info.rx_stbc && !cfg->ht_rx_stbc)
2178 ht_cap_info.rx_stbc = cfg->ht_rx_stbc;
2179
2180 /* Set the LDPC capability */
2181 if (ht_cap_info.adv_coding_cap && !cfg->ht_rx_ldpc)
2182 ht_cap_info.adv_coding_cap = cfg->ht_rx_ldpc;
2183
2184 if (ht_cap_info.short_gi_20_mhz && !cfg->ht_sgi_20)
2185 ht_cap_info.short_gi_20_mhz = cfg->ht_sgi_20;
2186
2187 if (ht_cap_info.short_gi_40_mhz && !cfg->ht_sgi_40)
2188 ht_cap_info.short_gi_40_mhz = cfg->ht_sgi_40;
2189
2190 hdd_debug("gHtSMPS ini: %d, dynamic_smps fw cap: %d",
2191 ht_cap_info.mimo_power_save, cfg->dynamic_smps);
2192 if (ht_cap_info.mimo_power_save == HDD_SMPS_MODE_DYNAMIC) {
2193 if (cfg->dynamic_smps)
2194 ht_cap_info.mimo_power_save = HDD_SMPS_MODE_DYNAMIC;
2195 else
2196 ht_cap_info.mimo_power_save = HDD_SMPS_MODE_DISABLED;
2197 }
2198
2199 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
2200 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
2201
2202 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &b_enable1x1);
2203 if (!QDF_IS_STATUS_SUCCESS(status))
2204 hdd_err("unable to get vht_enable2x2");
2205
2206 b_enable1x1 = b_enable1x1 && (cfg->num_rf_chains == 2);
2207
2208 status = ucfg_mlme_set_vht_enable2x2(hdd_ctx->psoc, b_enable1x1);
2209 if (!QDF_IS_STATUS_SUCCESS(status))
2210 hdd_err("unable to set vht_enable2x2");
2211
2212 if (!b_enable1x1)
2213 ht_cap_info.tx_stbc = 0;
2214
2215 if (!(cfg->ht_tx_stbc && b_enable1x1))
2216 ht_cap_info.tx_stbc = 0;
2217
2218 status = ucfg_mlme_set_ht_cap_info(hdd_ctx->psoc, ht_cap_info);
2219 if (status != QDF_STATUS_SUCCESS)
2220 hdd_err("could not set HT capability to CCM");
2221 #define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
2222 value_len = SIZE_OF_SUPPORTED_MCS_SET;
2223 if (ucfg_mlme_get_supported_mcs_set(
2224 hdd_ctx->psoc, mcs_set,
2225 &value_len) == QDF_STATUS_SUCCESS) {
2226 hdd_debug("Read MCS rate set");
2227 if (cfg->num_rf_chains > SIZE_OF_SUPPORTED_MCS_SET)
2228 cfg->num_rf_chains = SIZE_OF_SUPPORTED_MCS_SET;
2229
2230 if (b_enable1x1) {
2231 for (value = 0; value < cfg->num_rf_chains; value++)
2232 mcs_set[value] =
2233 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
2234
2235 status = ucfg_mlme_set_supported_mcs_set(
2236 hdd_ctx->psoc,
2237 mcs_set,
2238 (qdf_size_t)SIZE_OF_SUPPORTED_MCS_SET);
2239 if (QDF_IS_STATUS_ERROR(status))
2240 hdd_err("could not set MCS SET to CCM");
2241 }
2242 }
2243 #undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
2244 }
2245
hdd_update_tgt_vht_cap(struct hdd_context * hdd_ctx,struct wma_tgt_vht_cap * cfg)2246 static void hdd_update_tgt_vht_cap(struct hdd_context *hdd_ctx,
2247 struct wma_tgt_vht_cap *cfg)
2248 {
2249 QDF_STATUS status;
2250 struct wiphy *wiphy = hdd_ctx->wiphy;
2251 struct ieee80211_supported_band *band_5g =
2252 wiphy->bands[HDD_NL80211_BAND_5GHZ];
2253 uint32_t ch_width;
2254 struct wma_caps_per_phy caps_per_phy = {0};
2255 bool vht_enable_2x2;
2256 uint32_t tx_highest_data_rate;
2257 uint32_t rx_highest_data_rate;
2258
2259 if (!band_5g) {
2260 hdd_debug("5GHz band disabled, skipping capability population");
2261 return;
2262 }
2263
2264 status = ucfg_mlme_update_vht_cap(hdd_ctx->psoc, cfg);
2265 if (QDF_IS_STATUS_ERROR(status))
2266 hdd_err("could not update vht capabilities");
2267
2268 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &vht_enable_2x2);
2269 if (!QDF_IS_STATUS_SUCCESS(status))
2270 hdd_err("unable to get vht_enable2x2");
2271
2272 if (vht_enable_2x2) {
2273 tx_highest_data_rate =
2274 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2;
2275 rx_highest_data_rate =
2276 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2;
2277 } else {
2278 tx_highest_data_rate =
2279 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
2280 rx_highest_data_rate =
2281 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
2282 }
2283
2284 status = ucfg_mlme_cfg_set_vht_rx_supp_data_rate(hdd_ctx->psoc,
2285 rx_highest_data_rate);
2286 if (!QDF_IS_STATUS_SUCCESS(status))
2287 hdd_err("Failed to set rx_supp_data_rate");
2288
2289 status = ucfg_mlme_cfg_set_vht_tx_supp_data_rate(hdd_ctx->psoc,
2290 tx_highest_data_rate);
2291 if (!QDF_IS_STATUS_SUCCESS(status))
2292 hdd_err("Failed to set tx_supp_data_rate");
2293
2294 /* Update the real highest data rate to wiphy */
2295 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ) {
2296 if (vht_enable_2x2) {
2297 tx_highest_data_rate =
2298 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2_SGI80;
2299 rx_highest_data_rate =
2300 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2_SGI80;
2301 } else {
2302 tx_highest_data_rate =
2303 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1_SGI80;
2304 rx_highest_data_rate =
2305 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1_SGI80;
2306 }
2307 }
2308
2309 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
2310 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
2311 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
2312 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
2313 else
2314 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
2315
2316
2317 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
2318 band_5g->vht_cap.cap |=
2319 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2320 ch_width = VHT_CAP_160_AND_80P80_SUPP;
2321 } else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
2322 band_5g->vht_cap.cap |=
2323 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2324 ch_width = VHT_CAP_160_SUPP;
2325 } else {
2326 ch_width = VHT_CAP_NO_160M_SUPP;
2327 }
2328
2329 status = ucfg_mlme_set_vht_ch_width(hdd_ctx->psoc, ch_width);
2330 if (QDF_IS_STATUS_ERROR(status))
2331 hdd_err("could not set the channel width");
2332 else
2333 hdd_debug("supported channel width %d", ch_width);
2334
2335 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC) {
2336 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
2337 hdd_debug("VHT RxLDPC capability is set");
2338 } else {
2339 /*
2340 * Get the RX LDPC capability for the NON DBS
2341 * hardware mode for 5G band
2342 */
2343 status = wma_get_caps_for_phyidx_hwmode(&caps_per_phy,
2344 HW_MODE_DBS_NONE, CDS_BAND_5GHZ);
2345 if ((QDF_IS_STATUS_SUCCESS(status)) &&
2346 (caps_per_phy.vht_5g & WMI_VHT_CAP_RX_LDPC)) {
2347 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
2348 hdd_debug("VHT RX LDPC capability is set");
2349 }
2350 }
2351
2352 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
2353 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
2354 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
2355 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
2356
2357 if (vht_enable_2x2 && (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC))
2358 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
2359
2360 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
2361 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
2362 if (vht_enable_2x2 && (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS))
2363 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
2364 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
2365 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
2366
2367 band_5g->vht_cap.cap |=
2368 (cfg->vht_max_ampdu_len_exp <<
2369 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
2370
2371 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
2372 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
2373 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
2374 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
2375 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
2376 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
2377 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
2378 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
2379
2380 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
2381 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
2382
2383 band_5g->vht_cap.vht_mcs.rx_highest = cpu_to_le16(rx_highest_data_rate);
2384 band_5g->vht_cap.vht_mcs.tx_highest = cpu_to_le16(tx_highest_data_rate);
2385 }
2386
2387 /**
2388 * hdd_generate_macaddr_auto() - Auto-generate mac address
2389 * @hdd_ctx: Pointer to the HDD context
2390 *
2391 * Auto-generate mac address using device serial number.
2392 * Keep the first 3 bytes of OUI as before and replace
2393 * the last 3 bytes with the lower 3 bytes of serial number.
2394 *
2395 * Return: 0 for success
2396 * Non zero failure code for errors
2397 */
hdd_generate_macaddr_auto(struct hdd_context * hdd_ctx)2398 static int hdd_generate_macaddr_auto(struct hdd_context *hdd_ctx)
2399 {
2400 unsigned int serialno = 0;
2401 struct qdf_mac_addr mac_addr = {
2402 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
2403 };
2404
2405 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
2406 if (serialno == 0)
2407 return -EINVAL;
2408
2409 serialno &= 0x00ffffff;
2410
2411 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
2412 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
2413 mac_addr.bytes[5] = serialno & 0xff;
2414
2415 hdd_update_macaddr(hdd_ctx, mac_addr, true);
2416 return 0;
2417 }
2418
hdd_sar_target_config(struct hdd_context * hdd_ctx,struct wma_tgt_cfg * cfg)2419 static void hdd_sar_target_config(struct hdd_context *hdd_ctx,
2420 struct wma_tgt_cfg *cfg)
2421 {
2422 hdd_ctx->sar_version = cfg->sar_version;
2423 }
2424
hdd_update_vhtcap_2g(struct hdd_context * hdd_ctx)2425 static void hdd_update_vhtcap_2g(struct hdd_context *hdd_ctx)
2426 {
2427 uint64_t chip_mode = 0;
2428 QDF_STATUS status;
2429 bool b2g_vht_cfg = false;
2430 bool b2g_vht_target = false;
2431 struct wma_caps_per_phy caps_per_phy = {0};
2432 struct wmi_unified *wmi_handle;
2433
2434 wmi_handle = get_wmi_unified_hdl_from_psoc(hdd_ctx->psoc);
2435 if (!wmi_handle) {
2436 hdd_err("wmi handle is NULL");
2437 return;
2438 }
2439
2440 status = ucfg_mlme_get_vht_for_24ghz(hdd_ctx->psoc, &b2g_vht_cfg);
2441 if (QDF_IS_STATUS_ERROR(status)) {
2442 hdd_err("Failed to get 2g vht mode");
2443 return;
2444 }
2445 if (wmi_service_enabled(wmi_handle, wmi_service_ext_msg)) {
2446 status = wma_get_caps_for_phyidx_hwmode(&caps_per_phy,
2447 HW_MODE_DBS_NONE,
2448 CDS_BAND_2GHZ);
2449 if (QDF_IS_STATUS_ERROR(status)) {
2450 hdd_err("Failed to get phy caps");
2451 return;
2452 }
2453 if (caps_per_phy.vht_2g)
2454 b2g_vht_target = true;
2455 } else {
2456 status = wlan_reg_get_chip_mode(hdd_ctx->pdev, &chip_mode);
2457 if (QDF_IS_STATUS_ERROR(status)) {
2458 hdd_err("Failed to get chip mode");
2459 return;
2460 }
2461 b2g_vht_target =
2462 (chip_mode & HOST_REGDMN_MODE_11AC_VHT20_2G) ?
2463 true : false;
2464 }
2465
2466 b2g_vht_cfg = b2g_vht_cfg && b2g_vht_target;
2467 hdd_debug("vht 2g target: %d, cfg: %d", b2g_vht_target, b2g_vht_cfg);
2468 status = ucfg_mlme_set_vht_for_24ghz(hdd_ctx->psoc, b2g_vht_cfg);
2469 if (QDF_IS_STATUS_ERROR(status)) {
2470 hdd_err("Failed to update 2g vht mode");
2471 return;
2472 }
2473 }
2474
hdd_extract_fw_version_info(struct hdd_context * hdd_ctx)2475 static void hdd_extract_fw_version_info(struct hdd_context *hdd_ctx)
2476 {
2477 hdd_ctx->fw_version_info.major_spid =
2478 HDD_FW_VER_MAJOR_SPID(hdd_ctx->target_fw_version);
2479 hdd_ctx->fw_version_info.minor_spid =
2480 HDD_FW_VER_MINOR_SPID(hdd_ctx->target_fw_version);
2481 hdd_ctx->fw_version_info.siid =
2482 HDD_FW_VER_SIID(hdd_ctx->target_fw_version);
2483 hdd_ctx->fw_version_info.crmid =
2484 HDD_FW_VER_CRM_ID(hdd_ctx->target_fw_version);
2485 hdd_ctx->fw_version_info.sub_id =
2486 HDD_FW_VER_SUB_ID(hdd_ctx->target_fw_vers_ext);
2487 hdd_ctx->fw_version_info.rel_id =
2488 HDD_FW_VER_REL_ID(hdd_ctx->target_fw_vers_ext);
2489 }
2490
2491 #if defined(WLAN_FEATURE_11AX) && \
2492 (defined(CFG80211_SBAND_IFTYPE_DATA_BACKPORT) || \
2493 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)))
2494
2495 static void
hdd_update_wiphy_he_mcs(struct ieee80211_sband_iftype_data * iftype_data,tDot11fIEhe_cap * he_cap_cfg)2496 hdd_update_wiphy_he_mcs(struct ieee80211_sband_iftype_data *iftype_data,
2497 tDot11fIEhe_cap *he_cap_cfg)
2498 {
2499 if (!iftype_data || !he_cap_cfg) {
2500 hdd_err("Unable to update wiphy he_mcs");
2501 return;
2502 }
2503
2504 iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80 =
2505 he_cap_cfg->tx_he_mcs_map_lt_80;
2506 iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160 =
2507 *((uint16_t *)he_cap_cfg->tx_he_mcs_map_160);
2508 iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80p80 =
2509 *((uint16_t *)he_cap_cfg->tx_he_mcs_map_80_80);
2510 }
2511
2512 #if defined(CONFIG_BAND_6GHZ) && (defined(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START))
hdd_update_wiphy_he_6ghz_capa(struct hdd_context * hdd_ctx)2513 static void hdd_update_wiphy_he_6ghz_capa(struct hdd_context *hdd_ctx)
2514 {
2515 uint16_t he_6ghz_capa = 0;
2516 uint8_t min_mpdu_start_spacing;
2517 uint8_t max_ampdu_len_exp;
2518 uint8_t max_mpdu_len;
2519 uint8_t sm_pow_save;
2520
2521 ucfg_mlme_get_ht_mpdu_density(hdd_ctx->psoc, &min_mpdu_start_spacing);
2522 he_6ghz_capa |= FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START,
2523 min_mpdu_start_spacing);
2524
2525 ucfg_mlme_cfg_get_vht_ampdu_len_exp(hdd_ctx->psoc, &max_ampdu_len_exp);
2526 he_6ghz_capa |= FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP,
2527 max_ampdu_len_exp);
2528
2529 ucfg_mlme_cfg_get_vht_max_mpdu_len(hdd_ctx->psoc, &max_mpdu_len);
2530 he_6ghz_capa |= FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN,
2531 max_mpdu_len);
2532
2533 ucfg_mlme_cfg_get_ht_smps(hdd_ctx->psoc, &sm_pow_save);
2534 he_6ghz_capa |= FIELD_PREP(IEEE80211_HE_6GHZ_CAP_SM_PS, sm_pow_save);
2535
2536 he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
2537 he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS;
2538
2539 hdd_ctx->iftype_data_6g->he_6ghz_capa.capa = he_6ghz_capa;
2540 }
2541 #else
hdd_update_wiphy_he_6ghz_capa(struct hdd_context * hdd_ctx)2542 static inline void hdd_update_wiphy_he_6ghz_capa(struct hdd_context *hdd_ctx)
2543 {
2544 }
2545 #endif
2546
2547 #if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
2548 (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
2549 static void
hdd_update_wiphy_he_caps_6ghz(struct hdd_context * hdd_ctx,tDot11fIEhe_cap * he_cap_cfg)2550 hdd_update_wiphy_he_caps_6ghz(struct hdd_context *hdd_ctx,
2551 tDot11fIEhe_cap *he_cap_cfg)
2552 {
2553 struct ieee80211_supported_band *band_6g =
2554 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_6GHZ];
2555 uint8_t *phy_info =
2556 hdd_ctx->iftype_data_6g->he_cap.he_cap_elem.phy_cap_info;
2557 uint8_t *mac_info_6g =
2558 hdd_ctx->iftype_data_6g->he_cap.he_cap_elem.mac_cap_info;
2559 uint8_t max_fw_bw = sme_get_vht_ch_width();
2560
2561 if (!band_6g || !phy_info) {
2562 hdd_debug("6ghz not supported in wiphy");
2563 return;
2564 }
2565
2566 hdd_ctx->iftype_data_6g->types_mask =
2567 (BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP));
2568 hdd_ctx->iftype_data_6g->he_cap.has_he = true;
2569 band_6g->n_iftype_data = 1;
2570
2571 if (max_fw_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ)
2572 phy_info[0] |=
2573 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
2574 if (max_fw_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
2575 phy_info[0] |=
2576 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
2577 if (max_fw_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
2578 phy_info[0] |=
2579 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
2580
2581 if (he_cap_cfg->twt_request)
2582 mac_info_6g[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ;
2583
2584 if (he_cap_cfg->twt_responder)
2585 mac_info_6g[0] |= IEEE80211_HE_MAC_CAP0_TWT_RES;
2586
2587 hdd_update_wiphy_he_6ghz_capa(hdd_ctx);
2588
2589 hdd_update_wiphy_he_mcs(hdd_ctx->iftype_data_6g, he_cap_cfg);
2590
2591 band_6g->iftype_data = hdd_ctx->iftype_data_6g;
2592 }
2593 #else
2594 static inline void
hdd_update_wiphy_he_caps_6ghz(struct hdd_context * hdd_ctx,tDot11fIEhe_cap * he_cap_cfg)2595 hdd_update_wiphy_he_caps_6ghz(struct hdd_context *hdd_ctx,
2596 tDot11fIEhe_cap *he_cap_cfg)
2597 {
2598 }
2599 #endif
2600
hdd_update_wiphy_he_cap(struct hdd_context * hdd_ctx)2601 static void hdd_update_wiphy_he_cap(struct hdd_context *hdd_ctx)
2602 {
2603 tDot11fIEhe_cap he_cap_cfg;
2604 struct ieee80211_supported_band *band_2g =
2605 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ];
2606 struct ieee80211_supported_band *band_5g =
2607 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ];
2608 QDF_STATUS status;
2609 uint8_t *phy_info_5g =
2610 hdd_ctx->iftype_data_5g->he_cap.he_cap_elem.phy_cap_info;
2611 uint8_t max_fw_bw = sme_get_vht_ch_width();
2612 uint32_t channel_bonding_mode_2g;
2613 uint8_t *phy_info_2g =
2614 hdd_ctx->iftype_data_2g->he_cap.he_cap_elem.phy_cap_info;
2615 uint8_t *mac_info_2g =
2616 hdd_ctx->iftype_data_2g->he_cap.he_cap_elem.mac_cap_info;
2617 uint8_t *mac_info_5g =
2618 hdd_ctx->iftype_data_5g->he_cap.he_cap_elem.mac_cap_info;
2619
2620 status = ucfg_mlme_cfg_get_he_caps(hdd_ctx->psoc, &he_cap_cfg);
2621
2622 if (QDF_IS_STATUS_ERROR(status))
2623 return;
2624
2625 if (band_2g) {
2626 hdd_ctx->iftype_data_2g->types_mask =
2627 (BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP));
2628 hdd_ctx->iftype_data_2g->he_cap.has_he = he_cap_cfg.present;
2629 band_2g->n_iftype_data = 1;
2630 hdd_update_wiphy_he_mcs(hdd_ctx->iftype_data_2g, &he_cap_cfg);
2631 band_2g->iftype_data = hdd_ctx->iftype_data_2g;
2632
2633 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
2634 &channel_bonding_mode_2g);
2635 if (channel_bonding_mode_2g)
2636 phy_info_2g[0] |=
2637 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
2638
2639 if (he_cap_cfg.twt_request)
2640 mac_info_2g[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ;
2641
2642 if (he_cap_cfg.twt_responder)
2643 mac_info_2g[0] |= IEEE80211_HE_MAC_CAP0_TWT_RES;
2644 }
2645 if (band_5g) {
2646 hdd_ctx->iftype_data_5g->types_mask =
2647 (BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP));
2648 hdd_ctx->iftype_data_5g->he_cap.has_he = he_cap_cfg.present;
2649 band_5g->n_iftype_data = 1;
2650 hdd_update_wiphy_he_mcs(hdd_ctx->iftype_data_5g, &he_cap_cfg);
2651 band_5g->iftype_data = hdd_ctx->iftype_data_5g;
2652
2653 if (max_fw_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ)
2654 phy_info_5g[0] |=
2655 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
2656 if (max_fw_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
2657 phy_info_5g[0] |=
2658 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
2659 if (max_fw_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
2660 phy_info_5g[0] |=
2661 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
2662
2663 if (he_cap_cfg.twt_request)
2664 mac_info_5g[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ;
2665
2666 if (he_cap_cfg.twt_responder)
2667 mac_info_5g[0] |= IEEE80211_HE_MAC_CAP0_TWT_RES;
2668 }
2669
2670 hdd_update_wiphy_he_caps_6ghz(hdd_ctx, &he_cap_cfg);
2671 }
2672 #else
hdd_update_wiphy_he_cap(struct hdd_context * hdd_ctx)2673 static void hdd_update_wiphy_he_cap(struct hdd_context *hdd_ctx)
2674 {
2675 }
2676 #endif
2677
hdd_component_cfg_chan_to_freq(struct wlan_objmgr_pdev * pdev)2678 static void hdd_component_cfg_chan_to_freq(struct wlan_objmgr_pdev *pdev)
2679 {
2680 ucfg_mlme_cfg_chan_to_freq(pdev);
2681 }
2682
hdd_update_band_cap_from_dot11mode(struct hdd_context * hdd_ctx,uint32_t band_capability)2683 static uint32_t hdd_update_band_cap_from_dot11mode(
2684 struct hdd_context *hdd_ctx, uint32_t band_capability)
2685 {
2686 if (hdd_ctx->config->dot11Mode == eHDD_DOT11_MODE_AUTO)
2687 return band_capability;
2688
2689 if (hdd_ctx->config->dot11Mode == eHDD_DOT11_MODE_11b ||
2690 hdd_ctx->config->dot11Mode == eHDD_DOT11_MODE_11g ||
2691 hdd_ctx->config->dot11Mode == eHDD_DOT11_MODE_11g_ONLY ||
2692 hdd_ctx->config->dot11Mode == eHDD_DOT11_MODE_11b_ONLY)
2693 band_capability = (band_capability & (~BIT(REG_BAND_5G)));
2694
2695 if (hdd_ctx->config->dot11Mode == eHDD_DOT11_MODE_11a)
2696 band_capability = (band_capability & (~BIT(REG_BAND_2G)));
2697
2698 if (hdd_ctx->config->dot11Mode != eHDD_DOT11_MODE_11ax_ONLY &&
2699 hdd_ctx->config->dot11Mode != eHDD_DOT11_MODE_11ax)
2700 band_capability = (band_capability & (~BIT(REG_BAND_6G)));
2701
2702 qdf_debug("Update band capability %x", band_capability);
2703 return band_capability;
2704 }
2705
2706 #ifdef FEATURE_WPSS_THERMAL_MITIGATION
2707 static inline
hdd_update_multi_client_thermal_support(struct hdd_context * hdd_ctx)2708 void hdd_update_multi_client_thermal_support(struct hdd_context *hdd_ctx)
2709 {
2710 struct wmi_unified *wmi_handle;
2711
2712 wmi_handle = get_wmi_unified_hdl_from_psoc(hdd_ctx->psoc);
2713 if (!wmi_handle)
2714 return;
2715
2716 hdd_ctx->multi_client_thermal_mitigation =
2717 wmi_service_enabled(wmi_handle,
2718 wmi_service_thermal_multi_client_support);
2719 }
2720 #else
2721 static inline
hdd_update_multi_client_thermal_support(struct hdd_context * hdd_ctx)2722 void hdd_update_multi_client_thermal_support(struct hdd_context *hdd_ctx)
2723 {
2724 }
2725 #endif
2726
2727 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
hdd_lpc_enable_powersave(struct hdd_context * hdd_ctx)2728 static void hdd_lpc_enable_powersave(struct hdd_context *hdd_ctx)
2729 {
2730 struct hdd_adapter *sta_adapter;
2731
2732 if (!ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc))
2733 return;
2734
2735 ucfg_fwol_configure_global_params(hdd_ctx->psoc, hdd_ctx->pdev);
2736
2737 if (wma_enable_disable_imps(hdd_ctx->pdev->pdev_objmgr.wlan_pdev_id, 1))
2738 hdd_err("IMPS feature enable failed");
2739
2740 sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
2741 if (!sta_adapter) {
2742 hdd_debug("STA adapter does not exist");
2743 return;
2744 }
2745
2746 wlan_hdd_set_powersave(sta_adapter->deflink, true, 0);
2747 }
2748
hdd_lpc_disable_powersave(struct hdd_context * hdd_ctx)2749 static void hdd_lpc_disable_powersave(struct hdd_context *hdd_ctx)
2750 {
2751 struct hdd_adapter *sta_adapter;
2752
2753 if (!ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc))
2754 return;
2755
2756 ucfg_fwol_set_ilp_config(hdd_ctx->psoc, hdd_ctx->pdev, 0);
2757
2758 if (wma_enable_disable_imps(hdd_ctx->pdev->pdev_objmgr.wlan_pdev_id, 0))
2759 hdd_err("IMPS feature disable failed");
2760
2761 sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
2762 if (!sta_adapter) {
2763 hdd_err("STA adapter does not exist");
2764 return;
2765 }
2766 wlan_hdd_set_powersave(sta_adapter->deflink, false, 0);
2767 }
2768 #else
hdd_lpc_enable_powersave(struct hdd_context * hdd_ctx)2769 static inline void hdd_lpc_enable_powersave(struct hdd_context *hdd_ctx)
2770 {
2771 }
2772
hdd_lpc_disable_powersave(struct hdd_context * hdd_ctx)2773 static inline void hdd_lpc_disable_powersave(struct hdd_context *hdd_ctx)
2774 {
2775 }
2776 #endif
2777
hdd_update_tgt_cfg(hdd_handle_t hdd_handle,struct wma_tgt_cfg * cfg)2778 int hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
2779 {
2780 int ret;
2781 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
2782 uint32_t temp_band_cap, band_capability;
2783 struct cds_config_info *cds_cfg = cds_get_ini_config();
2784 uint8_t antenna_mode;
2785 uint8_t sub_20_chan_width;
2786 QDF_STATUS status;
2787 mac_handle_t mac_handle;
2788 bool bval = false;
2789 uint8_t value = 0;
2790 uint32_t fine_time_meas_cap = 0;
2791 enum nss_chains_band_info band;
2792 bool enable_dynamic_cfg;
2793
2794 if (!hdd_ctx) {
2795 hdd_err("HDD context is NULL");
2796 return -EINVAL;
2797 }
2798 ret = hdd_objmgr_create_and_store_pdev(hdd_ctx);
2799 if (ret) {
2800 QDF_DEBUG_PANIC("Failed to create pdev; errno:%d", ret);
2801 return -EINVAL;
2802 }
2803
2804 hdd_debug("New pdev has been created with pdev_id = %u",
2805 hdd_ctx->pdev->pdev_objmgr.wlan_pdev_id);
2806
2807 status = dispatcher_pdev_open(hdd_ctx->pdev);
2808 if (QDF_IS_STATUS_ERROR(status)) {
2809 QDF_DEBUG_PANIC("dispatcher pdev open failed; status:%d",
2810 status);
2811 ret = qdf_status_to_os_return(status);
2812 goto exit;
2813 }
2814
2815 status = hdd_component_pdev_open(hdd_ctx->pdev);
2816 if (QDF_IS_STATUS_ERROR(status)) {
2817 QDF_DEBUG_PANIC("hdd component pdev open failed; status:%d",
2818 status);
2819 ret = qdf_status_to_os_return(status);
2820 goto dispatcher_close;
2821 }
2822 /*
2823 * For 6GHz support this api is added to convert mlme cfgs
2824 * channel numbers to frequency
2825 */
2826 hdd_component_cfg_chan_to_freq(hdd_ctx->pdev);
2827
2828 hdd_objmgr_update_tgt_max_vdev_psoc(hdd_ctx, cfg->max_intf_count);
2829
2830 ucfg_ipa_set_dp_handle(hdd_ctx->psoc,
2831 cds_get_context(QDF_MODULE_ID_SOC));
2832 ucfg_ipa_set_pdev_id(hdd_ctx->psoc, OL_TXRX_PDEV_ID);
2833
2834 status = ucfg_mlme_get_sub_20_chan_width(hdd_ctx->psoc,
2835 &sub_20_chan_width);
2836 if (QDF_IS_STATUS_ERROR(status)) {
2837 hdd_err("Failed to get sub_20_chan_width config");
2838 ret = qdf_status_to_os_return(status);
2839 goto pdev_close;
2840 }
2841
2842 if (cds_cfg) {
2843 if (sub_20_chan_width !=
2844 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
2845 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
2846 cds_cfg->sub_20_channel_width =
2847 WLAN_SUB_20_CH_WIDTH_NONE;
2848 } else {
2849 cds_cfg->sub_20_channel_width = sub_20_chan_width;
2850 }
2851 }
2852
2853 status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
2854 if (QDF_IS_STATUS_ERROR(status)) {
2855 hdd_err("Failed to get MLME band capability");
2856 ret = qdf_status_to_os_return(status);
2857 goto pdev_close;
2858 }
2859
2860 band_capability =
2861 hdd_update_band_cap_from_dot11mode(hdd_ctx, band_capability);
2862
2863 /* first store the INI band capability */
2864 temp_band_cap = band_capability;
2865
2866 band_capability = cfg->band_cap;
2867 hdd_ctx->is_fils_roaming_supported =
2868 cfg->services.is_fils_roaming_supported;
2869
2870 hdd_ctx->config->is_11k_offload_supported =
2871 cfg->services.is_11k_offload_supported;
2872
2873 /*
2874 * merge the target band capability with INI setting if the merge has
2875 * at least 1 band enabled
2876 */
2877 temp_band_cap &= band_capability;
2878 if (!temp_band_cap)
2879 hdd_warn("ini BandCapability not supported by the target");
2880 else
2881 band_capability = temp_band_cap;
2882
2883 status = ucfg_mlme_set_band_capability(hdd_ctx->psoc, band_capability);
2884 if (QDF_IS_STATUS_ERROR(status)) {
2885 hdd_err("Failed to set MLME Band Capability");
2886 ret = qdf_status_to_os_return(status);
2887 goto pdev_close;
2888 }
2889
2890 hdd_ctx->curr_band = band_capability;
2891 hdd_ctx->psoc->soc_nif.user_config.band_capability = hdd_ctx->curr_band;
2892
2893 status = wlan_hdd_update_wiphy_supported_band(hdd_ctx);
2894 if (QDF_IS_STATUS_ERROR(status)) {
2895 hdd_err("Failed to update wiphy band info");
2896 goto pdev_close;
2897 }
2898
2899 status = ucfg_reg_set_band(hdd_ctx->pdev, band_capability);
2900 if (QDF_IS_STATUS_ERROR(status))
2901 /*
2902 * Continue, Do not close the pdev from here as if host fails
2903 * to update band information if cc_list event is not received
2904 * by this time, then also driver load should happen.
2905 */
2906 hdd_err("Failed to update regulatory band info");
2907
2908 if (!cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
2909 hdd_ctx->reg.reg_domain = cfg->reg_domain;
2910 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
2911 }
2912
2913 /* This can be extended to other configurations like ht, vht cap... */
2914 status = wlan_hdd_validate_mac_address(&cfg->hw_macaddr);
2915 if (QDF_IS_STATUS_SUCCESS(status))
2916 qdf_mem_copy(&hdd_ctx->hw_macaddr, &cfg->hw_macaddr,
2917 QDF_MAC_ADDR_SIZE);
2918
2919 hdd_ctx->target_fw_version = cfg->target_fw_version;
2920 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
2921 hdd_extract_fw_version_info(hdd_ctx);
2922
2923 hdd_ctx->hw_bd_id = cfg->hw_bd_id;
2924 qdf_mem_copy(&hdd_ctx->hw_bd_info, &cfg->hw_bd_info,
2925 sizeof(cfg->hw_bd_info));
2926
2927 if (cfg->max_intf_count > WLAN_MAX_VDEVS) {
2928 hdd_err("fw max vdevs (%u) > host max vdevs (%u); using %u",
2929 cfg->max_intf_count, WLAN_MAX_VDEVS, WLAN_MAX_VDEVS);
2930 hdd_ctx->max_intf_count = WLAN_MAX_VDEVS;
2931 } else {
2932 hdd_ctx->max_intf_count = cfg->max_intf_count;
2933 }
2934
2935 hdd_sar_target_config(hdd_ctx, cfg);
2936 hdd_lpass_target_config(hdd_ctx, cfg);
2937
2938 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
2939
2940 hdd_update_tgt_services(hdd_ctx, &cfg->services);
2941
2942 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
2943
2944 sme_update_bfer_caps_as_per_nss_chains(hdd_ctx->mac_handle, cfg);
2945
2946 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
2947 if (cfg->services.en_11ax &&
2948 (hdd_ctx->config->dot11Mode == eHDD_DOT11_MODE_AUTO ||
2949 hdd_ctx->config->dot11Mode == eHDD_DOT11_MODE_11ax ||
2950 hdd_ctx->config->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY)) {
2951 hdd_debug("11AX: 11ax is enabled - update HDD config");
2952 hdd_update_tgt_he_cap(hdd_ctx, cfg);
2953 hdd_update_wiphy_he_cap(hdd_ctx);
2954 }
2955 hdd_update_tgt_twt_cap(hdd_ctx, cfg);
2956 hdd_update_tgt_eht_cap(hdd_ctx, cfg);
2957 hdd_update_wiphy_eht_cap(hdd_ctx);
2958 ucfg_mlme_update_tgt_mlo_cap(hdd_ctx->psoc);
2959
2960 for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++) {
2961 sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle,
2962 QDF_STA_MODE, band);
2963 sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle,
2964 QDF_SAP_MODE, band);
2965 sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle,
2966 QDF_TDLS_MODE, band);
2967 sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle,
2968 QDF_P2P_DEVICE_MODE,
2969 band);
2970 sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle,
2971 QDF_OCB_MODE, band);
2972 sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle,
2973 QDF_TDLS_MODE, band);
2974 }
2975
2976 hdd_update_vdev_nss(hdd_ctx);
2977
2978 status =
2979 ucfg_mlme_get_enable_dynamic_nss_chains_cfg(hdd_ctx->psoc,
2980 &enable_dynamic_cfg);
2981 if (QDF_IS_STATUS_ERROR(status)) {
2982 hdd_err("unable to get enable dynamic config");
2983 hdd_ctx->dynamic_nss_chains_support = false;
2984 } else {
2985 hdd_ctx->dynamic_nss_chains_support =
2986 cfg->dynamic_nss_chains_support &
2987 enable_dynamic_cfg;
2988 hdd_debug("Dynamic nss chain support FW %d driver %d",
2989 cfg->dynamic_nss_chains_support, enable_dynamic_cfg);
2990 }
2991
2992 status = ucfg_mlme_update_dynamic_nss_chains_support
2993 (hdd_ctx->psoc, hdd_ctx->dynamic_nss_chains_support);
2994 if (QDF_IS_STATUS_ERROR(status))
2995 hdd_err("unable to set dynamic_nss_chains_support");
2996
2997 ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, &fine_time_meas_cap);
2998 fine_time_meas_cap &= cfg->fine_time_measurement_cap;
2999 status = ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
3000 fine_time_meas_cap);
3001 if (QDF_IS_STATUS_ERROR(status)) {
3002 hdd_err("failed to set fine_time_meas_cap, 0x%x, ox%x",
3003 fine_time_meas_cap, cfg->fine_time_measurement_cap);
3004 ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc,
3005 &fine_time_meas_cap);
3006 }
3007
3008 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
3009 hdd_debug("fine_time_meas_cap: 0x%x", fine_time_meas_cap);
3010
3011 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval);
3012 if (!QDF_IS_STATUS_SUCCESS(status))
3013 hdd_err("unable to get vht_enable2x2");
3014
3015 antenna_mode = (bval == 0x01) ?
3016 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
3017 hdd_update_smps_antenna_mode(hdd_ctx, antenna_mode);
3018 hdd_debug("Init current antenna mode: %d",
3019 hdd_ctx->current_antenna_mode);
3020
3021 hdd_ctx->rcpi_enabled = cfg->rcpi_enabled;
3022
3023 status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
3024 &value);
3025 if (QDF_IS_STATUS_ERROR(status)) {
3026 status = false;
3027 hdd_err("set tx_bfee_ant_supp failed");
3028 }
3029
3030 status = ucfg_mlme_set_restricted_80p80_bw_supp(hdd_ctx->psoc,
3031 cfg->restricted_80p80_bw_supp);
3032 if (QDF_IS_STATUS_ERROR(status))
3033 hdd_err("Failed to set MLME restircted 80p80 BW support");
3034
3035 if ((value > MLME_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_FW_DEF) &&
3036 !cfg->tx_bfee_8ss_enabled) {
3037 status = ucfg_mlme_cfg_set_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
3038 MLME_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_FW_DEF);
3039 if (QDF_IS_STATUS_ERROR(status)) {
3040 status = false;
3041 hdd_err("set tx_bfee_ant_supp failed");
3042 }
3043 }
3044
3045 hdd_update_tid_to_link_supported(hdd_ctx, &cfg->services);
3046 mac_handle = hdd_ctx->mac_handle;
3047
3048 hdd_debug("txBFCsnValue %d", value);
3049
3050 /*
3051 * Update txBFCsnValue and NumSoundingDim values to vhtcap in wiphy
3052 */
3053 hdd_update_wiphy_vhtcap(hdd_ctx);
3054
3055 hdd_update_vhtcap_2g(hdd_ctx);
3056
3057 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
3058
3059 wlan_config_sched_scan_plans_to_wiphy(hdd_ctx->wiphy, hdd_ctx->psoc);
3060 /*
3061 * This needs to be done after HDD pdev is created and stored since
3062 * it will access the HDD pdev object lock.
3063 */
3064 hdd_runtime_suspend_context_init(hdd_ctx);
3065
3066 /* Configure NAN datapath features */
3067 hdd_nan_datapath_target_config(hdd_ctx, cfg);
3068 ucfg_nan_set_tgt_caps(hdd_ctx->psoc, &cfg->nan_caps);
3069 hdd_ctx->dfs_cac_offload = cfg->dfs_cac_offload;
3070 hdd_ctx->lte_coex_ant_share = cfg->services.lte_coex_ant_share;
3071 hdd_ctx->obss_scan_offload = cfg->services.obss_scan_offload;
3072 ucfg_scan_set_obss_scan_offload(hdd_ctx->psoc,
3073 hdd_ctx->obss_scan_offload);
3074 status = ucfg_mlme_set_obss_detection_offload_enabled(
3075 hdd_ctx->psoc, cfg->obss_detection_offloaded);
3076 if (QDF_IS_STATUS_ERROR(status))
3077 hdd_err("Couldn't pass WNI_CFG_OBSS_DETECTION_OFFLOAD to CFG");
3078
3079 status = ucfg_mlme_set_obss_color_collision_offload_enabled(
3080 hdd_ctx->psoc, cfg->obss_color_collision_offloaded);
3081 if (QDF_IS_STATUS_ERROR(status))
3082 hdd_err("Failed to set WNI_CFG_OBSS_COLOR_COLLISION_OFFLOAD");
3083
3084 ucfg_mlme_set_bss_color_collision_det_support(
3085 hdd_ctx->psoc,
3086 cfg->obss_color_collision_offloaded);
3087 if (!cfg->obss_color_collision_offloaded) {
3088 status = ucfg_mlme_set_bss_color_collision_det_sta(
3089 hdd_ctx->psoc,
3090 cfg->obss_color_collision_offloaded);
3091 if (QDF_IS_STATUS_ERROR(status))
3092 hdd_err("Failed to set CFG_BSS_CLR_COLLISION_DET_STA");
3093 }
3094
3095 hdd_update_score_config(hdd_ctx);
3096 hdd_update_multi_client_thermal_support(hdd_ctx);
3097
3098 ucfg_psoc_mlme_set_11be_capab(hdd_ctx->psoc, cfg->services.en_11be);
3099 return 0;
3100
3101 dispatcher_close:
3102 dispatcher_pdev_close(hdd_ctx->pdev);
3103 pdev_close:
3104 hdd_component_pdev_close(hdd_ctx->pdev);
3105 exit:
3106 hdd_objmgr_release_and_destroy_pdev(hdd_ctx);
3107
3108 return ret;
3109 }
3110
hdd_dfs_indicate_radar(struct hdd_context * hdd_ctx)3111 bool hdd_dfs_indicate_radar(struct hdd_context *hdd_ctx)
3112 {
3113 struct hdd_adapter *adapter, *next_adapter = NULL;
3114 struct hdd_ap_ctx *ap_ctx;
3115 uint32_t ap_chan;
3116 bool dfs_disable_channel_switch = false;
3117 struct wlan_hdd_link_info *link_info;
3118
3119 if (!hdd_ctx) {
3120 hdd_info("Couldn't get hdd_ctx");
3121 return true;
3122 }
3123
3124 ucfg_mlme_get_dfs_disable_channel_switch(hdd_ctx->psoc,
3125 &dfs_disable_channel_switch);
3126 if (dfs_disable_channel_switch) {
3127 hdd_info("skip tx block hdd_ctx=%pK, disableDFSChSwitch=%d",
3128 hdd_ctx, dfs_disable_channel_switch);
3129 return true;
3130 }
3131
3132 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
3133 NET_DEV_HOLD_DFS_INDICATE_RADAR) {
3134
3135 if (adapter->device_mode != QDF_SAP_MODE &&
3136 adapter->device_mode != QDF_P2P_GO_MODE)
3137 goto next_adapter;
3138
3139 hdd_adapter_for_each_active_link_info(adapter, link_info) {
3140 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
3141 ap_chan = ap_ctx->operating_chan_freq;
3142 if (!wlan_reg_is_passive_or_disable_for_pwrmode(hdd_ctx->pdev,
3143 ap_chan, REG_CURRENT_PWR_MODE))
3144 continue;
3145
3146 ap_ctx->dfs_cac_block_tx = true;
3147 hdd_info("tx blocked for vdev: %d", link_info->vdev_id);
3148 if (link_info->vdev_id != WLAN_UMAC_VDEV_ID_MAX)
3149 cdp_fc_vdev_flush(
3150 cds_get_context(QDF_MODULE_ID_SOC),
3151 link_info->vdev_id);
3152 }
3153 next_adapter:
3154 hdd_adapter_dev_put_debug(adapter,
3155 NET_DEV_HOLD_DFS_INDICATE_RADAR);
3156 }
3157
3158 return true;
3159 }
3160
hdd_is_valid_mac_address(const uint8_t * mac_addr)3161 bool hdd_is_valid_mac_address(const uint8_t *mac_addr)
3162 {
3163 int xdigit = 0;
3164 int separator = 0;
3165
3166 while (*mac_addr) {
3167 if (isxdigit(*mac_addr)) {
3168 xdigit++;
3169 } else if (':' == *mac_addr) {
3170 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
3171 break;
3172
3173 ++separator;
3174 } else {
3175 /* Invalid MAC found */
3176 return false;
3177 }
3178 ++mac_addr;
3179 }
3180 return xdigit == 12 && (separator == 5 || separator == 0);
3181 }
3182
3183 /**
3184 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
3185 * @dev: Handle to struct net_device to be updated.
3186 *
3187 * Return: None
3188 */
hdd_mon_mode_ether_setup(struct net_device * dev)3189 static void hdd_mon_mode_ether_setup(struct net_device *dev)
3190 {
3191 dev->header_ops = NULL;
3192 dev->type = ARPHRD_IEEE80211_RADIOTAP;
3193 dev->hard_header_len = ETH_HLEN;
3194 dev->mtu = ETH_DATA_LEN;
3195 dev->addr_len = ETH_ALEN;
3196 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
3197 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
3198 dev->priv_flags |= IFF_TX_SKB_SHARING;
3199
3200 memset(dev->broadcast, 0xFF, ETH_ALEN);
3201 }
3202
3203 #ifdef FEATURE_MONITOR_MODE_SUPPORT
3204 /**
3205 * hdd_mon_turn_off_ps_and_wow() - Update monitor mode struct net_device.
3206 * @hdd_ctx: Pointer to HDD context.
3207 *
3208 * Return: None
3209 */
hdd_mon_turn_off_ps_and_wow(struct hdd_context * hdd_ctx)3210 static void hdd_mon_turn_off_ps_and_wow(struct hdd_context *hdd_ctx)
3211 {
3212 ucfg_pmo_set_power_save_mode(hdd_ctx->psoc,
3213 PMO_PS_ADVANCED_POWER_SAVE_DISABLE);
3214 ucfg_pmo_set_wow_enable(hdd_ctx->psoc, PMO_WOW_DISABLE_BOTH);
3215 }
3216
3217 /**
3218 * __hdd_mon_open() - HDD Open function
3219 * @dev: Pointer to net_device structure
3220 *
3221 * This is called in response to ifconfig up
3222 *
3223 * Return: 0 for success; non-zero for failure
3224 */
__hdd_mon_open(struct net_device * dev)3225 static int __hdd_mon_open(struct net_device *dev)
3226 {
3227 int ret;
3228 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3229 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3230 struct bbm_params param = {0};
3231
3232 hdd_enter_dev(dev);
3233
3234 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
3235 hdd_debug_rl("Monitor interface is already up");
3236 return 0;
3237 }
3238
3239 ret = wlan_hdd_validate_context(hdd_ctx);
3240 if (ret)
3241 return ret;
3242
3243 hdd_mon_mode_ether_setup(dev);
3244
3245 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
3246 ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) ||
3247 ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc)) {
3248 ret = hdd_trigger_psoc_idle_restart(hdd_ctx);
3249 if (ret) {
3250 hdd_err("Failed to start WLAN modules return");
3251 return ret;
3252 }
3253 hdd_err("hdd_wlan_start_modules() successful !");
3254
3255 if ((!test_bit(SME_SESSION_OPENED,
3256 &adapter->deflink->link_flags)) ||
3257 (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))) {
3258 ret = hdd_start_adapter(adapter, true);
3259 if (ret) {
3260 hdd_err("Failed to start adapter :%d",
3261 adapter->device_mode);
3262 return ret;
3263 }
3264 hdd_err("hdd_start_adapters() successful !");
3265 }
3266 hdd_mon_turn_off_ps_and_wow(hdd_ctx);
3267 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
3268 }
3269
3270 if (con_mode != QDF_GLOBAL_MONITOR_MODE &&
3271 (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) ||
3272 ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc))) {
3273 hdd_info("Acquire wakelock for STA + monitor mode");
3274
3275 qdf_wake_lock_acquire(&hdd_ctx->monitor_mode_wakelock,
3276 WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);
3277 hdd_lpc_disable_powersave(hdd_ctx);
3278 qdf_runtime_pm_prevent_suspend(
3279 &hdd_ctx->runtime_context.monitor_mode);
3280 }
3281
3282 ret = hdd_set_mon_rx_cb(dev);
3283
3284 if (!ret)
3285 ret = hdd_enable_monitor_mode(dev);
3286
3287 if (!ret) {
3288 param.policy = BBM_DRIVER_MODE_POLICY;
3289 param.policy_info.driver_mode = QDF_GLOBAL_MONITOR_MODE;
3290 ucfg_dp_bbm_apply_independent_policy(hdd_ctx->psoc, ¶m);
3291 ucfg_dp_set_current_throughput_level(hdd_ctx->psoc,
3292 PLD_BUS_WIDTH_VERY_HIGH);
3293 }
3294
3295 return ret;
3296 }
3297
3298 /**
3299 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
3300 * @net_dev: Pointer to net_device structure
3301 *
3302 * This is called in response to ifconfig up
3303 *
3304 * Return: 0 for success; non-zero for failure
3305 */
hdd_mon_open(struct net_device * net_dev)3306 static int hdd_mon_open(struct net_device *net_dev)
3307 {
3308 int errno;
3309 struct osif_vdev_sync *vdev_sync;
3310
3311 errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
3312 if (errno)
3313 return errno;
3314
3315 errno = __hdd_mon_open(net_dev);
3316
3317 osif_vdev_sync_trans_stop(vdev_sync);
3318
3319 return errno;
3320 }
3321 #endif
3322
3323 #ifdef WLAN_FEATURE_PKT_CAPTURE
3324 /**
3325 * __hdd_pktcapture_open() - HDD Open function
3326 * @dev: Pointer to net_device structure
3327 *
3328 * This is called in response to ifconfig up
3329 *
3330 * Return: 0 for success; non-zero for failure
3331 */
__hdd_pktcapture_open(struct net_device * dev)3332 static int __hdd_pktcapture_open(struct net_device *dev)
3333 {
3334 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3335 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3336 struct hdd_adapter *sta_adapter;
3337 QDF_STATUS status;
3338 struct wlan_objmgr_vdev *vdev;
3339 int ret;
3340
3341 hdd_enter_dev(dev);
3342
3343 ret = wlan_hdd_validate_context(hdd_ctx);
3344 if (ret)
3345 return ret;
3346
3347 sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
3348 if (!sta_adapter) {
3349 hdd_err("No station interface found");
3350 return -EINVAL;
3351 }
3352
3353 vdev = hdd_objmgr_get_vdev_by_user(sta_adapter->deflink, WLAN_OSIF_ID);
3354 if (!vdev)
3355 return -EINVAL;
3356
3357 hdd_mon_mode_ether_setup(dev);
3358
3359 status = ucfg_dp_register_pkt_capture_callbacks(vdev);
3360 ret = qdf_status_to_os_return(status);
3361 if (ret) {
3362 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
3363 return ret;
3364 }
3365
3366 adapter->deflink->vdev = vdev;
3367 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
3368 sta_adapter->mon_adapter = adapter;
3369
3370 return ret;
3371 }
3372
3373 /**
3374 * hdd_pktcapture_open() - Wrapper function for hdd_pktcapture_open to
3375 * protect it from SSR
3376 * @net_dev: Pointer to net_device structure
3377 *
3378 * This is called in response to ifconfig up
3379 *
3380 * Return: 0 for success; non-zero for failure
3381 */
hdd_pktcapture_open(struct net_device * net_dev)3382 static int hdd_pktcapture_open(struct net_device *net_dev)
3383 {
3384 int errno;
3385 struct osif_vdev_sync *vdev_sync;
3386
3387 errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
3388 if (errno)
3389 return errno;
3390
3391 errno = __hdd_pktcapture_open(net_dev);
3392
3393 osif_vdev_sync_trans_stop(vdev_sync);
3394
3395 return errno;
3396 }
3397
3398 /**
3399 * hdd_unmap_monitor_interface_vdev() - unmap monitor interface vdev and
3400 * deregister packet capture callbacks
3401 * @sta_adapter: station adapter
3402 *
3403 * Return: void
3404 */
3405 static void
hdd_unmap_monitor_interface_vdev(struct hdd_adapter * sta_adapter)3406 hdd_unmap_monitor_interface_vdev(struct hdd_adapter *sta_adapter)
3407 {
3408 struct hdd_adapter *mon_adapter = sta_adapter->mon_adapter;
3409
3410 if (mon_adapter && hdd_is_interface_up(mon_adapter)) {
3411 ucfg_pkt_capture_deregister_callbacks(
3412 mon_adapter->deflink->vdev);
3413 hdd_objmgr_put_vdev_by_user(mon_adapter->deflink->vdev,
3414 WLAN_OSIF_ID);
3415 mon_adapter->deflink->vdev = NULL;
3416 hdd_reset_monitor_interface(sta_adapter);
3417 }
3418 }
3419
3420 /**
3421 * hdd_map_monitor_interface_vdev() - Map monitor interface vdev and
3422 * register packet capture callbacks
3423 * @sta_adapter: Station adapter
3424 *
3425 * Return: None
3426 */
hdd_map_monitor_interface_vdev(struct hdd_adapter * sta_adapter)3427 static void hdd_map_monitor_interface_vdev(struct hdd_adapter *sta_adapter)
3428 {
3429 struct hdd_adapter *mon_adapter;
3430 QDF_STATUS status;
3431 struct wlan_objmgr_vdev *vdev;
3432 int ret;
3433
3434 mon_adapter = hdd_get_adapter(sta_adapter->hdd_ctx, QDF_MONITOR_MODE);
3435 if (!mon_adapter) {
3436 hdd_debug("No monitor interface found");
3437 return;
3438 }
3439
3440 if (!mon_adapter || !hdd_is_interface_up(mon_adapter)) {
3441 hdd_debug("Monitor interface is not up\n");
3442 return;
3443 }
3444
3445 if (!wlan_hdd_is_session_type_monitor(mon_adapter->device_mode))
3446 return;
3447
3448 vdev = hdd_objmgr_get_vdev_by_user(sta_adapter->deflink, WLAN_OSIF_ID);
3449 if (!vdev)
3450 return;
3451
3452 status = ucfg_dp_register_pkt_capture_callbacks(vdev);
3453 ret = qdf_status_to_os_return(status);
3454 if (ret) {
3455 hdd_err("Failed registering packet capture callbacks");
3456 hdd_objmgr_put_vdev_by_user(vdev,
3457 WLAN_OSIF_ID);
3458 return;
3459 }
3460
3461 mon_adapter->deflink->vdev = vdev;
3462 sta_adapter->mon_adapter = mon_adapter;
3463 }
3464
hdd_reset_monitor_interface(struct hdd_adapter * sta_adapter)3465 void hdd_reset_monitor_interface(struct hdd_adapter *sta_adapter)
3466 {
3467 sta_adapter->mon_adapter = NULL;
3468 }
3469
3470 struct hdd_adapter *
hdd_is_pkt_capture_mon_enable(struct hdd_adapter * sta_adapter)3471 hdd_is_pkt_capture_mon_enable(struct hdd_adapter *sta_adapter)
3472 {
3473 return sta_adapter->mon_adapter;
3474 }
3475 #else
3476 static inline void
hdd_unmap_monitor_interface_vdev(struct hdd_adapter * sta_adapter)3477 hdd_unmap_monitor_interface_vdev(struct hdd_adapter *sta_adapter)
3478 {
3479 }
3480
3481 static inline void
hdd_map_monitor_interface_vdev(struct hdd_adapter * sta_adapter)3482 hdd_map_monitor_interface_vdev(struct hdd_adapter *sta_adapter)
3483 {
3484 }
3485 #endif
3486
3487 static QDF_STATUS
wlan_hdd_update_dbs_scan_and_fw_mode_config(void)3488 wlan_hdd_update_dbs_scan_and_fw_mode_config(void)
3489 {
3490 struct policy_mgr_dual_mac_config cfg = {0};
3491 QDF_STATUS status;
3492 uint32_t chnl_sel_logic_conc = 0;
3493 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3494 uint8_t dual_mac_feature = DISABLE_DBS_CXN_AND_SCAN;
3495
3496 if (!hdd_ctx)
3497 return QDF_STATUS_E_FAILURE;
3498
3499 /*
3500 * ROME platform doesn't support any DBS related commands in FW,
3501 * so if driver sends wmi command with dual_mac_config with all set to
3502 * 0 then FW wouldn't respond back and driver would timeout on waiting
3503 * for response. Check if FW supports DBS to eliminate ROME vs
3504 * NON-ROME platform.
3505 */
3506 if (!policy_mgr_find_if_fw_supports_dbs(hdd_ctx->psoc))
3507 return QDF_STATUS_SUCCESS;
3508
3509 if (hdd_ctx->is_dual_mac_cfg_updated) {
3510 hdd_debug("dual mac config has already been updated, skip");
3511 return QDF_STATUS_SUCCESS;
3512 }
3513
3514 cfg.scan_config = 0;
3515 cfg.fw_mode_config = 0;
3516 cfg.set_dual_mac_cb = policy_mgr_soc_set_dual_mac_cfg_cb;
3517 if (policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc)) {
3518 status =
3519 ucfg_policy_mgr_get_chnl_select_plcy(hdd_ctx->psoc,
3520 &chnl_sel_logic_conc);
3521 if (status != QDF_STATUS_SUCCESS) {
3522 hdd_err("can't get chnl sel policy, use def");
3523 return status;
3524 }
3525 }
3526 status =
3527 ucfg_policy_mgr_get_dual_mac_feature(hdd_ctx->psoc,
3528 &dual_mac_feature);
3529 if (status != QDF_STATUS_SUCCESS) {
3530 hdd_err("ucfg_policy_mgr_get_dual_mac_feature failed, use def");
3531 return status;
3532 }
3533
3534 if (dual_mac_feature != DISABLE_DBS_CXN_AND_SCAN) {
3535 status = policy_mgr_get_updated_scan_and_fw_mode_config(
3536 hdd_ctx->psoc, &cfg.scan_config,
3537 &cfg.fw_mode_config,
3538 dual_mac_feature,
3539 chnl_sel_logic_conc);
3540
3541 if (status != QDF_STATUS_SUCCESS) {
3542 hdd_err("wma_get_updated_scan_and_fw_mode_config failed %d",
3543 status);
3544 return status;
3545 }
3546 }
3547
3548 hdd_debug("send scan_cfg: 0x%x fw_mode_cfg: 0x%x to fw",
3549 cfg.scan_config, cfg.fw_mode_config);
3550
3551 status = sme_soc_set_dual_mac_config(cfg);
3552 if (QDF_IS_STATUS_ERROR(status)) {
3553 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
3554 return status;
3555 }
3556 hdd_ctx->is_dual_mac_cfg_updated = true;
3557
3558 return QDF_STATUS_SUCCESS;
3559 }
3560
3561 /**
3562 * hdd_max_sta_interface_up_count_reached() - check sta/p2p_cli vdev count
3563 * @adapter: HDD adapter
3564 *
3565 * Return: true if vdev limit reached
3566 */
hdd_max_sta_interface_up_count_reached(struct hdd_adapter * adapter)3567 static bool hdd_max_sta_interface_up_count_reached(struct hdd_adapter *adapter)
3568 {
3569 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3570 struct hdd_adapter *temp_adapter = NULL, *next_adapter = NULL;
3571 uint8_t intf_count = 0;
3572 wlan_net_dev_ref_dbgid dbgid =
3573 NET_DEV_HOLD_MAX_STA_INTERFACE_UP_COUNT_REACHED;
3574
3575 if (0 == CFG_TGT_DEFAULT_MAX_STA_VDEVS)
3576 return false;
3577
3578 /*
3579 * Check for max no of supported STA/P2PCLI VDEVs before
3580 * creating another one.
3581 */
3582 hdd_for_each_adapter_dev_held_safe(hdd_ctx, temp_adapter,
3583 next_adapter, dbgid) {
3584 if ((temp_adapter != adapter) &&
3585 (temp_adapter->dev->flags & IFF_UP) &&
3586 ((temp_adapter->device_mode == QDF_STA_MODE) ||
3587 (temp_adapter->device_mode == QDF_P2P_CLIENT_MODE)))
3588 intf_count++;
3589
3590 hdd_adapter_dev_put_debug(temp_adapter, dbgid);
3591 }
3592
3593 if (intf_count >= CFG_TGT_DEFAULT_MAX_STA_VDEVS) {
3594 hdd_err("Max limit reached sta vdev-current %d max %d",
3595 intf_count, CFG_TGT_DEFAULT_MAX_STA_VDEVS);
3596 return true;
3597 }
3598 return false;
3599 }
3600
3601 #if (defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)) && \
3602 (defined(CFG80211_IFTYPE_MLO_LINK_SUPPORT) || \
3603 defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT)) && \
3604 !defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
hdd_start_link_adapter(struct hdd_adapter * sta_adapter)3605 static int hdd_start_link_adapter(struct hdd_adapter *sta_adapter)
3606 {
3607 int i, ret = 0;
3608 struct hdd_mlo_adapter_info *mlo_adapter_info;
3609 struct hdd_adapter *link_adapter;
3610
3611 hdd_enter_dev(sta_adapter->dev);
3612 mlo_adapter_info = &sta_adapter->mlo_adapter_info;
3613
3614 for (i = 0; i < WLAN_MAX_MLD; i++) {
3615 link_adapter = mlo_adapter_info->link_adapter[i];
3616 if (!link_adapter)
3617 continue;
3618 if (link_adapter->mlo_adapter_info.associate_with_ml_adapter) {
3619 /* TODO have proper references here */
3620 qdf_spin_lock_bh(&link_adapter->deflink->vdev_lock);
3621 link_adapter->deflink->vdev =
3622 sta_adapter->deflink->vdev;
3623 link_adapter->deflink->vdev_id =
3624 sta_adapter->deflink->vdev_id;
3625 qdf_spin_unlock_bh(&link_adapter->deflink->vdev_lock);
3626
3627 sta_adapter->link_info[i].vdev_id =
3628 sta_adapter->deflink->vdev_id;
3629 continue;
3630 }
3631 ret = hdd_start_station_adapter(link_adapter);
3632 if (!ret) {
3633 sta_adapter->link_info[i].vdev_id =
3634 link_adapter->deflink->vdev_id;
3635 }
3636 }
3637
3638 hdd_adapter_update_mlo_mgr_mac_addr(sta_adapter);
3639
3640 hdd_exit();
3641 return ret;
3642 }
3643
hdd_stop_link_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter * sta_adapter)3644 static int hdd_stop_link_adapter(struct hdd_context *hdd_ctx,
3645 struct hdd_adapter *sta_adapter)
3646 {
3647 int i, ret = 0;
3648 struct hdd_mlo_adapter_info *mlo_adapter_info;
3649 struct hdd_adapter *link_adapter;
3650
3651 hdd_enter_dev(sta_adapter->dev);
3652 hdd_debug("Stop adapter for link mode : %s(%d)",
3653 qdf_opmode_str(sta_adapter->device_mode),
3654 sta_adapter->deflink->vdev_id);
3655
3656 mlo_adapter_info = &sta_adapter->mlo_adapter_info;
3657 for (i = 0; i < WLAN_MAX_MLD; i++) {
3658 link_adapter = mlo_adapter_info->link_adapter[i];
3659 if (!link_adapter)
3660 continue;
3661
3662 if (link_adapter->mlo_adapter_info.associate_with_ml_adapter) {
3663 /* TODO have proper references here */
3664 qdf_spin_lock_bh(&link_adapter->deflink->vdev_lock);
3665 link_adapter->deflink->vdev = NULL;
3666 link_adapter->deflink->vdev_id = 0xff;
3667 qdf_spin_unlock_bh(&link_adapter->deflink->vdev_lock);
3668 continue;
3669 }
3670 ret = hdd_stop_adapter_ext(hdd_ctx, link_adapter);
3671 }
3672
3673 hdd_exit();
3674 return ret;
3675 }
3676 #else
hdd_start_link_adapter(struct hdd_adapter * link_adapter)3677 static int hdd_start_link_adapter(struct hdd_adapter *link_adapter)
3678 {
3679 return 0;
3680 }
3681
hdd_stop_link_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter * link_adapter)3682 static int hdd_stop_link_adapter(struct hdd_context *hdd_ctx,
3683 struct hdd_adapter *link_adapter)
3684 {
3685 return 0;
3686 }
3687 #endif
3688
3689 /**
3690 * hdd_start_adapter() - Wrapper function for device specific adapter
3691 * @adapter: pointer to HDD adapter
3692 * @rtnl_held: true if rtnl lock is taken, otherwise false
3693 *
3694 * This function is called to start the device specific adapter for
3695 * the mode passed in the adapter's device_mode.
3696 *
3697 * Return: 0 for success; non-zero for failure
3698 */
hdd_start_adapter(struct hdd_adapter * adapter,bool rtnl_held)3699 int hdd_start_adapter(struct hdd_adapter *adapter, bool rtnl_held)
3700 {
3701
3702 int ret;
3703 enum QDF_OPMODE device_mode = adapter->device_mode;
3704
3705 hdd_enter_dev(adapter->dev);
3706
3707 switch (device_mode) {
3708 case QDF_MONITOR_MODE:
3709 ret = hdd_start_station_adapter(adapter);
3710 if (ret)
3711 goto err_start_adapter;
3712 hdd_set_idle_ps_config(adapter->hdd_ctx, false);
3713 break;
3714 case QDF_STA_MODE:
3715 case QDF_P2P_CLIENT_MODE:
3716 if (hdd_max_sta_interface_up_count_reached(adapter))
3717 goto err_start_adapter;
3718 fallthrough;
3719 case QDF_P2P_DEVICE_MODE:
3720 case QDF_OCB_MODE:
3721 case QDF_NAN_DISC_MODE:
3722 ret = hdd_start_station_adapter(adapter);
3723 if (ret)
3724 goto err_start_adapter;
3725
3726 if (device_mode == QDF_STA_MODE) {
3727 ret = hdd_start_link_adapter(adapter);
3728 if (ret)
3729 hdd_err("Failed to start link adapter:%d", ret);
3730 }
3731 break;
3732 case QDF_P2P_GO_MODE:
3733 case QDF_SAP_MODE:
3734 ret = hdd_start_ap_adapter(adapter, rtnl_held);
3735 if (ret)
3736 goto err_start_adapter;
3737 break;
3738 case QDF_FTM_MODE:
3739 /* vdevs are dynamically managed by firmware in FTM */
3740 hdd_register_wext(adapter->dev);
3741 goto exit_with_success;
3742 default:
3743 hdd_err("Invalid session type %d", device_mode);
3744 QDF_ASSERT(0);
3745 goto err_start_adapter;
3746 }
3747
3748 if (hdd_set_fw_params(adapter))
3749 hdd_err("Failed to set the FW params for the adapter!");
3750
3751 if (adapter->deflink->vdev_id != WLAN_UMAC_VDEV_ID_MAX) {
3752 ret = wlan_hdd_cfg80211_register_frames(adapter);
3753 if (ret < 0) {
3754 hdd_err("Failed to register frames - ret %d", ret);
3755 goto err_start_adapter;
3756 }
3757 }
3758
3759 wlan_hdd_update_dbs_scan_and_fw_mode_config();
3760
3761 exit_with_success:
3762 hdd_create_adapter_sysfs_files(adapter);
3763
3764 hdd_exit();
3765
3766 return 0;
3767
3768 err_start_adapter:
3769 return -EINVAL;
3770 }
3771
hdd_update_hw_sw_info(struct hdd_context * hdd_ctx)3772 void hdd_update_hw_sw_info(struct hdd_context *hdd_ctx)
3773 {
3774 void *hif_sc;
3775 size_t target_hw_name_len;
3776 const char *target_hw_name;
3777 uint8_t *buf;
3778 uint32_t buf_len;
3779
3780 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
3781 if (!hif_sc)
3782 return;
3783
3784 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
3785 &hdd_ctx->target_hw_revision,
3786 &target_hw_name);
3787
3788 qdf_mem_zero(hdd_ctx->target_hw_name, MAX_TGT_HW_NAME_LEN);
3789
3790 target_hw_name_len = strlen(target_hw_name) + 1;
3791
3792 if (target_hw_name_len <= MAX_TGT_HW_NAME_LEN) {
3793 qdf_mem_copy(hdd_ctx->target_hw_name, target_hw_name,
3794 target_hw_name_len);
3795 } else {
3796 hdd_err("target_hw_name_len is greater than MAX_TGT_HW_NAME_LEN");
3797 return;
3798 }
3799
3800 hdd_debug("target_hw_name = %s", hdd_ctx->target_hw_name);
3801
3802 buf = qdf_mem_malloc(WE_MAX_STR_LEN);
3803 if (buf) {
3804 buf_len = hdd_wlan_get_version(hdd_ctx, WE_MAX_STR_LEN, buf);
3805 hdd_nofl_debug("%s", buf);
3806 qdf_mem_free(buf);
3807 }
3808 }
3809
3810 /**
3811 * hdd_update_cds_ac_specs_params() - update cds ac_specs params
3812 * @hdd_ctx: Pointer to hdd context
3813 *
3814 * Return: none
3815 */
3816 static void
hdd_update_cds_ac_specs_params(struct hdd_context * hdd_ctx)3817 hdd_update_cds_ac_specs_params(struct hdd_context *hdd_ctx)
3818 {
3819 uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM] = {0};
3820 qdf_size_t out_size = 0;
3821 int i;
3822 struct cds_context *cds_ctx;
3823
3824 if (!hdd_ctx)
3825 return;
3826
3827 if (!hdd_ctx->config) {
3828 /* Do nothing if hdd_ctx is invalid */
3829 hdd_err("Warning: hdd_ctx->cfg_ini is NULL");
3830 return;
3831 }
3832
3833 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
3834 if (!cds_ctx)
3835 return;
3836
3837 for (i = 0; i < QCA_WLAN_AC_ALL; i++) {
3838 switch (i) {
3839 case QCA_WLAN_AC_BE:
3840 qdf_uint8_array_parse(
3841 cfg_get(hdd_ctx->psoc,
3842 CFG_DP_ENABLE_TX_SCHED_WRR_BE),
3843 tx_sched_wrr_param,
3844 sizeof(tx_sched_wrr_param),
3845 &out_size);
3846 break;
3847 case QCA_WLAN_AC_BK:
3848 qdf_uint8_array_parse(
3849 cfg_get(hdd_ctx->psoc,
3850 CFG_DP_ENABLE_TX_SCHED_WRR_BK),
3851 tx_sched_wrr_param,
3852 sizeof(tx_sched_wrr_param),
3853 &out_size);
3854 break;
3855 case QCA_WLAN_AC_VI:
3856 qdf_uint8_array_parse(
3857 cfg_get(hdd_ctx->psoc,
3858 CFG_DP_ENABLE_TX_SCHED_WRR_VI),
3859 tx_sched_wrr_param,
3860 sizeof(tx_sched_wrr_param),
3861 &out_size);
3862 break;
3863 case QCA_WLAN_AC_VO:
3864 qdf_uint8_array_parse(
3865 cfg_get(hdd_ctx->psoc,
3866 CFG_DP_ENABLE_TX_SCHED_WRR_VO),
3867 tx_sched_wrr_param,
3868 sizeof(tx_sched_wrr_param),
3869 &out_size);
3870 break;
3871 default:
3872 break;
3873 }
3874
3875 if (out_size == TX_SCHED_WRR_PARAMS_NUM) {
3876 cds_ctx->ac_specs[i].wrr_skip_weight =
3877 tx_sched_wrr_param[0];
3878 cds_ctx->ac_specs[i].credit_threshold =
3879 tx_sched_wrr_param[1];
3880 cds_ctx->ac_specs[i].send_limit =
3881 tx_sched_wrr_param[2];
3882 cds_ctx->ac_specs[i].credit_reserve =
3883 tx_sched_wrr_param[3];
3884 cds_ctx->ac_specs[i].discard_weight =
3885 tx_sched_wrr_param[4];
3886 }
3887
3888 out_size = 0;
3889 }
3890 }
3891
hdd_wlan_get_version(struct hdd_context * hdd_ctx,const size_t version_len,uint8_t * version)3892 uint32_t hdd_wlan_get_version(struct hdd_context *hdd_ctx,
3893 const size_t version_len, uint8_t *version)
3894 {
3895 uint32_t size;
3896 uint8_t reg_major = 0, reg_minor = 0, bdf_major = 0, bdf_minor = 0;
3897 struct target_psoc_info *tgt_hdl;
3898
3899 if (!hdd_ctx) {
3900 hdd_err("Invalid context, HDD context is null");
3901 return 0;
3902 }
3903
3904 if (!version || version_len == 0) {
3905 hdd_err("Invalid buffer pointr or buffer len\n");
3906 return 0;
3907 }
3908 tgt_hdl = wlan_psoc_get_tgt_if_handle(hdd_ctx->psoc);
3909 if (tgt_hdl)
3910 target_psoc_get_version_info(tgt_hdl, ®_major, ®_minor,
3911 &bdf_major, &bdf_minor);
3912
3913 size = scnprintf(version, version_len,
3914 "Host SW:%s, FW:%d.%d.%d.%d.%d.%d, HW:%s, Board ver: %x Ref design id: %x, Customer id: %x, Project id: %x, Board Data Rev: %x, REG DB: %u:%u, BDF REG DB: %u:%u",
3915 QWLAN_VERSIONSTR,
3916 hdd_ctx->fw_version_info.major_spid,
3917 hdd_ctx->fw_version_info.minor_spid,
3918 hdd_ctx->fw_version_info.siid,
3919 hdd_ctx->fw_version_info.rel_id,
3920 hdd_ctx->fw_version_info.crmid,
3921 hdd_ctx->fw_version_info.sub_id,
3922 hdd_ctx->target_hw_name,
3923 hdd_ctx->hw_bd_info.bdf_version,
3924 hdd_ctx->hw_bd_info.ref_design_id,
3925 hdd_ctx->hw_bd_info.customer_id,
3926 hdd_ctx->hw_bd_info.project_id,
3927 hdd_ctx->hw_bd_info.board_data_rev,
3928 reg_major, reg_minor, bdf_major, bdf_minor);
3929
3930 return size;
3931 }
3932
hdd_set_11ax_rate(struct hdd_adapter * adapter,int set_value,struct sap_config * sap_config)3933 int hdd_set_11ax_rate(struct hdd_adapter *adapter, int set_value,
3934 struct sap_config *sap_config)
3935 {
3936 uint8_t preamble = 0, nss = 0, rix = 0;
3937 int ret;
3938 mac_handle_t mac_handle = adapter->hdd_ctx->mac_handle;
3939
3940 if (!sap_config) {
3941 if (!sme_is_feature_supported_by_fw(DOT11AX)) {
3942 hdd_err("Target does not support 11ax");
3943 return -EIO;
3944 }
3945 } else if (sap_config->SapHw_mode != eCSR_DOT11_MODE_11ax &&
3946 sap_config->SapHw_mode != eCSR_DOT11_MODE_11ax_ONLY) {
3947 hdd_err("Invalid hw mode, SAP hw_mode= 0x%x, ch_freq = %d",
3948 sap_config->SapHw_mode, sap_config->chan_freq);
3949 return -EIO;
3950 }
3951
3952 if (set_value != 0xffff) {
3953 rix = RC_2_RATE_IDX_11AX(set_value);
3954 preamble = WMI_RATE_PREAMBLE_HE;
3955 nss = HT_RC_2_STREAMS_11AX(set_value);
3956
3957 set_value = hdd_assemble_rate_code(preamble, nss, rix);
3958 } else {
3959 ret = sme_set_auto_rate_he_ltf(mac_handle,
3960 adapter->deflink->vdev_id,
3961 QCA_WLAN_HE_LTF_AUTO);
3962 }
3963
3964 hdd_info("SET_11AX_RATE val %d rix %d preamble %x nss %d",
3965 set_value, rix, preamble, nss);
3966
3967 ret = wma_cli_set_command(adapter->deflink->vdev_id,
3968 wmi_vdev_param_fixed_rate,
3969 set_value, VDEV_CMD);
3970
3971 return ret;
3972 }
3973
hdd_assemble_rate_code(uint8_t preamble,uint8_t nss,uint8_t rate)3974 int hdd_assemble_rate_code(uint8_t preamble, uint8_t nss, uint8_t rate)
3975 {
3976 return ucfg_mlme_assemble_rate_code(preamble, nss, rate);
3977 }
3978
3979 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
wlan_hdd_get_mode_for_non_connected_vdev(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id)3980 static enum policy_mgr_con_mode wlan_hdd_get_mode_for_non_connected_vdev(
3981 struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
3982 {
3983 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3984 struct hdd_adapter *adapter;
3985 enum policy_mgr_con_mode mode;
3986 struct wlan_hdd_link_info *link_info;
3987
3988 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
3989 if (!link_info) {
3990 hdd_err("Invalid vdev");
3991 return PM_MAX_NUM_OF_MODE;
3992 }
3993
3994 adapter = link_info->adapter;
3995 mode = policy_mgr_qdf_opmode_to_pm_con_mode(psoc,
3996 adapter->device_mode,
3997 vdev_id);
3998 return mode;
3999 }
4000
4001 /**
4002 * hdd_is_chan_switch_in_progress() - Check if any adapter has channel switch in
4003 * progress
4004 *
4005 * Return: true, if any adapter has channel switch in
4006 * progress else false
4007 */
hdd_is_chan_switch_in_progress(void)4008 static bool hdd_is_chan_switch_in_progress(void)
4009 {
4010 struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
4011 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
4012 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_IS_CHAN_SWITCH_IN_PROGRESS;
4013 struct hdd_ap_ctx *ap_ctx;
4014 struct wlan_hdd_link_info *link_info;
4015 bool is_restart;
4016 struct wlan_objmgr_vdev *vdev;
4017
4018 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
4019 dbgid) {
4020 if (adapter->device_mode != QDF_SAP_MODE &&
4021 adapter->device_mode != QDF_P2P_GO_MODE)
4022 goto next_adapter;
4023
4024 hdd_adapter_for_each_active_link_info(adapter, link_info) {
4025 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
4026 vdev = hdd_objmgr_get_vdev_by_user(link_info,
4027 WLAN_OSIF_ID);
4028 if (!vdev)
4029 continue;
4030 is_restart = false;
4031 if (wlan_vdev_is_restart_progress(vdev) ==
4032 QDF_STATUS_SUCCESS) {
4033 hdd_debug("vdev: %d restart in progress",
4034 wlan_vdev_get_id(vdev));
4035 is_restart = true;
4036 }
4037 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
4038
4039 if (is_restart ||
4040 qdf_atomic_read(&ap_ctx->ch_switch_in_progress)) {
4041 hdd_debug("channel switch progress for vdev_id %d",
4042 link_info->vdev_id);
4043 hdd_adapter_dev_put_debug(adapter, dbgid);
4044 if (next_adapter)
4045 hdd_adapter_dev_put_debug(next_adapter,
4046 dbgid);
4047 return true;
4048 }
4049 }
4050 next_adapter:
4051 hdd_adapter_dev_put_debug(adapter, dbgid);
4052 }
4053
4054 return false;
4055 }
4056
4057 /**
4058 * hdd_is_cac_in_progress() - Check if any SAP connection is performing
4059 * CAC on DFS channel
4060 *
4061 * Return: true, if any of existing SAP is performing CAC
4062 * or else false
4063 */
hdd_is_cac_in_progress(void)4064 static bool hdd_is_cac_in_progress(void)
4065 {
4066 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
4067
4068 if (!hdd_ctx)
4069 return false;
4070
4071 return (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS);
4072 }
4073
4074 static QDF_STATUS
wlan_hdd_set_tx_rx_nss_cb(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,uint8_t tx_nss,uint8_t rx_nss)4075 wlan_hdd_set_tx_rx_nss_cb(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
4076 uint8_t tx_nss, uint8_t rx_nss)
4077 {
4078 struct wlan_hdd_link_info *link_info;
4079
4080 link_info = wlan_hdd_get_link_info_from_vdev(psoc, vdev_id);
4081 if (!link_info) {
4082 hdd_err("Invalid vdev %d", vdev_id);
4083 return QDF_STATUS_E_FAILURE;
4084 }
4085
4086 return hdd_update_nss(link_info, tx_nss, rx_nss);
4087 }
4088
hdd_register_policy_manager_callback(struct wlan_objmgr_psoc * psoc)4089 static void hdd_register_policy_manager_callback(
4090 struct wlan_objmgr_psoc *psoc)
4091 {
4092 struct policy_mgr_hdd_cbacks hdd_cbacks;
4093
4094 qdf_mem_zero(&hdd_cbacks, sizeof(hdd_cbacks));
4095 hdd_cbacks.sap_restart_chan_switch_cb =
4096 hdd_sap_restart_chan_switch_cb;
4097 hdd_cbacks.wlan_hdd_get_channel_for_sap_restart =
4098 wlan_hdd_get_channel_for_sap_restart;
4099 hdd_cbacks.get_mode_for_non_connected_vdev =
4100 wlan_hdd_get_mode_for_non_connected_vdev;
4101 hdd_cbacks.hdd_get_device_mode = hdd_get_device_mode;
4102 hdd_cbacks.hdd_is_chan_switch_in_progress =
4103 hdd_is_chan_switch_in_progress;
4104 hdd_cbacks.hdd_is_cac_in_progress =
4105 hdd_is_cac_in_progress;
4106 hdd_cbacks.wlan_hdd_set_sap_csa_reason =
4107 wlan_hdd_set_sap_csa_reason;
4108 hdd_cbacks.hdd_get_ap_6ghz_capable = hdd_get_ap_6ghz_capable;
4109 hdd_cbacks.wlan_hdd_indicate_active_ndp_cnt =
4110 hdd_indicate_active_ndp_cnt;
4111 hdd_cbacks.wlan_get_ap_prefer_conc_ch_params =
4112 wlan_get_ap_prefer_conc_ch_params;
4113 hdd_cbacks.wlan_get_sap_acs_band =
4114 wlan_get_sap_acs_band;
4115 hdd_cbacks.wlan_check_cc_intf_cb = wlan_hdd_check_cc_intf_cb;
4116 hdd_cbacks.wlan_set_tx_rx_nss_cb = wlan_hdd_set_tx_rx_nss_cb;
4117
4118 if (QDF_STATUS_SUCCESS !=
4119 policy_mgr_register_hdd_cb(psoc, &hdd_cbacks)) {
4120 hdd_err("HDD callback registration with policy manager failed");
4121 }
4122 }
4123 #else
hdd_register_policy_manager_callback(struct wlan_objmgr_psoc * psoc)4124 static void hdd_register_policy_manager_callback(
4125 struct wlan_objmgr_psoc *psoc)
4126 {
4127 }
4128 #endif
4129
4130 #ifdef WLAN_SUPPORT_GAP_LL_PS_MODE
hdd_register_green_ap_callback(struct wlan_objmgr_pdev * pdev)4131 static void hdd_register_green_ap_callback(struct wlan_objmgr_pdev *pdev)
4132 {
4133 struct green_ap_hdd_callback hdd_cback;
4134 qdf_mem_zero(&hdd_cback, sizeof(hdd_cback));
4135
4136 hdd_cback.send_event = wlan_hdd_send_green_ap_ll_ps_event;
4137
4138 if (QDF_STATUS_SUCCESS !=
4139 green_ap_register_hdd_callback(pdev, &hdd_cback)) {
4140 hdd_err("HDD callback registration for Green AP failed");
4141 }
4142 }
4143 #else
hdd_register_green_ap_callback(struct wlan_objmgr_pdev * pdev)4144 static inline void hdd_register_green_ap_callback(struct wlan_objmgr_pdev *pdev)
4145 {
4146 }
4147 #endif
4148
4149 #ifdef WLAN_FEATURE_NAN
4150 #ifdef WLAN_FEATURE_SR
hdd_register_sr_concurrency_cb(struct nan_callbacks * cb_obj)4151 static void hdd_register_sr_concurrency_cb(struct nan_callbacks *cb_obj)
4152 {
4153 cb_obj->nan_sr_concurrency_update = hdd_nan_sr_concurrency_update;
4154 }
4155 #else
hdd_register_sr_concurrency_cb(struct nan_callbacks * cb_obj)4156 static void hdd_register_sr_concurrency_cb(struct nan_callbacks *cb_obj)
4157 {}
4158 #endif
hdd_nan_register_callbacks(struct hdd_context * hdd_ctx)4159 static void hdd_nan_register_callbacks(struct hdd_context *hdd_ctx)
4160 {
4161 struct nan_callbacks cb_obj = {0};
4162
4163 cb_obj.ndi_open = hdd_ndi_open;
4164 cb_obj.ndi_close = hdd_ndi_close;
4165 cb_obj.ndi_set_mode = hdd_ndi_set_mode;
4166 cb_obj.ndi_start = hdd_ndi_start;
4167 cb_obj.ndi_delete = hdd_ndi_delete;
4168 cb_obj.drv_ndi_create_rsp_handler = hdd_ndi_drv_ndi_create_rsp_handler;
4169 cb_obj.drv_ndi_delete_rsp_handler = hdd_ndi_drv_ndi_delete_rsp_handler;
4170
4171 cb_obj.new_peer_ind = hdd_ndp_new_peer_handler;
4172 cb_obj.peer_departed_ind = hdd_ndp_peer_departed_handler;
4173
4174 cb_obj.nan_concurrency_update = hdd_nan_concurrency_update;
4175 cb_obj.set_mc_list = hdd_update_multicast_list;
4176
4177 hdd_register_sr_concurrency_cb(&cb_obj);
4178
4179 os_if_nan_register_hdd_callbacks(hdd_ctx->psoc, &cb_obj);
4180 }
4181 #else
hdd_nan_register_callbacks(struct hdd_context * hdd_ctx)4182 static inline void hdd_nan_register_callbacks(struct hdd_context *hdd_ctx)
4183 {
4184 }
4185 #endif
4186
4187 #ifdef CONFIG_LEAK_DETECTION
4188 /**
4189 * hdd_check_for_leaks() - Perform runtime memory leak checks
4190 * @hdd_ctx: the global HDD context
4191 * @is_ssr: true if SSR is in progress
4192 *
4193 * This API triggers runtime memory leak detection. This feature enforces the
4194 * policy that any memory allocated at runtime must also be released at runtime.
4195 *
4196 * Allocating memory at runtime and releasing it at unload is effectively a
4197 * memory leak for configurations which never unload (e.g. LONU, statically
4198 * compiled driver). Such memory leaks are NOT false positives, and must be
4199 * fixed.
4200 *
4201 * Return: None
4202 */
hdd_check_for_leaks(struct hdd_context * hdd_ctx,bool is_ssr)4203 static void hdd_check_for_leaks(struct hdd_context *hdd_ctx, bool is_ssr)
4204 {
4205 /* DO NOT REMOVE these checks; for false positives, read above first */
4206
4207 wlan_objmgr_psoc_check_for_leaks(hdd_ctx->psoc);
4208
4209 /* many adapter resources are not freed by design during SSR */
4210 if (is_ssr)
4211 return;
4212
4213 qdf_wake_lock_check_for_leaks();
4214 qdf_delayed_work_check_for_leaks();
4215 qdf_mc_timer_check_for_leaks();
4216 qdf_nbuf_map_check_for_leaks();
4217 qdf_periodic_work_check_for_leaks();
4218 qdf_mem_check_for_leaks();
4219 }
4220
4221 /**
4222 * hdd_debug_domain_set() - Set qdf debug domain
4223 * @domain: debug domain to be set
4224 *
4225 * In the scenario of system reboot, it may have thread accessing debug domain
4226 * for memory allocation/free, other than the one trying to change it.
4227 * If debug domain is changed after a memory allocation but before the free,
4228 * it will hit debug domain mismatch assertion in memory free.
4229 * To avoid such assertion, skip debug domain transition if system reboot is
4230 * in progress.
4231 *
4232 * Return: 0 if the specified debug domain has been set, -EBUSY otherwise
4233 */
hdd_debug_domain_set(enum qdf_debug_domain domain)4234 static int hdd_debug_domain_set(enum qdf_debug_domain domain)
4235 {
4236 int ret = 0;
4237
4238 if (cds_sys_reboot_protect()) {
4239 hdd_info("System is rebooting, skip debug domain transition");
4240 ret = -EBUSY;
4241 } else {
4242 qdf_debug_domain_set(domain);
4243 }
4244
4245 cds_sys_reboot_unprotect();
4246
4247 return ret;
4248 }
4249
4250 #define hdd_debug_domain_get() qdf_debug_domain_get()
4251 #else
hdd_check_for_objmgr_peer_leaks(struct wlan_objmgr_psoc * psoc)4252 static void hdd_check_for_objmgr_peer_leaks(struct wlan_objmgr_psoc *psoc)
4253 {
4254 uint32_t vdev_id;
4255 struct wlan_objmgr_vdev *vdev;
4256 struct wlan_objmgr_peer *peer;
4257
4258 /* get module id which cause the leak and release ref */
4259 wlan_objmgr_for_each_psoc_vdev(psoc, vdev_id, vdev) {
4260 wlan_objmgr_for_each_vdev_peer(vdev, peer) {
4261 qdf_atomic_t *ref_id_dbg;
4262 int ref_id;
4263 int32_t refs;
4264
4265 ref_id_dbg = vdev->vdev_objmgr.ref_id_dbg;
4266 wlan_objmgr_for_each_refs(ref_id_dbg, ref_id, refs)
4267 wlan_objmgr_peer_release_ref(peer, ref_id);
4268 }
4269 }
4270 }
4271
hdd_check_for_objmgr_leaks(struct hdd_context * hdd_ctx)4272 static void hdd_check_for_objmgr_leaks(struct hdd_context *hdd_ctx)
4273 {
4274 uint32_t vdev_id, pdev_id;
4275 struct wlan_objmgr_psoc *psoc;
4276 struct wlan_objmgr_vdev *vdev;
4277 struct wlan_objmgr_pdev *pdev;
4278 /*
4279 * leak detection is disabled, force release the references for the wlan
4280 * to recover cleanly.
4281 */
4282 psoc = hdd_ctx->psoc;
4283 if (!psoc)
4284 return;
4285
4286
4287 hdd_check_for_objmgr_peer_leaks(psoc);
4288
4289 wlan_objmgr_for_each_psoc_vdev(psoc, vdev_id, vdev) {
4290 qdf_atomic_t *ref_id_dbg;
4291 int ref_id;
4292 int32_t refs;
4293
4294 ref_id_dbg = vdev->vdev_objmgr.ref_id_dbg;
4295 wlan_objmgr_for_each_refs(ref_id_dbg, ref_id, refs) {
4296 wlan_objmgr_vdev_release_ref(vdev, ref_id);
4297 }
4298 }
4299
4300 wlan_objmgr_for_each_psoc_pdev(psoc, pdev_id, pdev) {
4301 qdf_atomic_t *ref_id_dbg;
4302 int ref_id;
4303 int32_t refs;
4304
4305 ref_id_dbg = pdev->pdev_objmgr.ref_id_dbg;
4306 wlan_objmgr_for_each_refs(ref_id_dbg, ref_id, refs)
4307 wlan_objmgr_pdev_release_ref(pdev, ref_id);
4308 }
4309 }
4310
hdd_check_for_leaks(struct hdd_context * hdd_ctx,bool is_ssr)4311 static void hdd_check_for_leaks(struct hdd_context *hdd_ctx, bool is_ssr)
4312 {
4313 hdd_check_for_objmgr_leaks(hdd_ctx);
4314 }
4315
4316 #define hdd_debug_domain_set(domain) 0
4317 #define hdd_debug_domain_get() DEFAULT_DEBUG_DOMAIN_INIT
4318 #endif /* CONFIG_LEAK_DETECTION */
4319
4320 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
4321 /**
4322 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
4323 * @data: pointer to struct hdd_context
4324 *
4325 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
4326 * Then new ACS request will do a fresh scan without reusing the cached
4327 * scan information.
4328 *
4329 * Return: void
4330 */
hdd_skip_acs_scan_timer_handler(void * data)4331 static void hdd_skip_acs_scan_timer_handler(void *data)
4332 {
4333 struct hdd_context *hdd_ctx = data;
4334 mac_handle_t mac_handle;
4335
4336 hdd_debug("ACS Scan result expired. Reset ACS scan skip");
4337 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
4338 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4339 qdf_mem_free(hdd_ctx->last_acs_freq_list);
4340 hdd_ctx->last_acs_freq_list = NULL;
4341 hdd_ctx->num_of_channels = 0;
4342 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
4343
4344 mac_handle = hdd_ctx->mac_handle;
4345 if (!mac_handle)
4346 return;
4347 }
4348
hdd_skip_acs_scan_timer_init(struct hdd_context * hdd_ctx)4349 static void hdd_skip_acs_scan_timer_init(struct hdd_context *hdd_ctx)
4350 {
4351 QDF_STATUS status;
4352
4353 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
4354 QDF_TIMER_TYPE_SW,
4355 hdd_skip_acs_scan_timer_handler,
4356 hdd_ctx);
4357 if (QDF_IS_STATUS_ERROR(status))
4358 hdd_err("Failed to init ACS Skip timer");
4359 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
4360 }
4361
hdd_skip_acs_scan_timer_deinit(struct hdd_context * hdd_ctx)4362 static void hdd_skip_acs_scan_timer_deinit(struct hdd_context *hdd_ctx)
4363 {
4364 if (QDF_TIMER_STATE_RUNNING ==
4365 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4366 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
4367 }
4368
4369 if (!QDF_IS_STATUS_SUCCESS
4370 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
4371 hdd_err("Cannot deallocate ACS Skip timer");
4372 }
4373 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4374 qdf_mem_free(hdd_ctx->last_acs_freq_list);
4375 hdd_ctx->last_acs_freq_list = NULL;
4376 hdd_ctx->num_of_channels = 0;
4377 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
4378 }
4379 #else
hdd_skip_acs_scan_timer_init(struct hdd_context * hdd_ctx)4380 static void hdd_skip_acs_scan_timer_init(struct hdd_context *hdd_ctx) {}
hdd_skip_acs_scan_timer_deinit(struct hdd_context * hdd_ctx)4381 static void hdd_skip_acs_scan_timer_deinit(struct hdd_context *hdd_ctx) {}
4382 #endif
4383
4384 /**
4385 * hdd_update_country_code - Update country code
4386 * @hdd_ctx: HDD context
4387 *
4388 * Update country code based on module parameter country_code
4389 *
4390 * Return: 0 on success and errno on failure
4391 */
hdd_update_country_code(struct hdd_context * hdd_ctx)4392 int hdd_update_country_code(struct hdd_context *hdd_ctx)
4393 {
4394 if (!country_code ||
4395 !ucfg_reg_is_user_country_set_allowed(hdd_ctx->psoc))
4396 return 0;
4397
4398 return hdd_reg_set_country(hdd_ctx, country_code);
4399 }
4400
4401 #ifdef WLAN_NS_OFFLOAD
4402 /**
4403 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
4404 * @hdd_ctx: Pointer to hdd context
4405 *
4406 * Unregister for IPv6 address change notifications.
4407 *
4408 * Return: None
4409 */
hdd_wlan_unregister_ip6_notifier(struct hdd_context * hdd_ctx)4410 static void hdd_wlan_unregister_ip6_notifier(struct hdd_context *hdd_ctx)
4411 {
4412 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4413 }
4414
4415 /**
4416 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
4417 * @hdd_ctx: Pointer to hdd context
4418 *
4419 * Register for IPv6 address change notifications.
4420 *
4421 * Return: 0 on success and errno on failure.
4422 */
hdd_wlan_register_ip6_notifier(struct hdd_context * hdd_ctx)4423 static int hdd_wlan_register_ip6_notifier(struct hdd_context *hdd_ctx)
4424 {
4425 int ret;
4426
4427 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4428 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4429 if (ret) {
4430 hdd_err("Failed to register IPv6 notifier: %d", ret);
4431 goto out;
4432 }
4433
4434 hdd_debug("Registered IPv6 notifier");
4435 out:
4436 return ret;
4437 }
4438 #else
4439 /**
4440 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
4441 * @hdd_ctx: Pointer to hdd context
4442 *
4443 * Unregister for IPv6 address change notifications.
4444 *
4445 * Return: None
4446 */
hdd_wlan_unregister_ip6_notifier(struct hdd_context * hdd_ctx)4447 static void hdd_wlan_unregister_ip6_notifier(struct hdd_context *hdd_ctx)
4448 {
4449 }
4450
4451 /**
4452 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
4453 * @hdd_ctx: Pointer to hdd context
4454 *
4455 * Register for IPv6 address change notifications.
4456 *
4457 * Return: None
4458 */
hdd_wlan_register_ip6_notifier(struct hdd_context * hdd_ctx)4459 static int hdd_wlan_register_ip6_notifier(struct hdd_context *hdd_ctx)
4460 {
4461 return 0;
4462 }
4463 #endif
4464
4465 #ifdef FEATURE_RUNTIME_PM
4466 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
hdd_pm_qos_add_notifier(struct hdd_context * hdd_ctx)4467 static int hdd_pm_qos_add_notifier(struct hdd_context *hdd_ctx)
4468 {
4469 return dev_pm_qos_add_notifier(hdd_ctx->parent_dev,
4470 &hdd_ctx->pm_qos_notifier,
4471 DEV_PM_QOS_RESUME_LATENCY);
4472 }
4473
hdd_pm_qos_remove_notifier(struct hdd_context * hdd_ctx)4474 static int hdd_pm_qos_remove_notifier(struct hdd_context *hdd_ctx)
4475 {
4476 return dev_pm_qos_remove_notifier(hdd_ctx->parent_dev,
4477 &hdd_ctx->pm_qos_notifier,
4478 DEV_PM_QOS_RESUME_LATENCY);
4479 }
4480 #else
hdd_pm_qos_add_notifier(struct hdd_context * hdd_ctx)4481 static int hdd_pm_qos_add_notifier(struct hdd_context *hdd_ctx)
4482 {
4483 return pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY,
4484 &hdd_ctx->pm_qos_notifier);
4485 }
4486
hdd_pm_qos_remove_notifier(struct hdd_context * hdd_ctx)4487 static int hdd_pm_qos_remove_notifier(struct hdd_context *hdd_ctx)
4488 {
4489 return pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY,
4490 &hdd_ctx->pm_qos_notifier);
4491 }
4492 #endif
4493
4494 /**
4495 * hdd_wlan_register_pm_qos_notifier() - register PM QOS notifier
4496 * @hdd_ctx: Pointer to hdd context
4497 *
4498 * Register for PM QOS change notifications.
4499 *
4500 * Return: None
4501 */
hdd_wlan_register_pm_qos_notifier(struct hdd_context * hdd_ctx)4502 static int hdd_wlan_register_pm_qos_notifier(struct hdd_context *hdd_ctx)
4503 {
4504 int ret;
4505
4506 qdf_spinlock_create(&hdd_ctx->pm_qos_lock);
4507
4508 /* if gRuntimePM is 1 then feature is enabled without CXPC */
4509 if (hdd_ctx->config->runtime_pm != hdd_runtime_pm_dynamic) {
4510 hdd_debug("Dynamic Runtime PM disabled");
4511 return 0;
4512 }
4513
4514 hdd_ctx->pm_qos_notifier.notifier_call = wlan_hdd_pm_qos_notify;
4515 ret = hdd_pm_qos_add_notifier(hdd_ctx);
4516 if (ret)
4517 hdd_err("Failed to register PM_QOS notifier: %d", ret);
4518 else
4519 hdd_debug("PM QOS Notifier registered");
4520
4521 return ret;
4522 }
4523
4524 /**
4525 * hdd_wlan_unregister_pm_qos_notifier() - unregister PM QOS notifier
4526 * @hdd_ctx: Pointer to hdd context
4527 *
4528 * Unregister for PM QOS change notifications.
4529 *
4530 * Return: None
4531 */
hdd_wlan_unregister_pm_qos_notifier(struct hdd_context * hdd_ctx)4532 static void hdd_wlan_unregister_pm_qos_notifier(struct hdd_context *hdd_ctx)
4533 {
4534 int ret;
4535
4536 if (hdd_ctx->config->runtime_pm != hdd_runtime_pm_dynamic) {
4537 hdd_debug("Dynamic Runtime PM disabled");
4538 qdf_spinlock_destroy(&hdd_ctx->pm_qos_lock);
4539 return;
4540 }
4541
4542 ret = hdd_pm_qos_remove_notifier(hdd_ctx);
4543 if (ret)
4544 hdd_warn("Failed to remove qos notifier, err = %d\n", ret);
4545
4546 qdf_spin_lock_irqsave(&hdd_ctx->pm_qos_lock);
4547
4548 if (hdd_ctx->runtime_pm_prevented) {
4549 hif_rtpm_put(HIF_RTPM_PUT_NOIDLE, HIF_RTPM_ID_PM_QOS_NOTIFY);
4550 hdd_ctx->runtime_pm_prevented = false;
4551 }
4552
4553 qdf_spin_unlock_irqrestore(&hdd_ctx->pm_qos_lock);
4554
4555 qdf_spinlock_destroy(&hdd_ctx->pm_qos_lock);
4556 }
4557 #else
hdd_wlan_register_pm_qos_notifier(struct hdd_context * hdd_ctx)4558 static int hdd_wlan_register_pm_qos_notifier(struct hdd_context *hdd_ctx)
4559 {
4560 return 0;
4561 }
4562
hdd_wlan_unregister_pm_qos_notifier(struct hdd_context * hdd_ctx)4563 static void hdd_wlan_unregister_pm_qos_notifier(struct hdd_context *hdd_ctx)
4564 {
4565 }
4566 #endif
4567
4568 /**
4569 * hdd_enable_power_management() - API to Enable Power Management
4570 * @hdd_ctx: HDD context
4571 *
4572 * API invokes Bus Interface Layer power management functionality
4573 *
4574 * Return: None
4575 */
hdd_enable_power_management(struct hdd_context * hdd_ctx)4576 static void hdd_enable_power_management(struct hdd_context *hdd_ctx)
4577 {
4578 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
4579
4580 if (!hif_ctx)
4581 return;
4582
4583 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
4584 hdd_wlan_register_pm_qos_notifier(hdd_ctx);
4585 }
4586
4587 /**
4588 * hdd_disable_power_management() - API to disable Power Management
4589 * @hdd_ctx: HDD context
4590 *
4591 * API disable Bus Interface Layer Power management functionality
4592 *
4593 * Return: None
4594 */
hdd_disable_power_management(struct hdd_context * hdd_ctx)4595 static void hdd_disable_power_management(struct hdd_context *hdd_ctx)
4596 {
4597 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
4598
4599 if (!hif_ctx)
4600 return;
4601
4602 hdd_wlan_unregister_pm_qos_notifier(hdd_ctx);
4603 hif_disable_power_management(hif_ctx);
4604 }
4605
4606 /**
4607 * hdd_register_notifiers - Register netdev notifiers.
4608 * @hdd_ctx: HDD context
4609 *
4610 * Register netdev notifiers like IPv4 and IPv6.
4611 *
4612 * Return: 0 on success and errno on failure
4613 */
hdd_register_notifiers(struct hdd_context * hdd_ctx)4614 static int hdd_register_notifiers(struct hdd_context *hdd_ctx)
4615 {
4616 int ret;
4617
4618 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4619 if (ret)
4620 goto out;
4621
4622 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4623 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4624 if (ret) {
4625 hdd_err("Failed to register IPv4 notifier: %d", ret);
4626 goto unregister_ip6_notifier;
4627 }
4628
4629 ret = osif_dp_nud_register_netevent_notifier(hdd_ctx->psoc);
4630 if (ret) {
4631 hdd_err("Failed to register netevent notifier: %d",
4632 ret);
4633 goto unregister_inetaddr_notifier;
4634 }
4635
4636 return 0;
4637
4638 unregister_inetaddr_notifier:
4639 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4640 unregister_ip6_notifier:
4641 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4642 out:
4643 return ret;
4644 }
4645
4646 #ifdef WLAN_FEATURE_WMI_SEND_RECV_QMI
4647 static inline
hdd_set_qmi_stats_enabled(struct hdd_context * hdd_ctx)4648 void hdd_set_qmi_stats_enabled(struct hdd_context *hdd_ctx)
4649 {
4650 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(hdd_ctx->psoc);
4651
4652 if (!wmi_handle) {
4653 hdd_err("could not get wmi handle");
4654 return;
4655 }
4656
4657 wmi_set_qmi_stats(wmi_handle, hdd_ctx->config->is_qmi_stats_enabled);
4658 }
4659 #else
4660 static inline
hdd_set_qmi_stats_enabled(struct hdd_context * hdd_ctx)4661 void hdd_set_qmi_stats_enabled(struct hdd_context *hdd_ctx)
4662 {
4663 }
4664 #endif
4665
4666 #ifdef CONFIG_FW_LOGS_BASED_ON_INI
4667 /**
4668 * hdd_set_fw_log_params() - Set log parameters to FW
4669 * @hdd_ctx: HDD Context
4670 * @vdev_id: vdev_id
4671 *
4672 * This function set the FW Debug log level based on the INI.
4673 *
4674 * Return: None
4675 */
hdd_set_fw_log_params(struct hdd_context * hdd_ctx,uint8_t vdev_id)4676 static void hdd_set_fw_log_params(struct hdd_context *hdd_ctx,
4677 uint8_t vdev_id)
4678 {
4679 QDF_STATUS status;
4680 uint16_t enable_fw_log_level, enable_fw_log_type;
4681 int ret;
4682
4683 if (!hdd_ctx->config->enable_fw_log) {
4684 hdd_debug("enable_fw_log not enabled in INI");
4685 return;
4686 }
4687
4688 /* Enable FW logs based on INI configuration */
4689 status = ucfg_fwol_get_enable_fw_log_type(hdd_ctx->psoc,
4690 &enable_fw_log_type);
4691 if (QDF_IS_STATUS_ERROR(status))
4692 return;
4693 ret = sme_cli_set_command(vdev_id, WMI_DBGLOG_TYPE,
4694 enable_fw_log_type, DBG_CMD);
4695 if (ret != 0)
4696 hdd_err("Failed to enable FW log type ret %d", ret);
4697
4698 status = ucfg_fwol_get_enable_fw_log_level(hdd_ctx->psoc,
4699 &enable_fw_log_level);
4700 if (QDF_IS_STATUS_ERROR(status))
4701 return;
4702 ret = sme_cli_set_command(vdev_id, WMI_DBGLOG_LOG_LEVEL,
4703 enable_fw_log_level, DBG_CMD);
4704 if (ret != 0)
4705 hdd_err("Failed to enable FW log level ret %d", ret);
4706
4707 sme_enable_fw_module_log_level(hdd_ctx->mac_handle, vdev_id);
4708 }
4709 #else
hdd_set_fw_log_params(struct hdd_context * hdd_ctx,uint8_t vdev_id)4710 static void hdd_set_fw_log_params(struct hdd_context *hdd_ctx, uint8_t vdev_id)
4711 {
4712 }
4713
4714 #endif
4715
4716 /**
4717 * hdd_features_deinit() - Deinit features
4718 * @hdd_ctx: HDD context
4719 *
4720 * De-Initialize features and their feature context.
4721 *
4722 * Return: none.
4723 */
hdd_features_deinit(struct hdd_context * hdd_ctx)4724 static void hdd_features_deinit(struct hdd_context *hdd_ctx)
4725 {
4726 wlan_hdd_gpio_wakeup_deinit(hdd_ctx);
4727 wlan_hdd_twt_deinit(hdd_ctx);
4728 wlan_hdd_deinit_chan_info(hdd_ctx);
4729 wlan_hdd_tsf_deinit(hdd_ctx);
4730 if (cds_is_packet_log_enabled())
4731 hdd_pktlog_enable_disable(hdd_ctx, false, 0, 0);
4732 }
4733
4734 /**
4735 * hdd_deconfigure_cds() -De-Configure cds
4736 * @hdd_ctx: HDD context
4737 *
4738 * Deconfigure Cds modules before WLAN firmware is down.
4739 *
4740 * Return: 0 on success and errno on failure.
4741 */
hdd_deconfigure_cds(struct hdd_context * hdd_ctx)4742 static int hdd_deconfigure_cds(struct hdd_context *hdd_ctx)
4743 {
4744 QDF_STATUS qdf_status;
4745 int ret = 0;
4746
4747 hdd_enter();
4748
4749 wlan_hdd_hang_event_notifier_unregister();
4750 /* De-init features */
4751 hdd_features_deinit(hdd_ctx);
4752
4753 qdf_status = policy_mgr_deregister_mode_change_cb(hdd_ctx->psoc);
4754 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
4755 hdd_debug("Failed to deregister mode change cb with Policy Manager");
4756
4757 qdf_status = cds_disable(hdd_ctx->psoc);
4758 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4759 hdd_err("Failed to Disable the CDS Modules! :%d",
4760 qdf_status);
4761 ret = -EINVAL;
4762 }
4763
4764 if (ucfg_ipa_uc_ol_deinit(hdd_ctx->pdev) != QDF_STATUS_SUCCESS) {
4765 hdd_err("Failed to disconnect pipes");
4766 ret = -EINVAL;
4767 }
4768
4769 hdd_exit();
4770 return ret;
4771 }
4772
4773 /**
4774 * hdd_qmi_register_callbacks() - Register QMI callbacks
4775 * @hdd_ctx: HDD context
4776 *
4777 * Return: None
4778 */
hdd_qmi_register_callbacks(struct hdd_context * hdd_ctx)4779 static inline void hdd_qmi_register_callbacks(struct hdd_context *hdd_ctx)
4780 {
4781 struct wlan_qmi_psoc_callbacks cb_obj;
4782
4783 os_if_qmi_register_callbacks(hdd_ctx->psoc, &cb_obj);
4784 }
4785
4786 /**
4787 * hdd_set_pcie_params() - Set pcie params
4788 * @hdd_ctx: HDD context
4789 * @index: index value
4790 * @param: pointer to vdev/pdev set param info
4791 *
4792 * Checks for pcie_config value and sets
4793 * corresponding params
4794 *
4795 * Return: 0 on success and errno on failure.
4796 */
hdd_set_pcie_params(struct hdd_context * hdd_ctx,uint8_t index,struct dev_set_param * param)4797 static int hdd_set_pcie_params(struct hdd_context *hdd_ctx,
4798 uint8_t index, struct dev_set_param *param)
4799 {
4800 int ret = 0;
4801 uint8_t check_value = 0;
4802
4803 ret = ucfg_fwol_get_pcie_config(hdd_ctx->psoc, &check_value);
4804 if (QDF_IS_STATUS_SUCCESS(ret)) {
4805 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4806 ret = mlme_check_index_setparam(param,
4807 wmi_pdev_param_pcie_config,
4808 (int)check_value, index++,
4809 FTM_MAX_PDEV_PARAMS);
4810 } else {
4811 ret = mlme_check_index_setparam(param,
4812 wmi_pdev_param_pcie_config,
4813 (int)check_value, index++,
4814 MAX_PDEV_PRE_ENABLE_PARAMS);
4815 }
4816 if (QDF_IS_STATUS_ERROR(ret)) {
4817 hdd_err("failed to set wmi_pdev_param_pcie_config");
4818 return ret;
4819 }
4820 }
4821 return ret;
4822 }
4823
4824 #ifdef FEATURE_SET
4825 #ifdef WLAN_FEATURE_11BE
4826 /**
4827 * hdd_is_cfg_dot11_mode_11be() - Check if dot11 mode is 11 be
4828 * @dot11_mode: Input dot11_mode which needs to be checked
4829 *
4830 * Return: True, ifinput dot11_mode is 11be dot11 mode else return false
4831 */
hdd_is_cfg_dot11_mode_11be(enum hdd_dot11_mode dot11_mode)4832 static bool hdd_is_cfg_dot11_mode_11be(enum hdd_dot11_mode dot11_mode)
4833 {
4834 return (dot11_mode == eHDD_DOT11_MODE_11be ||
4835 dot11_mode == eHDD_DOT11_MODE_11be_ONLY);
4836 }
4837
4838 /**
4839 * hdd_is_11be_supported() - Check if 11be is supported or not
4840 * @hdd_ctx: Pointer to hdd context
4841 *
4842 * Return: True, if 11be is supported else return false
4843 */
hdd_is_11be_supported(struct hdd_context * hdd_ctx)4844 static bool hdd_is_11be_supported(struct hdd_context *hdd_ctx)
4845 {
4846 bool mlo_capab;
4847
4848 ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &mlo_capab);
4849 if (!mlo_capab)
4850 return false;
4851
4852 return true;
4853 }
4854 #else
4855
hdd_is_cfg_dot11_mode_11be(enum hdd_dot11_mode dot11_mode)4856 static bool hdd_is_cfg_dot11_mode_11be(enum hdd_dot11_mode dot11_mode)
4857 {
4858 return false;
4859 }
4860
hdd_is_11be_supported(struct hdd_context * hdd_ctx)4861 static bool hdd_is_11be_supported(struct hdd_context *hdd_ctx)
4862 {
4863 return false;
4864 }
4865 #endif
4866
4867 WMI_HOST_WIFI_STANDARD
hdd_get_wifi_standard(struct hdd_context * hdd_ctx,enum hdd_dot11_mode dot11_mode,uint32_t band_capability)4868 hdd_get_wifi_standard(struct hdd_context *hdd_ctx,
4869 enum hdd_dot11_mode dot11_mode, uint32_t band_capability)
4870 {
4871 WMI_HOST_WIFI_STANDARD wifi_standard = WMI_HOST_WIFI_STANDARD_4;
4872
4873 if (dot11_mode == eHDD_DOT11_MODE_AUTO) {
4874 if (hdd_is_11be_supported(hdd_ctx))
4875 wifi_standard = WMI_HOST_WIFI_STANDARD_7;
4876 else if (band_capability & BIT(REG_BAND_6G))
4877 wifi_standard = WMI_HOST_WIFI_STANDARD_6E;
4878 else
4879 wifi_standard = WMI_HOST_WIFI_STANDARD_6;
4880 } else if (hdd_is_cfg_dot11_mode_11be(dot11_mode)) {
4881 wifi_standard = WMI_HOST_WIFI_STANDARD_7;
4882 } else if (dot11_mode == eHDD_DOT11_MODE_11ax ||
4883 (dot11_mode == eHDD_DOT11_MODE_11ax_ONLY)) {
4884 if (band_capability & BIT(REG_BAND_6G))
4885 wifi_standard = WMI_HOST_WIFI_STANDARD_6E;
4886 else
4887 wifi_standard = WMI_HOST_WIFI_STANDARD_6;
4888 } else if ((dot11_mode == eHDD_DOT11_MODE_11ac) ||
4889 (dot11_mode == eHDD_DOT11_MODE_11ac_ONLY)) {
4890 wifi_standard = WMI_HOST_WIFI_STANDARD_5;
4891 }
4892
4893 return wifi_standard;
4894 }
4895
4896 /**
4897 * hdd_populate_feature_set_cds_config() - Populate cds feature set config
4898 * @hdd_ctx: hdd context pointer
4899 *
4900 * Return: None
4901 */
hdd_populate_feature_set_cds_config(struct hdd_context * hdd_ctx)4902 static void hdd_populate_feature_set_cds_config(struct hdd_context *hdd_ctx)
4903 {
4904 struct wlan_objmgr_psoc *psoc;
4905 uint32_t band_capability;
4906 QDF_STATUS status;
4907 struct cds_config_info *cds_cfg;
4908
4909 if (!hdd_ctx)
4910 return;
4911
4912 cds_cfg = cds_get_ini_config();
4913 if (!cds_cfg) {
4914 hdd_err("CDS config is null.");
4915 return;
4916 }
4917
4918 psoc = hdd_ctx->psoc;
4919
4920 cds_cfg->get_wifi_features = hdd_ctx->config->get_wifi_features;
4921
4922 status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
4923 if (QDF_IS_STATUS_ERROR(status))
4924 hdd_err("Failed to get MLME band capability");
4925
4926 band_capability =
4927 hdd_update_band_cap_from_dot11mode(hdd_ctx, band_capability);
4928
4929 cds_cfg->cds_feature_set.wifi_standard =
4930 hdd_get_wifi_standard(hdd_ctx,
4931 hdd_ctx->config->dot11Mode,
4932 band_capability);
4933
4934 cds_cfg->cds_feature_set.sap_5g_supported =
4935 band_capability & BIT(REG_BAND_5G);
4936
4937 cds_cfg->cds_feature_set.sap_6g_supported =
4938 band_capability & BIT(REG_BAND_6G);
4939 cds_cfg->cds_feature_set.band_capability = band_capability;
4940 }
4941 #else
4942 WMI_HOST_WIFI_STANDARD
hdd_get_wifi_standard(struct hdd_context * hdd_ctx,enum hdd_dot11_mode dot11_mode,uint32_t band_capability)4943 hdd_get_wifi_standard(struct hdd_context *hdd_ctx,
4944 enum hdd_dot11_mode dot11_mode, uint32_t band_capability)
4945 {
4946 return WMI_HOST_WIFI_STANDARD_5;
4947 }
4948
4949 static inline void
hdd_populate_feature_set_cds_config(struct hdd_context * hdd_ctx)4950 hdd_populate_feature_set_cds_config(struct hdd_context *hdd_ctx)
4951 {
4952 }
4953 #endif
4954
hdd_wlan_start_modules(struct hdd_context * hdd_ctx,bool reinit)4955 int hdd_wlan_start_modules(struct hdd_context *hdd_ctx, bool reinit)
4956 {
4957 int ret = 0;
4958 qdf_device_t qdf_dev;
4959 QDF_STATUS status;
4960 bool unint = false;
4961 void *hif_ctx;
4962 struct target_psoc_info *tgt_hdl;
4963 unsigned long thermal_state = 0;
4964 uint8_t index = 0;
4965 struct dev_set_param setparam[MAX_PDEV_PRE_ENABLE_PARAMS] = {};
4966
4967 hdd_enter();
4968 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
4969 if (!qdf_dev) {
4970 hdd_exit();
4971 return -EINVAL;
4972 }
4973
4974 hdd_psoc_idle_timer_stop(hdd_ctx);
4975
4976 if (hdd_ctx->driver_status == DRIVER_MODULES_ENABLED) {
4977 hdd_debug("Driver modules already Enabled");
4978 hdd_exit();
4979 return 0;
4980 }
4981
4982 cds_set_driver_state_module_stop(false);
4983
4984 switch (hdd_ctx->driver_status) {
4985 case DRIVER_MODULES_UNINITIALIZED:
4986 hdd_nofl_debug("Wlan transitioning (UNINITIALIZED -> CLOSED)");
4987 unint = true;
4988 fallthrough;
4989 case DRIVER_MODULES_CLOSED:
4990 hdd_nofl_debug("Wlan transitioning (CLOSED -> ENABLED)");
4991 ret = hdd_debug_domain_set(QDF_DEBUG_DOMAIN_ACTIVE);
4992 if (ret)
4993 goto abort;
4994
4995 if (!reinit && !unint) {
4996 ret = pld_power_on(qdf_dev->dev);
4997 if (ret) {
4998 hdd_err("Failed to power up device; errno:%d",
4999 ret);
5000 goto release_lock;
5001 }
5002 }
5003
5004 hdd_init_adapter_ops_wq(hdd_ctx);
5005 pld_set_fw_log_mode(hdd_ctx->parent_dev,
5006 hdd_ctx->config->enable_fw_log);
5007 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
5008 qdf_dev->bus_type,
5009 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
5010 HIF_ENABLE_TYPE_PROBE);
5011 if (ret) {
5012 hdd_err("Failed to open hif; errno: %d", ret);
5013 goto power_down;
5014 }
5015
5016 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
5017 if (!hif_ctx) {
5018 ret = -EINVAL;
5019 goto power_down;
5020 }
5021
5022 status = ol_cds_init(qdf_dev, hif_ctx);
5023 if (status != QDF_STATUS_SUCCESS) {
5024 hdd_err("No Memory to Create BMI Context; status: %d",
5025 status);
5026 ret = qdf_status_to_os_return(status);
5027 goto hif_close;
5028 }
5029
5030 if (hdd_get_conparam() == QDF_GLOBAL_EPPING_MODE) {
5031 status = epping_open();
5032 if (status) {
5033 hdd_err("Failed to open in epping mode: %d",
5034 status);
5035 ret = -EINVAL;
5036 goto cds_free;
5037 }
5038
5039 status = epping_enable(qdf_dev->dev, false);
5040 if (status) {
5041 hdd_err("Failed to enable in epping mode : %d",
5042 status);
5043 epping_close();
5044 goto cds_free;
5045 }
5046
5047 hdd_info("epping mode enabled");
5048 break;
5049 }
5050
5051 if (pld_is_ipa_offload_disabled(qdf_dev->dev))
5052 ucfg_ipa_set_pld_enable(false);
5053
5054 ucfg_ipa_component_config_update(hdd_ctx->psoc);
5055
5056 hdd_update_cds_ac_specs_params(hdd_ctx);
5057
5058 hdd_dp_register_callbacks(hdd_ctx);
5059
5060 hdd_qmi_register_callbacks(hdd_ctx);
5061
5062 status = hdd_component_psoc_open(hdd_ctx->psoc);
5063 if (QDF_IS_STATUS_ERROR(status)) {
5064 hdd_err("Failed to Open legacy components; status: %d",
5065 status);
5066 ret = qdf_status_to_os_return(status);
5067 goto ipa_component_free;
5068 }
5069
5070 ret = hdd_update_config(hdd_ctx);
5071 if (ret) {
5072 hdd_err("Failed to update configuration; errno: %d",
5073 ret);
5074 goto ipa_component_free;
5075 }
5076
5077 status = wbuff_module_init();
5078 if (QDF_IS_STATUS_ERROR(status))
5079 hdd_err("WBUFF init unsuccessful; status: %d", status);
5080
5081 status = cds_open(hdd_ctx->psoc);
5082 if (QDF_IS_STATUS_ERROR(status)) {
5083 hdd_err("Failed to Open CDS; status: %d", status);
5084 ret = qdf_status_to_os_return(status);
5085 goto psoc_close;
5086 }
5087
5088 hdd_populate_feature_set_cds_config(hdd_ctx);
5089
5090 hdd_set_qmi_stats_enabled(hdd_ctx);
5091
5092 hdd_ctx->mac_handle = cds_get_context(QDF_MODULE_ID_SME);
5093
5094 ucfg_dp_set_rx_thread_affinity(hdd_ctx->psoc);
5095
5096 /* initialize components configurations after psoc open */
5097 ret = hdd_update_components_config(hdd_ctx);
5098 if (ret) {
5099 hdd_err("Failed to update component configs; errno: %d",
5100 ret);
5101 goto close;
5102 }
5103
5104 /* Override PS params for monitor mode */
5105 if (hdd_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
5106 hdd_override_all_ps(hdd_ctx);
5107
5108 status = cds_dp_open(hdd_ctx->psoc);
5109 if (!QDF_IS_STATUS_SUCCESS(status)) {
5110 hdd_err("Failed to Open cds post open; status: %d",
5111 status);
5112 ret = qdf_status_to_os_return(status);
5113 goto close;
5114 }
5115 /* Set IRQ affinity for WLAN DP and CE IRQS */
5116 hif_config_irq_set_perf_affinity_hint(hif_ctx);
5117
5118 ret = hdd_register_cb(hdd_ctx);
5119 if (ret) {
5120 hdd_err("Failed to register HDD callbacks!");
5121 goto cds_txrx_free;
5122 }
5123
5124 ret = hdd_register_notifiers(hdd_ctx);
5125 if (ret)
5126 goto deregister_cb;
5127
5128 /*
5129 * NAN component requires certain operations like, open adapter,
5130 * close adapter, etc. to be initiated by HDD, for those
5131 * register HDD callbacks with UMAC's NAN component.
5132 */
5133 hdd_nan_register_callbacks(hdd_ctx);
5134
5135 hdd_son_register_callbacks(hdd_ctx);
5136
5137 hdd_sr_register_callbacks(hdd_ctx);
5138
5139 wlan_hdd_register_btc_chain_mode_handler(hdd_ctx->psoc);
5140
5141 wlan_hdd_register_afc_pld_cb(hdd_ctx->psoc);
5142
5143 status = cds_pre_enable();
5144 if (!QDF_IS_STATUS_SUCCESS(status)) {
5145 hdd_err("Failed to pre-enable CDS; status: %d", status);
5146 ret = qdf_status_to_os_return(status);
5147 goto unregister_notifiers;
5148 }
5149
5150 hdd_register_policy_manager_callback(
5151 hdd_ctx->psoc);
5152
5153 /*
5154 * Call this function before hdd_enable_power_management. Since
5155 * it is required to trigger WMI_PDEV_DMA_RING_CFG_REQ_CMDID
5156 * to FW when power save isn't enable.
5157 */
5158 hdd_spectral_register_to_dbr(hdd_ctx);
5159
5160 hdd_create_sysfs_files(hdd_ctx);
5161 hdd_update_hw_sw_info(hdd_ctx);
5162
5163 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5164 hdd_enable_power_management(hdd_ctx);
5165 hdd_err("in ftm mode, no need to configure cds modules");
5166 hdd_info("Enable FW log in ftm mode");
5167 /*
5168 * Since vdev is not created for FTM mode,
5169 * in FW use vdev_id = 0.
5170 */
5171 hdd_set_fw_log_params(hdd_ctx, 0);
5172 ret = hdd_set_pcie_params(hdd_ctx, index, setparam);
5173 if (QDF_IS_STATUS_ERROR(ret))
5174 break;
5175 index++;
5176 ret = sme_send_multi_pdev_vdev_set_params(
5177 MLME_PDEV_SETPARAM,
5178 WMI_PDEV_ID_SOC, setparam, index);
5179 if (QDF_IS_STATUS_ERROR(ret)) {
5180 hdd_err("failed to send pdev set params");
5181 return ret;
5182 }
5183
5184 ret = -EINVAL;
5185 break;
5186 }
5187
5188 ret = hdd_configure_cds(hdd_ctx);
5189 if (ret) {
5190 hdd_err("Failed to Enable cds modules; errno: %d", ret);
5191 goto sched_disable;
5192 }
5193
5194 if (hdd_get_conparam() == QDF_GLOBAL_MISSION_MODE) {
5195 status = ucfg_dp_direct_link_init(hdd_ctx->psoc);
5196 if (QDF_IS_STATUS_ERROR(status)) {
5197 cds_err("Failed to initialize Direct Link datapath");
5198 ret = -EINVAL;
5199 goto deconfigure_cds;
5200 }
5201 }
5202
5203 hdd_enable_power_management(hdd_ctx);
5204
5205 hdd_skip_acs_scan_timer_init(hdd_ctx);
5206
5207 hdd_set_hif_init_phase(hif_ctx, false);
5208 hdd_hif_set_enable_detection(hif_ctx, true);
5209
5210 wlan_hdd_start_connectivity_logging(hdd_ctx);
5211
5212 break;
5213
5214 default:
5215 QDF_DEBUG_PANIC("Unknown driver state:%d",
5216 hdd_ctx->driver_status);
5217 ret = -EINVAL;
5218 goto release_lock;
5219 }
5220
5221 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
5222 hdd_nofl_debug("Wlan transitioned (now ENABLED)");
5223
5224 ucfg_ipa_reg_is_driver_unloading_cb(hdd_ctx->pdev,
5225 cds_is_driver_unloading);
5226 ucfg_ipa_reg_sap_xmit_cb(hdd_ctx->pdev,
5227 hdd_softap_ipa_start_xmit);
5228 ucfg_ipa_reg_send_to_nw_cb(hdd_ctx->pdev,
5229 hdd_ipa_send_nbuf_to_network);
5230 ucfg_dp_reg_ipa_rsp_ind(hdd_ctx->pdev);
5231
5232 if (!pld_get_thermal_state(hdd_ctx->parent_dev, &thermal_state,
5233 THERMAL_MONITOR_APPS)) {
5234 if (thermal_state > QCA_WLAN_VENDOR_THERMAL_LEVEL_NONE)
5235 hdd_send_thermal_mitigation_val(hdd_ctx,
5236 thermal_state,
5237 THERMAL_MONITOR_APPS);
5238 }
5239
5240 if (!pld_get_thermal_state(hdd_ctx->parent_dev, &thermal_state,
5241 THERMAL_MONITOR_WPSS)) {
5242 if (thermal_state > QCA_WLAN_VENDOR_THERMAL_LEVEL_NONE)
5243 hdd_send_thermal_mitigation_val(hdd_ctx, thermal_state,
5244 THERMAL_MONITOR_WPSS);
5245 }
5246
5247 hdd_exit();
5248
5249 return 0;
5250
5251 deconfigure_cds:
5252 hdd_deconfigure_cds(hdd_ctx);
5253 sched_disable:
5254 /*
5255 * Disable scheduler 1st so that scheduler thread doesn't send messages
5256 * to fw in parallel to the cleanup
5257 */
5258 dispatcher_disable();
5259 hdd_destroy_sysfs_files();
5260 cds_post_disable();
5261 unregister_notifiers:
5262 hdd_unregister_notifiers(hdd_ctx);
5263
5264 deregister_cb:
5265 hdd_deregister_cb(hdd_ctx);
5266
5267 cds_txrx_free:
5268
5269 tgt_hdl = wlan_psoc_get_tgt_if_handle(hdd_ctx->psoc);
5270
5271 if (tgt_hdl && target_psoc_get_wmi_ready(tgt_hdl))
5272 hdd_runtime_suspend_context_deinit(hdd_ctx);
5273
5274 if (hdd_ctx->pdev) {
5275 dispatcher_pdev_close(hdd_ctx->pdev);
5276 hdd_objmgr_release_and_destroy_pdev(hdd_ctx);
5277 }
5278
5279 cds_dp_close(hdd_ctx->psoc);
5280
5281 close:
5282 dispatcher_disable();
5283 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
5284 hdd_info("Wlan transition aborted (now CLOSED)");
5285
5286 cds_close(hdd_ctx->psoc);
5287
5288 psoc_close:
5289 hdd_component_psoc_close(hdd_ctx->psoc);
5290 wlan_global_lmac_if_close(hdd_ctx->psoc);
5291 cds_deinit_ini_config();
5292
5293 ipa_component_free:
5294 ucfg_ipa_component_config_free();
5295
5296 cds_free:
5297 ol_cds_free();
5298
5299 hif_close:
5300 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
5301 hdd_hif_close(hdd_ctx, hif_ctx);
5302 power_down:
5303 hdd_deinit_adapter_ops_wq(hdd_ctx);
5304 if (!reinit && !unint)
5305 pld_power_off(qdf_dev->dev);
5306 release_lock:
5307 cds_shutdown_notifier_purge();
5308 hdd_check_for_leaks(hdd_ctx, reinit);
5309 hdd_debug_domain_set(QDF_DEBUG_DOMAIN_INIT);
5310
5311 abort:
5312 cds_set_driver_state_module_stop(true);
5313
5314 hdd_exit();
5315
5316 return ret;
5317 }
5318
5319 #ifdef WIFI_POS_CONVERGED
hdd_activate_wifi_pos(struct hdd_context * hdd_ctx)5320 static int hdd_activate_wifi_pos(struct hdd_context *hdd_ctx)
5321 {
5322 int ret = os_if_wifi_pos_register_nl();
5323
5324 if (ret)
5325 hdd_err("os_if_wifi_pos_register_nl failed");
5326
5327 return ret;
5328 }
5329
hdd_deactivate_wifi_pos(void)5330 static int hdd_deactivate_wifi_pos(void)
5331 {
5332 int ret = os_if_wifi_pos_deregister_nl();
5333
5334 if (ret)
5335 hdd_err("os_if_wifi_pos_deregister_nl failed");
5336
5337 return ret;
5338 }
5339
5340 /**
5341 * hdd_populate_wifi_pos_cfg - populates wifi_pos parameters
5342 * @hdd_ctx: hdd context
5343 *
5344 * Return: status of operation
5345 */
hdd_populate_wifi_pos_cfg(struct hdd_context * hdd_ctx)5346 static void hdd_populate_wifi_pos_cfg(struct hdd_context *hdd_ctx)
5347 {
5348 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
5349 uint16_t neighbor_scan_max_chan_time;
5350 uint16_t neighbor_scan_min_chan_time;
5351
5352 wifi_pos_set_oem_target_type(psoc, hdd_ctx->target_type);
5353 wifi_pos_set_oem_fw_version(psoc, hdd_ctx->target_fw_version);
5354 wifi_pos_set_drv_ver_major(psoc, QWLAN_VERSION_MAJOR);
5355 wifi_pos_set_drv_ver_minor(psoc, QWLAN_VERSION_MINOR);
5356 wifi_pos_set_drv_ver_patch(psoc, QWLAN_VERSION_PATCH);
5357 wifi_pos_set_drv_ver_build(psoc, QWLAN_VERSION_BUILD);
5358 ucfg_mlme_get_neighbor_scan_max_chan_time(psoc,
5359 &neighbor_scan_max_chan_time);
5360 ucfg_mlme_get_neighbor_scan_min_chan_time(psoc,
5361 &neighbor_scan_min_chan_time);
5362 wifi_pos_set_dwell_time_min(psoc, neighbor_scan_min_chan_time);
5363 wifi_pos_set_dwell_time_max(psoc, neighbor_scan_max_chan_time);
5364 }
5365 #else
hdd_activate_wifi_pos(struct hdd_context * hdd_ctx)5366 static int hdd_activate_wifi_pos(struct hdd_context *hdd_ctx)
5367 {
5368 return oem_activate_service(hdd_ctx);
5369 }
5370
hdd_deactivate_wifi_pos(void)5371 static int hdd_deactivate_wifi_pos(void)
5372 {
5373 return oem_deactivate_service();
5374 }
5375
hdd_populate_wifi_pos_cfg(struct hdd_context * hdd_ctx)5376 static void hdd_populate_wifi_pos_cfg(struct hdd_context *hdd_ctx)
5377 {
5378 }
5379 #endif
5380
5381 /**
5382 * __hdd_open() - HDD Open function
5383 * @dev: Pointer to net_device structure
5384 *
5385 * This is called in response to ifconfig up
5386 *
5387 * Return: 0 for success; non-zero for failure
5388 */
__hdd_open(struct net_device * dev)5389 static int __hdd_open(struct net_device *dev)
5390 {
5391 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5392 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5393 int ret;
5394 struct wlan_hdd_link_info *link_info = adapter->deflink;
5395
5396 hdd_enter_dev(dev);
5397
5398 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
5399 TRACE_CODE_HDD_OPEN_REQUEST,
5400 link_info->vdev_id, adapter->device_mode);
5401
5402 /* Nothing to be done if device is unloading */
5403 if (cds_is_driver_unloading()) {
5404 hdd_err("Driver is unloading can not open the hdd");
5405 return -EBUSY;
5406 }
5407
5408 if (cds_is_driver_recovering()) {
5409 hdd_err("WLAN is currently recovering; Please try again.");
5410 return -EBUSY;
5411 }
5412
5413 /*
5414 * This scenario can be hit in cases where in the wlan driver after
5415 * registering the netdevices and there is a failure in driver
5416 * initialization. So return error gracefully because the netdevices
5417 * will be de-registered as part of the load failure.
5418 */
5419
5420 if (!cds_is_driver_loaded()) {
5421 hdd_err("Failed to start the wlan driver!!");
5422 return -EIO;
5423 }
5424
5425 ret = wlan_hdd_validate_context(hdd_ctx);
5426 if (ret) {
5427 hdd_err("Can't start WLAN module, WiFi Disabled");
5428 return ret;
5429 }
5430
5431 ret = hdd_trigger_psoc_idle_restart(hdd_ctx);
5432 if (ret) {
5433 hdd_err("Failed to start WLAN modules return");
5434 return ret;
5435 }
5436
5437 if (!test_bit(SME_SESSION_OPENED, &link_info->link_flags)) {
5438 ret = hdd_start_adapter(adapter, true);
5439 if (ret) {
5440 hdd_err("Failed to start adapter :%d",
5441 adapter->device_mode);
5442 return ret;
5443 }
5444 }
5445
5446 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
5447 if (hdd_cm_is_vdev_associated(link_info)) {
5448 hdd_debug("Enabling Tx Queues");
5449 /* Enable TX queues only when we are connected */
5450 wlan_hdd_netif_queue_control(adapter,
5451 WLAN_START_ALL_NETIF_QUEUE,
5452 WLAN_CONTROL_PATH);
5453 }
5454
5455 /* Enable carrier and transmit queues for NDI */
5456 if (WLAN_HDD_IS_NDI(adapter)) {
5457 hdd_debug("Enabling Tx Queues");
5458 wlan_hdd_netif_queue_control(adapter,
5459 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
5460 WLAN_CONTROL_PATH);
5461 }
5462
5463 hdd_populate_wifi_pos_cfg(hdd_ctx);
5464 hdd_lpass_notify_start(link_info);
5465
5466 if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
5467 PACKET_CAPTURE_MODE_DISABLE)
5468 hdd_map_monitor_interface_vdev(adapter);
5469
5470 return 0;
5471 }
5472
5473 /**
5474 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
5475 * @net_dev: Pointer to net_device structure
5476 *
5477 * This is called in response to ifconfig up
5478 *
5479 * Return: 0 for success; non-zero for failure
5480 */
hdd_open(struct net_device * net_dev)5481 static int hdd_open(struct net_device *net_dev)
5482 {
5483 int errno;
5484 struct osif_vdev_sync *vdev_sync;
5485
5486 errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
5487 if (errno)
5488 return errno;
5489
5490 errno = __hdd_open(net_dev);
5491 if (!errno)
5492 osif_vdev_cache_command(vdev_sync, NO_COMMAND);
5493
5494 osif_vdev_sync_trans_stop(vdev_sync);
5495
5496 return errno;
5497 }
5498
hdd_stop_no_trans(struct net_device * dev)5499 int hdd_stop_no_trans(struct net_device *dev)
5500 {
5501 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5502 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5503 int ret;
5504 mac_handle_t mac_handle;
5505
5506 hdd_enter_dev(dev);
5507
5508 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
5509 TRACE_CODE_HDD_STOP_REQUEST,
5510 adapter->deflink->vdev_id, adapter->device_mode);
5511
5512 ret = wlan_hdd_validate_context(hdd_ctx);
5513 if (ret)
5514 return ret;
5515
5516 /* Nothing to be done if the interface is not opened */
5517 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
5518 hdd_err("NETDEV Interface is not OPENED");
5519 return -ENODEV;
5520 }
5521
5522 mac_handle = hdd_ctx->mac_handle;
5523
5524 if (!wlan_hdd_is_session_type_monitor(adapter->device_mode) &&
5525 adapter->device_mode != QDF_FTM_MODE) {
5526 hdd_debug("Disabling Auto Power save timer");
5527 sme_ps_disable_auto_ps_timer(
5528 mac_handle,
5529 adapter->deflink->vdev_id);
5530 }
5531
5532 /*
5533 * Disable TX on the interface, after this hard_start_xmit() will not
5534 * be called on that interface
5535 */
5536 hdd_debug("Disabling queues, adapter device mode: %s(%d)",
5537 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
5538
5539 wlan_hdd_netif_queue_control(adapter,
5540 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
5541 WLAN_CONTROL_PATH);
5542
5543 if (adapter->device_mode == QDF_STA_MODE)
5544 hdd_lpass_notify_stop(hdd_ctx);
5545
5546 /*
5547 * NAN data interface is different in some sense. The traffic on NDI is
5548 * bursty in nature and depends on the need to transfer. The service
5549 * layer may down the interface after the usage and up again when
5550 * required. In some sense, the NDI is expected to be available
5551 * (like SAP) iface until NDI delete request is issued by the service
5552 * layer. Skip BSS termination and adapter deletion for NAN Data
5553 * interface (NDI).
5554 */
5555 if (WLAN_HDD_IS_NDI(adapter))
5556 goto reset_iface_opened;
5557
5558 /*
5559 * The interface is marked as down for outside world (aka kernel)
5560 * But the driver is pretty much alive inside. The driver needs to
5561 * tear down the existing connection on the netdev (session)
5562 * cleanup the data pipes and wait until the control plane is stabilized
5563 * for this interface. The call also needs to wait until the above
5564 * mentioned actions are completed before returning to the caller.
5565 * Notice that hdd_stop_adapter is requested not to close the session
5566 * That is intentional to be able to scan if it is a STA/P2P interface
5567 */
5568 hdd_stop_adapter(hdd_ctx, adapter);
5569
5570 /* DeInit the adapter. This ensures datapath cleanup as well */
5571 hdd_deinit_adapter(hdd_ctx, adapter, true);
5572
5573 reset_iface_opened:
5574 /* Make sure the interface is marked as closed */
5575 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
5576 if (!hdd_is_any_interface_open(hdd_ctx))
5577 hdd_psoc_idle_timer_start(hdd_ctx);
5578 hdd_exit();
5579
5580 return 0;
5581 }
5582
5583 /**
5584 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
5585 * @net_dev: pointer to net_device structure
5586 *
5587 * This is called in response to ifconfig down
5588 *
5589 * Return: 0 for success and error number for failure
5590 */
hdd_stop(struct net_device * net_dev)5591 static int hdd_stop(struct net_device *net_dev)
5592 {
5593 int errno;
5594 struct osif_vdev_sync *vdev_sync;
5595
5596 errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
5597 if (errno) {
5598 if (vdev_sync)
5599 osif_vdev_cache_command(vdev_sync, INTERFACE_DOWN);
5600 return errno;
5601 }
5602
5603 errno = hdd_stop_no_trans(net_dev);
5604
5605 osif_vdev_sync_trans_stop(vdev_sync);
5606
5607 return errno;
5608 }
5609
5610 /**
5611 * hdd_uninit() - HDD uninit function
5612 * @dev: Pointer to net_device structure
5613 *
5614 * This is called during the netdev unregister to uninitialize all data
5615 * associated with the device
5616 *
5617 * This function must be protected by a transition
5618 *
5619 * Return: None
5620 */
hdd_uninit(struct net_device * dev)5621 static void hdd_uninit(struct net_device *dev)
5622 {
5623 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5624 struct hdd_context *hdd_ctx;
5625
5626 hdd_enter_dev(dev);
5627
5628 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
5629 hdd_err("Invalid magic");
5630 goto exit;
5631 }
5632
5633 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5634 if (!hdd_ctx) {
5635 hdd_err("NULL hdd_ctx");
5636 goto exit;
5637 }
5638
5639 if (dev != adapter->dev)
5640 hdd_err("Invalid device reference");
5641
5642 hdd_deinit_adapter(hdd_ctx, adapter, true);
5643
5644 /* after uninit our adapter structure will no longer be valid */
5645 adapter->magic = 0;
5646
5647 exit:
5648 hdd_exit();
5649 }
5650
hdd_open_cesium_nl_sock(void)5651 static int hdd_open_cesium_nl_sock(void)
5652 {
5653 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
5654 struct netlink_kernel_cfg cfg = {
5655 .groups = WLAN_NLINK_MCAST_GRP_ID,
5656 .input = NULL
5657 };
5658 #endif
5659 int ret = 0;
5660
5661 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
5662 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
5663 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
5664 THIS_MODULE,
5665 #endif
5666 &cfg);
5667 #else
5668 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
5669 WLAN_NLINK_MCAST_GRP_ID,
5670 NULL, NULL, THIS_MODULE);
5671 #endif
5672
5673 if (!cesium_nl_srv_sock) {
5674 hdd_err("NLINK: cesium netlink_kernel_create failed");
5675 ret = -ECONNREFUSED;
5676 }
5677
5678 return ret;
5679 }
5680
hdd_close_cesium_nl_sock(void)5681 static void hdd_close_cesium_nl_sock(void)
5682 {
5683 if (cesium_nl_srv_sock) {
5684 netlink_kernel_release(cesium_nl_srv_sock);
5685 cesium_nl_srv_sock = NULL;
5686 }
5687 }
5688
hdd_update_dynamic_mac(struct hdd_context * hdd_ctx,struct qdf_mac_addr * curr_mac_addr,struct qdf_mac_addr * new_mac_addr)5689 void hdd_update_dynamic_mac(struct hdd_context *hdd_ctx,
5690 struct qdf_mac_addr *curr_mac_addr,
5691 struct qdf_mac_addr *new_mac_addr)
5692 {
5693 uint8_t i;
5694
5695 hdd_enter();
5696
5697 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
5698 if (!qdf_mem_cmp(
5699 curr_mac_addr->bytes,
5700 &hdd_ctx->dynamic_mac_list[i].dynamic_mac.bytes[0],
5701 sizeof(struct qdf_mac_addr))) {
5702 qdf_mem_copy(&hdd_ctx->dynamic_mac_list[i].dynamic_mac,
5703 new_mac_addr->bytes,
5704 sizeof(struct qdf_mac_addr));
5705 break;
5706 }
5707 }
5708
5709 hdd_exit();
5710 }
5711
5712 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
5713 !defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
hdd_set_mld_address(struct hdd_adapter * adapter,const struct qdf_mac_addr * mac_addr)5714 void hdd_set_mld_address(struct hdd_adapter *adapter,
5715 const struct qdf_mac_addr *mac_addr)
5716 {
5717 int i;
5718 bool eht_capab;
5719 struct hdd_adapter *link_adapter;
5720 struct hdd_mlo_adapter_info *mlo_adapter_info;
5721
5722 ucfg_psoc_mlme_get_11be_capab(adapter->hdd_ctx->psoc, &eht_capab);
5723 if (adapter->mlo_adapter_info.is_ml_adapter && eht_capab) {
5724 mlo_adapter_info = &adapter->mlo_adapter_info;
5725 for (i = 0; i < WLAN_MAX_MLD; i++) {
5726 link_adapter = mlo_adapter_info->link_adapter[i];
5727 if (link_adapter)
5728 qdf_copy_macaddr(&link_adapter->mld_addr,
5729 mac_addr);
5730 }
5731 qdf_copy_macaddr(&adapter->mld_addr, mac_addr);
5732 }
5733 }
5734
5735 /**
5736 * hdd_get_netdev_by_vdev_mac() - Get Netdev based on MAC
5737 * @mac_addr: Vdev MAC address
5738 *
5739 * Get netdev from adapter based upon Vdev MAC address.
5740 *
5741 * Return: netdev pointer.
5742 */
5743 static qdf_netdev_t
hdd_get_netdev_by_vdev_mac(struct qdf_mac_addr * mac_addr)5744 hdd_get_netdev_by_vdev_mac(struct qdf_mac_addr *mac_addr)
5745 {
5746 struct hdd_context *hdd_ctx;
5747 struct hdd_adapter *adapter;
5748 struct hdd_adapter *ml_adapter;
5749
5750 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
5751 if (!hdd_ctx) {
5752 hdd_err("Invalid HDD context");
5753 return NULL;
5754 }
5755
5756 adapter = hdd_get_adapter_by_macaddr(hdd_ctx, mac_addr->bytes);
5757 if (!adapter) {
5758 hdd_err("Adapter not foud for MAC " QDF_MAC_ADDR_FMT "",
5759 QDF_MAC_ADDR_REF(mac_addr->bytes));
5760 return NULL;
5761 }
5762
5763 if (adapter->mlo_adapter_info.is_link_adapter &&
5764 adapter->mlo_adapter_info.associate_with_ml_adapter) {
5765 ml_adapter = adapter->mlo_adapter_info.ml_adapter;
5766 adapter = ml_adapter;
5767 }
5768
5769 return adapter->dev;
5770 }
5771 #else
5772 static qdf_netdev_t
hdd_get_netdev_by_vdev_mac(struct qdf_mac_addr * mac_addr)5773 hdd_get_netdev_by_vdev_mac(struct qdf_mac_addr *mac_addr)
5774 {
5775 struct hdd_context *hdd_ctx;
5776 struct hdd_adapter *adapter;
5777
5778 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
5779 if (!hdd_ctx) {
5780 hdd_err("Invalid HDD context");
5781 return NULL;
5782 }
5783
5784 adapter = hdd_get_adapter_by_macaddr(hdd_ctx, mac_addr->bytes);
5785 if (!adapter) {
5786 hdd_err("Adapter not foud for MAC " QDF_MAC_ADDR_FMT "",
5787 QDF_MAC_ADDR_REF(mac_addr->bytes));
5788 return NULL;
5789 }
5790
5791 return adapter->dev;
5792 }
5793 #endif
5794
5795 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
5796 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
5797 !defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
hdd_update_set_mac_addr_req_ctx(struct hdd_adapter * adapter,void * req_ctx)5798 static void hdd_update_set_mac_addr_req_ctx(struct hdd_adapter *adapter,
5799 void *req_ctx)
5800 {
5801 adapter->set_mac_addr_req_ctx = req_ctx;
5802 if (adapter->mlo_adapter_info.associate_with_ml_adapter)
5803 adapter->mlo_adapter_info.ml_adapter->set_mac_addr_req_ctx =
5804 req_ctx;
5805 }
5806 #else
hdd_update_set_mac_addr_req_ctx(struct hdd_adapter * adapter,void * req_ctx)5807 static void hdd_update_set_mac_addr_req_ctx(struct hdd_adapter *adapter,
5808 void *req_ctx)
5809 {
5810 adapter->set_mac_addr_req_ctx = req_ctx;
5811 }
5812 #endif
5813
5814 /**
5815 * hdd_is_dynamic_set_mac_addr_supported() - API to check dynamic MAC address
5816 * update is supported or not
5817 * @hdd_ctx: Pointer to the HDD context
5818 *
5819 * Return: true or false
5820 */
5821 static inline bool
hdd_is_dynamic_set_mac_addr_supported(struct hdd_context * hdd_ctx)5822 hdd_is_dynamic_set_mac_addr_supported(struct hdd_context *hdd_ctx)
5823 {
5824 return hdd_ctx->is_vdev_macaddr_dynamic_update_supported;
5825 }
5826
hdd_is_dynamic_set_mac_addr_allowed(struct hdd_adapter * adapter)5827 bool hdd_is_dynamic_set_mac_addr_allowed(struct hdd_adapter *adapter)
5828 {
5829 if (!adapter->deflink->vdev) {
5830 hdd_err("VDEV is NULL");
5831 return false;
5832 }
5833
5834 if (!hdd_is_dynamic_set_mac_addr_supported(adapter->hdd_ctx)) {
5835 hdd_info_rl("On iface up, set mac address change isn't supported");
5836 return false;
5837 }
5838
5839 switch (adapter->device_mode) {
5840 case QDF_STA_MODE:
5841 if (!cm_is_vdev_disconnected(adapter->deflink->vdev)) {
5842 hdd_info_rl("VDEV is not in disconnected state, set mac address isn't supported");
5843 return false;
5844 }
5845 return true;
5846 case QDF_P2P_DEVICE_MODE:
5847 return ucfg_is_p2p_device_dynamic_set_mac_addr_supported(adapter->hdd_ctx->psoc);
5848 case QDF_SAP_MODE:
5849 if (test_bit(SOFTAP_BSS_STARTED,
5850 &adapter->deflink->link_flags)) {
5851 hdd_info_rl("SAP is in up state, set mac address isn't supported");
5852 return false;
5853 } else {
5854 return true;
5855 }
5856 default:
5857 hdd_info_rl("Dynamic set mac address isn't supported for opmode:%d",
5858 adapter->device_mode);
5859 return false;
5860 }
5861 }
5862
hdd_dynamic_mac_address_set(struct wlan_hdd_link_info * link_info,struct qdf_mac_addr mac_addr,struct qdf_mac_addr mld_addr,bool update_self_peer)5863 int hdd_dynamic_mac_address_set(struct wlan_hdd_link_info *link_info,
5864 struct qdf_mac_addr mac_addr,
5865 struct qdf_mac_addr mld_addr,
5866 bool update_self_peer)
5867 {
5868 int ret;
5869 void *cookie;
5870 bool update_mld_addr;
5871 uint32_t fw_resp_status;
5872 QDF_STATUS status = QDF_STATUS_SUCCESS;
5873 struct osif_request *request;
5874 struct wlan_objmgr_vdev *vdev;
5875 struct hdd_adapter *adapter = link_info->adapter;
5876 struct hdd_context *hdd_ctx = adapter->hdd_ctx;
5877 struct mac_addr_set_priv *priv;
5878 static const struct osif_request_params params = {
5879 .priv_size = sizeof(*priv),
5880 .timeout_ms = WLAN_SET_MAC_ADDR_TIMEOUT
5881 };
5882
5883 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
5884 if (!vdev)
5885 return -EINVAL;
5886
5887 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_P2P_DEVICE_MODE) {
5888 status = ucfg_vdev_mgr_cdp_vdev_detach(vdev);
5889 if (QDF_IS_STATUS_ERROR(status)) {
5890 hdd_err("Failed to detach CDP vdev. Status:%d", status);
5891 ret = qdf_status_to_os_return(status);
5892 goto vdev_ref;
5893 }
5894 }
5895 request = osif_request_alloc(¶ms);
5896 if (!request) {
5897 hdd_err("request alloc fail");
5898 status = QDF_STATUS_E_NOMEM;
5899 ret = -ENOMEM;
5900 goto status_ret;
5901 }
5902
5903 /* Host should hold a wake lock until the FW event response is received
5904 * the WMI event would not be a wake up event.
5905 */
5906 qdf_runtime_pm_prevent_suspend(
5907 &hdd_ctx->runtime_context.dyn_mac_addr_update);
5908 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DYN_MAC_ADDR_UPDATE);
5909
5910 cookie = osif_request_cookie(request);
5911 hdd_update_set_mac_addr_req_ctx(adapter, cookie);
5912
5913 priv = (struct mac_addr_set_priv *)osif_request_priv(request);
5914
5915 /* For p2p device mode, need send delete self peer cmd to F/W,
5916 * To avoid p2p new DP vdev is created before old DP vdev deleted,
5917 * don't create new DP vdev until both self peer delete rsp and set
5918 * mac addr rsp received, so initialize pending_rsp_cnt as 2.
5919 *
5920 * For other mode like STA/SAP, don't need send delete self peer cmd
5921 * to F/W, only need wait set mad addr rsp, so initialize
5922 * pending_rsp_cnt as 1.
5923 */
5924 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_DEVICE_MODE)
5925 qdf_atomic_set(&priv->pending_rsp_cnt, 2);
5926 else
5927 qdf_atomic_set(&priv->pending_rsp_cnt, 1);
5928
5929 status = sme_send_set_mac_addr(mac_addr, mld_addr, vdev);
5930 ret = qdf_status_to_os_return(status);
5931 if (QDF_IS_STATUS_ERROR(status)) {
5932 hdd_nofl_err("Failed to send set MAC address command. Status:%d",
5933 status);
5934 osif_request_put(request);
5935 goto status_ret;
5936 } else {
5937 ret = osif_request_wait_for_response(request);
5938 if (ret) {
5939 hdd_err("Set MAC address response timed out");
5940 } else {
5941 fw_resp_status = priv->fw_resp_status;
5942 if (fw_resp_status) {
5943 hdd_err("Set MAC address failed in FW. Status: %d",
5944 fw_resp_status);
5945 ret = -EAGAIN;
5946 }
5947 }
5948 }
5949
5950 osif_request_put(request);
5951
5952 if (qdf_is_macaddr_zero(&mld_addr))
5953 update_mld_addr = false;
5954 else
5955 update_mld_addr = true;
5956
5957 status = sme_update_vdev_mac_addr(vdev, mac_addr, mld_addr,
5958 update_self_peer, update_mld_addr,
5959 ret);
5960
5961 status_ret:
5962 if (QDF_IS_STATUS_ERROR(status)) {
5963 ret = qdf_status_to_os_return(status);
5964 goto allow_suspend;
5965 } else if (!ret) {
5966 status = ucfg_dp_update_link_mac_addr(vdev, &mac_addr, false);
5967 if (QDF_IS_STATUS_ERROR(status)) {
5968 ret = qdf_status_to_os_return(status);
5969 hdd_err("DP link MAC update failed");
5970 goto allow_suspend;
5971 }
5972 }
5973 sme_vdev_set_data_tx_callback(vdev);
5974
5975 /* Update FW WoW pattern with new MAC address */
5976 ucfg_pmo_del_wow_pattern(vdev);
5977 ucfg_pmo_register_wow_default_patterns(vdev);
5978 hdd_tx_latency_restore_config(link_info);
5979
5980 allow_suspend:
5981 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DYN_MAC_ADDR_UPDATE);
5982 qdf_runtime_pm_allow_suspend(
5983 &hdd_ctx->runtime_context.dyn_mac_addr_update);
5984
5985 vdev_ref:
5986 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
5987
5988 return ret;
5989 }
5990
hdd_set_mac_addr_event_cb(uint8_t vdev_id,uint8_t status)5991 static void hdd_set_mac_addr_event_cb(uint8_t vdev_id, uint8_t status)
5992 {
5993 struct hdd_context *hdd_ctx;
5994 struct wlan_hdd_link_info *link_info;
5995 struct osif_request *req;
5996 struct mac_addr_set_priv *priv;
5997
5998 osif_debug("enter");
5999 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6000 if (!hdd_ctx) {
6001 hdd_err("Invalid HDD context");
6002 return;
6003 }
6004
6005 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6006 if (!link_info) {
6007 hdd_err("No adapter found for VDEV ID:%d", vdev_id);
6008 return;
6009 }
6010
6011 req = osif_request_get(link_info->adapter->set_mac_addr_req_ctx);
6012 if (!req) {
6013 osif_err("Obsolete request for VDEV ID:%d", vdev_id);
6014 return;
6015 }
6016
6017 priv = (struct mac_addr_set_priv *)osif_request_priv(req);
6018
6019 if (qdf_atomic_dec_and_test(&priv->pending_rsp_cnt)) {
6020 priv->fw_resp_status = status;
6021 osif_request_complete(req);
6022 }
6023
6024 osif_request_put(req);
6025 }
6026 #else
6027 static inline bool
hdd_is_dynamic_set_mac_addr_supported(struct hdd_context * hdd_ctx)6028 hdd_is_dynamic_set_mac_addr_supported(struct hdd_context *hdd_ctx)
6029 {
6030 return false;
6031 }
6032 #endif
6033
6034 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
6035 static QDF_STATUS
hdd_adapter_update_links_on_link_switch(struct wlan_hdd_link_info * cur_link_info,struct wlan_hdd_link_info * new_link_info)6036 hdd_adapter_update_links_on_link_switch(struct wlan_hdd_link_info *cur_link_info,
6037 struct wlan_hdd_link_info *new_link_info)
6038 {
6039 unsigned long link_flags;
6040 struct wlan_objmgr_vdev *vdev;
6041 int cur_link_idx, new_link_idx;
6042 uint8_t cur_old_pos, cur_new_pos;
6043 struct vdev_osif_priv *vdev_priv;
6044 struct hdd_adapter *adapter = cur_link_info->adapter;
6045
6046 /* Update the new position of current and new link info
6047 * in the link info array.
6048 */
6049 cur_link_idx = hdd_adapter_get_index_of_link_info(cur_link_info);
6050 new_link_idx = hdd_adapter_get_index_of_link_info(new_link_info);
6051
6052 cur_old_pos = adapter->curr_link_info_map[cur_link_idx];
6053 cur_new_pos = adapter->curr_link_info_map[new_link_idx];
6054
6055 adapter->curr_link_info_map[new_link_idx] = cur_old_pos;
6056 adapter->curr_link_info_map[cur_link_idx] = cur_new_pos;
6057
6058 /* Move VDEV from current link info to new link info */
6059 qdf_atomic_clear_bit(cur_link_idx, &adapter->active_links);
6060 qdf_spin_lock_bh(&cur_link_info->vdev_lock);
6061 vdev = cur_link_info->vdev;
6062 cur_link_info->vdev = NULL;
6063 cur_link_info->vdev_id = WLAN_INVALID_VDEV_ID;
6064 qdf_spin_unlock_bh(&cur_link_info->vdev_lock);
6065
6066 qdf_spin_lock_bh(&new_link_info->vdev_lock);
6067 new_link_info->vdev = vdev;
6068 new_link_info->vdev_id = wlan_vdev_get_id(vdev);
6069 qdf_spin_unlock_bh(&new_link_info->vdev_lock);
6070 qdf_atomic_set_bit(new_link_idx, &adapter->active_links);
6071
6072 /* Move the link flags between current and new link info */
6073 link_flags = new_link_info->link_flags;
6074 new_link_info->link_flags = cur_link_info->link_flags;
6075 cur_link_info->link_flags = link_flags;
6076
6077 /* Update VDEV-OSIF priv pointer to new link info */
6078 vdev_priv = wlan_vdev_get_ospriv(new_link_info->vdev);
6079 vdev_priv->legacy_osif_priv = new_link_info;
6080
6081 return QDF_STATUS_SUCCESS;
6082 }
6083
6084 struct wlan_hdd_link_info *
hdd_get_link_info_by_ieee_link_id(struct hdd_adapter * adapter,int32_t link_id)6085 hdd_get_link_info_by_ieee_link_id(struct hdd_adapter *adapter, int32_t link_id)
6086 {
6087 struct wlan_hdd_link_info *link_info;
6088 struct hdd_station_ctx *sta_ctx;
6089
6090 if (!adapter || link_id == WLAN_INVALID_LINK_ID) {
6091 hdd_err("NULL adapter or invalid link ID");
6092 return NULL;
6093 }
6094
6095 hdd_adapter_for_each_link_info(adapter, link_info) {
6096 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
6097 if (sta_ctx->conn_info.ieee_link_id == link_id)
6098 return link_info;
6099 }
6100
6101 return NULL;
6102 }
6103
6104 QDF_STATUS
hdd_link_switch_vdev_mac_addr_update(int32_t ieee_old_link_id,int32_t ieee_new_link_id,uint8_t vdev_id)6105 hdd_link_switch_vdev_mac_addr_update(int32_t ieee_old_link_id,
6106 int32_t ieee_new_link_id, uint8_t vdev_id)
6107 {
6108 QDF_STATUS status = QDF_STATUS_E_INVAL;
6109 struct hdd_context *hdd_ctx;
6110 struct hdd_adapter *adapter;
6111 struct wlan_objmgr_vdev *vdev;
6112 struct wlan_hdd_link_info *cur_link_info, *new_link_info;
6113 struct hdd_station_ctx *sta_ctx;
6114
6115 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6116 if (!hdd_ctx) {
6117 hdd_err("HDD ctx NULL");
6118 return QDF_STATUS_E_INVAL;
6119 }
6120
6121 cur_link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6122 if (!cur_link_info) {
6123 hdd_err("VDEV %d not found", vdev_id);
6124 return status;
6125 }
6126
6127 vdev = hdd_objmgr_get_vdev_by_user(cur_link_info, WLAN_OSIF_ID);
6128 if (!vdev) {
6129 hdd_err("Invalid VDEV %d", vdev_id);
6130 return status;
6131 }
6132
6133 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(cur_link_info);
6134 if (sta_ctx->conn_info.ieee_link_id != ieee_old_link_id) {
6135 hdd_err("Link id %d mismatch", sta_ctx->conn_info.ieee_link_id);
6136 goto release_ref;
6137 }
6138
6139 adapter = cur_link_info->adapter;
6140 new_link_info = hdd_get_link_info_by_ieee_link_id(adapter,
6141 ieee_new_link_id);
6142 if (!new_link_info) {
6143 hdd_err("Link id %d not found", ieee_new_link_id);
6144 goto release_ref;
6145 }
6146
6147 status = ucfg_dp_update_link_mac_addr(vdev, &new_link_info->link_addr,
6148 true);
6149 if (QDF_IS_STATUS_ERROR(status)) {
6150 hdd_err("DP link MAC update failed");
6151 goto release_ref;
6152 }
6153
6154 status = hdd_adapter_update_links_on_link_switch(cur_link_info,
6155 new_link_info);
6156 if (QDF_IS_STATUS_ERROR(status)) {
6157 hdd_err("Failed to update adapter link info");
6158 goto release_ref;
6159 }
6160
6161 hdd_adapter_update_mlo_mgr_mac_addr(adapter);
6162 sme_vdev_set_data_tx_callback(vdev);
6163 ucfg_pmo_del_wow_pattern(vdev);
6164 ucfg_pmo_register_wow_default_patterns(vdev);
6165
6166 release_ref:
6167 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
6168 return status;
6169 }
6170 #endif
6171
6172 /**
6173 * __hdd_set_mac_address() - set the user specified mac address
6174 * @dev: Pointer to the net device.
6175 * @addr: Pointer to the sockaddr.
6176 *
6177 * This function sets the user specified mac address using
6178 * the command ifconfig wlanX hw ether <mac address>.
6179 *
6180 * Return: 0 for success, non zero for failure
6181 */
__hdd_set_mac_address(struct net_device * dev,void * addr)6182 static int __hdd_set_mac_address(struct net_device *dev, void *addr)
6183 {
6184 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6185 struct hdd_adapter *adapter_temp;
6186 struct hdd_context *hdd_ctx;
6187 struct sockaddr *psta_mac_addr = addr;
6188 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
6189 int ret;
6190 struct qdf_mac_addr mac_addr;
6191 bool net_if_running = netif_running(dev);
6192
6193 hdd_enter_dev(dev);
6194
6195 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6196 ret = wlan_hdd_validate_context(hdd_ctx);
6197 if (0 != ret)
6198 return ret;
6199
6200 if (net_if_running) {
6201 if (!hdd_is_dynamic_set_mac_addr_allowed(adapter))
6202 return -ENOTSUPP;
6203 }
6204
6205 qdf_mem_copy(&mac_addr, psta_mac_addr->sa_data, sizeof(mac_addr));
6206 adapter_temp = hdd_get_adapter_by_macaddr(hdd_ctx, mac_addr.bytes);
6207 if (adapter_temp) {
6208 if (!qdf_str_cmp(adapter_temp->dev->name, dev->name))
6209 return 0;
6210 hdd_err("%s adapter exist with same address " QDF_MAC_ADDR_FMT,
6211 adapter_temp->dev->name,
6212 QDF_MAC_ADDR_REF(mac_addr.bytes));
6213 return -EINVAL;
6214 }
6215 qdf_ret_status = wlan_hdd_validate_mac_address(&mac_addr);
6216 if (QDF_IS_STATUS_ERROR(qdf_ret_status))
6217 return -EINVAL;
6218
6219 hdd_nofl_debug("Changing MAC to "
6220 QDF_MAC_ADDR_FMT " of the interface %s ",
6221 QDF_MAC_ADDR_REF(mac_addr.bytes), dev->name);
6222
6223 if (net_if_running && adapter->deflink->vdev) {
6224 ret = hdd_update_vdev_mac_address(adapter, mac_addr);
6225 if (ret)
6226 return ret;
6227 }
6228
6229 hdd_set_mld_address(adapter, &mac_addr);
6230
6231 hdd_update_dynamic_mac(hdd_ctx, &adapter->mac_addr, &mac_addr);
6232 ucfg_dp_update_intf_mac(hdd_ctx->psoc, &adapter->mac_addr, &mac_addr,
6233 adapter->deflink->vdev);
6234 memcpy(&adapter->mac_addr, psta_mac_addr->sa_data, ETH_ALEN);
6235 qdf_net_update_net_device_dev_addr(dev, psta_mac_addr->sa_data,
6236 ETH_ALEN);
6237
6238 hdd_exit();
6239 return ret;
6240 }
6241
6242 /**
6243 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
6244 * function from SSR
6245 * @net_dev: pointer to net_device structure
6246 * @addr: Pointer to the sockaddr
6247 *
6248 * This function sets the user specified mac address using
6249 * the command ifconfig wlanX hw ether <mac address>.
6250 *
6251 * Return: 0 for success.
6252 */
hdd_set_mac_address(struct net_device * net_dev,void * addr)6253 static int hdd_set_mac_address(struct net_device *net_dev, void *addr)
6254 {
6255 struct osif_vdev_sync *vdev_sync;
6256 int errno;
6257
6258 errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
6259 if (errno)
6260 return errno;
6261
6262 errno = __hdd_set_mac_address(net_dev, addr);
6263
6264 osif_vdev_sync_op_stop(vdev_sync);
6265
6266 return errno;
6267 }
6268
wlan_hdd_get_derived_intf_addr(struct hdd_context * hdd_ctx)6269 static uint8_t *wlan_hdd_get_derived_intf_addr(struct hdd_context *hdd_ctx)
6270 {
6271 int i, j;
6272
6273 i = qdf_ffz(hdd_ctx->derived_intf_addr_mask);
6274 if (i < 0 || i >= hdd_ctx->num_derived_addr)
6275 return NULL;
6276 qdf_atomic_set_bit(i, &hdd_ctx->derived_intf_addr_mask);
6277 hdd_nofl_debug("Assigning MAC from derived list "QDF_MAC_ADDR_FMT,
6278 QDF_MAC_ADDR_REF(hdd_ctx->derived_mac_addr[i].bytes));
6279
6280 /* Copy the mac in dynamic mac list at first free position */
6281 for (j = 0; j < QDF_MAX_CONCURRENCY_PERSONA; j++) {
6282 if (qdf_is_macaddr_zero(&hdd_ctx->
6283 dynamic_mac_list[j].dynamic_mac))
6284 break;
6285 }
6286 if (j == QDF_MAX_CONCURRENCY_PERSONA) {
6287 hdd_err("Max interfaces are up");
6288 return NULL;
6289 }
6290
6291 qdf_mem_copy(&hdd_ctx->dynamic_mac_list[j].dynamic_mac.bytes,
6292 &hdd_ctx->derived_mac_addr[i].bytes,
6293 sizeof(struct qdf_mac_addr));
6294 hdd_ctx->dynamic_mac_list[j].is_provisioned_mac = false;
6295 hdd_ctx->dynamic_mac_list[j].bit_position = i;
6296
6297 return hdd_ctx->derived_mac_addr[i].bytes;
6298 }
6299
wlan_hdd_get_provisioned_intf_addr(struct hdd_context * hdd_ctx)6300 static uint8_t *wlan_hdd_get_provisioned_intf_addr(struct hdd_context *hdd_ctx)
6301 {
6302 int i, j;
6303
6304 i = qdf_ffz(hdd_ctx->provisioned_intf_addr_mask);
6305 if (i < 0 || i >= hdd_ctx->num_provisioned_addr)
6306 return NULL;
6307 qdf_atomic_set_bit(i, &hdd_ctx->provisioned_intf_addr_mask);
6308 hdd_debug("Assigning MAC from provisioned list "QDF_MAC_ADDR_FMT,
6309 QDF_MAC_ADDR_REF(hdd_ctx->provisioned_mac_addr[i].bytes));
6310
6311 /* Copy the mac in dynamic mac list at first free position */
6312 for (j = 0; j < QDF_MAX_CONCURRENCY_PERSONA; j++) {
6313 if (qdf_is_macaddr_zero(&hdd_ctx->
6314 dynamic_mac_list[j].dynamic_mac))
6315 break;
6316 }
6317 if (j == QDF_MAX_CONCURRENCY_PERSONA) {
6318 hdd_err("Max interfaces are up");
6319 return NULL;
6320 }
6321
6322 qdf_mem_copy(&hdd_ctx->dynamic_mac_list[j].dynamic_mac.bytes,
6323 &hdd_ctx->provisioned_mac_addr[i].bytes,
6324 sizeof(struct qdf_mac_addr));
6325 hdd_ctx->dynamic_mac_list[j].is_provisioned_mac = true;
6326 hdd_ctx->dynamic_mac_list[j].bit_position = i;
6327 return hdd_ctx->provisioned_mac_addr[i].bytes;
6328 }
6329
wlan_hdd_get_intf_addr(struct hdd_context * hdd_ctx,enum QDF_OPMODE interface_type)6330 uint8_t *wlan_hdd_get_intf_addr(struct hdd_context *hdd_ctx,
6331 enum QDF_OPMODE interface_type)
6332 {
6333 uint8_t *mac_addr = NULL;
6334
6335 if (qdf_atomic_test_bit(interface_type,
6336 (unsigned long *)
6337 (&hdd_ctx->config->provisioned_intf_pool)))
6338 mac_addr = wlan_hdd_get_provisioned_intf_addr(hdd_ctx);
6339
6340 if ((!mac_addr) &&
6341 (qdf_atomic_test_bit(interface_type,
6342 (unsigned long *)
6343 (&hdd_ctx->config->derived_intf_pool))))
6344 mac_addr = wlan_hdd_get_derived_intf_addr(hdd_ctx);
6345
6346 if (!mac_addr)
6347 hdd_err("MAC is not available in both the lists");
6348 return mac_addr;
6349 }
6350
wlan_hdd_release_intf_addr(struct hdd_context * hdd_ctx,uint8_t * releaseAddr)6351 void wlan_hdd_release_intf_addr(struct hdd_context *hdd_ctx,
6352 uint8_t *releaseAddr)
6353 {
6354 int i;
6355 int mac_pos_in_mask;
6356
6357 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
6358 if (!memcmp(releaseAddr,
6359 hdd_ctx->dynamic_mac_list[i].dynamic_mac.bytes,
6360 QDF_MAC_ADDR_SIZE)) {
6361 mac_pos_in_mask =
6362 hdd_ctx->dynamic_mac_list[i].bit_position;
6363 if (hdd_ctx->dynamic_mac_list[i].is_provisioned_mac) {
6364 qdf_atomic_clear_bit(
6365 mac_pos_in_mask,
6366 &hdd_ctx->
6367 provisioned_intf_addr_mask);
6368 hdd_debug("Releasing MAC from provisioned list");
6369 hdd_debug(
6370 QDF_MAC_ADDR_FMT,
6371 QDF_MAC_ADDR_REF(releaseAddr));
6372 } else {
6373 qdf_atomic_clear_bit(
6374 mac_pos_in_mask, &hdd_ctx->
6375 derived_intf_addr_mask);
6376 hdd_debug("Releasing MAC from derived list");
6377 hdd_debug(QDF_MAC_ADDR_FMT,
6378 QDF_MAC_ADDR_REF(releaseAddr));
6379 }
6380 qdf_zero_macaddr(&hdd_ctx->
6381 dynamic_mac_list[i].dynamic_mac);
6382 hdd_ctx->dynamic_mac_list[i].is_provisioned_mac =
6383 false;
6384 hdd_ctx->dynamic_mac_list[i].bit_position = 0;
6385 break;
6386 }
6387
6388 }
6389 if (i == QDF_MAX_CONCURRENCY_PERSONA)
6390 hdd_debug("Releasing non existing MAC " QDF_MAC_ADDR_FMT,
6391 QDF_MAC_ADDR_REF(releaseAddr));
6392 }
6393
6394 /**
6395 * hdd_set_derived_multicast_list(): Add derived peer multicast address list in
6396 * multicast list request to the FW
6397 * @psoc: Pointer to psoc
6398 * @adapter: Pointer to hdd adapter
6399 * @mc_list_request: Multicast list request to the FW
6400 * @mc_count: number of multicast addresses received from the kernel
6401 *
6402 * Return: None
6403 */
6404 static void
hdd_set_derived_multicast_list(struct wlan_objmgr_psoc * psoc,struct hdd_adapter * adapter,struct pmo_mc_addr_list_params * mc_list_request,int * mc_count)6405 hdd_set_derived_multicast_list(struct wlan_objmgr_psoc *psoc,
6406 struct hdd_adapter *adapter,
6407 struct pmo_mc_addr_list_params *mc_list_request,
6408 int *mc_count)
6409 {
6410 int i = 0, j = 0, list_count = *mc_count;
6411 struct qdf_mac_addr *peer_mc_addr_list = NULL;
6412 uint8_t driver_mc_cnt = 0;
6413 uint32_t max_ndp_sessions = 0;
6414
6415 cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions);
6416
6417 ucfg_nan_get_peer_mc_list(adapter->deflink->vdev, &peer_mc_addr_list);
6418
6419 for (j = 0; j < max_ndp_sessions; j++) {
6420 for (i = 0; i < list_count; i++) {
6421 if (qdf_is_macaddr_zero(&peer_mc_addr_list[j]) ||
6422 qdf_is_macaddr_equal(&mc_list_request->mc_addr[i],
6423 &peer_mc_addr_list[j]))
6424 break;
6425 }
6426 if (i == list_count) {
6427 qdf_mem_copy(
6428 &(mc_list_request->mc_addr[list_count +
6429 driver_mc_cnt].bytes),
6430 peer_mc_addr_list[j].bytes, ETH_ALEN);
6431 hdd_debug("mlist[%d] = " QDF_MAC_ADDR_FMT,
6432 list_count + driver_mc_cnt,
6433 QDF_MAC_ADDR_REF(
6434 mc_list_request->mc_addr[list_count +
6435 driver_mc_cnt].bytes));
6436 driver_mc_cnt++;
6437 }
6438 }
6439 *mc_count += driver_mc_cnt;
6440 }
6441
6442 /**
6443 * __hdd_set_multicast_list() - set the multicast address list
6444 * @dev: Pointer to the WLAN device.
6445 *
6446 * This function sets the multicast address list.
6447 *
6448 * Return: None
6449 */
__hdd_set_multicast_list(struct net_device * dev)6450 static void __hdd_set_multicast_list(struct net_device *dev)
6451 {
6452 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6453 int i = 0, errno;
6454 struct netdev_hw_addr *ha;
6455 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6456 struct pmo_mc_addr_list_params *mc_list_request = NULL;
6457 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
6458 int mc_count = 0;
6459
6460 if (hdd_ctx->hdd_wlan_suspended) {
6461 hdd_err_rl("Device is system suspended");
6462 return;
6463 }
6464
6465 hdd_enter_dev(dev);
6466 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
6467 return;
6468
6469 errno = wlan_hdd_validate_context(hdd_ctx);
6470 if (errno)
6471 return;
6472
6473 errno = hdd_validate_adapter(adapter);
6474 if (errno)
6475 return;
6476
6477 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
6478 hdd_debug("Driver module is closed");
6479 return;
6480 }
6481
6482 mc_list_request = qdf_mem_malloc(sizeof(*mc_list_request));
6483 if (!mc_list_request)
6484 return;
6485
6486 qdf_spin_lock_bh(&adapter->mc_list_lock);
6487 /* Delete already configured multicast address list */
6488 if (adapter->mc_addr_list.mc_cnt > 0)
6489 hdd_disable_and_flush_mc_addr_list(adapter,
6490 pmo_mc_list_change_notify);
6491
6492 if (dev->flags & IFF_ALLMULTI) {
6493 hdd_debug("allow all multicast frames");
6494 hdd_disable_and_flush_mc_addr_list(adapter,
6495 pmo_mc_list_change_notify);
6496 } else {
6497 mc_count = netdev_mc_count(dev);
6498 if (mc_count > ucfg_pmo_max_mc_addr_supported(psoc)) {
6499 hdd_debug("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
6500 ucfg_pmo_max_mc_addr_supported(psoc));
6501 hdd_disable_and_flush_mc_addr_list(adapter,
6502 pmo_mc_list_change_notify);
6503 adapter->mc_addr_list.mc_cnt = 0;
6504 goto free_req;
6505 }
6506 netdev_for_each_mc_addr(ha, dev) {
6507 if (i == mc_count)
6508 break;
6509 memset(&(mc_list_request->mc_addr[i].bytes),
6510 0, ETH_ALEN);
6511 memcpy(&(mc_list_request->mc_addr[i].bytes),
6512 ha->addr, ETH_ALEN);
6513 hdd_debug("mlist[%d] = "QDF_MAC_ADDR_FMT, i,
6514 QDF_MAC_ADDR_REF(mc_list_request->mc_addr[i].bytes));
6515 i++;
6516 }
6517
6518 if (adapter->device_mode == QDF_NDI_MODE)
6519 hdd_set_derived_multicast_list(psoc, adapter,
6520 mc_list_request,
6521 &mc_count);
6522 }
6523
6524 adapter->mc_addr_list.mc_cnt = mc_count;
6525 mc_list_request->psoc = psoc;
6526 mc_list_request->vdev_id = adapter->deflink->vdev_id;
6527 mc_list_request->count = mc_count;
6528
6529 errno = hdd_cache_mc_addr_list(mc_list_request);
6530 if (errno) {
6531 hdd_debug("Failed to cache MC address list for vdev %u; errno:%d",
6532 adapter->deflink->vdev_id, errno);
6533 goto free_req;
6534 }
6535
6536 hdd_enable_mc_addr_filtering(adapter, pmo_mc_list_change_notify);
6537
6538 free_req:
6539 qdf_spin_unlock_bh(&adapter->mc_list_lock);
6540 qdf_mem_free(mc_list_request);
6541 }
6542
6543 /**
6544 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
6545 * @net_dev: pointer to net_device
6546 *
6547 * Return: none
6548 */
hdd_set_multicast_list(struct net_device * net_dev)6549 static void hdd_set_multicast_list(struct net_device *net_dev)
6550 {
6551 struct osif_vdev_sync *vdev_sync;
6552
6553 if (osif_vdev_sync_op_start(net_dev, &vdev_sync))
6554 return;
6555
6556 __hdd_set_multicast_list(net_dev);
6557
6558 osif_vdev_sync_op_stop(vdev_sync);
6559 }
6560
hdd_update_multicast_list(struct wlan_objmgr_vdev * vdev)6561 void hdd_update_multicast_list(struct wlan_objmgr_vdev *vdev)
6562 {
6563 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6564 struct wlan_hdd_link_info *link_info;
6565 struct hdd_adapter *adapter;
6566 uint8_t vdev_id = wlan_vdev_get_id(vdev);
6567 struct net_device *net_dev;
6568
6569 if (!hdd_ctx) {
6570 hdd_err("hdd_ctx is null");
6571 return;
6572 }
6573
6574 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6575 if (!link_info) {
6576 hdd_err("adapter is null for vdev_id %d", vdev_id);
6577 return;
6578 }
6579
6580 adapter = link_info->adapter;
6581 if (!adapter) {
6582 hdd_err("adapter is null for vdev_id %d", vdev_id);
6583 return;
6584 }
6585
6586 net_dev = adapter->dev;
6587 if (!net_dev) {
6588 hdd_err("netdev is null");
6589 return;
6590 }
6591
6592 __hdd_set_multicast_list(net_dev);
6593 }
6594
6595 #ifdef WLAN_FEATURE_TSF_PTP
6596 static const struct ethtool_ops wlan_ethtool_ops = {
6597 .get_ts_info = wlan_get_ts_info,
6598 };
6599 #endif
6600
6601 /**
6602 * __hdd_fix_features - Adjust the feature flags needed to be updated
6603 * @net_dev: Handle to net_device
6604 * @features: Currently enabled feature flags
6605 *
6606 * Return: Adjusted feature flags on success, old feature on failure
6607 */
__hdd_fix_features(struct net_device * net_dev,netdev_features_t features)6608 static netdev_features_t __hdd_fix_features(struct net_device *net_dev,
6609 netdev_features_t features)
6610 {
6611 netdev_features_t feature_change_req = features;
6612 netdev_features_t feature_tso_csum;
6613 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
6614
6615 if (!adapter->handle_feature_update) {
6616 hdd_debug("Not triggered by hdd_netdev_update_features");
6617 return features;
6618 }
6619
6620 feature_tso_csum = hdd_get_tso_csum_feature_flags();
6621 if (hdd_is_legacy_connection(adapter->deflink)) {
6622 /* Disable checksum and TSO */
6623 feature_change_req &= ~feature_tso_csum;
6624 adapter->tso_csum_feature_enabled = 0;
6625 } else {
6626 /* Enable checksum and TSO */
6627 feature_change_req |= feature_tso_csum;
6628 adapter->tso_csum_feature_enabled = 1;
6629 }
6630 hdd_debug("vdev mode %d current features 0x%llx, requesting feature change 0x%llx",
6631 adapter->device_mode, net_dev->features,
6632 feature_change_req);
6633
6634 return feature_change_req;
6635 }
6636
6637 /**
6638 * hdd_fix_features() - Wrapper for __hdd_fix_features to protect it from SSR
6639 * @net_dev: Pointer to net_device structure
6640 * @features: Updated features set
6641 *
6642 * Adjusts the feature request, do not update the device yet.
6643 *
6644 * Return: updated feature for success, incoming feature as is on failure
6645 */
hdd_fix_features(struct net_device * net_dev,netdev_features_t features)6646 static netdev_features_t hdd_fix_features(struct net_device *net_dev,
6647 netdev_features_t features)
6648 {
6649 int errno;
6650 int changed_features = features;
6651 struct osif_vdev_sync *vdev_sync;
6652
6653 errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
6654 if (errno)
6655 return features;
6656
6657 changed_features = __hdd_fix_features(net_dev, features);
6658
6659 osif_vdev_sync_op_stop(vdev_sync);
6660
6661 return changed_features;
6662 }
6663 /**
6664 * __hdd_set_features - Notify device about change in features
6665 * @net_dev: Handle to net_device
6666 * @features: Existing + requested feature after resolving the dependency
6667 *
6668 * Return: 0 on success, non zero error on failure
6669 */
__hdd_set_features(struct net_device * net_dev,netdev_features_t features)6670 static int __hdd_set_features(struct net_device *net_dev,
6671 netdev_features_t features)
6672 {
6673 struct hdd_adapter *adapter = netdev_priv(net_dev);
6674 ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
6675
6676 if (!adapter->handle_feature_update) {
6677 hdd_debug("Not triggered by hdd_netdev_update_features");
6678 return 0;
6679 }
6680
6681 if (!soc)
6682 return 0;
6683
6684 hdd_debug("vdev mode %d vdev_id %d current features 0x%llx, changed features 0x%llx",
6685 adapter->device_mode, adapter->deflink->vdev_id,
6686 net_dev->features, features);
6687
6688 return 0;
6689 }
6690
6691 /**
6692 * hdd_set_features() - Wrapper for __hdd_set_features to protect it from SSR
6693 * @net_dev: Pointer to net_device structure
6694 * @features: Updated features set
6695 *
6696 * Is called to update device configurations for changed features.
6697 *
6698 * Return: 0 for success, non-zero for failure
6699 */
hdd_set_features(struct net_device * net_dev,netdev_features_t features)6700 static int hdd_set_features(struct net_device *net_dev,
6701 netdev_features_t features)
6702 {
6703 int errno;
6704 struct osif_vdev_sync *vdev_sync;
6705
6706 errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
6707 if (errno) {
6708 /*
6709 * Only invoke from netdev_feature_update_work expected,
6710 * which is from CLD inside.
6711 * Ignore others from upper stack during loading phase,
6712 * and return success to avoid failure print from kernel.
6713 */
6714 hdd_debug("VDEV in transition, ignore set_features");
6715 return 0;
6716 }
6717
6718 errno = __hdd_set_features(net_dev, features);
6719
6720 osif_vdev_sync_op_stop(vdev_sync);
6721
6722 return errno;
6723 }
6724
6725 #define HDD_NETDEV_FEATURES_UPDATE_MAX_WAIT_COUNT 10
6726 #define HDD_NETDEV_FEATURES_UPDATE_WAIT_INTERVAL_MS 20
6727
hdd_netdev_update_features(struct hdd_adapter * adapter)6728 void hdd_netdev_update_features(struct hdd_adapter *adapter)
6729 {
6730 struct net_device *net_dev = adapter->dev;
6731 ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
6732 bool request_feature_update = false;
6733 int wait_count = HDD_NETDEV_FEATURES_UPDATE_MAX_WAIT_COUNT;
6734
6735 if (!soc)
6736 return;
6737
6738 if (!cdp_cfg_get(soc, cfg_dp_disable_legacy_mode_csum_offload))
6739 return;
6740
6741 switch (adapter->device_mode) {
6742 case QDF_STA_MODE:
6743 if (cdp_cfg_get(soc, cfg_dp_enable_ip_tcp_udp_checksum_offload))
6744 request_feature_update = true;
6745 break;
6746 default:
6747 break;
6748 }
6749
6750 if (request_feature_update) {
6751 hdd_debug("Update net_dev features for device mode %d",
6752 adapter->device_mode);
6753 while (!adapter->delete_in_progress) {
6754 if (rtnl_trylock()) {
6755 adapter->handle_feature_update = true;
6756 netdev_update_features(net_dev);
6757 adapter->handle_feature_update = false;
6758 rtnl_unlock();
6759 break;
6760 }
6761
6762 if (wait_count--) {
6763 qdf_sleep(
6764 HDD_NETDEV_FEATURES_UPDATE_WAIT_INTERVAL_MS);
6765 } else {
6766 /*
6767 * We have failed to updated the netdev
6768 * features for very long, so enable the queues
6769 * now. The impact of not being able to update
6770 * the netdev feature is lower TPUT when
6771 * switching from legacy to non-legacy mode.
6772 */
6773 hdd_err("Failed to update netdev features for device mode %d",
6774 adapter->device_mode);
6775 break;
6776 }
6777 }
6778 }
6779 }
6780
6781 static const struct net_device_ops wlan_drv_ops = {
6782 .ndo_open = hdd_open,
6783 .ndo_stop = hdd_stop,
6784 .ndo_uninit = hdd_uninit,
6785 .ndo_start_xmit = hdd_hard_start_xmit,
6786 .ndo_fix_features = hdd_fix_features,
6787 .ndo_set_features = hdd_set_features,
6788 .ndo_tx_timeout = hdd_tx_timeout,
6789 .ndo_get_stats = hdd_get_stats,
6790 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
6791 .ndo_do_ioctl = hdd_ioctl,
6792 #endif
6793 .ndo_set_mac_address = hdd_set_mac_address,
6794 .ndo_select_queue = hdd_select_queue,
6795 .ndo_set_rx_mode = hdd_set_multicast_list,
6796 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
6797 .ndo_siocdevprivate = hdd_dev_private_ioctl,
6798 #endif
6799 };
6800
6801 #ifdef FEATURE_MONITOR_MODE_SUPPORT
6802 /* Monitor mode net_device_ops, does not Tx and most of operations. */
6803 static const struct net_device_ops wlan_mon_drv_ops = {
6804 .ndo_open = hdd_mon_open,
6805 .ndo_stop = hdd_stop,
6806 .ndo_get_stats = hdd_get_stats,
6807 };
6808
6809 /**
6810 * hdd_set_mon_ops() - update net_device ops for monitor mode
6811 * @dev: Handle to struct net_device to be updated.
6812 * Return: None
6813 */
hdd_set_mon_ops(struct net_device * dev)6814 static void hdd_set_mon_ops(struct net_device *dev)
6815 {
6816 dev->netdev_ops = &wlan_mon_drv_ops;
6817 }
6818
6819 #ifdef WLAN_FEATURE_TSF_PTP
hdd_set_station_ops(struct net_device * dev)6820 void hdd_set_station_ops(struct net_device *dev)
6821 {
6822 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) {
6823 hdd_set_mon_ops(dev);
6824 } else {
6825 dev->netdev_ops = &wlan_drv_ops;
6826 dev->ethtool_ops = &wlan_ethtool_ops;
6827 }
6828 }
6829 #else
hdd_set_station_ops(struct net_device * dev)6830 void hdd_set_station_ops(struct net_device *dev)
6831 {
6832 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
6833 hdd_set_mon_ops(dev);
6834 else
6835 dev->netdev_ops = &wlan_drv_ops;
6836 }
6837
6838 #endif
6839 #else
6840 #ifdef WLAN_FEATURE_TSF_PTP
hdd_set_station_ops(struct net_device * dev)6841 void hdd_set_station_ops(struct net_device *dev)
6842 {
6843 dev->netdev_ops = &wlan_drv_ops;
6844 dev->ethtool_ops = &wlan_ethtool_ops;
6845 }
6846 #else
hdd_set_station_ops(struct net_device * dev)6847 void hdd_set_station_ops(struct net_device *dev)
6848 {
6849 dev->netdev_ops = &wlan_drv_ops;
6850 }
6851 #endif
hdd_set_mon_ops(struct net_device * dev)6852 static void hdd_set_mon_ops(struct net_device *dev)
6853 {
6854 }
6855 #endif
6856
6857 #ifdef WLAN_FEATURE_PKT_CAPTURE
6858 /* Packet Capture mode net_device_ops, does not Tx and most of operations. */
6859 static const struct net_device_ops wlan_pktcapture_drv_ops = {
6860 .ndo_open = hdd_pktcapture_open,
6861 .ndo_stop = hdd_stop,
6862 .ndo_get_stats = hdd_get_stats,
6863 };
6864
hdd_set_pktcapture_ops(struct net_device * dev)6865 static void hdd_set_pktcapture_ops(struct net_device *dev)
6866 {
6867 dev->netdev_ops = &wlan_pktcapture_drv_ops;
6868 }
6869 #else
hdd_set_pktcapture_ops(struct net_device * dev)6870 static void hdd_set_pktcapture_ops(struct net_device *dev)
6871 {
6872 }
6873 #endif
6874
6875 #ifdef MULTI_CLIENT_LL_SUPPORT
6876 /**
6877 * hdd_set_multi_client_ll_support() - set multi client ll support flag in
6878 * allocated station hdd adapter
6879 * @adapter: pointer to hdd adapter
6880 *
6881 * Return: none
6882 */
hdd_set_multi_client_ll_support(struct hdd_adapter * adapter)6883 static void hdd_set_multi_client_ll_support(struct hdd_adapter *adapter)
6884 {
6885 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6886 bool multi_client_ll_ini_support, multi_client_ll_caps;
6887
6888 ucfg_mlme_cfg_get_multi_client_ll_ini_support(hdd_ctx->psoc,
6889 &multi_client_ll_ini_support);
6890 multi_client_ll_caps =
6891 ucfg_mlme_get_wlm_multi_client_ll_caps(hdd_ctx->psoc);
6892
6893 hdd_debug("fw caps: %d, ini: %d", multi_client_ll_caps,
6894 multi_client_ll_ini_support);
6895 if (multi_client_ll_caps && multi_client_ll_ini_support)
6896 adapter->multi_client_ll_support = true;
6897 }
6898 #else
6899 static inline void
hdd_set_multi_client_ll_support(struct hdd_adapter * adapter)6900 hdd_set_multi_client_ll_support(struct hdd_adapter *adapter)
6901 {
6902 }
6903 #endif
6904
6905 /**
6906 * hdd_alloc_station_adapter() - allocate the station hdd adapter
6907 * @hdd_ctx: global hdd context
6908 * @mac_addr: mac address to assign to the interface
6909 * @name_assign_type: name assignment type
6910 * @name: User-visible name of the interface
6911 * @session_type: interface type to be created
6912 *
6913 * hdd adapter pointer would point to the netdev->priv space, this function
6914 * would retrieve the pointer, and setup the hdd adapter configuration.
6915 *
6916 * Return: the pointer to hdd adapter, otherwise NULL
6917 */
6918 static struct hdd_adapter *
hdd_alloc_station_adapter(struct hdd_context * hdd_ctx,tSirMacAddr mac_addr,unsigned char name_assign_type,const char * name,uint8_t session_type)6919 hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr,
6920 unsigned char name_assign_type, const char *name,
6921 uint8_t session_type)
6922 {
6923 struct net_device *dev;
6924 struct hdd_adapter *adapter;
6925 QDF_STATUS qdf_status;
6926 uint8_t latency_level;
6927
6928 /* cfg80211 initialization and registration */
6929 dev = alloc_netdev_mqs(sizeof(*adapter), name,
6930 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
6931 name_assign_type,
6932 #endif
6933 ((cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE ||
6934 wlan_hdd_is_session_type_monitor(session_type)) ?
6935 hdd_mon_mode_ether_setup : ether_setup),
6936 NUM_TX_QUEUES, NUM_RX_QUEUES);
6937
6938 if (!dev) {
6939 hdd_err("Failed to allocate new net_device '%s'", name);
6940 return NULL;
6941 }
6942
6943 adapter = netdev_priv(dev);
6944
6945 qdf_mem_zero(adapter, sizeof(*adapter));
6946 adapter->dev = dev;
6947 adapter->deflink = &adapter->link_info[WLAN_HDD_DEFLINK_IDX];
6948 adapter->hdd_ctx = hdd_ctx;
6949 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
6950 qdf_atomic_set_bit(WLAN_HDD_DEFLINK_IDX, &adapter->active_links);
6951
6952 qdf_status = hdd_monitor_mode_qdf_create_event(adapter, session_type);
6953 if (QDF_IS_STATUS_ERROR(qdf_status)) {
6954 hdd_err_rl("create monitor mode vdve up event failed");
6955 goto free_net_dev;
6956 }
6957
6958 hdd_update_dynamic_tsf_sync(adapter);
6959 adapter->is_link_up_service_needed = false;
6960 adapter->send_mode_change = true;
6961
6962 /* Cache station count initialize to zero */
6963 qdf_atomic_init(&adapter->cache_sta_count);
6964
6965 /* Init the net_device structure */
6966 strlcpy(dev->name, name, IFNAMSIZ);
6967
6968 qdf_net_update_net_device_dev_addr(dev, mac_addr, sizeof(tSirMacAddr));
6969 qdf_mem_copy(adapter->mac_addr.bytes, mac_addr, sizeof(tSirMacAddr));
6970 dev->watchdog_timeo = HDD_TX_TIMEOUT;
6971
6972 if (wlan_hdd_is_session_type_monitor(session_type)) {
6973 if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
6974 PACKET_CAPTURE_MODE_DISABLE)
6975 hdd_set_pktcapture_ops(adapter->dev);
6976 if (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) ||
6977 ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc))
6978 hdd_set_mon_ops(adapter->dev);
6979 } else {
6980 hdd_set_station_ops(adapter->dev);
6981 }
6982
6983 hdd_dev_setup_destructor(dev);
6984 dev->ieee80211_ptr = &adapter->wdev;
6985 dev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
6986 adapter->wdev.wiphy = hdd_ctx->wiphy;
6987 adapter->wdev.netdev = dev;
6988 qdf_status = ucfg_mlme_cfg_get_wlm_level(hdd_ctx->psoc, &latency_level);
6989 if (QDF_IS_STATUS_ERROR(qdf_status)) {
6990 hdd_debug("Can't get latency level");
6991 latency_level =
6992 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL;
6993 }
6994 adapter->latency_level = latency_level;
6995 hdd_set_multi_client_ll_support(adapter);
6996
6997 /* set dev's parent to underlying device */
6998 SET_NETDEV_DEV(dev, hdd_ctx->parent_dev);
6999 spin_lock_init(&adapter->pause_map_lock);
7000 adapter->start_time = qdf_system_ticks();
7001 adapter->last_time = adapter->start_time;
7002
7003 qdf_atomic_init(&adapter->is_ll_stats_req_pending);
7004 hdd_init_get_sta_in_ll_stats_config(adapter);
7005 hdd_init_link_state_config(adapter);
7006
7007 return adapter;
7008
7009 free_net_dev:
7010 free_netdev(adapter->dev);
7011
7012 return NULL;
7013 }
7014
7015 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) || \
7016 (defined CFG80211_CHANGE_NETDEV_REGISTRATION_SEMANTICS))
7017 static int
hdd_register_netdevice(struct hdd_adapter * adapter,struct net_device * dev,struct hdd_adapter_create_param * params)7018 hdd_register_netdevice(struct hdd_adapter *adapter, struct net_device *dev,
7019 struct hdd_adapter_create_param *params)
7020 {
7021 int ret;
7022
7023 if (params->is_add_virtual_iface)
7024 ret = wlan_cfg80211_register_netdevice(dev);
7025 else
7026 ret = register_netdevice(dev);
7027
7028 return ret;
7029 }
7030 #else
7031 static int
hdd_register_netdevice(struct hdd_adapter * adapter,struct net_device * dev,struct hdd_adapter_create_param * params)7032 hdd_register_netdevice(struct hdd_adapter *adapter, struct net_device *dev,
7033 struct hdd_adapter_create_param *params)
7034 {
7035 return register_netdevice(dev);
7036 }
7037 #endif
7038
7039 static QDF_STATUS
hdd_register_interface(struct hdd_adapter * adapter,bool rtnl_held,struct hdd_adapter_create_param * params)7040 hdd_register_interface(struct hdd_adapter *adapter, bool rtnl_held,
7041 struct hdd_adapter_create_param *params)
7042 {
7043 struct net_device *dev = adapter->dev;
7044 int ret;
7045
7046 hdd_enter();
7047
7048 if (rtnl_held) {
7049 if (strnchr(dev->name, IFNAMSIZ - 1, '%')) {
7050
7051 ret = dev_alloc_name(dev, dev->name);
7052 if (ret < 0) {
7053 hdd_err(
7054 "unable to get dev name: %s, err = 0x%x",
7055 dev->name, ret);
7056 return QDF_STATUS_E_FAILURE;
7057 }
7058 }
7059 hdd_debug("hdd_register_netdevice(%s) type:%d", dev->name,
7060 adapter->device_mode);
7061 ret = hdd_register_netdevice(adapter, dev, params);
7062 if (ret) {
7063 hdd_err("register_netdevice(%s) failed, err = 0x%x",
7064 dev->name, ret);
7065 return QDF_STATUS_E_FAILURE;
7066 }
7067 } else {
7068 hdd_debug("register_netdev(%s) type:%d", dev->name,
7069 adapter->device_mode);
7070 ret = register_netdev(dev);
7071 if (ret) {
7072 hdd_err("register_netdev(%s) failed, err = 0x%x",
7073 dev->name, ret);
7074 return QDF_STATUS_E_FAILURE;
7075 }
7076 }
7077 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
7078
7079 hdd_exit();
7080
7081 return QDF_STATUS_SUCCESS;
7082 }
7083
hdd_sme_close_session_callback(uint8_t vdev_id)7084 QDF_STATUS hdd_sme_close_session_callback(uint8_t vdev_id)
7085 {
7086 struct hdd_adapter *adapter;
7087 struct hdd_context *hdd_ctx;
7088 struct wlan_hdd_link_info *link_info;
7089
7090 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7091 if (!hdd_ctx)
7092 return QDF_STATUS_E_FAILURE;
7093
7094 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
7095 if (!link_info) {
7096 hdd_err("Invalid vdev %d", vdev_id);
7097 return QDF_STATUS_E_INVAL;
7098 }
7099
7100 adapter = link_info->adapter;
7101 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
7102 hdd_err("Invalid magic");
7103 return QDF_STATUS_NOT_INITIALIZED;
7104 }
7105
7106 clear_bit(SME_SESSION_OPENED, &link_info->link_flags);
7107 qdf_spin_lock_bh(&link_info->vdev_lock);
7108 link_info->vdev_id = WLAN_UMAC_VDEV_ID_MAX;
7109 qdf_spin_unlock_bh(&link_info->vdev_lock);
7110
7111 /*
7112 * We can be blocked while waiting for scheduled work to be
7113 * flushed, and the adapter structure can potentially be freed, in
7114 * which case the magic will have been reset. So make sure the
7115 * magic is still good, and hence the adapter structure is still
7116 * valid, before signaling completion
7117 */
7118 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
7119 complete(&link_info->vdev_destroy_event);
7120
7121 return QDF_STATUS_SUCCESS;
7122 }
7123
hdd_vdev_ready(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * bridgeaddr)7124 int hdd_vdev_ready(struct wlan_objmgr_vdev *vdev,
7125 struct qdf_mac_addr *bridgeaddr)
7126 {
7127 QDF_STATUS status;
7128
7129 status = pmo_vdev_ready(vdev, bridgeaddr);
7130 if (QDF_IS_STATUS_ERROR(status))
7131 return qdf_status_to_os_return(status);
7132
7133 status = ucfg_reg_11d_vdev_created_update(vdev);
7134 if (QDF_IS_STATUS_ERROR(status))
7135 return qdf_status_to_os_return(status);
7136
7137 if (wma_capability_enhanced_mcast_filter())
7138 status = ucfg_pmo_enhanced_mc_filter_enable(vdev);
7139 else
7140 status = ucfg_pmo_enhanced_mc_filter_disable(vdev);
7141
7142 return qdf_status_to_os_return(status);
7143 }
7144
7145 /**
7146 * hdd_check_wait_for_hw_mode_completion - Check hw mode in progress
7147 * @hdd_ctx: hdd context
7148 *
7149 * Check and wait for hw mode response if any hw mode change is
7150 * in progress. Vdev delete will purge the serialization queue
7151 * for the vdev. It will cause issues when the fw event coming
7152 * up later and no active hw mode change req ser command in queue.
7153 *
7154 * Return void
7155 */
hdd_check_wait_for_hw_mode_completion(struct hdd_context * hdd_ctx)7156 static void hdd_check_wait_for_hw_mode_completion(struct hdd_context *hdd_ctx)
7157 {
7158 QDF_STATUS status;
7159
7160 if (!wlan_hdd_validate_context(hdd_ctx) &&
7161 policy_mgr_is_hw_mode_change_in_progress(
7162 hdd_ctx->psoc)) {
7163 status = policy_mgr_wait_for_connection_update(
7164 hdd_ctx->psoc);
7165 if (!QDF_IS_STATUS_SUCCESS(status)) {
7166 hdd_nofl_debug("qdf wait for hw mode event failed!!");
7167 }
7168 }
7169 }
7170
hdd_stop_last_active_connection(struct hdd_context * hdd_ctx,struct wlan_objmgr_vdev * vdev)7171 static void hdd_stop_last_active_connection(struct hdd_context *hdd_ctx,
7172 struct wlan_objmgr_vdev *vdev)
7173 {
7174 enum policy_mgr_con_mode mode;
7175 struct wlan_objmgr_psoc *psoc;
7176 enum QDF_OPMODE op_mode;
7177
7178 /* If this is the last active connection check
7179 * and stop the opportunistic timer.
7180 */
7181 psoc = wlan_vdev_get_psoc(vdev);
7182 op_mode = wlan_vdev_mlme_get_opmode(vdev);
7183 mode = policy_mgr_qdf_opmode_to_pm_con_mode(psoc, op_mode,
7184 wlan_vdev_get_id(vdev));
7185 if ((policy_mgr_get_connection_count(psoc) == 1 &&
7186 policy_mgr_mode_specific_connection_count(psoc,
7187 mode, NULL) == 1) ||
7188 (!policy_mgr_get_connection_count(psoc) &&
7189 !hdd_is_any_sta_connecting(hdd_ctx))) {
7190 policy_mgr_check_and_stop_opportunistic_timer(
7191 psoc,
7192 wlan_vdev_get_id(vdev));
7193 }
7194 }
7195
hdd_vdev_destroy_event_wait(struct hdd_context * hdd_ctx,struct wlan_objmgr_vdev * vdev)7196 static int hdd_vdev_destroy_event_wait(struct hdd_context *hdd_ctx,
7197 struct wlan_objmgr_vdev *vdev)
7198 {
7199 long rc;
7200 QDF_STATUS status;
7201 uint8_t vdev_id;
7202 struct wlan_hdd_link_info *link_info;
7203 struct qdf_mac_addr *mld_addr;
7204 struct wlan_objmgr_psoc *psoc = NULL;
7205
7206 vdev_id = wlan_vdev_get_id(vdev);
7207 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
7208 if (!link_info) {
7209 hdd_err("Invalid vdev");
7210 return -EINVAL;
7211 }
7212
7213 psoc = wlan_vdev_get_psoc(vdev);
7214 if (!psoc) {
7215 obj_mgr_err("Failed to get psoc");
7216 return QDF_STATUS_E_FAILURE;
7217 }
7218
7219 /* Detach DP vdev from DP MLO Device Context */
7220 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
7221
7222 if (!qdf_is_macaddr_zero(mld_addr)) {
7223 /* only for MLO vdev's */
7224
7225 if (cdp_mlo_dev_ctxt_detach(wlan_psoc_get_dp_handle(psoc),
7226 wlan_vdev_get_id(vdev),
7227 (uint8_t *)mld_addr)
7228 != QDF_STATUS_SUCCESS) {
7229 obj_mgr_err("Failed to detach DP vdev from DP MLO Dev ctxt");
7230 QDF_BUG(0);
7231 return QDF_STATUS_E_FAILURE;
7232 }
7233 }
7234
7235 /* close sme session (destroy vdev in firmware via legacy API) */
7236 INIT_COMPLETION(link_info->vdev_destroy_event);
7237 status = sme_vdev_delete(hdd_ctx->mac_handle, vdev);
7238 if (QDF_IS_STATUS_ERROR(status)) {
7239 hdd_err("vdev %d: failed to delete with status:%d",
7240 vdev_id, status);
7241 return -EAGAIN;
7242 }
7243
7244 /* block on a completion variable until sme session is closed */
7245 rc = wait_for_completion_timeout(
7246 &link_info->vdev_destroy_event,
7247 msecs_to_jiffies(SME_CMD_VDEV_CREATE_DELETE_TIMEOUT));
7248 if (!rc) {
7249 hdd_err("vdev %d: timed out waiting for delete", vdev_id);
7250 clear_bit(SME_SESSION_OPENED, &link_info->link_flags);
7251 sme_cleanup_session(hdd_ctx->mac_handle, vdev_id);
7252 cds_flush_logs(WLAN_LOG_TYPE_FATAL,
7253 WLAN_LOG_INDICATOR_HOST_DRIVER,
7254 WLAN_LOG_REASON_VDEV_DELETE_RSP_TIMED_OUT,
7255 true, true);
7256 return -EINVAL;
7257 }
7258
7259 hdd_nofl_info("vdev %d destroyed successfully", vdev_id);
7260 return 0;
7261 }
7262
7263 static inline
hdd_vdev_deinit_components(struct wlan_objmgr_vdev * vdev)7264 void hdd_vdev_deinit_components(struct wlan_objmgr_vdev *vdev)
7265 {
7266 ucfg_pmo_del_wow_pattern(vdev);
7267 ucfg_son_disable_cbs(vdev);
7268 }
7269
7270 static inline
hdd_reset_vdev_info(struct wlan_hdd_link_info * link_info)7271 void hdd_reset_vdev_info(struct wlan_hdd_link_info *link_info)
7272 {
7273 qdf_spin_lock_bh(&link_info->vdev_lock);
7274 link_info->vdev = NULL;
7275 qdf_spin_unlock_bh(&link_info->vdev_lock);
7276 }
7277
hdd_vdev_destroy(struct wlan_hdd_link_info * link_info)7278 int hdd_vdev_destroy(struct wlan_hdd_link_info *link_info)
7279 {
7280 int ret;
7281 uint8_t vdev_id;
7282 struct hdd_context *hdd_ctx;
7283 struct wlan_objmgr_vdev *vdev;
7284 struct wlan_objmgr_psoc *psoc;
7285 enum QDF_OPMODE op_mode;
7286
7287 vdev_id = link_info->vdev_id;
7288 hdd_nofl_debug("destroying vdev %d", vdev_id);
7289 /* vdev created sanity check */
7290 if (!test_bit(SME_SESSION_OPENED, &link_info->link_flags)) {
7291 hdd_nofl_debug("vdev %u does not exist", vdev_id);
7292 return -EINVAL;
7293 }
7294
7295 hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
7296
7297 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
7298 if (!vdev)
7299 return -EINVAL;
7300
7301 psoc = wlan_vdev_get_psoc(vdev);
7302 if (!psoc) {
7303 hdd_err("invalid psoc");
7304 return -EINVAL;
7305 }
7306 op_mode = wlan_vdev_mlme_get_opmode(vdev);
7307
7308 hdd_stop_last_active_connection(hdd_ctx, vdev);
7309 hdd_check_wait_for_hw_mode_completion(hdd_ctx);
7310 ucfg_scan_vdev_set_disable(vdev, REASON_VDEV_DOWN);
7311 wlan_hdd_scan_abort(link_info);
7312 hdd_vdev_deinit_components(vdev);
7313 hdd_mlo_t2lm_unregister_callback(vdev);
7314 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
7315
7316 hdd_reset_vdev_info(link_info);
7317 osif_cm_osif_priv_deinit(vdev);
7318
7319 /* Release the hdd reference */
7320 wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);
7321
7322 /* Get runtime lock to prevent runtime suspend */
7323 qdf_runtime_pm_prevent_suspend(&hdd_ctx->runtime_context.vdev_destroy);
7324
7325 ret = hdd_vdev_destroy_event_wait(hdd_ctx, vdev);
7326
7327 ucfg_reg_11d_vdev_delete_update(psoc, op_mode, vdev_id);
7328
7329 qdf_runtime_pm_allow_suspend(&hdd_ctx->runtime_context.vdev_destroy);
7330 return ret;
7331 }
7332
7333 void
hdd_store_nss_chains_cfg_in_vdev(struct hdd_context * hdd_ctx,struct wlan_objmgr_vdev * vdev)7334 hdd_store_nss_chains_cfg_in_vdev(struct hdd_context *hdd_ctx,
7335 struct wlan_objmgr_vdev *vdev)
7336 {
7337 struct wlan_mlme_nss_chains vdev_ini_cfg;
7338
7339 /* Populate the nss chain params from ini for this vdev type */
7340 sme_populate_nss_chain_params(hdd_ctx->mac_handle, &vdev_ini_cfg,
7341 wlan_vdev_mlme_get_opmode(vdev),
7342 hdd_ctx->num_rf_chains);
7343
7344 /* Store the nss chain config into the vdev */
7345 sme_store_nss_chains_cfg_in_vdev(vdev, &vdev_ini_cfg);
7346 }
7347
hdd_is_vdev_in_conn_state(struct wlan_hdd_link_info * link_info)7348 bool hdd_is_vdev_in_conn_state(struct wlan_hdd_link_info *link_info)
7349 {
7350 switch (link_info->adapter->device_mode) {
7351 case QDF_STA_MODE:
7352 case QDF_P2P_CLIENT_MODE:
7353 case QDF_P2P_DEVICE_MODE:
7354 return hdd_cm_is_vdev_associated(link_info);
7355 case QDF_SAP_MODE:
7356 case QDF_P2P_GO_MODE:
7357 return (test_bit(SOFTAP_BSS_STARTED,
7358 &link_info->link_flags));
7359 default:
7360 hdd_err("Device mode %d invalid",
7361 link_info->adapter->device_mode);
7362 return 0;
7363 }
7364 }
7365
7366 #define MAX_VDEV_RTT_PARAMS 2
7367 /* params being sent:
7368 * wmi_vdev_param_enable_disable_rtt_responder_role
7369 * wmi_vdev_param_enable_disable_rtt_initiator_role
7370 */
7371 static QDF_STATUS
hdd_vdev_configure_rtt_params(struct wlan_objmgr_vdev * vdev)7372 hdd_vdev_configure_rtt_params(struct wlan_objmgr_vdev *vdev)
7373 {
7374 QDF_STATUS status;
7375 struct wlan_objmgr_psoc *psoc;
7376 uint32_t fine_time_meas_cap = 0;
7377 uint8_t vdev_id = wlan_vdev_get_id(vdev);
7378 struct dev_set_param vdevsetparam[MAX_VDEV_RTT_PARAMS] = {};
7379 uint8_t index = 0;
7380 WMI_FW_SUB_FEAT_CAPS wmi_fw_rtt_respr, wmi_fw_rtt_initr;
7381
7382 switch (wlan_vdev_mlme_get_opmode(vdev)) {
7383 case QDF_STA_MODE:
7384 wmi_fw_rtt_respr = WMI_FW_STA_RTT_RESPR;
7385 wmi_fw_rtt_initr = WMI_FW_STA_RTT_INITR;
7386 break;
7387 case QDF_SAP_MODE:
7388 wmi_fw_rtt_respr = WMI_FW_AP_RTT_RESPR;
7389 wmi_fw_rtt_initr = WMI_FW_AP_RTT_INITR;
7390 break;
7391 default:
7392 return QDF_STATUS_SUCCESS;
7393 }
7394
7395 psoc = wlan_vdev_get_psoc(vdev);
7396
7397 ucfg_mlme_get_fine_time_meas_cap(psoc, &fine_time_meas_cap);
7398 status = mlme_check_index_setparam(
7399 vdevsetparam,
7400 wmi_vdev_param_enable_disable_rtt_responder_role,
7401 (fine_time_meas_cap & wmi_fw_rtt_respr), index++,
7402 MAX_VDEV_RTT_PARAMS);
7403 if (QDF_IS_STATUS_ERROR(status))
7404 return status;
7405
7406 status = mlme_check_index_setparam(
7407 vdevsetparam,
7408 wmi_vdev_param_enable_disable_rtt_initiator_role,
7409 (fine_time_meas_cap & wmi_fw_rtt_initr), index++,
7410 MAX_VDEV_RTT_PARAMS);
7411 if (QDF_IS_STATUS_ERROR(status))
7412 return status;
7413
7414 status = sme_send_multi_pdev_vdev_set_params(MLME_VDEV_SETPARAM,
7415 vdev_id, vdevsetparam,
7416 index);
7417 if (QDF_IS_STATUS_ERROR(status))
7418 hdd_err("failed to set RTT_RESPONDER,INITIATOR params:%d",
7419 status);
7420
7421 return status;
7422 }
7423
hdd_store_vdev_info(struct wlan_hdd_link_info * link_info,struct wlan_objmgr_vdev * vdev)7424 static void hdd_store_vdev_info(struct wlan_hdd_link_info *link_info,
7425 struct wlan_objmgr_vdev *vdev)
7426 {
7427 struct vdev_osif_priv *osif_priv;
7428
7429 osif_priv = wlan_vdev_get_ospriv(vdev);
7430 if (osif_priv) {
7431 osif_priv->wdev = link_info->adapter->dev->ieee80211_ptr;
7432 osif_priv->legacy_osif_priv = link_info;
7433 }
7434
7435 qdf_spin_lock_bh(&link_info->vdev_lock);
7436 link_info->vdev_id = wlan_vdev_get_id(vdev);
7437 link_info->vdev = vdev;
7438 qdf_spin_unlock_bh(&link_info->vdev_lock);
7439 }
7440
7441 static void
hdd_init_station_context(struct wlan_hdd_link_info * link_info)7442 hdd_init_station_context(struct wlan_hdd_link_info *link_info)
7443 {
7444 struct hdd_station_ctx *sta_ctx;
7445 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
7446
7447 /* Set the default operation channel freq and auth type to open */
7448 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
7449 sta_ctx->conn_info.chan_freq = hdd_ctx->config->operating_chan_freq;
7450 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
7451 hdd_roam_profile_init(link_info);
7452 }
7453
hdd_vdev_set_ht_vht_ies(mac_handle_t mac_handle,struct wlan_objmgr_vdev * vdev)7454 static void hdd_vdev_set_ht_vht_ies(mac_handle_t mac_handle,
7455 struct wlan_objmgr_vdev *vdev)
7456 {
7457 QDF_STATUS status;
7458 struct wlan_objmgr_psoc *psoc;
7459 bool bval = false;
7460
7461 psoc = wlan_vdev_get_psoc(vdev);
7462 status = ucfg_mlme_get_vht_enable2x2(psoc, &bval);
7463 if (QDF_IS_STATUS_ERROR(status))
7464 hdd_err("unable to get vht_enable2x2");
7465
7466 sme_set_pdev_ht_vht_ies(mac_handle, bval);
7467 sme_set_vdev_ies_per_band(mac_handle, wlan_vdev_get_id(vdev),
7468 wlan_vdev_mlme_get_opmode(vdev));
7469 }
7470
7471 static void
hdd_vdev_configure_rtt_mac_randomization(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)7472 hdd_vdev_configure_rtt_mac_randomization(struct wlan_objmgr_psoc *psoc,
7473 struct wlan_objmgr_vdev *vdev)
7474 {
7475 int errno;
7476 QDF_STATUS status;
7477 bool bval = false;
7478
7479 status = ucfg_mlme_get_rtt_mac_randomization(psoc, &bval);
7480 if (QDF_IS_STATUS_ERROR(status))
7481 hdd_err("unable to get RTT MAC randomization value");
7482
7483 hdd_debug("setting RTT mac randomization param: %d", bval);
7484 errno = sme_cli_set_command(
7485 wlan_vdev_get_id(vdev),
7486 wmi_vdev_param_enable_disable_rtt_initiator_random_mac,
7487 bval, VDEV_CMD);
7488
7489 if (errno)
7490 hdd_err("RTT mac randomization param set failed %d", errno);
7491 }
7492
7493 static void
hdd_vdev_configure_max_tdls_params(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)7494 hdd_vdev_configure_max_tdls_params(struct wlan_objmgr_psoc *psoc,
7495 struct wlan_objmgr_vdev *vdev)
7496 {
7497 uint16_t max_peer_count;
7498 bool target_bigtk_support = false;
7499
7500 /*
7501 * Max peer can be tdls peers + self peer + bss peer +
7502 * temp bss peer for roaming create/delete peer at same time
7503 */
7504 max_peer_count = cfg_tdls_get_max_peer_count(psoc);
7505 max_peer_count += 3;
7506 wlan_vdev_set_max_peer_count(vdev, max_peer_count);
7507
7508 ucfg_mlme_get_bigtk_support(psoc, &target_bigtk_support);
7509 if (target_bigtk_support)
7510 mlme_set_bigtk_support(vdev, true);
7511 }
7512
7513 static inline void
hdd_vdev_configure_nan_params(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)7514 hdd_vdev_configure_nan_params(struct wlan_objmgr_psoc *psoc,
7515 struct wlan_objmgr_vdev *vdev)
7516 {
7517 sme_cli_set_command(
7518 wlan_vdev_get_id(vdev),
7519 wmi_vdev_param_allow_nan_initial_discovery_of_mp0_cluster,
7520 cfg_nan_get_support_mp0_discovery(psoc), VDEV_CMD);
7521 }
7522
7523 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_EXTERNAL_AUTH_MLO_SUPPORT)
7524 static void
hdd_set_vdev_mlo_external_sae_auth_conversion(struct wlan_objmgr_vdev * vdev,enum QDF_OPMODE mode)7525 hdd_set_vdev_mlo_external_sae_auth_conversion(struct wlan_objmgr_vdev *vdev,
7526 enum QDF_OPMODE mode)
7527 {
7528 if (mode == QDF_STA_MODE || mode == QDF_SAP_MODE)
7529 wlan_vdev_set_mlo_external_sae_auth_conversion(vdev, true);
7530 }
7531 #else
7532 static inline void
hdd_set_vdev_mlo_external_sae_auth_conversion(struct wlan_objmgr_vdev * vdev,enum QDF_OPMODE mode)7533 hdd_set_vdev_mlo_external_sae_auth_conversion(struct wlan_objmgr_vdev *vdev,
7534 enum QDF_OPMODE mode)
7535 {
7536 }
7537 #endif
7538
7539 static void
hdd_vdev_configure_rtscts_enable(struct hdd_context * hdd_ctx,struct wlan_objmgr_vdev * vdev)7540 hdd_vdev_configure_rtscts_enable(struct hdd_context *hdd_ctx,
7541 struct wlan_objmgr_vdev *vdev)
7542 {
7543 int ret;
7544 QDF_STATUS status;
7545 uint16_t rts_profile = 0;
7546
7547 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
7548 return;
7549
7550 status = ucfg_fwol_get_rts_profile(hdd_ctx->psoc, &rts_profile);
7551 if (QDF_IS_STATUS_ERROR(status)) {
7552 hdd_err("FAILED TO GET RTSCTS Profile status:%d", status);
7553 return;
7554 }
7555
7556 ret = sme_cli_set_command(wlan_vdev_get_id(vdev),
7557 wmi_vdev_param_enable_rtscts,
7558 rts_profile,
7559 VDEV_CMD);
7560 if (ret)
7561 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
7562 }
7563
7564 static void
hdd_vdev_configure_usr_ps_params(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct wlan_hdd_link_info * link_info)7565 hdd_vdev_configure_usr_ps_params(struct wlan_objmgr_psoc *psoc,
7566 struct wlan_objmgr_vdev *vdev,
7567 struct wlan_hdd_link_info *link_info)
7568 {
7569 struct hdd_adapter *adapter = link_info->adapter;
7570
7571 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE || !adapter)
7572 return;
7573
7574 ucfg_mlme_set_user_ps(psoc, wlan_vdev_get_id(vdev),
7575 adapter->allow_power_save);
7576 }
7577
7578 static void
hdd_vdev_configure_opmode_params(struct hdd_context * hdd_ctx,struct wlan_objmgr_vdev * vdev,struct wlan_hdd_link_info * link_info)7579 hdd_vdev_configure_opmode_params(struct hdd_context *hdd_ctx,
7580 struct wlan_objmgr_vdev *vdev,
7581 struct wlan_hdd_link_info *link_info)
7582 {
7583 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
7584 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev);
7585
7586 switch (opmode) {
7587 case QDF_STA_MODE:
7588 hdd_vdev_configure_rtt_mac_randomization(psoc, vdev);
7589 hdd_vdev_configure_max_tdls_params(psoc, vdev);
7590 hdd_vdev_configure_usr_ps_params(psoc, vdev, link_info);
7591 break;
7592 case QDF_P2P_CLIENT_MODE:
7593 hdd_vdev_configure_max_tdls_params(psoc, vdev);
7594 hdd_vdev_configure_usr_ps_params(psoc, vdev, link_info);
7595 break;
7596 case QDF_NAN_DISC_MODE:
7597 hdd_vdev_configure_nan_params(psoc, vdev);
7598 break;
7599 default:
7600 break;
7601 }
7602
7603 ucfg_fwol_configure_vdev_params(psoc, vdev);
7604 hdd_set_vdev_mlo_external_sae_auth_conversion(vdev, opmode);
7605 hdd_store_nss_chains_cfg_in_vdev(hdd_ctx, vdev);
7606 hdd_vdev_configure_rtscts_enable(hdd_ctx, vdev);
7607 }
7608
7609 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
7610 defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
7611 static int
hdd_populate_vdev_create_params(struct wlan_hdd_link_info * link_info,struct wlan_vdev_create_params * vdev_params)7612 hdd_populate_vdev_create_params(struct wlan_hdd_link_info *link_info,
7613 struct wlan_vdev_create_params *vdev_params)
7614 {
7615 struct hdd_adapter *adapter = link_info->adapter;
7616
7617 vdev_params->opmode = adapter->device_mode;
7618 vdev_params->size_vdev_priv = sizeof(struct vdev_osif_priv);
7619
7620 if (hdd_adapter_is_ml_adapter(adapter)) {
7621 qdf_ether_addr_copy(vdev_params->mldaddr,
7622 adapter->mac_addr.bytes);
7623 qdf_ether_addr_copy(vdev_params->macaddr,
7624 link_info->link_addr.bytes);
7625 } else {
7626 qdf_ether_addr_copy(vdev_params->macaddr,
7627 adapter->mac_addr.bytes);
7628 }
7629 return 0;
7630 }
7631 #elif defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
7632 static int
hdd_populate_vdev_create_params(struct wlan_hdd_link_info * link_info,struct wlan_vdev_create_params * vdev_params)7633 hdd_populate_vdev_create_params(struct wlan_hdd_link_info *link_info,
7634 struct wlan_vdev_create_params *vdev_params)
7635 {
7636 struct hdd_adapter *adapter = link_info->adapter;
7637 struct hdd_mlo_adapter_info *mlo_adapter_info;
7638 struct hdd_adapter *link_adapter;
7639 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7640 bool eht_capab;
7641
7642 hdd_enter_dev(adapter->dev);
7643 mlo_adapter_info = &adapter->mlo_adapter_info;
7644
7645 ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
7646 if (mlo_adapter_info->is_ml_adapter && eht_capab &&
7647 adapter->device_mode == QDF_STA_MODE) {
7648 link_adapter = hdd_get_assoc_link_adapter(adapter);
7649 if (link_adapter) {
7650 qdf_ether_addr_copy(vdev_params->macaddr,
7651 link_adapter->mac_addr.bytes);
7652 } else {
7653 return -EINVAL;
7654 }
7655 } else {
7656 qdf_ether_addr_copy(vdev_params->macaddr,
7657 adapter->mac_addr.bytes);
7658 }
7659
7660 vdev_params->opmode = adapter->device_mode;
7661
7662 if (eht_capab) {
7663 qdf_ether_addr_copy(vdev_params->mldaddr,
7664 adapter->mld_addr.bytes);
7665 }
7666
7667 vdev_params->size_vdev_priv = sizeof(struct vdev_osif_priv);
7668 hdd_exit();
7669
7670 return 0;
7671 }
7672 #else
7673 static int
hdd_populate_vdev_create_params(struct wlan_hdd_link_info * link_info,struct wlan_vdev_create_params * vdev_params)7674 hdd_populate_vdev_create_params(struct wlan_hdd_link_info *link_info,
7675 struct wlan_vdev_create_params *vdev_params)
7676 {
7677 struct hdd_adapter *adapter = link_info->adapter;
7678
7679 vdev_params->opmode = adapter->device_mode;
7680 qdf_ether_addr_copy(vdev_params->macaddr, adapter->mac_addr.bytes);
7681 vdev_params->size_vdev_priv = sizeof(struct vdev_osif_priv);
7682 return 0;
7683 }
7684 #endif
7685
hdd_vdev_create(struct wlan_hdd_link_info * link_info)7686 int hdd_vdev_create(struct wlan_hdd_link_info *link_info)
7687 {
7688 QDF_STATUS status;
7689 int errno = 0;
7690 struct hdd_adapter *adapter = link_info->adapter;
7691 struct hdd_context *hdd_ctx;
7692 struct wlan_objmgr_vdev *vdev;
7693 struct wlan_vdev_create_params vdev_params = {0};
7694
7695 hdd_nofl_debug("creating new vdev");
7696
7697 /* do vdev create via objmgr */
7698 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7699
7700 errno = hdd_populate_vdev_create_params(link_info, &vdev_params);
7701 if (errno)
7702 return errno;
7703
7704 vdev = sme_vdev_create(hdd_ctx->mac_handle, &vdev_params);
7705 if (!vdev) {
7706 hdd_err("failed to create vdev");
7707 return -EINVAL;
7708 }
7709
7710 if (wlan_objmgr_vdev_try_get_ref(vdev, WLAN_HDD_ID_OBJ_MGR) !=
7711 QDF_STATUS_SUCCESS) {
7712 errno = QDF_STATUS_E_INVAL;
7713 sme_vdev_delete(hdd_ctx->mac_handle, vdev);
7714 return -EINVAL;
7715 }
7716
7717 hdd_store_vdev_info(link_info, vdev);
7718 osif_cm_osif_priv_init(vdev);
7719
7720 if (hdd_adapter_is_ml_adapter(adapter))
7721 hdd_mlo_t2lm_register_callback(vdev);
7722
7723 set_bit(SME_SESSION_OPENED, &link_info->link_flags);
7724 status = sme_vdev_post_vdev_create_setup(hdd_ctx->mac_handle, vdev);
7725 if (QDF_IS_STATUS_ERROR(status)) {
7726 hdd_err("Failed to setup the vdev");
7727 errno = qdf_status_to_os_return(status);
7728 goto hdd_vdev_destroy_procedure;
7729 }
7730
7731 /* firmware ready for component communication, raise vdev_ready event */
7732 errno = hdd_vdev_ready(vdev,
7733 (struct qdf_mac_addr *)hdd_ctx->bridgeaddr);
7734 if (errno) {
7735 hdd_err("failed to dispatch vdev ready event: %d", errno);
7736 goto hdd_vdev_destroy_procedure;
7737 }
7738
7739 hdd_vdev_configure_opmode_params(hdd_ctx, vdev, link_info);
7740
7741 hdd_nofl_debug("vdev %d created successfully", link_info->vdev_id);
7742
7743 return errno;
7744
7745 hdd_vdev_destroy_procedure:
7746 QDF_BUG(!hdd_vdev_destroy(link_info));
7747
7748 return errno;
7749 }
7750
hdd_init_station_mode(struct wlan_hdd_link_info * link_info)7751 QDF_STATUS hdd_init_station_mode(struct wlan_hdd_link_info *link_info)
7752 {
7753 struct hdd_adapter *adapter = link_info->adapter;
7754 struct hdd_context *hdd_ctx;
7755 QDF_STATUS status;
7756 mac_handle_t mac_handle;
7757 uint32_t roam_triggers;
7758 struct wlan_objmgr_vdev *vdev;
7759
7760 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7761 mac_handle = hdd_ctx->mac_handle;
7762
7763 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_INIT_DEINIT_ID);
7764 if (!vdev) {
7765 status = QDF_STATUS_E_NULL_VALUE;
7766 goto vdev_destroy;
7767 }
7768
7769 hdd_vdev_set_ht_vht_ies(mac_handle, vdev);
7770 hdd_init_station_context(link_info);
7771
7772 status = hdd_wmm_adapter_init(adapter);
7773 if (QDF_STATUS_SUCCESS != status) {
7774 hdd_err("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
7775 status, status);
7776 goto error_wmm_init;
7777 }
7778 set_bit(WMM_INIT_DONE, &adapter->event_flags);
7779
7780 /* rcpi info initialization */
7781 qdf_mem_zero(&adapter->rcpi, sizeof(adapter->rcpi));
7782
7783 if (adapter->device_mode == QDF_STA_MODE) {
7784 roam_triggers = ucfg_mlme_get_roaming_triggers(hdd_ctx->psoc);
7785 mlme_set_roam_trigger_bitmap(hdd_ctx->psoc,
7786 link_info->vdev_id,
7787 roam_triggers);
7788
7789 status = hdd_vdev_configure_rtt_params(vdev);
7790 if (QDF_IS_STATUS_ERROR(status))
7791 goto error_wmm_init;
7792 }
7793
7794 hdd_tsf_auto_report_init(adapter);
7795 hdd_objmgr_put_vdev_by_user(vdev, WLAN_INIT_DEINIT_ID);
7796
7797 return QDF_STATUS_SUCCESS;
7798
7799 error_wmm_init:
7800 hdd_objmgr_put_vdev_by_user(vdev, WLAN_INIT_DEINIT_ID);
7801
7802 vdev_destroy:
7803 QDF_BUG(!hdd_vdev_destroy(link_info));
7804
7805 return status;
7806 }
7807
net_dev_ref_debug_string_from_id(wlan_net_dev_ref_dbgid dbgid)7808 static char *net_dev_ref_debug_string_from_id(wlan_net_dev_ref_dbgid dbgid)
7809 {
7810 static const char *strings[] = {
7811 "NET_DEV_HOLD_ID_RESERVED",
7812 "NET_DEV_HOLD_GET_STA_CONNECTION_IN_PROGRESS",
7813 "NET_DEV_HOLD_CHECK_DFS_CHANNEL_FOR_ADAPTER",
7814 "NET_DEV_HOLD_GET_SAP_OPERATING_BAND",
7815 "NET_DEV_HOLD_RECOVERY_NOTIFIER_CALL",
7816 "NET_DEV_HOLD_IS_ANY_STA_CONNECTING",
7817 "NET_DEV_HOLD_SAP_DESTROY_CTX_ALL",
7818 "NET_DEV_HOLD_DRV_CMD_MAX_TX_POWER",
7819 "NET_DEV_HOLD_IPA_SET_TX_FLOW_INFO",
7820 "NET_DEV_HOLD_SET_RPS_CPU_MASK",
7821 "NET_DEV_HOLD_DFS_INDICATE_RADAR",
7822 "NET_DEV_HOLD_MAX_STA_INTERFACE_UP_COUNT_REACHED",
7823 "NET_DEV_HOLD_IS_CHAN_SWITCH_IN_PROGRESS",
7824 "NET_DEV_HOLD_STA_DESTROY_CTX_ALL",
7825 "NET_DEV_HOLD_CHECK_FOR_EXISTING_MACADDR",
7826 "NET_DEV_HOLD_DEINIT_ALL_ADAPTERS",
7827 "NET_DEV_HOLD_STOP_ALL_ADAPTERS",
7828 "NET_DEV_HOLD_RESET_ALL_ADAPTERS",
7829 "NET_DEV_HOLD_IS_ANY_INTERFACE_OPEN",
7830 "NET_DEV_HOLD_START_ALL_ADAPTERS",
7831 "NET_DEV_HOLD_GET_ADAPTER_BY_RAND_MACADDR",
7832 "NET_DEV_HOLD_GET_ADAPTER_BY_MACADDR",
7833 "NET_DEV_HOLD_GET_ADAPTER_BY_VDEV",
7834 "NET_DEV_HOLD_ADAPTER_GET_BY_REFERENCE",
7835 "NET_DEV_HOLD_GET_ADAPTER_BY_IFACE_NAME",
7836 "NET_DEV_HOLD_GET_ADAPTER",
7837 "NET_DEV_HOLD_GET_OPERATING_CHAN_FREQ",
7838 "NET_DEV_HOLD_UNREGISTER_WEXT_ALL_ADAPTERS",
7839 "NET_DEV_HOLD_ABORT_MAC_SCAN_ALL_ADAPTERS",
7840 "NET_DEV_HOLD_ABORT_SCHED_SCAN_ALL_ADAPTERS",
7841 "NET_DEV_HOLD_GET_FIRST_VALID_ADAPTER",
7842 "NET_DEV_HOLD_CLEAR_RPS_CPU_MASK",
7843 "NET_DEV_HOLD_BUS_BW_WORK_HANDLER",
7844 "NET_DEV_HOLD_DISPLAY_NETIF_QUEUE_HISTORY_COMPACT",
7845 "NET_DEV_HOLD_DISPLAY_NETIF_QUEUE_HISTORY",
7846 "NET_DEV_HOLD_CLEAR_NETIF_QUEUE_HISTORY",
7847 "NET_DEV_HOLD_UNSAFE_CHANNEL_RESTART_SAP",
7848 "NET_DEV_HOLD_INDICATE_MGMT_FRAME",
7849 "NET_DEV_HOLD_STATE_INFO_DUMP",
7850 "NET_DEV_HOLD_DISABLE_ROAMING",
7851 "NET_DEV_HOLD_ENABLE_ROAMING",
7852 "NET_DEV_HOLD_AUTO_SHUTDOWN_ENABLE",
7853 "NET_DEV_HOLD_GET_CON_SAP_ADAPTER",
7854 "NET_DEV_HOLD_IS_ANY_ADAPTER_CONNECTED",
7855 "NET_DEV_HOLD_IS_ROAMING_IN_PROGRESS",
7856 "NET_DEV_HOLD_DEL_P2P_INTERFACE",
7857 "NET_DEV_HOLD_IS_NDP_ALLOWED",
7858 "NET_DEV_HOLD_NDI_OPEN",
7859 "NET_DEV_HOLD_SEND_OEM_REG_RSP_NLINK_MSG",
7860 "NET_DEV_HOLD_PERIODIC_STA_STATS_DISPLAY",
7861 "NET_DEV_HOLD_SUSPEND_WLAN",
7862 "NET_DEV_HOLD_RESUME_WLAN",
7863 "NET_DEV_HOLD_SSR_RESTART_SAP",
7864 "NET_DEV_HOLD_SEND_DEFAULT_SCAN_IES",
7865 "NET_DEV_HOLD_CFG80211_SUSPEND_WLAN",
7866 "NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_STA",
7867 "NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_SAP",
7868 "NET_DEV_HOLD_CACHE_STATION_STATS_CB",
7869 "NET_DEV_HOLD_DISPLAY_TXRX_STATS",
7870 "NET_DEV_HOLD_START_PRE_CAC_TRANS",
7871 "NET_DEV_HOLD_IS_ANY_STA_CONNECTED",
7872 "NET_DEV_HOLD_GET_ADAPTER_BY_BSSID",
7873 "NET_DEV_HOLD_ALLOW_NEW_INTF",
7874 "NET_DEV_HOLD_ID_MAX"};
7875 int32_t num_dbg_strings = QDF_ARRAY_SIZE(strings);
7876
7877 if (dbgid >= num_dbg_strings) {
7878 char *ret = "";
7879
7880 hdd_err("Debug string not found for debug id %d", dbgid);
7881 return ret;
7882 }
7883
7884 return (char *)strings[dbgid];
7885 }
7886
hdd_check_for_net_dev_ref_leak(struct hdd_adapter * adapter)7887 void hdd_check_for_net_dev_ref_leak(struct hdd_adapter *adapter)
7888 {
7889 int i, id;
7890
7891 for (id = 0; id < NET_DEV_HOLD_ID_MAX; id++) {
7892 for (i = 0; i < MAX_NET_DEV_REF_LEAK_ITERATIONS; i++) {
7893 if (!qdf_atomic_read(
7894 &adapter->net_dev_hold_ref_count[id]))
7895 break;
7896 hdd_info("net_dev held for debug id %s",
7897 net_dev_ref_debug_string_from_id(id));
7898 qdf_sleep(NET_DEV_REF_LEAK_ITERATION_SLEEP_TIME_MS);
7899 }
7900 if (i == MAX_NET_DEV_REF_LEAK_ITERATIONS) {
7901 hdd_err("net_dev hold reference leak detected for debug id: %s",
7902 net_dev_ref_debug_string_from_id(id));
7903 QDF_BUG(0);
7904 }
7905 }
7906 }
7907
7908 /**
7909 * hdd_deinit_station_mode() - De-initialize the station adapter
7910 * @adapter: HDD adapter pointer
7911 *
7912 * This function De-initializes the STA/P2P/OCB adapter.
7913 *
7914 * Return: None.
7915 */
hdd_deinit_station_mode(struct hdd_adapter * adapter)7916 static void hdd_deinit_station_mode(struct hdd_adapter *adapter)
7917 {
7918 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
7919 hdd_wmm_adapter_close(adapter);
7920 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
7921 }
7922 }
7923
hdd_deinit_session(struct hdd_adapter * adapter)7924 void hdd_deinit_session(struct hdd_adapter *adapter)
7925 {
7926 struct wlan_hdd_link_info *link_info;
7927
7928 hdd_enter();
7929
7930 switch (adapter->device_mode) {
7931 case QDF_STA_MODE:
7932 case QDF_P2P_CLIENT_MODE:
7933 case QDF_MONITOR_MODE:
7934 case QDF_P2P_DEVICE_MODE:
7935 case QDF_NDI_MODE:
7936 case QDF_NAN_DISC_MODE:
7937 {
7938 hdd_deinit_station_mode(adapter);
7939 break;
7940 }
7941
7942 case QDF_SAP_MODE:
7943 case QDF_P2P_GO_MODE:
7944 {
7945 hdd_adapter_for_each_active_link_info(adapter, link_info)
7946 hdd_deinit_ap_mode(link_info);
7947 break;
7948 }
7949
7950 default:
7951 break;
7952 }
7953
7954 if (adapter->scan_info.default_scan_ies) {
7955 qdf_mem_free(adapter->scan_info.default_scan_ies);
7956 adapter->scan_info.default_scan_ies = NULL;
7957 adapter->scan_info.default_scan_ies_len = 0;
7958 }
7959
7960 hdd_exit();
7961 }
7962
hdd_deinit_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,bool rtnl_held)7963 void hdd_deinit_adapter(struct hdd_context *hdd_ctx,
7964 struct hdd_adapter *adapter,
7965 bool rtnl_held)
7966 {
7967 hdd_enter_dev(adapter->dev);
7968
7969 hdd_wext_unregister(adapter->dev, rtnl_held);
7970 hdd_deinit_session(adapter);
7971 hdd_exit();
7972 }
7973
7974 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) && \
7975 defined(WLAN_FEATURE_11AX)
7976 /**
7977 * hdd_cleanup_he_operation_info() - cleanup he operation info
7978 * @link_info: pointer to link_info struct in adapter
7979 *
7980 * This function destroys he operation information
7981 *
7982 * Return: none
7983 */
hdd_cleanup_he_operation_info(struct wlan_hdd_link_info * link_info)7984 static void hdd_cleanup_he_operation_info(struct wlan_hdd_link_info *link_info)
7985 {
7986 struct hdd_station_ctx *hdd_sta_ctx;
7987
7988 hdd_debug("cleanup he operation info");
7989
7990 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
7991
7992 if (hdd_sta_ctx->cache_conn_info.he_operation) {
7993 qdf_mem_free(hdd_sta_ctx->cache_conn_info.he_operation);
7994 hdd_sta_ctx->cache_conn_info.he_operation = NULL;
7995 }
7996 }
7997 #else
7998 static inline void
hdd_cleanup_he_operation_info(struct wlan_hdd_link_info * link_info)7999 hdd_cleanup_he_operation_info(struct wlan_hdd_link_info *link_info)
8000 {
8001 }
8002 #endif
8003
8004 /**
8005 * hdd_cleanup_prev_ap_bcn_ie() - cleanup previous ap beacon ie
8006 * @link_info: pointer to link_info struct in adapter
8007 *
8008 * This function destroys previous ap beacon information
8009 *
8010 * Return: none
8011 */
hdd_cleanup_prev_ap_bcn_ie(struct wlan_hdd_link_info * link_info)8012 static void hdd_cleanup_prev_ap_bcn_ie(struct wlan_hdd_link_info *link_info)
8013 {
8014 struct hdd_station_ctx *hdd_sta_ctx;
8015 struct element_info *bcn_ie;
8016
8017 hdd_debug("cleanup previous ap bcn ie");
8018
8019 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
8020 bcn_ie = &hdd_sta_ctx->conn_info.prev_ap_bcn_ie;
8021
8022 if (bcn_ie->ptr) {
8023 qdf_mem_free(bcn_ie->ptr);
8024 bcn_ie->ptr = NULL;
8025 bcn_ie->len = 0;
8026 }
8027 }
8028
hdd_cleanup_conn_info(struct wlan_hdd_link_info * link_info)8029 void hdd_cleanup_conn_info(struct wlan_hdd_link_info *link_info)
8030 {
8031 hdd_cleanup_he_operation_info(link_info);
8032 hdd_cleanup_prev_ap_bcn_ie(link_info);
8033 }
8034
8035 /**
8036 * hdd_sta_destroy_ctx_all() - cleanup all station contexts
8037 * @hdd_ctx: Global HDD context
8038 *
8039 * This function destroys all the station contexts
8040 *
8041 * Return: none
8042 */
hdd_sta_destroy_ctx_all(struct hdd_context * hdd_ctx)8043 static void hdd_sta_destroy_ctx_all(struct hdd_context *hdd_ctx)
8044 {
8045 struct hdd_adapter *adapter, *next_adapter = NULL;
8046 struct wlan_hdd_link_info *link_info;
8047
8048 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
8049 NET_DEV_HOLD_STA_DESTROY_CTX_ALL) {
8050 if (adapter->device_mode == QDF_STA_MODE) {
8051 hdd_adapter_for_each_link_info(adapter, link_info) {
8052 hdd_cleanup_conn_info(link_info);
8053 }
8054 }
8055 hdd_adapter_dev_put_debug(adapter,
8056 NET_DEV_HOLD_STA_DESTROY_CTX_ALL);
8057 }
8058 }
8059
8060 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) || \
8061 (defined CFG80211_CHANGE_NETDEV_REGISTRATION_SEMANTICS))
8062 static void
hdd_unregister_netdevice(struct hdd_adapter * adapter,struct net_device * dev)8063 hdd_unregister_netdevice(struct hdd_adapter *adapter, struct net_device *dev)
8064 {
8065 if (adapter->is_virtual_iface) {
8066 wlan_cfg80211_unregister_netdevice(dev);
8067 adapter->is_virtual_iface = false;
8068 } else {
8069 unregister_netdevice(dev);
8070 }
8071 }
8072 #else
8073 static void
hdd_unregister_netdevice(struct hdd_adapter * adapter,struct net_device * dev)8074 hdd_unregister_netdevice(struct hdd_adapter *adapter, struct net_device *dev)
8075 {
8076 unregister_netdevice(dev);
8077 }
8078 #endif
8079
hdd_adapter_destroy_vdev_info(struct hdd_adapter * adapter)8080 static inline void hdd_adapter_destroy_vdev_info(struct hdd_adapter *adapter)
8081 {
8082 struct wlan_hdd_link_info *link_info;
8083
8084 hdd_adapter_for_each_link_info(adapter, link_info) {
8085 qdf_event_destroy(&link_info->acs_complete_event);
8086 qdf_spinlock_destroy(&link_info->vdev_lock);
8087 }
8088 }
8089
hdd_cleanup_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,bool rtnl_held)8090 static void hdd_cleanup_adapter(struct hdd_context *hdd_ctx,
8091 struct hdd_adapter *adapter,
8092 bool rtnl_held)
8093 {
8094 struct net_device *dev = NULL;
8095
8096 if (adapter)
8097 dev = adapter->dev;
8098 else {
8099 hdd_err("adapter is Null");
8100 return;
8101 }
8102
8103 hdd_apf_context_destroy(adapter);
8104 qdf_spinlock_destroy(&adapter->mc_list_lock);
8105 hdd_adapter_destroy_vdev_info(adapter);
8106 hdd_sta_info_deinit(&adapter->sta_info_list);
8107 hdd_sta_info_deinit(&adapter->cache_sta_info_list);
8108
8109 wlan_hdd_debugfs_csr_deinit(adapter);
8110
8111 hdd_debugfs_exit(adapter);
8112
8113 /*
8114 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
8115 * the driver is almost closed and cannot handle either control
8116 * messages or data. However, unregister_netdevice() call above will
8117 * eventually invoke hdd_stop(ndo_close) driver callback, which attempts
8118 * to close the active connections(basically excites control path) which
8119 * is not right. Setting this flag helps hdd_stop() to recognize that
8120 * the interface is closed and restricts any operations on that
8121 */
8122 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
8123
8124 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
8125 if (rtnl_held) {
8126 hdd_debug("hdd_unregister_netdevice(%s) type:%d",
8127 dev->name, adapter->device_mode);
8128 hdd_unregister_netdevice(adapter, dev);
8129 } else {
8130 hdd_debug("unregister_netdev(%s) type:%d", dev->name,
8131 adapter->device_mode);
8132 unregister_netdev(dev);
8133 }
8134 /*
8135 * Note that the adapter is no longer valid at this point
8136 * since the memory has been reclaimed
8137 */
8138 }
8139 }
8140
hdd_check_for_existing_macaddr(struct hdd_context * hdd_ctx,tSirMacAddr mac_addr)8141 static QDF_STATUS hdd_check_for_existing_macaddr(struct hdd_context *hdd_ctx,
8142 tSirMacAddr mac_addr)
8143 {
8144 struct hdd_adapter *adapter, *next_adapter = NULL;
8145 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_CHECK_FOR_EXISTING_MACADDR;
8146
8147 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
8148 dbgid) {
8149 if (!qdf_mem_cmp(adapter->mac_addr.bytes,
8150 mac_addr, sizeof(tSirMacAddr))) {
8151 hdd_adapter_dev_put_debug(adapter, dbgid);
8152 if (next_adapter)
8153 hdd_adapter_dev_put_debug(next_adapter,
8154 dbgid);
8155 return QDF_STATUS_E_FAILURE;
8156 }
8157 hdd_adapter_dev_put_debug(adapter, dbgid);
8158 }
8159
8160 return QDF_STATUS_SUCCESS;
8161 }
8162
8163 /**
8164 * hdd_configure_chain_mask() - programs chain mask to firmware
8165 * @adapter: HDD adapter
8166 *
8167 * Return: 0 on success or errno on failure
8168 */
hdd_configure_chain_mask(struct hdd_adapter * adapter)8169 static int hdd_configure_chain_mask(struct hdd_adapter *adapter)
8170 {
8171 QDF_STATUS status;
8172 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8173
8174 status = ucfg_mlme_configure_chain_mask(hdd_ctx->psoc,
8175 adapter->deflink->vdev_id);
8176 if (QDF_IS_STATUS_ERROR(status))
8177 goto error;
8178
8179 return 0;
8180
8181 error:
8182 hdd_debug("WMI PDEV set param failed");
8183 return -EINVAL;
8184 }
8185
hdd_adapter_update_mlo_mgr_mac_addr(struct hdd_adapter * adapter)8186 void hdd_adapter_update_mlo_mgr_mac_addr(struct hdd_adapter *adapter)
8187 {
8188 int i = 0;
8189 struct wlan_hdd_link_info *link_info;
8190 struct wlan_mlo_link_mac_update link_mac = {0};
8191
8192 if (!hdd_adapter_is_ml_adapter(adapter))
8193 return;
8194
8195 hdd_adapter_for_each_link_info(adapter, link_info) {
8196 link_mac.link_mac_info[i].vdev_id = link_info->vdev_id;
8197 qdf_copy_macaddr(&link_mac.link_mac_info[i++].link_mac_addr,
8198 &link_info->link_addr);
8199 }
8200
8201 link_mac.num_mac_update = i;
8202 mlo_mgr_update_link_info_mac_addr(adapter->deflink->vdev, &link_mac);
8203 }
8204
8205 #ifdef FEATURE_COEX
8206 /**
8207 * hdd_send_coex_config_params() - Send coex config params to FW
8208 * @hdd_ctx: HDD context
8209 * @adapter: Primary adapter context
8210 *
8211 * This function is used to send all coex config related params to FW
8212 *
8213 * Return: 0 on success and -EINVAL on failure
8214 */
hdd_send_coex_config_params(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)8215 static int hdd_send_coex_config_params(struct hdd_context *hdd_ctx,
8216 struct hdd_adapter *adapter)
8217 {
8218 struct wlan_objmgr_vdev *vdev;
8219 struct coex_config_params coex_cfg_params = {0};
8220 struct coex_multi_config *coex_multi_cfg = NULL;
8221 struct wlan_fwol_coex_config config = {0};
8222 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
8223 enum coex_btc_chain_mode btc_chain_mode;
8224 QDF_STATUS status;
8225 uint32_t i = 0;
8226
8227 if (!adapter) {
8228 hdd_err("adapter is invalid");
8229 goto err;
8230 }
8231
8232 if (!psoc) {
8233 hdd_err("HDD psoc is invalid");
8234 goto err;
8235 }
8236
8237 status = ucfg_fwol_get_coex_config_params(psoc, &config);
8238 if (QDF_IS_STATUS_ERROR(status)) {
8239 hdd_err("Unable to get coex config params");
8240 goto err;
8241 }
8242
8243 coex_multi_cfg = qdf_mem_malloc(sizeof(*coex_multi_cfg));
8244 if (!coex_multi_cfg)
8245 goto err;
8246
8247 coex_multi_cfg->vdev_id = adapter->deflink->vdev_id;
8248
8249 coex_multi_cfg->cfg_items[i].config_type = WMI_COEX_CONFIG_TX_POWER;
8250 coex_multi_cfg->cfg_items[i].config_arg1 = config.max_tx_power_for_btc;
8251
8252 wma_nofl_debug("TXP[W][send_coex_cfg]: %d",
8253 config.max_tx_power_for_btc);
8254
8255 if (++i > COEX_MULTI_CONFIG_MAX_CNT)
8256 goto err;
8257
8258 coex_multi_cfg->cfg_items[i].config_type =
8259 WMI_COEX_CONFIG_HANDOVER_RSSI;
8260 coex_multi_cfg->cfg_items[i].config_arg1 =
8261 config.wlan_low_rssi_threshold;
8262
8263 if (++i > COEX_MULTI_CONFIG_MAX_CNT)
8264 goto err;
8265
8266 coex_multi_cfg->cfg_items[i].config_type = WMI_COEX_CONFIG_BTC_MODE;
8267
8268 /* Modify BTC_MODE according to BTC_CHAIN_MODE */
8269 status = ucfg_coex_psoc_get_btc_chain_mode(psoc, &btc_chain_mode);
8270 if (QDF_IS_STATUS_ERROR(status)) {
8271 hdd_err("Failed to get btc chain mode");
8272 btc_chain_mode = WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED;
8273 }
8274
8275 if (btc_chain_mode <= WLAN_COEX_BTC_CHAIN_MODE_HYBRID)
8276 coex_multi_cfg->cfg_items[i].config_arg1 = btc_chain_mode;
8277 else
8278 coex_multi_cfg->cfg_items[i].config_arg1 = config.btc_mode;
8279
8280 hdd_debug("Configured BTC mode is %d, BTC chain mode is 0x%x, set BTC mode to %d",
8281 config.btc_mode, btc_chain_mode,
8282 coex_multi_cfg->cfg_items[i].config_arg1);
8283
8284 if (++i > COEX_MULTI_CONFIG_MAX_CNT)
8285 goto err;
8286
8287 coex_multi_cfg->cfg_items[i].config_type =
8288 WMI_COEX_CONFIG_ANTENNA_ISOLATION;
8289 coex_multi_cfg->cfg_items[i].config_arg1 = config.antenna_isolation;
8290 if (++i > COEX_MULTI_CONFIG_MAX_CNT)
8291 goto err;
8292
8293 coex_multi_cfg->cfg_items[i].config_type =
8294 WMI_COEX_CONFIG_BT_LOW_RSSI_THRESHOLD;
8295 coex_multi_cfg->cfg_items[i].config_arg1 = config.bt_low_rssi_threshold;
8296
8297 if (++i > COEX_MULTI_CONFIG_MAX_CNT)
8298 goto err;
8299
8300 coex_multi_cfg->cfg_items[i].config_type =
8301 WMI_COEX_CONFIG_BT_INTERFERENCE_LEVEL;
8302 coex_multi_cfg->cfg_items[i].config_arg1 =
8303 config.bt_interference_low_ll;
8304 coex_multi_cfg->cfg_items[i].config_arg2 =
8305 config.bt_interference_low_ul;
8306 coex_multi_cfg->cfg_items[i].config_arg3 =
8307 config.bt_interference_medium_ll;
8308 coex_multi_cfg->cfg_items[i].config_arg4 =
8309 config.bt_interference_medium_ul;
8310 coex_multi_cfg->cfg_items[i].config_arg5 =
8311 config.bt_interference_high_ll;
8312 coex_multi_cfg->cfg_items[i].config_arg6 =
8313 config.bt_interference_high_ul;
8314
8315 if (++i > COEX_MULTI_CONFIG_MAX_CNT)
8316 goto err;
8317
8318 if (wlan_hdd_mpta_helper_enable(&coex_cfg_params, &config))
8319 goto err;
8320
8321 coex_multi_cfg->cfg_items[i].config_type =
8322 WMI_COEX_CONFIG_BT_SCO_ALLOW_WLAN_2G_SCAN;
8323 coex_multi_cfg->cfg_items[i].config_arg1 =
8324 config.bt_sco_allow_wlan_2g_scan;
8325
8326 if (++i > COEX_MULTI_CONFIG_MAX_CNT)
8327 goto err;
8328
8329 coex_multi_cfg->cfg_items[i].config_type =
8330 WMI_COEX_CONFIG_LE_SCAN_POLICY;
8331 coex_multi_cfg->cfg_items[i].config_arg1 = config.ble_scan_coex_policy;
8332
8333 if (++i > COEX_MULTI_CONFIG_MAX_CNT)
8334 goto err;
8335
8336 #ifdef FEATURE_COEX_TPUT_SHAPING_CONFIG
8337 coex_multi_cfg->cfg_items[i].config_type =
8338 WMI_COEX_CONFIG_ENABLE_TPUT_SHAPING;
8339 coex_multi_cfg->cfg_items[i].config_arg1 =
8340 config.coex_tput_shaping_enable;
8341
8342 if (++i > COEX_MULTI_CONFIG_MAX_CNT)
8343 goto err;
8344 #endif
8345
8346 coex_multi_cfg->num_configs = i;
8347
8348 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_COEX_ID);
8349 if (!vdev) {
8350 hdd_err("vdev is null");
8351 goto err;
8352 }
8353
8354 ucfg_coex_send_multi_config(vdev, coex_multi_cfg);
8355
8356 hdd_objmgr_put_vdev_by_user(vdev, WLAN_COEX_ID);
8357 qdf_mem_free(coex_multi_cfg);
8358
8359 return 0;
8360 err:
8361 qdf_mem_free(coex_multi_cfg);
8362 return -EINVAL;
8363 }
8364 #else
8365 /**
8366 * hdd_send_coex_config_params() - Send coex config params to FW
8367 * @hdd_ctx: HDD context
8368 * @adapter: Primary adapter context
8369 *
8370 * This function is used to send all coex config related params to FW
8371 *
8372 * Return: 0 on success and -EINVAL on failure
8373 */
hdd_send_coex_config_params(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)8374 static int hdd_send_coex_config_params(struct hdd_context *hdd_ctx,
8375 struct hdd_adapter *adapter)
8376 {
8377 struct coex_config_params coex_cfg_params = {0};
8378 struct wlan_fwol_coex_config config = {0};
8379 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
8380 enum coex_btc_chain_mode btc_chain_mode;
8381 QDF_STATUS status;
8382
8383 if (!adapter) {
8384 hdd_err("adapter is invalid");
8385 goto err;
8386 }
8387
8388 if (!psoc) {
8389 hdd_err("HDD psoc is invalid");
8390 goto err;
8391 }
8392
8393 status = ucfg_fwol_get_coex_config_params(psoc, &config);
8394 if (QDF_IS_STATUS_ERROR(status)) {
8395 hdd_err("Unable to get coex config params");
8396 goto err;
8397 }
8398
8399 coex_cfg_params.vdev_id = adapter->deflink->vdev_id;
8400 coex_cfg_params.config_type = WMI_COEX_CONFIG_TX_POWER;
8401 coex_cfg_params.config_arg1 = config.max_tx_power_for_btc;
8402
8403 wma_nofl_debug("TXP[W][send_coex_cfg]: %d",
8404 config.max_tx_power_for_btc);
8405
8406 status = sme_send_coex_config_cmd(&coex_cfg_params);
8407 if (QDF_IS_STATUS_ERROR(status)) {
8408 hdd_err("Failed to send coex Tx power");
8409 goto err;
8410 }
8411
8412 coex_cfg_params.config_type = WMI_COEX_CONFIG_HANDOVER_RSSI;
8413 coex_cfg_params.config_arg1 = config.wlan_low_rssi_threshold;
8414
8415 status = sme_send_coex_config_cmd(&coex_cfg_params);
8416 if (QDF_IS_STATUS_ERROR(status)) {
8417 hdd_err("Failed to send coex handover RSSI");
8418 goto err;
8419 }
8420
8421 coex_cfg_params.config_type = WMI_COEX_CONFIG_BTC_MODE;
8422
8423 /* Modify BTC_MODE according to BTC_CHAIN_MODE */
8424 status = ucfg_coex_psoc_get_btc_chain_mode(psoc, &btc_chain_mode);
8425 if (QDF_IS_STATUS_ERROR(status)) {
8426 hdd_err("Failed to get btc chain mode");
8427 btc_chain_mode = WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED;
8428 }
8429
8430 if (btc_chain_mode <= WLAN_COEX_BTC_CHAIN_MODE_HYBRID)
8431 coex_cfg_params.config_arg1 = btc_chain_mode;
8432 else
8433 coex_cfg_params.config_arg1 = config.btc_mode;
8434
8435 hdd_debug("Configured BTC mode is %d, BTC chain mode is 0x%x, set BTC mode to %d",
8436 config.btc_mode, btc_chain_mode,
8437 coex_cfg_params.config_arg1);
8438 status = sme_send_coex_config_cmd(&coex_cfg_params);
8439 if (QDF_IS_STATUS_ERROR(status)) {
8440 hdd_err("Failed to send coex BTC mode");
8441 goto err;
8442 }
8443
8444 coex_cfg_params.config_type = WMI_COEX_CONFIG_ANTENNA_ISOLATION;
8445 coex_cfg_params.config_arg1 = config.antenna_isolation;
8446
8447 status = sme_send_coex_config_cmd(&coex_cfg_params);
8448 if (QDF_IS_STATUS_ERROR(status)) {
8449 hdd_err("Failed to send coex antenna isolation");
8450 goto err;
8451 }
8452
8453 coex_cfg_params.config_type = WMI_COEX_CONFIG_BT_LOW_RSSI_THRESHOLD;
8454 coex_cfg_params.config_arg1 = config.bt_low_rssi_threshold;
8455
8456 status = sme_send_coex_config_cmd(&coex_cfg_params);
8457 if (QDF_IS_STATUS_ERROR(status)) {
8458 hdd_err("Failed to send coex BT low RSSI threshold");
8459 goto err;
8460 }
8461
8462 coex_cfg_params.config_type = WMI_COEX_CONFIG_BT_INTERFERENCE_LEVEL;
8463 coex_cfg_params.config_arg1 = config.bt_interference_low_ll;
8464 coex_cfg_params.config_arg2 = config.bt_interference_low_ul;
8465 coex_cfg_params.config_arg3 = config.bt_interference_medium_ll;
8466 coex_cfg_params.config_arg4 = config.bt_interference_medium_ul;
8467 coex_cfg_params.config_arg5 = config.bt_interference_high_ll;
8468 coex_cfg_params.config_arg6 = config.bt_interference_high_ul;
8469
8470 status = sme_send_coex_config_cmd(&coex_cfg_params);
8471 if (QDF_IS_STATUS_ERROR(status)) {
8472 hdd_err("Failed to send coex BT interference level");
8473 goto err;
8474 }
8475
8476 if (wlan_hdd_mpta_helper_enable(&coex_cfg_params, &config))
8477 goto err;
8478
8479 coex_cfg_params.config_type =
8480 WMI_COEX_CONFIG_BT_SCO_ALLOW_WLAN_2G_SCAN;
8481 coex_cfg_params.config_arg1 = config.bt_sco_allow_wlan_2g_scan;
8482
8483 status = sme_send_coex_config_cmd(&coex_cfg_params);
8484 if (QDF_IS_STATUS_ERROR(status)) {
8485 hdd_err("Failed to send coex BT sco allow wlan 2g scan");
8486 goto err;
8487 }
8488
8489 coex_cfg_params.config_type =
8490 WMI_COEX_CONFIG_LE_SCAN_POLICY;
8491 coex_cfg_params.config_arg1 = config.ble_scan_coex_policy;
8492
8493 status = sme_send_coex_config_cmd(&coex_cfg_params);
8494 if (QDF_IS_STATUS_ERROR(status)) {
8495 hdd_err("Failed to send coex BLE scan policy");
8496 goto err;
8497 }
8498
8499 #ifdef FEATURE_COEX_TPUT_SHAPING_CONFIG
8500 coex_cfg_params.config_type =
8501 WMI_COEX_CONFIG_ENABLE_TPUT_SHAPING;
8502 coex_cfg_params.config_arg1 = config.coex_tput_shaping_enable;
8503
8504 status = sme_send_coex_config_cmd(&coex_cfg_params);
8505 if (QDF_IS_STATUS_ERROR(status)) {
8506 hdd_err("Failed to send coex traffic shaping value %d",
8507 coex_cfg_params.config_arg1);
8508 goto err;
8509 }
8510 #endif
8511 return 0;
8512 err:
8513 return -EINVAL;
8514 }
8515 #endif
8516
8517 /**
8518 * hdd_send_coex_traffic_shaping_mode() - Send coex traffic shaping mode
8519 * to FW
8520 * @vdev_id: vdev ID
8521 * @mode: traffic shaping mode
8522 *
8523 * This function is used to send coex traffic shaping mode to FW
8524 *
8525 * Return: 0 on success and -EINVAL on failure
8526 */
hdd_send_coex_traffic_shaping_mode(uint8_t vdev_id,uint8_t mode)8527 int hdd_send_coex_traffic_shaping_mode(uint8_t vdev_id, uint8_t mode)
8528 {
8529 struct coex_config_params coex_cfg_params = {0};
8530
8531 coex_cfg_params.config_type = WMI_COEX_SET_TRAFFIC_SHAPING_MODE;
8532 coex_cfg_params.config_arg1 = mode;
8533 coex_cfg_params.vdev_id = vdev_id;
8534
8535 if (QDF_IS_STATUS_ERROR(sme_send_coex_config_cmd(&coex_cfg_params))) {
8536 hdd_err_rl("Failed to send coex traffic shaping mode");
8537 return -EINVAL;
8538 }
8539 return 0;
8540 }
8541
8542 #define MAX_PDEV_SET_FW_PARAMS 7
8543 /* params being sent:
8544 * 1.wmi_pdev_param_dtim_synth
8545 * 2.wmi_pdev_param_1ch_dtim_optimized_chain_selection
8546 * 3.wmi_pdev_param_tx_sch_delay
8547 * 4.wmi_pdev_param_en_update_scram_seed
8548 * 5.wmi_pdev_param_secondary_retry_enable
8549 * 6.wmi_pdev_param_set_sap_xlna_bypass
8550 * 7.wmi_pdev_param_set_dfs_chan_ageout_time
8551 */
8552
8553 /**
8554 * hdd_set_fw_params() - Set parameters to firmware
8555 * @adapter: HDD adapter
8556 *
8557 * This function Sets various parameters to fw once the
8558 * adapter is started.
8559 *
8560 * Return: 0 on success or errno on failure
8561 */
hdd_set_fw_params(struct hdd_adapter * adapter)8562 int hdd_set_fw_params(struct hdd_adapter *adapter)
8563 {
8564 int ret;
8565 uint16_t upper_brssi_thresh, lower_brssi_thresh;
8566 bool enable_dtim_1chrx;
8567 QDF_STATUS status;
8568 struct hdd_context *hdd_ctx;
8569 bool is_lprx_enabled;
8570 bool bval = false;
8571 uint8_t enable_tx_sch_delay, dfs_chan_ageout_time;
8572 uint32_t dtim_sel_diversity, enable_secondary_rate;
8573 bool sap_xlna_bypass;
8574 bool enable_ofdm_scrambler_seed = false;
8575 struct dev_set_param setparam[MAX_PDEV_SET_FW_PARAMS] = { };
8576 uint8_t index = 0;
8577
8578 hdd_enter_dev(adapter->dev);
8579
8580 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8581 if (!hdd_ctx)
8582 return -EINVAL;
8583
8584 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8585 hdd_debug("FTM Mode is active; nothing to do");
8586 return 0;
8587 }
8588
8589 /* The ini gEnableLPRx is deprecated. By default, the ini
8590 * is enabled. So, making the variable is_lprx_enabled true.
8591 */
8592 is_lprx_enabled = true;
8593
8594 ret = mlme_check_index_setparam(setparam, wmi_pdev_param_dtim_synth,
8595 is_lprx_enabled, index++,
8596 MAX_PDEV_SET_FW_PARAMS);
8597 if (QDF_IS_STATUS_ERROR(ret))
8598 goto error;
8599
8600 ucfg_mlme_get_dtim_selection_diversity(hdd_ctx->psoc,
8601 &dtim_sel_diversity);
8602 ret = mlme_check_index_setparam(
8603 setparam,
8604 wmi_pdev_param_1ch_dtim_optimized_chain_selection,
8605 dtim_sel_diversity, index++, MAX_PDEV_SET_FW_PARAMS);
8606 if (QDF_IS_STATUS_ERROR(ret))
8607 goto error;
8608
8609 if (QDF_IS_STATUS_SUCCESS(ucfg_fwol_get_enable_tx_sch_delay(
8610 hdd_ctx->psoc, &enable_tx_sch_delay))) {
8611 ret = mlme_check_index_setparam(
8612 setparam,
8613 wmi_pdev_param_tx_sch_delay,
8614 enable_tx_sch_delay, index++,
8615 MAX_PDEV_SET_FW_PARAMS);
8616 if (QDF_IS_STATUS_ERROR(ret))
8617 goto error;
8618 }
8619
8620 if (QDF_IS_STATUS_SUCCESS(ucfg_fwol_get_ofdm_scrambler_seed(
8621 hdd_ctx->psoc, &enable_ofdm_scrambler_seed))) {
8622 ret = mlme_check_index_setparam(
8623 setparam,
8624 wmi_pdev_param_en_update_scram_seed,
8625 enable_ofdm_scrambler_seed, index++,
8626 MAX_PDEV_SET_FW_PARAMS);
8627 if (QDF_IS_STATUS_ERROR(ret))
8628 goto error;
8629 }
8630
8631 if (QDF_IS_STATUS_SUCCESS(ucfg_fwol_get_enable_secondary_rate(
8632 hdd_ctx->psoc, &enable_secondary_rate))) {
8633 ret = mlme_check_index_setparam(
8634 setparam,
8635 wmi_pdev_param_secondary_retry_enable,
8636 enable_secondary_rate, index++,
8637 MAX_PDEV_SET_FW_PARAMS);
8638 if (QDF_IS_STATUS_ERROR(ret))
8639 goto error;
8640 }
8641 if (QDF_IS_STATUS_SUCCESS(ucfg_fwol_get_sap_xlna_bypass(
8642 hdd_ctx->psoc, &sap_xlna_bypass))) {
8643 ret = mlme_check_index_setparam(
8644 setparam,
8645 wmi_pdev_param_set_sap_xlna_bypass,
8646 sap_xlna_bypass, index++,
8647 MAX_PDEV_SET_FW_PARAMS);
8648 if (QDF_IS_STATUS_ERROR(ret))
8649 goto error;
8650 }
8651 wlan_mlme_get_dfs_chan_ageout_time(hdd_ctx->psoc,
8652 &dfs_chan_ageout_time);
8653 ret = mlme_check_index_setparam(
8654 setparam,
8655 wmi_pdev_param_set_dfs_chan_ageout_time,
8656 dfs_chan_ageout_time, index++,
8657 MAX_PDEV_SET_FW_PARAMS);
8658 if (QDF_IS_STATUS_ERROR(ret))
8659 goto error;
8660
8661 ret = sme_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
8662 WMI_PDEV_ID_SOC, setparam,
8663 index);
8664 if (QDF_IS_STATUS_ERROR(ret)) {
8665 goto error;
8666 }
8667 if (adapter->device_mode == QDF_STA_MODE) {
8668 status = ucfg_get_upper_brssi_thresh(hdd_ctx->psoc,
8669 &upper_brssi_thresh);
8670 if (QDF_IS_STATUS_ERROR(status))
8671 return -EINVAL;
8672
8673 sme_set_smps_cfg(adapter->deflink->vdev_id,
8674 HDD_STA_SMPS_PARAM_UPPER_BRSSI_THRESH,
8675 upper_brssi_thresh);
8676
8677 status = ucfg_get_lower_brssi_thresh(hdd_ctx->psoc,
8678 &lower_brssi_thresh);
8679 if (QDF_IS_STATUS_ERROR(status))
8680 return -EINVAL;
8681
8682 sme_set_smps_cfg(adapter->deflink->vdev_id,
8683 HDD_STA_SMPS_PARAM_LOWER_BRSSI_THRESH,
8684 lower_brssi_thresh);
8685
8686 status = ucfg_get_enable_dtim_1chrx(hdd_ctx->psoc,
8687 &enable_dtim_1chrx);
8688 if (QDF_IS_STATUS_ERROR(status))
8689 return -EINVAL;
8690
8691 sme_set_smps_cfg(adapter->deflink->vdev_id,
8692 HDD_STA_SMPS_PARAM_DTIM_1CHRX_ENABLE,
8693 enable_dtim_1chrx);
8694 }
8695
8696 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval);
8697 if (!QDF_IS_STATUS_SUCCESS(status))
8698 hdd_err("unable to get vht_enable2x2");
8699
8700 if (bval) {
8701 hdd_debug("configuring 2x2 mode fw params");
8702
8703 ret = sme_set_cck_tx_fir_override(hdd_ctx->mac_handle,
8704 adapter->deflink->vdev_id);
8705 if (ret) {
8706 hdd_err("wmi_pdev_param_enable_cck_tfir_override set failed %d",
8707 ret);
8708 goto error;
8709 }
8710
8711 hdd_configure_chain_mask(adapter);
8712 } else {
8713 #define HDD_DTIM_1CHAIN_RX_ID 0x5
8714 #define HDD_SMPS_PARAM_VALUE_S 29
8715 hdd_debug("configuring 1x1 mode fw params");
8716
8717 /*
8718 * Disable DTIM 1 chain Rx when in 1x1,
8719 * we are passing two value
8720 * as param_id << 29 | param_value.
8721 * Below param_value = 0(disable)
8722 */
8723 ret = sme_cli_set_command(adapter->deflink->vdev_id,
8724 WMI_STA_SMPS_PARAM_CMDID,
8725 HDD_DTIM_1CHAIN_RX_ID <<
8726 HDD_SMPS_PARAM_VALUE_S,
8727 VDEV_CMD);
8728 if (ret) {
8729 hdd_err("DTIM 1 chain set failed %d", ret);
8730 goto error;
8731 }
8732
8733 #undef HDD_DTIM_1CHAIN_RX_ID
8734 #undef HDD_SMPS_PARAM_VALUE_S
8735
8736 hdd_configure_chain_mask(adapter);
8737 }
8738
8739 ret = sme_set_enable_mem_deep_sleep(hdd_ctx->mac_handle,
8740 adapter->deflink->vdev_id);
8741 if (ret) {
8742 hdd_err("wmi_pdev_param_hyst_en set failed %d", ret);
8743 goto error;
8744 }
8745
8746 if (!hdd_ctx->is_fw_dbg_log_levels_configured) {
8747 hdd_set_fw_log_params(hdd_ctx, adapter->deflink->vdev_id);
8748 hdd_ctx->is_fw_dbg_log_levels_configured = true;
8749 }
8750
8751 ret = hdd_send_coex_config_params(hdd_ctx, adapter);
8752 if (ret) {
8753 hdd_warn("Error initializing coex config params");
8754 goto error;
8755 }
8756
8757 hdd_exit();
8758
8759 return 0;
8760
8761 error:
8762 return -EINVAL;
8763 }
8764
8765 /**
8766 * hdd_init_completion() - Initialize Completion Variables
8767 * @adapter: HDD adapter
8768 *
8769 * This function Initialize the completion variables for
8770 * a particular adapter
8771 *
8772 * Return: None
8773 */
hdd_init_completion(struct hdd_adapter * adapter)8774 static void hdd_init_completion(struct hdd_adapter *adapter)
8775 {
8776 init_completion(&adapter->disconnect_comp_var);
8777 init_completion(&adapter->linkup_event_var);
8778 init_completion(&adapter->lfr_fw_status.disable_lfr_event);
8779 }
8780
hdd_reset_locally_admin_bit(struct hdd_context * hdd_ctx,tSirMacAddr mac_addr)8781 static void hdd_reset_locally_admin_bit(struct hdd_context *hdd_ctx,
8782 tSirMacAddr mac_addr)
8783 {
8784 int i;
8785 /*
8786 * Reset locally administered bit for dynamic_mac_list
8787 * also as while releasing the MAC address for any
8788 * interface mac will be compared with dynamic mac list
8789 */
8790 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
8791 if (!qdf_mem_cmp(
8792 mac_addr,
8793 &hdd_ctx->
8794 dynamic_mac_list[i].dynamic_mac.bytes[0],
8795 sizeof(struct qdf_mac_addr))) {
8796 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(
8797 hdd_ctx->
8798 dynamic_mac_list[i].dynamic_mac.bytes);
8799 break;
8800 }
8801 }
8802 /*
8803 * Reset locally administered bit if the device mode is
8804 * STA
8805 */
8806 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(mac_addr);
8807 hdd_debug("locally administered bit reset in sta mode: "
8808 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(mac_addr));
8809 }
8810
wlan_hdd_cfg80211_scan_block_cb(struct work_struct * work)8811 static void wlan_hdd_cfg80211_scan_block_cb(struct work_struct *work)
8812 {
8813 struct hdd_adapter *adapter =
8814 container_of(work, struct hdd_adapter, scan_block_work);
8815 struct osif_vdev_sync *vdev_sync;
8816
8817 if (osif_vdev_sync_op_start(adapter->dev, &vdev_sync))
8818 return;
8819
8820 wlan_hdd_cfg80211_scan_block(adapter);
8821
8822 osif_vdev_sync_op_stop(vdev_sync);
8823 }
8824
8825 #if defined(WLAN_FEATURE_11BE_MLO) && \
8826 defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
8827 static inline void
wlan_hdd_set_ml_cap_for_sap_intf(struct hdd_adapter_create_param * create_params,enum QDF_OPMODE mode)8828 wlan_hdd_set_ml_cap_for_sap_intf(struct hdd_adapter_create_param *create_params,
8829 enum QDF_OPMODE mode)
8830 {
8831 if (mode != QDF_SAP_MODE)
8832 return;
8833
8834 create_params->is_ml_adapter = true;
8835 }
8836 #elif defined(WLAN_FEATURE_11BE_MLO)
8837 static inline void
wlan_hdd_set_ml_cap_for_sap_intf(struct hdd_adapter_create_param * create_params,enum QDF_OPMODE mode)8838 wlan_hdd_set_ml_cap_for_sap_intf(struct hdd_adapter_create_param *create_params,
8839 enum QDF_OPMODE mode)
8840 {
8841 if (mode != QDF_SAP_MODE)
8842 return;
8843
8844 create_params->is_ml_adapter = true;
8845 create_params->is_single_link = true;
8846 }
8847 #else
8848 static inline void
wlan_hdd_set_ml_cap_for_sap_intf(struct hdd_adapter_create_param * create_params,enum QDF_OPMODE mode)8849 wlan_hdd_set_ml_cap_for_sap_intf(struct hdd_adapter_create_param *create_params,
8850 enum QDF_OPMODE mode)
8851 {
8852 create_params->is_ml_adapter = false;
8853 }
8854 #endif /* WLAN_FEATURE_11BE_MLO */
8855
8856 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
8857 defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
8858 void
hdd_adapter_disable_all_links(struct hdd_adapter * adapter,bool clear_macaddr)8859 hdd_adapter_disable_all_links(struct hdd_adapter *adapter, bool clear_macaddr)
8860 {
8861 uint8_t idx_pos;
8862 struct wlan_hdd_link_info *link_info;
8863
8864 hdd_adapter_for_each_link_info(adapter, link_info) {
8865 if (clear_macaddr)
8866 qdf_zero_macaddr(&link_info->link_addr);
8867 idx_pos = hdd_adapter_get_index_of_link_info(link_info);
8868 adapter->curr_link_info_map[idx_pos] = idx_pos;
8869 }
8870
8871 adapter->deflink = &adapter->link_info[WLAN_HDD_DEFLINK_IDX];
8872 adapter->active_links = (1 << adapter->num_links_on_create) - 1;
8873 }
8874 #endif
8875
hdd_adapter_enable_links(struct hdd_adapter * adapter,struct hdd_adapter_create_param * params)8876 static void hdd_adapter_enable_links(struct hdd_adapter *adapter,
8877 struct hdd_adapter_create_param *params)
8878 {
8879 uint8_t num, link_idx;
8880
8881 /* Default link is already set on adapter allocation, only
8882 * enable other links if requested links is greater than 1
8883 */
8884 if (params->num_sessions <= 1) {
8885 adapter->num_links_on_create = 1;
8886 return;
8887 }
8888
8889 num = QDF_MIN(params->num_sessions, WLAN_MAX_MLD);
8890 for (link_idx = WLAN_HDD_DEFLINK_IDX; link_idx < num; link_idx++)
8891 qdf_atomic_set_bit(link_idx, &adapter->active_links);
8892
8893 adapter->num_links_on_create = num;
8894 }
8895
hdd_adapter_init_link_info(struct hdd_adapter * adapter)8896 static void hdd_adapter_init_link_info(struct hdd_adapter *adapter)
8897 {
8898 uint8_t idx_pos;
8899 struct wlan_hdd_link_info *link_info;
8900
8901 /* Initialize each member in link info array to default values */
8902 hdd_adapter_for_each_link_info(adapter, link_info) {
8903 link_info->adapter = adapter;
8904 link_info->vdev_id = WLAN_UMAC_VDEV_ID_MAX;
8905 qdf_spinlock_create(&link_info->vdev_lock);
8906 init_completion(&link_info->vdev_destroy_event);
8907 qdf_event_create(&link_info->acs_complete_event);
8908
8909 idx_pos = hdd_adapter_get_index_of_link_info(link_info);
8910 adapter->curr_link_info_map[idx_pos] = idx_pos;
8911 qdf_create_work(0, &link_info->chan_change_notify_work,
8912 hdd_chan_change_notify_work_handler,
8913 link_info);
8914 }
8915 }
8916
8917 /**
8918 * hdd_open_adapter() - open and setup the hdd adapter
8919 * @hdd_ctx: global hdd context
8920 * @session_type: type of the interface to be created
8921 * @iface_name: User-visible name of the interface
8922 * @mac_addr: MAC address to assign to the interface
8923 * @name_assign_type: the name of assign type of the netdev
8924 * @rtnl_held: the rtnl lock hold flag
8925 * @params: adapter create params
8926 *
8927 * This function open and setup the hdd adapter according to the device
8928 * type request, assign the name, the mac address assigned, and then prepared
8929 * the hdd related parameters, queue, lock and ready to start.
8930 *
8931 * Return: the pointer of hdd adapter, otherwise NULL.
8932 */
hdd_open_adapter(struct hdd_context * hdd_ctx,uint8_t session_type,const char * iface_name,tSirMacAddr mac_addr,unsigned char name_assign_type,bool rtnl_held,struct hdd_adapter_create_param * params)8933 struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx,
8934 uint8_t session_type,
8935 const char *iface_name,
8936 tSirMacAddr mac_addr,
8937 unsigned char name_assign_type,
8938 bool rtnl_held,
8939 struct hdd_adapter_create_param *params)
8940 {
8941 struct net_device *ndev = NULL;
8942 struct hdd_adapter *adapter = NULL, *sta_adapter = NULL;
8943 QDF_STATUS status = QDF_STATUS_E_FAILURE;
8944 uint32_t i;
8945 bool eht_capab = 0;
8946
8947 status = wlan_hdd_validate_mac_address((struct qdf_mac_addr *)mac_addr);
8948 if (QDF_IS_STATUS_ERROR(status)) {
8949 /* Not received valid mac_addr */
8950 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
8951 return NULL;
8952 }
8953
8954 status = hdd_check_for_existing_macaddr(hdd_ctx, mac_addr);
8955 if (QDF_STATUS_E_FAILURE == status) {
8956 hdd_err("Duplicate MAC addr: " QDF_MAC_ADDR_FMT
8957 " already exists",
8958 QDF_MAC_ADDR_REF(mac_addr));
8959 return NULL;
8960 }
8961
8962 if (params->only_wdev_register) {
8963 sta_adapter = hdd_get_ml_adapter(hdd_ctx);
8964 if (!sta_adapter) {
8965 hdd_err("not able to find the sta adapter");
8966 return NULL;
8967 }
8968 }
8969
8970 switch (session_type) {
8971 case QDF_STA_MODE:
8972 if (!(hdd_ctx->config->mac_provision ||
8973 params->only_wdev_register)) {
8974 hdd_reset_locally_admin_bit(hdd_ctx, mac_addr);
8975 /*
8976 * After resetting locally administered bit
8977 * again check if the new mac address is already
8978 * exists.
8979 */
8980 status = hdd_check_for_existing_macaddr(hdd_ctx,
8981 mac_addr);
8982 if (QDF_STATUS_E_FAILURE == status) {
8983 hdd_err("Duplicate MAC addr: " QDF_MAC_ADDR_FMT
8984 " already exists",
8985 QDF_MAC_ADDR_REF(mac_addr));
8986 return NULL;
8987 }
8988 }
8989
8990 fallthrough;
8991 case QDF_P2P_CLIENT_MODE:
8992 case QDF_P2P_DEVICE_MODE:
8993 case QDF_OCB_MODE:
8994 case QDF_NDI_MODE:
8995 case QDF_MONITOR_MODE:
8996 case QDF_NAN_DISC_MODE:
8997 adapter = hdd_alloc_station_adapter(hdd_ctx, mac_addr,
8998 name_assign_type,
8999 iface_name, session_type);
9000
9001 if (!adapter) {
9002 hdd_err("failed to allocate adapter for session %d",
9003 session_type);
9004 return NULL;
9005 }
9006
9007 ndev = adapter->dev;
9008
9009 status = ucfg_dp_create_intf(hdd_ctx->psoc, &adapter->mac_addr,
9010 (qdf_netdev_t)adapter->dev);
9011 if (QDF_IS_STATUS_ERROR(status))
9012 goto err_free_netdev;
9013
9014 if (QDF_P2P_CLIENT_MODE == session_type)
9015 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
9016 else if (QDF_P2P_DEVICE_MODE == session_type)
9017 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
9018 else if (QDF_MONITOR_MODE == session_type)
9019 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
9020 else if (QDF_NAN_DISC_MODE == session_type)
9021 wlan_hdd_set_nan_if_type(adapter);
9022 else
9023 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
9024
9025 adapter->device_mode = session_type;
9026
9027
9028 /*
9029 * Workqueue which gets scheduled in IPv4 notification
9030 * callback
9031 */
9032 INIT_WORK(&adapter->ipv4_notifier_work,
9033 hdd_ipv4_notifier_work_queue);
9034
9035 #ifdef WLAN_NS_OFFLOAD
9036 /*
9037 * Workqueue which gets scheduled in IPv6
9038 * notification callback.
9039 */
9040 INIT_WORK(&adapter->ipv6_notifier_work,
9041 hdd_ipv6_notifier_work_queue);
9042 #endif
9043 if (params->only_wdev_register) {
9044 hdd_register_wdev(sta_adapter, adapter, params);
9045 } else {
9046 status = hdd_register_interface(adapter, rtnl_held,
9047 params);
9048 if (QDF_STATUS_SUCCESS != status)
9049 goto err_destroy_dp_intf;
9050 /* Stop the Interface TX queue. */
9051 hdd_debug("Disabling queues");
9052 wlan_hdd_netif_queue_control(adapter,
9053 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
9054 WLAN_CONTROL_PATH);
9055 }
9056 break;
9057 case QDF_P2P_GO_MODE:
9058 case QDF_SAP_MODE:
9059 adapter = hdd_wlan_create_ap_dev(hdd_ctx, mac_addr,
9060 name_assign_type,
9061 (uint8_t *) iface_name);
9062 if (!adapter) {
9063 hdd_err("failed to allocate adapter for session %d",
9064 session_type);
9065 return NULL;
9066 }
9067
9068 ndev = adapter->dev;
9069
9070 status = ucfg_dp_create_intf(hdd_ctx->psoc, &adapter->mac_addr,
9071 (qdf_netdev_t)adapter->dev);
9072 if (QDF_IS_STATUS_ERROR(status))
9073 goto err_free_netdev;
9074
9075 adapter->wdev.iftype =
9076 (session_type ==
9077 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
9078 NL80211_IFTYPE_P2P_GO;
9079 adapter->device_mode = session_type;
9080
9081 status = hdd_register_interface(adapter, rtnl_held, params);
9082 if (QDF_STATUS_SUCCESS != status)
9083 goto err_destroy_dp_intf;
9084
9085 hdd_debug("Disabling queues");
9086 wlan_hdd_netif_queue_control(adapter,
9087 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
9088 WLAN_CONTROL_PATH);
9089
9090 /*
9091 * Workqueue which gets scheduled in IPv4 notification
9092 * callback
9093 */
9094 INIT_WORK(&adapter->ipv4_notifier_work,
9095 hdd_ipv4_notifier_work_queue);
9096
9097 #ifdef WLAN_NS_OFFLOAD
9098 /*
9099 * Workqueue which gets scheduled in IPv6
9100 * notification callback.
9101 */
9102 INIT_WORK(&adapter->ipv6_notifier_work,
9103 hdd_ipv6_notifier_work_queue);
9104 #endif
9105 if (!params->is_pre_cac_adapter)
9106 wlan_hdd_set_ml_cap_for_sap_intf(params, session_type);
9107 break;
9108 case QDF_FTM_MODE:
9109 adapter = hdd_alloc_station_adapter(hdd_ctx, mac_addr,
9110 name_assign_type,
9111 iface_name, session_type);
9112 if (!adapter) {
9113 hdd_err("Failed to allocate adapter for FTM mode");
9114 return NULL;
9115 }
9116
9117 ndev = adapter->dev;
9118
9119 status = ucfg_dp_create_intf(hdd_ctx->psoc, &adapter->mac_addr,
9120 (qdf_netdev_t)adapter->dev);
9121 if (QDF_IS_STATUS_ERROR(status))
9122 goto err_free_netdev;
9123
9124 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
9125 adapter->device_mode = session_type;
9126 status = hdd_register_interface(adapter, rtnl_held, params);
9127 if (QDF_STATUS_SUCCESS != status)
9128 goto err_destroy_dp_intf;
9129
9130 /* Stop the Interface TX queue. */
9131 hdd_debug("Disabling queues");
9132 wlan_hdd_netif_queue_control(adapter,
9133 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
9134 WLAN_CONTROL_PATH);
9135
9136 break;
9137 default:
9138 hdd_err("Invalid session type %d", session_type);
9139 QDF_ASSERT(0);
9140 return NULL;
9141 }
9142
9143 hdd_adapter_init_link_info(adapter);
9144 hdd_adapter_enable_links(adapter, params);
9145
9146 ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
9147 if (params->is_ml_adapter && eht_capab) {
9148 hdd_adapter_set_ml_adapter(adapter);
9149 if (params->is_single_link)
9150 hdd_adapter_set_sl_ml_adapter(adapter);
9151 }
9152
9153 status = hdd_adapter_feature_update_work_init(adapter);
9154 if (QDF_IS_STATUS_ERROR(status))
9155 goto err_cleanup_adapter;
9156
9157 adapter->upgrade_udp_qos_threshold = QCA_WLAN_AC_BK;
9158
9159 hdd_init_completion(adapter);
9160 INIT_WORK(&adapter->scan_block_work, wlan_hdd_cfg80211_scan_block_cb);
9161 INIT_WORK(&adapter->sap_stop_bss_work,
9162 hdd_stop_sap_due_to_invalid_channel);
9163 qdf_list_create(&adapter->blocked_scan_request_q, WLAN_MAX_SCAN_COUNT);
9164 qdf_mutex_create(&adapter->blocked_scan_request_q_lock);
9165 qdf_spinlock_create(&adapter->mc_list_lock);
9166 qdf_event_create(&adapter->peer_cleanup_done);
9167 hdd_sta_info_init(&adapter->sta_info_list);
9168 hdd_sta_info_init(&adapter->cache_sta_info_list);
9169
9170 for (i = 0; i < NET_DEV_HOLD_ID_MAX; i++)
9171 qdf_atomic_init(
9172 &adapter->net_dev_hold_ref_count[NET_DEV_HOLD_ID_MAX]);
9173
9174 /* Add it to the hdd's session list. */
9175 status = hdd_add_adapter_back(hdd_ctx, adapter);
9176 if (QDF_STATUS_SUCCESS != status)
9177 goto err_destroy_adapter_features_update_work;
9178
9179 hdd_apf_context_init(adapter);
9180
9181 policy_mgr_set_concurrency_mode(hdd_ctx->psoc, session_type);
9182
9183 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
9184 hdd_err("debugfs: Interface %s init failed",
9185 netdev_name(adapter->dev));
9186
9187 hdd_debug("%s interface created. iftype: %d", netdev_name(adapter->dev),
9188 session_type);
9189
9190 if (adapter->device_mode == QDF_STA_MODE)
9191 wlan_hdd_debugfs_csr_init(adapter);
9192
9193 return adapter;
9194
9195 err_destroy_adapter_features_update_work:
9196 hdd_adapter_feature_update_work_deinit(adapter);
9197
9198 err_cleanup_adapter:
9199 if (adapter) {
9200 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
9201 adapter = NULL;
9202 }
9203
9204 err_destroy_dp_intf:
9205 ucfg_dp_destroy_intf(hdd_ctx->psoc, &adapter->mac_addr);
9206
9207 err_free_netdev:
9208 if (ndev)
9209 free_netdev(ndev);
9210
9211 return NULL;
9212 }
9213
__hdd_close_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,bool rtnl_held)9214 static void __hdd_close_adapter(struct hdd_context *hdd_ctx,
9215 struct hdd_adapter *adapter,
9216 bool rtnl_held)
9217 {
9218 struct qdf_mac_addr adapter_mac;
9219 struct wlan_hdd_link_info *link_info;
9220
9221 qdf_copy_macaddr(&adapter_mac, &adapter->mac_addr);
9222 if (adapter->device_mode == QDF_STA_MODE) {
9223 hdd_adapter_for_each_link_info(adapter, link_info)
9224 hdd_cleanup_conn_info(link_info);
9225 }
9226
9227 hdd_adapter_for_each_link_info(adapter, link_info)
9228 qdf_flush_work(&link_info->chan_change_notify_work);
9229
9230 qdf_list_destroy(&adapter->blocked_scan_request_q);
9231 qdf_mutex_destroy(&adapter->blocked_scan_request_q_lock);
9232 policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
9233 qdf_event_destroy(&adapter->peer_cleanup_done);
9234 hdd_adapter_feature_update_work_deinit(adapter);
9235 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
9236 ucfg_dp_destroy_intf(hdd_ctx->psoc, &adapter_mac);
9237 }
9238
hdd_close_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,bool rtnl_held)9239 void hdd_close_adapter(struct hdd_context *hdd_ctx,
9240 struct hdd_adapter *adapter,
9241 bool rtnl_held)
9242 {
9243 /*
9244 * Stop the global bus bandwidth timer while touching the adapter list
9245 * to avoid bad memory access by the timer handler.
9246 */
9247 ucfg_dp_bus_bw_compute_timer_stop(hdd_ctx->psoc);
9248
9249 hdd_check_for_net_dev_ref_leak(adapter);
9250 hdd_remove_adapter(hdd_ctx, adapter);
9251 __hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
9252
9253 /* conditionally restart the bw timer */
9254 ucfg_dp_bus_bw_compute_timer_try_start(hdd_ctx->psoc);
9255 }
9256
hdd_close_all_adapters(struct hdd_context * hdd_ctx,bool rtnl_held)9257 void hdd_close_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held)
9258 {
9259 struct hdd_adapter *adapter;
9260 struct osif_vdev_sync *vdev_sync;
9261 QDF_STATUS qdf_status;
9262
9263 hdd_enter();
9264
9265 while (QDF_IS_STATUS_SUCCESS(hdd_get_front_adapter(
9266 hdd_ctx, &adapter))) {
9267 /* If MLO is enabled unregister the link wdev's */
9268 if (adapter->device_mode == QDF_STA_MODE ||
9269 adapter->device_mode == QDF_SAP_MODE) {
9270 qdf_status = hdd_wlan_unregister_mlo_interfaces(adapter,
9271 rtnl_held);
9272 if (QDF_IS_STATUS_ERROR(qdf_status))
9273 continue;
9274 }
9275
9276 hdd_check_for_net_dev_ref_leak(adapter);
9277 hdd_remove_front_adapter(hdd_ctx, &adapter);
9278 vdev_sync = osif_vdev_sync_unregister(adapter->dev);
9279 if (vdev_sync)
9280 osif_vdev_sync_wait_for_ops(vdev_sync);
9281
9282 wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes);
9283 __hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
9284
9285 if (vdev_sync)
9286 osif_vdev_sync_destroy(vdev_sync);
9287 }
9288
9289 hdd_exit();
9290 }
9291
wlan_hdd_reset_prob_rspies(struct wlan_hdd_link_info * link_info)9292 void wlan_hdd_reset_prob_rspies(struct wlan_hdd_link_info *link_info)
9293 {
9294 struct qdf_mac_addr *bssid = NULL;
9295 tSirUpdateIE update_ie;
9296 mac_handle_t mac_handle;
9297 struct hdd_adapter *adapter = link_info->adapter;
9298
9299 switch (adapter->device_mode) {
9300 case QDF_STA_MODE:
9301 case QDF_P2P_CLIENT_MODE:
9302 {
9303 struct hdd_station_ctx *sta_ctx =
9304 WLAN_HDD_GET_STATION_CTX_PTR(link_info);
9305 bssid = &sta_ctx->conn_info.bssid;
9306 break;
9307 }
9308 case QDF_SAP_MODE:
9309 case QDF_P2P_GO_MODE:
9310 {
9311 bssid = &adapter->mac_addr;
9312 break;
9313 }
9314 case QDF_FTM_MODE:
9315 case QDF_P2P_DEVICE_MODE:
9316 default:
9317 /*
9318 * wlan_hdd_reset_prob_rspies should not have been called
9319 * for these kind of devices
9320 */
9321 hdd_err("Unexpected request for the current device type %d",
9322 adapter->device_mode);
9323 return;
9324 }
9325
9326 qdf_copy_macaddr(&update_ie.bssid, bssid);
9327 update_ie.vdev_id = link_info->vdev_id;
9328 update_ie.ieBufferlength = 0;
9329 update_ie.pAdditionIEBuffer = NULL;
9330 update_ie.append = true;
9331 update_ie.notify = false;
9332 mac_handle = hdd_adapter_get_mac_handle(adapter);
9333 if (sme_update_add_ie(mac_handle,
9334 &update_ie,
9335 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
9336 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
9337 }
9338 }
9339
9340 /**
9341 * hdd_ipa_ap_disconnect_evt() - Indicate wlan ipa ap disconnect event
9342 * @hdd_ctx: hdd context
9343 * @adapter: hdd adapter
9344 *
9345 * Return: None
9346 */
9347 static inline
hdd_ipa_ap_disconnect_evt(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)9348 void hdd_ipa_ap_disconnect_evt(struct hdd_context *hdd_ctx,
9349 struct hdd_adapter *adapter)
9350 {
9351 struct wlan_hdd_link_info *link_info;
9352
9353 link_info = adapter->deflink;
9354 if (ucfg_ipa_is_enabled()) {
9355 ucfg_ipa_uc_disconnect_ap(hdd_ctx->pdev,
9356 adapter->dev);
9357 ucfg_ipa_cleanup_dev_iface(hdd_ctx->pdev,
9358 adapter->dev,
9359 link_info->vdev_id);
9360 }
9361 }
9362
9363 #ifdef WLAN_FEATURE_NAN
9364 /**
9365 * hdd_ndp_state_cleanup() - API to set NDP state to Disconnected
9366 * @psoc: pointer to psoc object
9367 * @ndi_vdev_id: vdev_id of the NDI
9368 *
9369 * Return: None
9370 */
9371 static void
hdd_ndp_state_cleanup(struct wlan_objmgr_psoc * psoc,uint8_t ndi_vdev_id)9372 hdd_ndp_state_cleanup(struct wlan_objmgr_psoc *psoc, uint8_t ndi_vdev_id)
9373 {
9374 struct wlan_objmgr_vdev *ndi_vdev;
9375
9376 ndi_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, ndi_vdev_id,
9377 WLAN_NAN_ID);
9378 if (!ndi_vdev) {
9379 hdd_err("Cannot obtain NDI vdev object!");
9380 return;
9381 }
9382
9383 ucfg_nan_set_ndi_state(ndi_vdev, NAN_DATA_DISCONNECTED_STATE);
9384
9385 wlan_objmgr_vdev_release_ref(ndi_vdev, WLAN_NAN_ID);
9386 }
9387
9388 /**
9389 * hdd_peer_cleanup() - This API will delete NDP peer if exist and modifies
9390 * the NDP state.
9391 * @link_info: Link info pointer in HDD adapter
9392 *
9393 * Return: None
9394 */
hdd_peer_cleanup(struct wlan_hdd_link_info * link_info)9395 static void hdd_peer_cleanup(struct wlan_hdd_link_info *link_info)
9396 {
9397 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
9398 struct hdd_adapter *adapter = link_info->adapter;
9399 struct hdd_context *hdd_ctx = adapter->hdd_ctx;
9400
9401 /* Check if there is any peer present on the adapter */
9402 if (!hdd_any_valid_peer_present(link_info)) {
9403 /*
9404 * No peers are connected to the NDI. So, set the NDI state to
9405 * DISCONNECTED. If there are any peers, ucfg_nan_disable_ndi()
9406 * would take care of cleanup all the peers and setting the
9407 * state to DISCONNECTED.
9408 */
9409 hdd_ndp_state_cleanup(hdd_ctx->psoc, link_info->vdev_id);
9410 return;
9411 }
9412
9413 if (adapter->device_mode == QDF_NDI_MODE)
9414 qdf_status = ucfg_nan_disable_ndi(hdd_ctx->psoc,
9415 link_info->vdev_id);
9416
9417 if (QDF_IS_STATUS_ERROR(qdf_status))
9418 return;
9419
9420 qdf_status = qdf_wait_for_event_completion(&adapter->peer_cleanup_done,
9421 WLAN_WAIT_PEER_CLEANUP);
9422 if (QDF_IS_STATUS_ERROR(qdf_status))
9423 hdd_debug("peer_cleanup_done wait fail");
9424 }
9425 #else
9426 static inline void
hdd_ndp_state_cleanup(struct wlan_objmgr_psoc * psoc,uint8_t ndi_vdev_id)9427 hdd_ndp_state_cleanup(struct wlan_objmgr_psoc *psoc, uint8_t ndi_vdev_id)
9428 {
9429 }
9430
9431 static inline void
hdd_ndp_peer_cleanup(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)9432 hdd_ndp_peer_cleanup(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter)
9433 {
9434 }
9435
hdd_peer_cleanup(struct wlan_hdd_link_info * link_info)9436 static inline void hdd_peer_cleanup(struct wlan_hdd_link_info *link_info)
9437 {
9438 }
9439 #endif /* WLAN_FEATURE_NAN */
9440
9441 #ifdef FUNC_CALL_MAP
9442
9443 /**
9444 * hdd_dump_func_call_map() - Dump the function call map
9445 *
9446 * Return: None
9447 */
9448
hdd_dump_func_call_map(void)9449 static void hdd_dump_func_call_map(void)
9450 {
9451 char *cc_buf;
9452
9453 cc_buf = qdf_mem_malloc(QDF_FUNCTION_CALL_MAP_BUF_LEN);
9454 /*
9455 * These logs are required as these indicates the start and end of the
9456 * dump for the auto script to parse
9457 */
9458 hdd_info("Function call map dump start");
9459 qdf_get_func_call_map(cc_buf);
9460 qdf_trace_hex_dump(QDF_MODULE_ID_HDD,
9461 QDF_TRACE_LEVEL_DEBUG, cc_buf, QDF_FUNCTION_CALL_MAP_BUF_LEN);
9462 hdd_info("Function call map dump end");
9463 qdf_mem_free(cc_buf);
9464 }
9465 #else
hdd_dump_func_call_map(void)9466 static inline void hdd_dump_func_call_map(void)
9467 {
9468 }
9469 #endif
9470
hdd_reset_scan_operation(struct wlan_hdd_link_info * link_info)9471 static void hdd_reset_scan_operation(struct wlan_hdd_link_info *link_info)
9472 {
9473 switch (link_info->adapter->device_mode) {
9474 case QDF_STA_MODE:
9475 case QDF_P2P_CLIENT_MODE:
9476 case QDF_P2P_DEVICE_MODE:
9477 case QDF_NDI_MODE:
9478 wlan_hdd_scan_abort(link_info);
9479 wlan_hdd_cleanup_remain_on_channel_ctx(link_info);
9480 if (link_info->adapter->device_mode == QDF_STA_MODE) {
9481 struct wlan_objmgr_vdev *vdev;
9482
9483 vdev = hdd_objmgr_get_vdev_by_user(link_info,
9484 WLAN_OSIF_SCAN_ID);
9485 if (!vdev)
9486 break;
9487
9488 wlan_cfg80211_sched_scan_stop(vdev);
9489 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SCAN_ID);
9490 }
9491 break;
9492 case QDF_P2P_GO_MODE:
9493 wlan_hdd_cleanup_remain_on_channel_ctx(link_info);
9494 break;
9495 case QDF_SAP_MODE:
9496 qdf_atomic_set(&link_info->session.ap.acs_in_progress, 0);
9497 break;
9498 default:
9499 break;
9500 }
9501 }
9502
9503 #ifdef WLAN_OPEN_SOURCE
hdd_cancel_ip_notifier_work(struct hdd_adapter * adapter)9504 void hdd_cancel_ip_notifier_work(struct hdd_adapter *adapter)
9505 {
9506 cancel_work_sync(&adapter->ipv4_notifier_work);
9507 #ifdef WLAN_NS_OFFLOAD
9508 cancel_work_sync(&adapter->ipv6_notifier_work);
9509 #endif
9510 }
9511 #endif
9512
hdd_adapter_deregister_fc(struct hdd_adapter * adapter)9513 void hdd_adapter_deregister_fc(struct hdd_adapter *adapter)
9514 {
9515 hdd_deregister_hl_netdev_fc_timer(adapter);
9516 hdd_deregister_tx_flow_control(adapter);
9517 }
9518
hdd_stop_and_cleanup_ndi(struct wlan_hdd_link_info * link_info)9519 static void hdd_stop_and_cleanup_ndi(struct wlan_hdd_link_info *link_info)
9520 {
9521 QDF_STATUS status;
9522 unsigned long rc;
9523 struct hdd_adapter *adapter = link_info->adapter;
9524 struct hdd_context *hdd_ctx = adapter->hdd_ctx;
9525
9526 hdd_destroy_adapter_sysfs_files(adapter);
9527 /* For NDI do not use roam_profile */
9528 INIT_COMPLETION(adapter->disconnect_comp_var);
9529 hdd_peer_cleanup(link_info);
9530 status = sme_roam_ndi_stop(hdd_ctx->mac_handle, link_info->vdev_id);
9531 if (QDF_IS_STATUS_SUCCESS(status)) {
9532 rc = wait_for_completion_timeout(
9533 &adapter->disconnect_comp_var,
9534 msecs_to_jiffies(SME_CMD_STOP_BSS_TIMEOUT));
9535 if (!rc)
9536 hdd_warn("disconn_comp_var wait fail");
9537 hdd_cleanup_ndi(link_info);
9538 }
9539 }
9540
9541 static void
hdd_sta_disconnect_and_cleanup(struct wlan_hdd_link_info * link_info)9542 hdd_sta_disconnect_and_cleanup(struct wlan_hdd_link_info *link_info)
9543 {
9544 QDF_STATUS status;
9545 enum wlan_reason_code reason;
9546 struct hdd_adapter *adapter = link_info->adapter;
9547
9548 /*
9549 * On vdev delete wait for disconnect to
9550 * complete. i.e use sync API, so that the
9551 * vdev ref of MLME are cleaned and disconnect
9552 * complete before vdev is moved to logically
9553 * deleted.
9554 */
9555 if (cds_is_driver_recovering())
9556 reason = REASON_DEVICE_RECOVERY;
9557 else
9558 reason = REASON_IFACE_DOWN;
9559
9560 status = wlan_hdd_cm_issue_disconnect(link_info, reason, true);
9561 if (QDF_IS_STATUS_ERROR(status) && ucfg_ipa_is_enabled()) {
9562 hdd_err("STA disconnect failed");
9563 ucfg_ipa_uc_cleanup_sta(adapter->hdd_ctx->pdev, adapter->dev,
9564 link_info->vdev_id);
9565 }
9566 }
9567
9568 static void
hdd_disable_nan_active_disc(struct hdd_adapter * adapter)9569 hdd_disable_nan_active_disc(struct hdd_adapter *adapter)
9570 {
9571 struct hdd_context *hdd_ctx = adapter->hdd_ctx;
9572 enum QDF_OPMODE device_mode = adapter->device_mode;
9573
9574 if ((device_mode == QDF_NAN_DISC_MODE ||
9575 (device_mode == QDF_STA_MODE &&
9576 !ucfg_nan_is_vdev_creation_allowed(hdd_ctx->psoc))) &&
9577 ucfg_is_nan_conc_control_supported(hdd_ctx->psoc) &&
9578 ucfg_is_nan_disc_active(hdd_ctx->psoc))
9579 ucfg_disable_nan_discovery(hdd_ctx->psoc, NULL, 0);
9580 }
9581
9582 static void
hdd_monitor_mode_release_wakelock(struct wlan_hdd_link_info * link_info)9583 hdd_monitor_mode_release_wakelock(struct wlan_hdd_link_info *link_info)
9584 {
9585 struct hdd_adapter *adapter = link_info->adapter;
9586 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9587
9588 if (wlan_hdd_is_session_type_monitor(adapter->device_mode) &&
9589 (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) ||
9590 ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc))) {
9591 hdd_info("Release wakelock for STA + monitor mode!");
9592 os_if_dp_local_pkt_capture_stop(link_info->vdev);
9593 qdf_runtime_pm_allow_suspend(
9594 &hdd_ctx->runtime_context.monitor_mode);
9595 hdd_lpc_enable_powersave(hdd_ctx);
9596 qdf_wake_lock_release(&hdd_ctx->monitor_mode_wakelock,
9597 WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);
9598 }
9599 }
9600
9601 static void
hdd_monitor_mode_disable_and_delete(struct wlan_hdd_link_info * link_info)9602 hdd_monitor_mode_disable_and_delete(struct wlan_hdd_link_info *link_info)
9603 {
9604 QDF_STATUS status;
9605 struct hdd_adapter *adapter = link_info->adapter;
9606 struct hdd_context *hdd_ctx = adapter->hdd_ctx;
9607
9608 status = hdd_disable_monitor_mode();
9609 if (QDF_IS_STATUS_ERROR(status))
9610 hdd_err_rl("datapath reset failed for montior mode");
9611 hdd_set_idle_ps_config(hdd_ctx, true);
9612 status = hdd_monitor_mode_vdev_status(adapter);
9613 if (QDF_IS_STATUS_ERROR(status))
9614 hdd_err_rl("stop failed montior mode");
9615 sme_delete_mon_session(hdd_ctx->mac_handle, link_info->vdev_id);
9616 }
9617
9618 static void
hdd_stop_and_close_pre_cac_adapter(struct hdd_context * hdd_ctx,struct wlan_objmgr_vdev * vdev)9619 hdd_stop_and_close_pre_cac_adapter(struct hdd_context *hdd_ctx,
9620 struct wlan_objmgr_vdev *vdev)
9621 {
9622 if (!vdev)
9623 return;
9624
9625 if (!ucfg_pre_cac_adapter_is_active(vdev)) {
9626 ucfg_pre_cac_stop(hdd_ctx->psoc);
9627 hdd_close_pre_cac_adapter(hdd_ctx);
9628 } else {
9629 if (ucfg_pre_cac_set_status(vdev, false))
9630 hdd_err("Failed to set is_pre_cac_on to false");
9631 }
9632 }
9633
hdd_reset_ies_on_sap_stop(struct wlan_hdd_link_info * link_info)9634 static void hdd_reset_ies_on_sap_stop(struct wlan_hdd_link_info *link_info)
9635 {
9636 mac_handle_t mac_handle;
9637 tSirUpdateIE update_ie;
9638 QDF_STATUS status;
9639 struct hdd_adapter *adapter = link_info->adapter;
9640
9641 mac_handle = hdd_adapter_get_mac_handle(adapter);
9642 update_ie.vdev_id = link_info->vdev_id;
9643 update_ie.ieBufferlength = 0;
9644 update_ie.pAdditionIEBuffer = NULL;
9645 update_ie.append = false;
9646 update_ie.notify = false;
9647
9648 /* Probe bcn reset */
9649 status = sme_update_add_ie(mac_handle, &update_ie,
9650 eUPDATE_IE_PROBE_BCN);
9651 if (status == QDF_STATUS_E_FAILURE)
9652 hdd_err("Could not pass PROBE_RSP_BCN to PE");
9653
9654 /* Assoc resp reset */
9655 status = sme_update_add_ie(mac_handle, &update_ie,
9656 eUPDATE_IE_ASSOC_RESP);
9657 if (status == QDF_STATUS_E_FAILURE)
9658 hdd_err("Could not pass ASSOC_RSP to PE");
9659
9660 /* Reset WNI_CFG_PROBE_RSP Flags */
9661 wlan_hdd_reset_prob_rspies(link_info);
9662 }
9663
hdd_stop_station_adapter(struct hdd_adapter * adapter)9664 static void hdd_stop_station_adapter(struct hdd_adapter *adapter)
9665 {
9666 struct wlan_objmgr_vdev *vdev;
9667 enum QDF_OPMODE mode;
9668 struct wlan_hdd_link_info *link_info;
9669
9670 mode = adapter->device_mode;
9671 hdd_adapter_for_each_active_link_info(adapter, link_info) {
9672 vdev = hdd_objmgr_get_vdev_by_user(link_info,
9673 WLAN_INIT_DEINIT_ID);
9674 if (!vdev)
9675 continue;
9676
9677 if (mode == QDF_NDI_MODE)
9678 hdd_stop_and_cleanup_ndi(link_info);
9679 else if (!hdd_cm_is_disconnected(link_info))
9680 hdd_sta_disconnect_and_cleanup(link_info);
9681
9682 hdd_reset_scan_operation(link_info);
9683 wlan_hdd_cleanup_actionframe(link_info);
9684 wlan_hdd_flush_pmksa_cache(link_info);
9685
9686 if (mode == QDF_STA_MODE)
9687 ucfg_ipa_flush_pending_vdev_events(
9688 wlan_vdev_get_pdev(vdev),
9689 link_info->vdev_id);
9690 hdd_objmgr_put_vdev_by_user(vdev, WLAN_INIT_DEINIT_ID);
9691 hdd_vdev_destroy(link_info);
9692 }
9693
9694 hdd_disable_nan_active_disc(adapter);
9695 hdd_adapter_deregister_fc(adapter);
9696 hdd_cancel_ip_notifier_work(adapter);
9697 }
9698
hdd_stop_mon_adapter(struct hdd_adapter * adapter)9699 static int hdd_stop_mon_adapter(struct hdd_adapter *adapter)
9700 {
9701 struct wlan_objmgr_vdev *vdev;
9702 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9703 struct wlan_hdd_link_info *link_info = adapter->deflink;
9704
9705 vdev = hdd_objmgr_get_vdev_by_user(link_info,
9706 WLAN_INIT_DEINIT_ID);
9707 if (wlan_hdd_is_session_type_monitor(adapter->device_mode) &&
9708 vdev &&
9709 ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
9710 PACKET_CAPTURE_MODE_DISABLE) {
9711 struct hdd_adapter *sta_adapter;
9712
9713 ucfg_pkt_capture_deregister_callbacks(vdev);
9714 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9715 link_info->vdev = NULL;
9716
9717 sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
9718 if (!sta_adapter) {
9719 hdd_objmgr_put_vdev_by_user(vdev, WLAN_INIT_DEINIT_ID);
9720 hdd_err("No station interface found");
9721 return -EINVAL;
9722 }
9723 hdd_reset_monitor_interface(sta_adapter);
9724 }
9725
9726 hdd_monitor_mode_release_wakelock(link_info);
9727 wlan_hdd_scan_abort(link_info);
9728 hdd_adapter_deregister_fc(adapter);
9729 hdd_monitor_mode_disable_and_delete(link_info);
9730 if (vdev)
9731 hdd_objmgr_put_vdev_by_user(vdev, WLAN_INIT_DEINIT_ID);
9732
9733 hdd_vdev_destroy(link_info);
9734
9735 return 0;
9736 }
9737
hdd_stop_sap_go_adapter(struct hdd_adapter * adapter)9738 static void hdd_stop_sap_go_adapter(struct hdd_adapter *adapter)
9739 {
9740 enum QDF_OPMODE mode;
9741 struct hdd_ap_ctx *ap_ctx;
9742 struct sap_context *sap_ctx;
9743 struct sap_config *sap_config;
9744 struct hdd_hostapd_state *hostapd_state;
9745 struct wlan_objmgr_vdev *vdev;
9746 struct wlan_hdd_link_info *link_info = adapter->deflink;
9747 QDF_STATUS status = QDF_STATUS_SUCCESS;
9748 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9749 uint8_t link_id;
9750
9751 mode = adapter->device_mode;
9752 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
9753 sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
9754 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_INIT_DEINIT_ID);
9755
9756 if (mode == QDF_SAP_MODE) {
9757 wlan_hdd_scan_abort(link_info);
9758 hdd_abort_ongoing_sta_connection(hdd_ctx);
9759 /* Diassociate with all the peers before stop ap post */
9760 if (test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
9761 if (wlan_hdd_del_station(adapter, NULL))
9762 hdd_sap_indicate_disconnect_for_sta(adapter);
9763 }
9764 wlan_hdd_flush_pmksa_cache(link_info);
9765 sap_config = &ap_ctx->sap_config;
9766 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
9767 hdd_stop_and_close_pre_cac_adapter(hdd_ctx, vdev);
9768 }
9769 wlansap_cleanup_cac_timer(sap_ctx);
9770 cds_flush_work(&adapter->sap_stop_bss_work);
9771
9772 if (qdf_atomic_read(&ap_ctx->acs_in_progress)) {
9773 hdd_info("ACS in progress, wait for complete");
9774 qdf_wait_for_event_completion(&link_info->acs_complete_event,
9775 ACS_COMPLETE_TIMEOUT);
9776 }
9777
9778 if (mode == QDF_P2P_GO_MODE) {
9779 wlan_hdd_cleanup_remain_on_channel_ctx(link_info);
9780 hdd_abort_ongoing_sta_connection(hdd_ctx);
9781 }
9782
9783 hdd_adapter_deregister_fc(adapter);
9784 hdd_destroy_acs_timer(adapter);
9785
9786 mutex_lock(&hdd_ctx->sap_lock);
9787 if (test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
9788 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info);
9789 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
9790 status = wlansap_stop_bss(ap_ctx->sap_context);
9791 if (QDF_IS_STATUS_SUCCESS(status)) {
9792 status = qdf_wait_single_event(&hostapd_state->qdf_stop_bss_event,
9793 SME_CMD_STOP_BSS_TIMEOUT);
9794 if (QDF_IS_STATUS_ERROR(status)) {
9795 hdd_err("failure waiting for wlansap_stop_bss %d",
9796 status);
9797 hdd_ipa_ap_disconnect_evt(hdd_ctx, adapter);
9798 }
9799 } else {
9800 hdd_err("failure in wlansap_stop_bss");
9801 }
9802
9803 clear_bit(SOFTAP_BSS_STARTED, &link_info->link_flags);
9804 policy_mgr_decr_session_set_pcl(hdd_ctx->psoc,
9805 adapter->device_mode,
9806 link_info->vdev_id);
9807 hdd_green_ap_start_state_mc(hdd_ctx, adapter->device_mode,
9808 false);
9809
9810 hdd_reset_ies_on_sap_stop(link_info);
9811 }
9812
9813 /*
9814 * Note to restart sap after SSR driver needs below information
9815 * and is not cleared/freed on purpose in case of SAP SSR
9816 */
9817 if (!cds_is_driver_recovering()) {
9818 clear_bit(SOFTAP_INIT_DONE, &link_info->link_flags);
9819 qdf_mem_free(ap_ctx->beacon);
9820 ap_ctx->beacon = NULL;
9821
9822 if (vdev) {
9823 link_id = wlan_vdev_get_link_id(vdev);
9824 ucfg_crypto_free_key_by_link_id(hdd_ctx->psoc,
9825 &link_info->link_addr,
9826 link_id);
9827 }
9828 }
9829 /* Clear all the cached sta info */
9830 hdd_clear_cached_sta_info(adapter);
9831
9832 if (vdev && policy_mgr_is_dnsc_set(vdev))
9833 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0);
9834
9835 hdd_cancel_ip_notifier_work(adapter);
9836 sap_release_vdev_ref(sap_ctx);
9837
9838 if (mode == QDF_SAP_MODE)
9839 ucfg_ipa_flush_pending_vdev_events(hdd_ctx->pdev,
9840 link_info->vdev_id);
9841 if (vdev)
9842 hdd_objmgr_put_vdev_by_user(vdev, WLAN_INIT_DEINIT_ID);
9843 hdd_vdev_destroy(link_info);
9844 mutex_unlock(&hdd_ctx->sap_lock);
9845 ucfg_ipa_flush(hdd_ctx->pdev);
9846 }
9847
hdd_stop_ocb_adapter(struct hdd_adapter * adapter)9848 static void hdd_stop_ocb_adapter(struct hdd_adapter *adapter)
9849 {
9850 struct hdd_station_ctx *sta_ctx;
9851 struct wlan_objmgr_vdev *vdev;
9852 struct wlan_hdd_link_info *link_info = adapter->deflink;
9853
9854 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_INIT_DEINIT_ID);
9855 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
9856 cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC), OL_TXRX_PDEV_ID,
9857 sta_ctx->conn_info.peer_macaddr[0]);
9858 hdd_adapter_deregister_fc(adapter);
9859 if (vdev)
9860 hdd_objmgr_put_vdev_by_user(vdev, WLAN_INIT_DEINIT_ID);
9861 hdd_vdev_destroy(link_info);
9862 }
9863
hdd_stop_adapter_ext(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)9864 QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
9865 struct hdd_adapter *adapter)
9866 {
9867 QDF_STATUS status;
9868 struct wlan_hdd_link_info *link_info = adapter->deflink;
9869
9870 hdd_enter();
9871 hdd_destroy_adapter_sysfs_files(adapter);
9872
9873 if (adapter->device_mode == QDF_STA_MODE &&
9874 hdd_is_pkt_capture_mon_enable(adapter) &&
9875 ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
9876 PACKET_CAPTURE_MODE_DISABLE) {
9877 hdd_unmap_monitor_interface_vdev(adapter);
9878 }
9879
9880 if (link_info->vdev_id != WLAN_UMAC_VDEV_ID_MAX)
9881 wlan_hdd_cfg80211_deregister_frames(adapter);
9882
9883 hdd_stop_tsf_sync(adapter);
9884 cds_flush_work(&adapter->scan_block_work);
9885 wlan_hdd_cfg80211_scan_block(adapter);
9886 hdd_debug("Disabling queues");
9887 wlan_hdd_netif_queue_control(adapter,
9888 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
9889 WLAN_CONTROL_PATH);
9890
9891 switch (adapter->device_mode) {
9892 case QDF_STA_MODE:
9893 case QDF_P2P_CLIENT_MODE:
9894 case QDF_NDI_MODE:
9895 case QDF_P2P_DEVICE_MODE:
9896 case QDF_NAN_DISC_MODE:
9897 hdd_stop_station_adapter(adapter);
9898 break;
9899 case QDF_MONITOR_MODE:
9900 status = hdd_stop_mon_adapter(adapter);
9901 if (QDF_IS_STATUS_ERROR(status))
9902 return status;
9903
9904 break;
9905 case QDF_SAP_MODE:
9906 case QDF_P2P_GO_MODE:
9907 hdd_stop_sap_go_adapter(adapter);
9908 break;
9909 case QDF_OCB_MODE:
9910 hdd_stop_ocb_adapter(adapter);
9911 break;
9912 default:
9913 break;
9914 }
9915
9916 /* Moved from vdev destroy as it is per adapter */
9917 wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, adapter->dev);
9918
9919 /* Disable all links (expect default index) in adapter.
9920 * Set link address to NULL
9921 */
9922 hdd_adapter_disable_all_links(adapter, true);
9923
9924 /* This function should be invoked at the end of this api*/
9925 hdd_dump_func_call_map();
9926 hdd_exit();
9927
9928 return QDF_STATUS_SUCCESS;
9929 }
9930
hdd_stop_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)9931 QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
9932 struct hdd_adapter *adapter)
9933 {
9934 QDF_STATUS status;
9935
9936 if (adapter->device_mode == QDF_STA_MODE)
9937 status = hdd_stop_link_adapter(hdd_ctx, adapter);
9938
9939 status = hdd_stop_adapter_ext(hdd_ctx, adapter);
9940
9941 return status;
9942 }
9943
9944 /**
9945 * hdd_deinit_all_adapters - deinit all adapters
9946 * @hdd_ctx: HDD context
9947 * @rtnl_held: True if RTNL lock held
9948 *
9949 */
hdd_deinit_all_adapters(struct hdd_context * hdd_ctx,bool rtnl_held)9950 void hdd_deinit_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held)
9951 {
9952 struct hdd_adapter *adapter, *next_adapter = NULL;
9953
9954 hdd_enter();
9955
9956 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
9957 NET_DEV_HOLD_DEINIT_ALL_ADAPTERS) {
9958 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
9959 hdd_adapter_dev_put_debug(adapter,
9960 NET_DEV_HOLD_DEINIT_ALL_ADAPTERS);
9961 }
9962
9963 hdd_exit();
9964 }
9965
hdd_stop_all_adapters(struct hdd_context * hdd_ctx)9966 QDF_STATUS hdd_stop_all_adapters(struct hdd_context *hdd_ctx)
9967 {
9968 struct hdd_adapter *adapter, *next_adapter = NULL;
9969
9970 hdd_enter();
9971
9972 ucfg_pre_cac_stop(hdd_ctx->psoc);
9973 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
9974 NET_DEV_HOLD_STOP_ALL_ADAPTERS) {
9975 hdd_stop_adapter(hdd_ctx, adapter);
9976 hdd_adapter_dev_put_debug(adapter,
9977 NET_DEV_HOLD_STOP_ALL_ADAPTERS);
9978 }
9979
9980 hdd_exit();
9981
9982 return QDF_STATUS_SUCCESS;
9983 }
9984
hdd_set_netdev_flags(struct hdd_adapter * adapter)9985 void hdd_set_netdev_flags(struct hdd_adapter *adapter)
9986 {
9987 bool enable_csum = false;
9988 bool enable_lro;
9989 enum QDF_OPMODE device_mode;
9990 struct hdd_context *hdd_ctx;
9991 ol_txrx_soc_handle soc;
9992 uint64_t temp;
9993
9994 if (!adapter || !adapter->dev) {
9995 hdd_err("invalid input!");
9996 return;
9997 }
9998 device_mode = adapter->device_mode;
9999
10000 hdd_ctx = adapter->hdd_ctx;
10001 soc = cds_get_context(QDF_MODULE_ID_SOC);
10002
10003 if (!soc || !hdd_ctx) {
10004 hdd_err("invalid SOC or HDD context!");
10005 return;
10006 }
10007
10008 /* Determine device_mode specific configuration */
10009
10010 enable_lro = !!cdp_cfg_get(soc, cfg_dp_lro_enable);
10011 enable_csum = !!cdp_cfg_get(soc,
10012 cfg_dp_enable_ip_tcp_udp_checksum_offload);
10013 switch (device_mode) {
10014 case QDF_P2P_DEVICE_MODE:
10015 case QDF_P2P_CLIENT_MODE:
10016 enable_csum = !!cdp_cfg_get(soc,
10017 cfg_dp_enable_p2p_ip_tcp_udp_checksum_offload);
10018 break;
10019 case QDF_P2P_GO_MODE:
10020 enable_csum = !!cdp_cfg_get(soc,
10021 cfg_dp_enable_p2p_ip_tcp_udp_checksum_offload);
10022 enable_lro = false;
10023 break;
10024 case QDF_SAP_MODE:
10025 enable_lro = false;
10026 break;
10027 case QDF_NDI_MODE:
10028 case QDF_NAN_DISC_MODE:
10029 enable_csum = !!cdp_cfg_get(soc,
10030 cfg_dp_enable_nan_ip_tcp_udp_checksum_offload);
10031 break;
10032 default:
10033 break;
10034 }
10035
10036 /* Set netdev flags */
10037
10038 /*
10039 * In case of USB tethering, LRO is disabled. If SSR happened
10040 * during that time, then as part of SSR init, do not enable
10041 * the LRO again. Keep the LRO state same as before SSR.
10042 */
10043 if (enable_lro && !(qdf_atomic_read(&hdd_ctx->vendor_disable_lro_flag)))
10044 adapter->dev->features |= NETIF_F_LRO;
10045
10046 if (enable_csum)
10047 adapter->dev->features |=
10048 (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
10049
10050 if (cdp_cfg_get(soc, cfg_dp_tso_enable) && enable_csum) {
10051 adapter->dev->features |= TSO_FEATURE_FLAGS;
10052 adapter->tso_csum_feature_enabled = 1;
10053 }
10054
10055 if (cdp_cfg_get(soc, cfg_dp_sg_enable))
10056 adapter->dev->features |= NETIF_F_SG;
10057
10058 adapter->dev->features |= NETIF_F_RXCSUM;
10059 temp = (uint64_t)adapter->dev->features;
10060
10061 hdd_debug("adapter mode %u dev feature 0x%llx", device_mode, temp);
10062 }
10063
10064 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
10065 /**
10066 * hdd_adapter_abort_tx_flow() - Abort the tx flow control
10067 * @adapter: pointer to hdd adapter
10068 *
10069 * Resume tx and stop the tx flow control timer if the tx is paused
10070 * and the flow control timer is running. This function is called by
10071 * SSR to avoid the inconsistency of tx status before and after SSR.
10072 *
10073 * Return: void
10074 */
hdd_adapter_abort_tx_flow(struct hdd_adapter * adapter)10075 static void hdd_adapter_abort_tx_flow(struct hdd_adapter *adapter)
10076 {
10077 if (adapter->deflink->hdd_stats.tx_rx_stats.is_txflow_paused &&
10078 QDF_TIMER_STATE_RUNNING ==
10079 qdf_mc_timer_get_current_state(
10080 &adapter->tx_flow_control_timer)) {
10081 hdd_tx_resume_timer_expired_handler(adapter);
10082 qdf_mc_timer_stop(&adapter->tx_flow_control_timer);
10083 }
10084 }
10085 #else
hdd_adapter_abort_tx_flow(struct hdd_adapter * adapter)10086 static void hdd_adapter_abort_tx_flow(struct hdd_adapter *adapter)
10087 {
10088 }
10089 #endif
10090
hdd_reset_all_adapters(struct hdd_context * hdd_ctx)10091 QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx)
10092 {
10093 struct hdd_adapter *adapter, *next_adapter = NULL;
10094 bool value;
10095 struct wlan_objmgr_vdev *vdev;
10096 struct wlan_hdd_link_info *link_info;
10097
10098 hdd_enter();
10099
10100 ucfg_mlme_get_sap_internal_restart(hdd_ctx->psoc, &value);
10101
10102
10103 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10104 NET_DEV_HOLD_RESET_ALL_ADAPTERS) {
10105 hdd_info("[SSR] reset adapter with device mode %s(%d)",
10106 qdf_opmode_str(adapter->device_mode),
10107 adapter->device_mode);
10108
10109 hdd_adapter_for_each_active_link_info(adapter, link_info) {
10110 hdd_adapter_abort_tx_flow(adapter);
10111
10112 if ((adapter->device_mode == QDF_STA_MODE) ||
10113 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
10114 hdd_send_twt_del_all_sessions_to_userspace(link_info);
10115
10116 /* Stop tdls timers */
10117 vdev = hdd_objmgr_get_vdev_by_user(link_info,
10118 WLAN_OSIF_TDLS_ID);
10119 if (vdev) {
10120 hdd_notify_tdls_reset_adapter(vdev);
10121 hdd_objmgr_put_vdev_by_user(vdev,
10122 WLAN_OSIF_TDLS_ID);
10123 }
10124 }
10125
10126 if (value &&
10127 adapter->device_mode == QDF_SAP_MODE) {
10128 hdd_medium_assess_ssr_enable_flag();
10129 wlan_hdd_netif_queue_control(adapter,
10130 WLAN_STOP_ALL_NETIF_QUEUE,
10131 WLAN_CONTROL_PATH);
10132 } else {
10133 wlan_hdd_netif_queue_control(adapter,
10134 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
10135 WLAN_CONTROL_PATH);
10136 }
10137
10138 /*
10139 * Clear fc flag if it was set before SSR to avoid
10140 * TX queues permanently stopped after SSR.
10141 * Here WLAN_START_ALL_NETIF_QUEUE will actually
10142 * not start any queue since it's blocked by reason
10143 * WLAN_CONTROL_PATH.
10144 */
10145 if (adapter->pause_map & (1 << WLAN_DATA_FLOW_CONTROL))
10146 wlan_hdd_netif_queue_control(adapter,
10147 WLAN_START_ALL_NETIF_QUEUE,
10148 WLAN_DATA_FLOW_CONTROL);
10149
10150 hdd_reset_scan_operation(link_info);
10151 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
10152 hdd_wmm_adapter_close(adapter);
10153 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
10154 }
10155
10156 hdd_debug("Flush any mgmt references held by peer");
10157 hdd_stop_adapter(hdd_ctx, adapter);
10158 }
10159 hdd_adapter_dev_put_debug(adapter,
10160 NET_DEV_HOLD_RESET_ALL_ADAPTERS);
10161 }
10162
10163 hdd_exit();
10164
10165 return QDF_STATUS_SUCCESS;
10166 }
10167
hdd_is_any_link_opened(struct hdd_adapter * adapter)10168 static bool hdd_is_any_link_opened(struct hdd_adapter *adapter)
10169 {
10170 struct wlan_hdd_link_info *link_info;
10171
10172 hdd_adapter_for_each_active_link_info(adapter, link_info) {
10173 if (test_bit(SME_SESSION_OPENED, &link_info->link_flags))
10174 return true;
10175 }
10176 return false;
10177 }
10178
hdd_is_any_interface_open(struct hdd_context * hdd_ctx)10179 bool hdd_is_any_interface_open(struct hdd_context *hdd_ctx)
10180 {
10181 struct hdd_adapter *adapter, *next_adapter = NULL;
10182 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_IS_ANY_INTERFACE_OPEN;
10183
10184 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
10185 hdd_info("FTM mode, don't close the module");
10186 return true;
10187 }
10188
10189 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10190 dbgid) {
10191 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags) ||
10192 hdd_is_any_link_opened(adapter)) {
10193 hdd_adapter_dev_put_debug(adapter, dbgid);
10194 if (next_adapter)
10195 hdd_adapter_dev_put_debug(next_adapter, dbgid);
10196 return true;
10197 }
10198 hdd_adapter_dev_put_debug(adapter, dbgid);
10199 }
10200
10201 return false;
10202 }
10203
hdd_is_interface_up(struct hdd_adapter * adapter)10204 bool hdd_is_interface_up(struct hdd_adapter *adapter)
10205 {
10206 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
10207 return true;
10208 else
10209 return false;
10210 }
10211
10212 #ifdef FEATURE_MONITOR_MODE_SUPPORT
10213 #ifdef WLAN_FEATURE_11BE
wlan_hdd_is_mon_channel_bw_valid(enum phy_ch_width ch_width)10214 static inline bool wlan_hdd_is_mon_channel_bw_valid(enum phy_ch_width ch_width)
10215 {
10216 if (ch_width > CH_WIDTH_320MHZ ||
10217 (!cds_is_sub_20_mhz_enabled() && (ch_width == CH_WIDTH_5MHZ ||
10218 ch_width == CH_WIDTH_10MHZ)))
10219 return false;
10220
10221 return true;
10222 }
10223 #else
wlan_hdd_is_mon_channel_bw_valid(enum phy_ch_width ch_width)10224 static inline bool wlan_hdd_is_mon_channel_bw_valid(enum phy_ch_width ch_width)
10225 {
10226 if (ch_width > CH_WIDTH_10MHZ ||
10227 (!cds_is_sub_20_mhz_enabled() && (ch_width == CH_WIDTH_5MHZ ||
10228 ch_width == CH_WIDTH_10MHZ)))
10229 return false;
10230
10231 return true;
10232 }
10233 #endif
10234
wlan_hdd_set_mon_chan(struct hdd_adapter * adapter,qdf_freq_t freq,uint32_t bandwidth)10235 int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, qdf_freq_t freq,
10236 uint32_t bandwidth)
10237 {
10238 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10239 struct hdd_station_ctx *sta_ctx;
10240 struct hdd_mon_set_ch_info *ch_info;
10241 QDF_STATUS status;
10242 struct qdf_mac_addr bssid;
10243 struct channel_change_req *req;
10244 struct ch_params ch_params;
10245 enum phy_ch_width max_fw_bw;
10246 enum phy_ch_width ch_width;
10247 int ret;
10248
10249 if ((hdd_get_conparam() != QDF_GLOBAL_MONITOR_MODE) &&
10250 (!policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))) {
10251 hdd_err("Not supported, device is not in monitor mode");
10252 return -EINVAL;
10253 }
10254
10255 if (adapter->device_mode != QDF_MONITOR_MODE) {
10256 hdd_err_rl("Not supported, adapter is not in monitor mode");
10257 return -EINVAL;
10258 }
10259
10260 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
10261 ch_info = &sta_ctx->ch_info;
10262
10263 /* Verify the BW before accepting this request */
10264 ch_width = bandwidth;
10265
10266 if (!wlan_hdd_is_mon_channel_bw_valid(ch_width)) {
10267 hdd_err("invalid BW received %d", ch_width);
10268 return -EINVAL;
10269 }
10270
10271 max_fw_bw = sme_get_vht_ch_width();
10272
10273 hdd_debug("max fw BW %d ch width %d", max_fw_bw, ch_width);
10274 if ((ch_width == CH_WIDTH_160MHZ &&
10275 max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) ||
10276 (ch_width == CH_WIDTH_80P80MHZ &&
10277 max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)) {
10278 hdd_err("FW does not support this BW %d max BW supported %d",
10279 ch_width, max_fw_bw);
10280 return -EINVAL;
10281 }
10282
10283 if (!hdd_is_target_eht_phy_ch_width_supported(ch_width))
10284 return -EINVAL;
10285
10286 ret = hdd_validate_channel_and_bandwidth(adapter, freq, bandwidth);
10287 if (ret) {
10288 hdd_err("Invalid CH and BW combo");
10289 return ret;
10290 }
10291
10292 hdd_debug("Set monitor mode frequency %d", freq);
10293 qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
10294 QDF_MAC_ADDR_SIZE);
10295
10296 ch_params.ch_width = bandwidth;
10297 wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev, freq, 0,
10298 &ch_params,
10299 REG_CURRENT_PWR_MODE);
10300
10301 if (ch_params.ch_width == CH_WIDTH_INVALID) {
10302 hdd_err("Invalid capture channel or bandwidth for a country");
10303 return -EINVAL;
10304 }
10305 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, freq,
10306 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
10307 hdd_err("Failed to change hw mode");
10308 return -EINVAL;
10309 }
10310
10311 if (adapter->monitor_mode_vdev_up_in_progress) {
10312 hdd_err_rl("monitor mode vdev up in progress");
10313 return -EBUSY;
10314 }
10315
10316 status = qdf_event_reset(&adapter->qdf_monitor_mode_vdev_up_event);
10317 if (QDF_IS_STATUS_ERROR(status)) {
10318 hdd_err_rl("failed to reinit monitor mode vdev up event");
10319 return qdf_status_to_os_return(status);
10320 }
10321 adapter->monitor_mode_vdev_up_in_progress = true;
10322
10323 qdf_mem_zero(&ch_params, sizeof(struct ch_params));
10324
10325 req = qdf_mem_malloc(sizeof(struct channel_change_req));
10326 if (!req)
10327 return -ENOMEM;
10328 req->vdev_id = adapter->deflink->vdev_id;
10329 req->target_chan_freq = freq;
10330 req->ch_width = ch_width;
10331
10332 ch_params.ch_width = ch_width;
10333 hdd_select_cbmode(adapter, freq, 0, &ch_params);
10334
10335 req->sec_ch_offset = ch_params.sec_ch_offset;
10336 req->center_freq_seg0 = ch_params.center_freq_seg0;
10337 req->center_freq_seg1 = ch_params.center_freq_seg1;
10338
10339 sme_fill_channel_change_request(hdd_ctx->mac_handle, req,
10340 ch_info->phy_mode);
10341 status = sme_send_channel_change_req(hdd_ctx->mac_handle, req);
10342 qdf_mem_free(req);
10343 if (status) {
10344 hdd_err("Status: %d Failed to set sme_roam Channel for monitor mode",
10345 status);
10346 adapter->monitor_mode_vdev_up_in_progress = false;
10347 return qdf_status_to_os_return(status);
10348 }
10349
10350 adapter->mon_chan_freq = freq;
10351 adapter->mon_bandwidth = bandwidth;
10352
10353 /* block on a completion variable until vdev up success*/
10354 status = qdf_wait_for_event_completion(
10355 &adapter->qdf_monitor_mode_vdev_up_event,
10356 WLAN_MONITOR_MODE_VDEV_UP_EVT);
10357 if (QDF_IS_STATUS_ERROR(status)) {
10358 hdd_err_rl("monitor vdev up event time out vdev id: %d",
10359 adapter->deflink->vdev_id);
10360 if (adapter->qdf_monitor_mode_vdev_up_event.force_set)
10361 /*
10362 * SSR/PDR has caused shutdown, which has
10363 * forcefully set the event.
10364 */
10365 hdd_err_rl("monitor mode vdev up event forcefully set");
10366 else if (status == QDF_STATUS_E_TIMEOUT)
10367 hdd_err("monitor mode vdev up timed out");
10368 else
10369 hdd_err_rl("Failed monitor mode vdev up(status-%d)",
10370 status);
10371
10372 adapter->monitor_mode_vdev_up_in_progress = false;
10373 }
10374
10375 return qdf_status_to_os_return(status);
10376 }
10377 #endif
10378
10379 #if defined MSM_PLATFORM && (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0))
10380 /**
10381 * hdd_stop_p2p_go() - call cfg80211 API to stop P2P GO
10382 * @adapter: pointer to adapter
10383 *
10384 * This function calls cfg80211 API to stop P2P GO
10385 *
10386 * Return: None
10387 */
hdd_stop_p2p_go(struct hdd_adapter * adapter)10388 static void hdd_stop_p2p_go(struct hdd_adapter *adapter)
10389 {
10390 hdd_debug("[SSR] send stop ap to supplicant");
10391 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
10392 }
10393
hdd_delete_sta(struct hdd_adapter * adapter)10394 static inline void hdd_delete_sta(struct hdd_adapter *adapter)
10395 {
10396 }
10397
10398 #else
hdd_stop_p2p_go(struct hdd_adapter * adapter)10399 static void hdd_stop_p2p_go(struct hdd_adapter *adapter)
10400 {
10401 hdd_debug("[SSR] send stop iface ap to supplicant");
10402 cfg80211_stop_iface(adapter->hdd_ctx->wiphy, &adapter->wdev,
10403 GFP_KERNEL);
10404 }
10405
10406 /**
10407 * hdd_delete_sta() - call cfg80211 API to delete STA
10408 * @adapter: pointer to adapter
10409 *
10410 * This function calls cfg80211 API to delete STA
10411 *
10412 * Return: None
10413 */
hdd_delete_sta(struct hdd_adapter * adapter)10414 static void hdd_delete_sta(struct hdd_adapter *adapter)
10415 {
10416 struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT;
10417
10418 hdd_debug("[SSR] send restart supplicant");
10419 /* event supplicant to restart */
10420 cfg80211_del_sta(adapter->dev,
10421 (const u8 *)&bcast_mac.bytes[0],
10422 GFP_KERNEL);
10423 }
10424 #endif
10425
hdd_start_all_adapters(struct hdd_context * hdd_ctx,bool rtnl_held)10426 QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held)
10427 {
10428 struct hdd_adapter *adapter, *next_adapter = NULL;
10429 bool value;
10430 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_START_ALL_ADAPTERS;
10431 int ret;
10432
10433 hdd_enter();
10434
10435 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10436 dbgid) {
10437 if (!hdd_is_interface_up(adapter) &&
10438 adapter->device_mode != QDF_NDI_MODE) {
10439 hdd_adapter_dev_put_debug(adapter, dbgid);
10440 continue;
10441 }
10442
10443 hdd_debug("[SSR] start adapter with device mode %s(%d)",
10444 qdf_opmode_str(adapter->device_mode),
10445 adapter->device_mode);
10446
10447 hdd_wmm_dscp_initial_state(adapter);
10448
10449 switch (adapter->device_mode) {
10450 case QDF_STA_MODE:
10451 case QDF_P2P_CLIENT_MODE:
10452 case QDF_P2P_DEVICE_MODE:
10453 case QDF_NAN_DISC_MODE:
10454
10455 ret = hdd_start_station_adapter(adapter);
10456 if (ret) {
10457 hdd_err("[SSR] Failed to start station adapter: %d",
10458 ret);
10459 hdd_adapter_dev_put_debug(adapter, dbgid);
10460 continue;
10461 }
10462 if (adapter->device_mode == QDF_STA_MODE) {
10463 ret = hdd_start_link_adapter(adapter);
10464 if (ret) {
10465 hdd_err("[SSR] Failed to start link adapter: %d",
10466 ret);
10467 hdd_stop_adapter(hdd_ctx, adapter);
10468 hdd_adapter_dev_put_debug(adapter,
10469 dbgid);
10470 continue;
10471 }
10472 }
10473
10474 /* Open the gates for HDD to receive Wext commands */
10475 adapter->is_link_up_service_needed = false;
10476
10477 if ((adapter->device_mode == QDF_NAN_DISC_MODE ||
10478 (adapter->device_mode == QDF_STA_MODE &&
10479 !ucfg_nan_is_vdev_creation_allowed(
10480 hdd_ctx->psoc))) &&
10481 cds_is_driver_recovering())
10482 ucfg_nan_disable_ind_to_userspace(
10483 hdd_ctx->psoc);
10484
10485 hdd_register_tx_flow_control(adapter,
10486 hdd_tx_resume_timer_expired_handler,
10487 hdd_tx_resume_cb,
10488 hdd_tx_flow_control_is_pause);
10489
10490 hdd_register_hl_netdev_fc_timer(
10491 adapter,
10492 hdd_tx_resume_timer_expired_handler);
10493
10494 hdd_lpass_notify_start(adapter->deflink);
10495 break;
10496
10497 case QDF_SAP_MODE:
10498 ucfg_mlme_get_sap_internal_restart(hdd_ctx->psoc,
10499 &value);
10500 if (value)
10501 hdd_start_ap_adapter(adapter, rtnl_held);
10502
10503 break;
10504
10505 case QDF_P2P_GO_MODE:
10506 hdd_delete_sta(adapter);
10507 break;
10508 case QDF_MONITOR_MODE:
10509 if (wlan_hdd_is_session_type_monitor(
10510 adapter->device_mode) &&
10511 ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
10512 PACKET_CAPTURE_MODE_DISABLE) {
10513 struct hdd_adapter *sta_adapter;
10514
10515 sta_adapter = hdd_get_adapter(hdd_ctx,
10516 QDF_STA_MODE);
10517 if (!sta_adapter) {
10518 hdd_err("No station interface found");
10519 return -EINVAL;
10520 }
10521
10522 hdd_map_monitor_interface_vdev(sta_adapter);
10523 break;
10524 }
10525 hdd_start_station_adapter(adapter);
10526 hdd_set_mon_rx_cb(adapter->dev);
10527
10528 wlan_hdd_set_mon_chan(
10529 adapter, adapter->mon_chan_freq,
10530 adapter->mon_bandwidth);
10531 break;
10532 case QDF_NDI_MODE:
10533 hdd_ndi_start(adapter->dev->name, 0);
10534 break;
10535 default:
10536 break;
10537 }
10538 /*
10539 * Action frame registered in one adapter which will
10540 * applicable to all interfaces
10541 */
10542 if (hdd_set_fw_params(adapter))
10543 hdd_err("Failed to set adapter FW params after SSR!");
10544
10545 wlan_hdd_cfg80211_register_frames(adapter);
10546 hdd_create_adapter_sysfs_files(adapter);
10547 hdd_adapter_dev_put_debug(adapter, dbgid);
10548 }
10549
10550 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10551 dbgid) {
10552 if (!hdd_is_interface_up(adapter)) {
10553 hdd_adapter_dev_put_debug(adapter, dbgid);
10554 continue;
10555 }
10556
10557 if (adapter->device_mode == QDF_P2P_GO_MODE)
10558 hdd_stop_p2p_go(adapter);
10559
10560 hdd_adapter_dev_put_debug(adapter, dbgid);
10561 }
10562
10563 hdd_exit();
10564
10565 return QDF_STATUS_SUCCESS;
10566 }
10567
hdd_adapter_dev_hold_debug(struct hdd_adapter * adapter,wlan_net_dev_ref_dbgid dbgid)10568 void hdd_adapter_dev_hold_debug(struct hdd_adapter *adapter,
10569 wlan_net_dev_ref_dbgid dbgid)
10570 {
10571 if (dbgid >= NET_DEV_HOLD_ID_MAX) {
10572 hdd_err("Invalid debug id: %d", dbgid);
10573 QDF_BUG(0);
10574 }
10575 dev_hold(adapter->dev);
10576 qdf_atomic_inc(&adapter->net_dev_hold_ref_count[dbgid]);
10577 }
10578
hdd_adapter_dev_put_debug(struct hdd_adapter * adapter,wlan_net_dev_ref_dbgid dbgid)10579 void hdd_adapter_dev_put_debug(struct hdd_adapter *adapter,
10580 wlan_net_dev_ref_dbgid dbgid)
10581 {
10582 if (dbgid >= NET_DEV_HOLD_ID_MAX) {
10583 hdd_err("Invalid debug id: %d", dbgid);
10584 QDF_BUG(0);
10585 }
10586
10587 if (qdf_atomic_dec_return(
10588 &adapter->net_dev_hold_ref_count[dbgid]) < 0) {
10589 hdd_err("dev_put detected without dev_hold for debug id: %s",
10590 net_dev_ref_debug_string_from_id(dbgid));
10591 QDF_BUG(0);
10592 }
10593
10594 if (adapter->dev) {
10595 dev_put(adapter->dev);
10596 } else {
10597 hdd_err("adapter->dev is NULL");
10598 QDF_BUG(0);
10599 }
10600 }
10601
hdd_get_front_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter ** out_adapter)10602 QDF_STATUS hdd_get_front_adapter(struct hdd_context *hdd_ctx,
10603 struct hdd_adapter **out_adapter)
10604 {
10605 QDF_STATUS status;
10606 qdf_list_node_t *node;
10607
10608 *out_adapter = NULL;
10609
10610 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
10611 status = qdf_list_peek_front(&hdd_ctx->hdd_adapters, &node);
10612 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
10613
10614 if (QDF_IS_STATUS_ERROR(status))
10615 return status;
10616
10617 *out_adapter = qdf_container_of(node, struct hdd_adapter, node);
10618
10619 return QDF_STATUS_SUCCESS;
10620 }
10621
hdd_get_next_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter * current_adapter,struct hdd_adapter ** out_adapter)10622 QDF_STATUS hdd_get_next_adapter(struct hdd_context *hdd_ctx,
10623 struct hdd_adapter *current_adapter,
10624 struct hdd_adapter **out_adapter)
10625 {
10626 QDF_STATUS status;
10627 qdf_list_node_t *node;
10628
10629 *out_adapter = NULL;
10630
10631 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
10632 status = qdf_list_peek_next(&hdd_ctx->hdd_adapters,
10633 ¤t_adapter->node,
10634 &node);
10635 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
10636
10637 if (QDF_IS_STATUS_ERROR(status))
10638 return status;
10639
10640 *out_adapter = qdf_container_of(node, struct hdd_adapter, node);
10641
10642 return status;
10643 }
10644
hdd_get_front_adapter_no_lock(struct hdd_context * hdd_ctx,struct hdd_adapter ** out_adapter)10645 QDF_STATUS hdd_get_front_adapter_no_lock(struct hdd_context *hdd_ctx,
10646 struct hdd_adapter **out_adapter)
10647 {
10648 QDF_STATUS status;
10649 qdf_list_node_t *node;
10650
10651 *out_adapter = NULL;
10652
10653 status = qdf_list_peek_front(&hdd_ctx->hdd_adapters, &node);
10654
10655 if (QDF_IS_STATUS_ERROR(status))
10656 return status;
10657
10658 *out_adapter = qdf_container_of(node, struct hdd_adapter, node);
10659
10660 return QDF_STATUS_SUCCESS;
10661 }
10662
hdd_get_next_adapter_no_lock(struct hdd_context * hdd_ctx,struct hdd_adapter * current_adapter,struct hdd_adapter ** out_adapter)10663 QDF_STATUS hdd_get_next_adapter_no_lock(struct hdd_context *hdd_ctx,
10664 struct hdd_adapter *current_adapter,
10665 struct hdd_adapter **out_adapter)
10666 {
10667 QDF_STATUS status;
10668 qdf_list_node_t *node;
10669
10670 if (!current_adapter)
10671 return QDF_STATUS_E_INVAL;
10672
10673 *out_adapter = NULL;
10674
10675 status = qdf_list_peek_next(&hdd_ctx->hdd_adapters,
10676 ¤t_adapter->node,
10677 &node);
10678
10679 if (QDF_IS_STATUS_ERROR(status))
10680 return status;
10681
10682 *out_adapter = qdf_container_of(node, struct hdd_adapter, node);
10683
10684 return status;
10685 }
10686
hdd_remove_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)10687 QDF_STATUS hdd_remove_adapter(struct hdd_context *hdd_ctx,
10688 struct hdd_adapter *adapter)
10689 {
10690 QDF_STATUS status;
10691
10692 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
10693 status = qdf_list_remove_node(&hdd_ctx->hdd_adapters, &adapter->node);
10694 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
10695
10696 return status;
10697 }
10698
hdd_remove_front_adapter(struct hdd_context * hdd_ctx,struct hdd_adapter ** out_adapter)10699 QDF_STATUS hdd_remove_front_adapter(struct hdd_context *hdd_ctx,
10700 struct hdd_adapter **out_adapter)
10701 {
10702 QDF_STATUS status;
10703 qdf_list_node_t *node;
10704
10705 *out_adapter = NULL;
10706
10707 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
10708 status = qdf_list_remove_front(&hdd_ctx->hdd_adapters, &node);
10709 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
10710
10711 if (QDF_IS_STATUS_ERROR(status))
10712 return status;
10713
10714 *out_adapter = qdf_container_of(node, struct hdd_adapter, node);
10715
10716 return status;
10717 }
10718
hdd_add_adapter_back(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)10719 QDF_STATUS hdd_add_adapter_back(struct hdd_context *hdd_ctx,
10720 struct hdd_adapter *adapter)
10721 {
10722 QDF_STATUS status;
10723
10724 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
10725 status = qdf_list_insert_back(&hdd_ctx->hdd_adapters, &adapter->node);
10726 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
10727
10728 return status;
10729 }
10730
hdd_add_adapter_front(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)10731 QDF_STATUS hdd_add_adapter_front(struct hdd_context *hdd_ctx,
10732 struct hdd_adapter *adapter)
10733 {
10734 QDF_STATUS status;
10735
10736 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
10737 status = qdf_list_insert_front(&hdd_ctx->hdd_adapters, &adapter->node);
10738 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
10739
10740 return status;
10741 }
10742
hdd_validate_next_adapter(struct hdd_adapter ** curr,struct hdd_adapter ** next,wlan_net_dev_ref_dbgid dbg_id)10743 void hdd_validate_next_adapter(struct hdd_adapter **curr,
10744 struct hdd_adapter **next,
10745 wlan_net_dev_ref_dbgid dbg_id)
10746 {
10747 if (!*curr || !*next || *curr != *next)
10748 return;
10749
10750 hdd_err("Validation failed");
10751 hdd_adapter_dev_put_debug(*curr, dbg_id);
10752 *curr = NULL;
10753 *next = NULL;
10754 }
10755
hdd_adapter_iterate(hdd_adapter_iterate_cb cb,void * context)10756 QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb, void *context)
10757 {
10758 struct hdd_context *hdd_ctx;
10759 struct hdd_adapter *cache[HDD_MAX_ADAPTERS];
10760 struct hdd_adapter *adapter;
10761 uint32_t n_cache = 0;
10762 QDF_STATUS ret = QDF_STATUS_SUCCESS;
10763 QDF_STATUS status;
10764 int i;
10765 struct wlan_hdd_link_info *link_info;
10766
10767 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10768 if (unlikely(!hdd_ctx))
10769 return QDF_STATUS_E_FAILURE;
10770
10771 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
10772 for (hdd_get_front_adapter_no_lock(hdd_ctx, &adapter); adapter;
10773 hdd_get_next_adapter_no_lock(hdd_ctx, adapter, &adapter)) {
10774 cache[n_cache++] = adapter;
10775 }
10776 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
10777
10778 for (i = 0; i < n_cache; i++) {
10779 adapter = hdd_adapter_get_by_reference(hdd_ctx, cache[i]);
10780 if (!adapter) {
10781 /*
10782 * detected remove while iterating
10783 * concurrency failure
10784 */
10785 ret = QDF_STATUS_E_FAILURE;
10786 continue;
10787 }
10788 hdd_adapter_for_each_active_link_info(adapter, link_info) {
10789 status = cb(link_info, context);
10790 if (status != QDF_STATUS_SUCCESS) {
10791 hdd_adapter_put(adapter);
10792 return status;
10793 }
10794 }
10795 hdd_adapter_put(adapter);
10796 }
10797
10798 return ret;
10799 }
10800
hdd_get_adapter_by_rand_macaddr(struct hdd_context * hdd_ctx,tSirMacAddr mac_addr)10801 struct hdd_adapter *hdd_get_adapter_by_rand_macaddr(
10802 struct hdd_context *hdd_ctx, tSirMacAddr mac_addr)
10803 {
10804 struct hdd_adapter *adapter, *next_adapter = NULL;
10805 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_RAND_MACADDR;
10806 struct wlan_hdd_link_info *link_info;
10807
10808 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10809 dbgid) {
10810 if (adapter->device_mode != QDF_STA_MODE &&
10811 adapter->device_mode != QDF_P2P_CLIENT_MODE &&
10812 adapter->device_mode != QDF_P2P_DEVICE_MODE) {
10813 hdd_adapter_dev_put_debug(adapter, dbgid);
10814 continue;
10815 }
10816
10817 hdd_adapter_for_each_active_link_info(adapter, link_info) {
10818 if (ucfg_p2p_check_random_mac(hdd_ctx->psoc,
10819 link_info->vdev_id,
10820 mac_addr)) {
10821 hdd_adapter_dev_put_debug(adapter, dbgid);
10822 if (next_adapter)
10823 hdd_adapter_dev_put_debug(next_adapter,
10824 dbgid);
10825 return adapter;
10826 }
10827 }
10828 hdd_adapter_dev_put_debug(adapter, dbgid);
10829 }
10830
10831 return NULL;
10832 }
10833
10834 #ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
hdd_get_adapter_by_macaddr(struct hdd_context * hdd_ctx,tSirMacAddr mac_addr)10835 struct hdd_adapter *hdd_get_adapter_by_macaddr(struct hdd_context *hdd_ctx,
10836 tSirMacAddr mac_addr)
10837 {
10838 struct hdd_adapter *adapter, *next_adapter = NULL;
10839 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_MACADDR;
10840 struct qdf_mac_addr zero_mac_addr = QDF_MAC_ADDR_ZERO_INIT;
10841 struct wlan_hdd_link_info *link_info;
10842
10843 if (!qdf_mem_cmp(mac_addr, zero_mac_addr.bytes, sizeof(tSirMacAddr)))
10844 return NULL;
10845
10846 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10847 dbgid) {
10848 if (!qdf_mem_cmp(adapter->mac_addr.bytes,
10849 mac_addr, sizeof(tSirMacAddr))) {
10850 hdd_adapter_dev_put_debug(adapter, dbgid);
10851 if (next_adapter)
10852 hdd_adapter_dev_put_debug(next_adapter,
10853 dbgid);
10854 return adapter;
10855 }
10856 hdd_adapter_for_each_active_link_info(adapter, link_info) {
10857 if (!qdf_mem_cmp(link_info->link_addr.bytes,
10858 mac_addr, sizeof(tSirMacAddr))) {
10859 hdd_adapter_dev_put_debug(adapter, dbgid);
10860 if (next_adapter)
10861 hdd_adapter_dev_put_debug(next_adapter,
10862 dbgid);
10863 return adapter;
10864 }
10865 }
10866 hdd_adapter_dev_put_debug(adapter, dbgid);
10867 }
10868
10869 return NULL;
10870 }
10871
10872 struct wlan_hdd_link_info *
hdd_get_link_info_by_link_addr(struct hdd_context * hdd_ctx,struct qdf_mac_addr * link_addr)10873 hdd_get_link_info_by_link_addr(struct hdd_context *hdd_ctx,
10874 struct qdf_mac_addr *link_addr)
10875 {
10876 struct wlan_hdd_link_info *link_info;
10877 struct hdd_adapter *adapter, *next_adapter = NULL;
10878 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_MACADDR;
10879
10880 if (!link_addr || qdf_is_macaddr_zero(link_addr))
10881 return NULL;
10882
10883 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10884 dbgid) {
10885 hdd_adapter_for_each_link_info(adapter, link_info) {
10886 if (qdf_is_macaddr_equal(link_addr,
10887 &link_info->link_addr)) {
10888 hdd_adapter_dev_put_debug(adapter, dbgid);
10889 if (next_adapter)
10890 hdd_adapter_dev_put_debug(next_adapter,
10891 dbgid);
10892 return link_info;
10893 }
10894 }
10895 hdd_adapter_dev_put_debug(adapter, dbgid);
10896 }
10897
10898 return NULL;
10899 }
10900 #else
hdd_get_adapter_by_macaddr(struct hdd_context * hdd_ctx,tSirMacAddr mac_addr)10901 struct hdd_adapter *hdd_get_adapter_by_macaddr(struct hdd_context *hdd_ctx,
10902 tSirMacAddr mac_addr)
10903 {
10904 struct hdd_adapter *adapter, *next_adapter = NULL;
10905 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_MACADDR;
10906
10907 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10908 dbgid) {
10909 if (!qdf_mem_cmp(adapter->mac_addr.bytes,
10910 mac_addr, sizeof(tSirMacAddr))) {
10911 hdd_adapter_dev_put_debug(adapter, dbgid);
10912 if (next_adapter)
10913 hdd_adapter_dev_put_debug(next_adapter,
10914 dbgid);
10915 return adapter;
10916 }
10917
10918 if (hdd_adapter_is_sl_ml_adapter(adapter) &&
10919 !qdf_mem_cmp(adapter->mld_addr.bytes,
10920 mac_addr, sizeof(tSirMacAddr))) {
10921 hdd_adapter_dev_put_debug(adapter, dbgid);
10922 if (next_adapter)
10923 hdd_adapter_dev_put_debug(next_adapter, dbgid);
10924 return adapter;
10925 }
10926 hdd_adapter_dev_put_debug(adapter, dbgid);
10927 }
10928
10929 return NULL;
10930 }
10931
10932 struct wlan_hdd_link_info *
hdd_get_link_info_by_link_addr(struct hdd_context * hdd_ctx,struct qdf_mac_addr * link_addr)10933 hdd_get_link_info_by_link_addr(struct hdd_context *hdd_ctx,
10934 struct qdf_mac_addr *link_addr)
10935 {
10936 return NULL;
10937 }
10938 #endif
10939
10940 struct wlan_hdd_link_info *
hdd_get_link_info_by_vdev(struct hdd_context * hdd_ctx,uint32_t vdev_id)10941 hdd_get_link_info_by_vdev(struct hdd_context *hdd_ctx, uint32_t vdev_id)
10942 {
10943 struct hdd_adapter *adapter, *next_adapter = NULL;
10944 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_VDEV;
10945 struct wlan_hdd_link_info *link_info;
10946
10947 if (vdev_id == WLAN_INVALID_VDEV_ID)
10948 return NULL;
10949
10950 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10951 dbgid) {
10952 hdd_adapter_for_each_active_link_info(adapter, link_info) {
10953 if (link_info->vdev_id == vdev_id) {
10954 hdd_adapter_dev_put_debug(adapter, dbgid);
10955 if (next_adapter)
10956 hdd_adapter_dev_put_debug(next_adapter,
10957 dbgid);
10958 return link_info;
10959 }
10960 }
10961 hdd_adapter_dev_put_debug(adapter, dbgid);
10962 }
10963
10964 return NULL;
10965 }
10966
hdd_adapter_get_by_reference(struct hdd_context * hdd_ctx,struct hdd_adapter * reference)10967 struct hdd_adapter *hdd_adapter_get_by_reference(struct hdd_context *hdd_ctx,
10968 struct hdd_adapter *reference)
10969 {
10970 struct hdd_adapter *adapter, *next_adapter = NULL;
10971 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_ADAPTER_GET_BY_REFERENCE;
10972
10973 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
10974 dbgid) {
10975 if (adapter == reference) {
10976 dev_hold(adapter->dev);
10977 hdd_adapter_dev_put_debug(adapter, dbgid);
10978 if (next_adapter)
10979 hdd_adapter_dev_put_debug(next_adapter,
10980 dbgid);
10981 break;
10982 }
10983 hdd_adapter_dev_put_debug(adapter, dbgid);
10984 }
10985
10986 return adapter;
10987 }
10988
hdd_adapter_put(struct hdd_adapter * adapter)10989 void hdd_adapter_put(struct hdd_adapter *adapter)
10990 {
10991 dev_put(adapter->dev);
10992 }
10993
hdd_get_adapter_by_iface_name(struct hdd_context * hdd_ctx,const char * iface_name)10994 struct hdd_adapter *hdd_get_adapter_by_iface_name(struct hdd_context *hdd_ctx,
10995 const char *iface_name)
10996 {
10997 struct hdd_adapter *adapter, *next_adapter = NULL;
10998 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_IFACE_NAME;
10999
11000 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
11001 dbgid) {
11002 if (!qdf_str_cmp(adapter->dev->name, iface_name)) {
11003 hdd_adapter_dev_put_debug(adapter, dbgid);
11004 if (next_adapter)
11005 hdd_adapter_dev_put_debug(next_adapter,
11006 dbgid);
11007 return adapter;
11008 }
11009 hdd_adapter_dev_put_debug(adapter, dbgid);
11010 }
11011
11012 return NULL;
11013 }
11014
hdd_get_adapter_by_ifindex(struct hdd_context * hdd_ctx,uint32_t if_index)11015 struct hdd_adapter *hdd_get_adapter_by_ifindex(struct hdd_context *hdd_ctx,
11016 uint32_t if_index)
11017 {
11018 struct hdd_adapter *adapter, *next_adapter = NULL;
11019 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER;
11020
11021 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
11022 dbgid) {
11023 if (adapter->dev->ifindex == if_index) {
11024 hdd_adapter_dev_put_debug(adapter, dbgid);
11025 if (next_adapter)
11026 hdd_adapter_dev_put_debug(next_adapter,
11027 dbgid);
11028 return adapter;
11029 }
11030 hdd_adapter_dev_put_debug(adapter, dbgid);
11031 }
11032
11033 return NULL;
11034 }
11035
11036 /**
11037 * hdd_get_adapter() - to get adapter matching the mode
11038 * @hdd_ctx: hdd context
11039 * @mode: adapter mode
11040 *
11041 * This routine will return the pointer to adapter matching
11042 * with the passed mode.
11043 *
11044 * Return: pointer to adapter or null
11045 */
hdd_get_adapter(struct hdd_context * hdd_ctx,enum QDF_OPMODE mode)11046 struct hdd_adapter *hdd_get_adapter(struct hdd_context *hdd_ctx,
11047 enum QDF_OPMODE mode)
11048 {
11049 struct hdd_adapter *adapter, *next_adapter = NULL;
11050 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER;
11051
11052 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
11053 dbgid) {
11054 if (adapter->device_mode == mode) {
11055 hdd_adapter_dev_put_debug(adapter, dbgid);
11056 if (next_adapter)
11057 hdd_adapter_dev_put_debug(next_adapter,
11058 dbgid);
11059 return adapter;
11060 }
11061 hdd_adapter_dev_put_debug(adapter, dbgid);
11062 }
11063
11064 return NULL;
11065 }
11066
hdd_get_device_mode(uint32_t vdev_id)11067 enum QDF_OPMODE hdd_get_device_mode(uint32_t vdev_id)
11068 {
11069 struct hdd_context *hdd_ctx;
11070 struct wlan_hdd_link_info *link_info;
11071
11072 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11073 if (!hdd_ctx)
11074 return QDF_MAX_NO_OF_MODE;
11075
11076 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
11077 if (!link_info) {
11078 hdd_err("Invalid vdev");
11079 return QDF_MAX_NO_OF_MODE;
11080 }
11081
11082 return link_info->adapter->device_mode;
11083 }
11084
hdd_get_operating_chan_freq(struct hdd_context * hdd_ctx,enum QDF_OPMODE mode)11085 uint32_t hdd_get_operating_chan_freq(struct hdd_context *hdd_ctx,
11086 enum QDF_OPMODE mode)
11087 {
11088 struct hdd_adapter *adapter, *next_adapter = NULL;
11089 uint32_t oper_chan_freq = 0;
11090 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_OPERATING_CHAN_FREQ;
11091
11092 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
11093 dbgid) {
11094 if (mode == adapter->device_mode) {
11095 oper_chan_freq =
11096 hdd_get_link_info_home_channel(adapter->deflink);
11097 hdd_adapter_dev_put_debug(adapter, dbgid);
11098 if (next_adapter)
11099 hdd_adapter_dev_put_debug(next_adapter,
11100 dbgid);
11101 break;
11102 }
11103 hdd_adapter_dev_put_debug(adapter, dbgid);
11104 }
11105
11106 return oper_chan_freq;
11107 }
11108
hdd_unregister_wext_all_adapters(struct hdd_context * hdd_ctx,bool rtnl_held)11109 static inline QDF_STATUS hdd_unregister_wext_all_adapters(
11110 struct hdd_context *hdd_ctx,
11111 bool rtnl_held)
11112 {
11113 struct hdd_adapter *adapter, *next_adapter = NULL;
11114 wlan_net_dev_ref_dbgid dbgid =
11115 NET_DEV_HOLD_UNREGISTER_WEXT_ALL_ADAPTERS;
11116
11117 hdd_enter();
11118
11119 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
11120 dbgid) {
11121 if (adapter->device_mode == QDF_STA_MODE ||
11122 adapter->device_mode == QDF_P2P_CLIENT_MODE ||
11123 adapter->device_mode == QDF_P2P_DEVICE_MODE ||
11124 adapter->device_mode == QDF_SAP_MODE ||
11125 adapter->device_mode == QDF_P2P_GO_MODE) {
11126 hdd_wext_unregister(adapter->dev, rtnl_held);
11127 }
11128 hdd_adapter_dev_put_debug(adapter, dbgid);
11129 }
11130
11131 hdd_exit();
11132
11133 return QDF_STATUS_SUCCESS;
11134 }
11135
hdd_abort_mac_scan_all_adapters(struct hdd_context * hdd_ctx)11136 QDF_STATUS hdd_abort_mac_scan_all_adapters(struct hdd_context *hdd_ctx)
11137 {
11138 struct hdd_adapter *adapter, *next_adapter = NULL;
11139 wlan_net_dev_ref_dbgid dbgid =
11140 NET_DEV_HOLD_ABORT_MAC_SCAN_ALL_ADAPTERS;
11141 struct wlan_hdd_link_info *link_info;
11142
11143 hdd_enter();
11144
11145 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
11146 dbgid) {
11147 if (adapter->device_mode == QDF_STA_MODE ||
11148 adapter->device_mode == QDF_P2P_CLIENT_MODE ||
11149 adapter->device_mode == QDF_P2P_DEVICE_MODE ||
11150 adapter->device_mode == QDF_SAP_MODE ||
11151 adapter->device_mode == QDF_P2P_GO_MODE) {
11152 hdd_adapter_for_each_active_link_info(adapter,
11153 link_info) {
11154 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
11155 link_info->vdev_id,
11156 INVALID_SCAN_ID, true);
11157 }
11158 }
11159 hdd_adapter_dev_put_debug(adapter, dbgid);
11160 }
11161
11162 hdd_exit();
11163
11164 return QDF_STATUS_SUCCESS;
11165 }
11166
11167 /**
11168 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
11169 * adapters
11170 * @hdd_ctx: The HDD context containing the adapters to operate on
11171 *
11172 * return: QDF_STATUS_SUCCESS
11173 */
hdd_abort_sched_scan_all_adapters(struct hdd_context * hdd_ctx)11174 static QDF_STATUS hdd_abort_sched_scan_all_adapters(struct hdd_context *hdd_ctx)
11175 {
11176 struct hdd_adapter *adapter, *next_adapter = NULL;
11177 int err;
11178 wlan_net_dev_ref_dbgid dbgid =
11179 NET_DEV_HOLD_ABORT_SCHED_SCAN_ALL_ADAPTERS;
11180
11181 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
11182 dbgid) {
11183 if (adapter->device_mode == QDF_STA_MODE ||
11184 adapter->device_mode == QDF_P2P_CLIENT_MODE ||
11185 adapter->device_mode == QDF_P2P_DEVICE_MODE ||
11186 adapter->device_mode == QDF_SAP_MODE ||
11187 adapter->device_mode == QDF_P2P_GO_MODE) {
11188 err = wlan_hdd_sched_scan_stop(adapter->dev);
11189 if (err)
11190 hdd_err("Unable to stop scheduled scan");
11191 }
11192 hdd_adapter_dev_put_debug(adapter, dbgid);
11193 }
11194
11195 return QDF_STATUS_SUCCESS;
11196 }
11197
11198 /**
11199 * hdd_unregister_notifiers - Unregister netdev notifiers.
11200 * @hdd_ctx: HDD context
11201 *
11202 * Unregister netdev notifiers like IPv4 and IPv6.
11203 *
11204 * Return: None.
11205 */
hdd_unregister_notifiers(struct hdd_context * hdd_ctx)11206 void hdd_unregister_notifiers(struct hdd_context *hdd_ctx)
11207 {
11208 osif_dp_nud_unregister_netevent_notifier(hdd_ctx->psoc);
11209 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
11210
11211 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
11212 }
11213
11214 /**
11215 * hdd_exit_netlink_services - Exit netlink services
11216 * @hdd_ctx: HDD context
11217 *
11218 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
11219 * nl service.
11220 *
11221 * Return: None.
11222 */
hdd_exit_netlink_services(struct hdd_context * hdd_ctx)11223 static void hdd_exit_netlink_services(struct hdd_context *hdd_ctx)
11224 {
11225 spectral_scan_deactivate_service();
11226 cnss_diag_deactivate_service();
11227 hdd_close_cesium_nl_sock();
11228 ptt_sock_deactivate_svc();
11229 hdd_deactivate_wifi_pos();
11230
11231 nl_srv_exit();
11232 }
11233
11234 /**
11235 * hdd_init_netlink_services- Init netlink services
11236 * @hdd_ctx: HDD context
11237 *
11238 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
11239 * nl service.
11240 *
11241 * Return: 0 on success and errno on failure.
11242 */
hdd_init_netlink_services(struct hdd_context * hdd_ctx)11243 static int hdd_init_netlink_services(struct hdd_context *hdd_ctx)
11244 {
11245 int ret;
11246
11247 ret = wlan_hdd_nl_init(hdd_ctx);
11248 if (ret) {
11249 hdd_err("nl_srv_init failed: %d", ret);
11250 goto out;
11251 }
11252 cds_set_radio_index(hdd_ctx->radio_index);
11253
11254 ret = hdd_activate_wifi_pos(hdd_ctx);
11255 if (ret) {
11256 hdd_err("hdd_activate_wifi_pos failed: %d", ret);
11257 goto err_nl_srv;
11258 }
11259
11260 ptt_sock_activate_svc();
11261
11262 ret = hdd_open_cesium_nl_sock();
11263 if (ret)
11264 hdd_err("hdd_open_cesium_nl_sock failed ret: %d", ret);
11265
11266 ret = cnss_diag_activate_service();
11267 if (ret) {
11268 hdd_err("cnss_diag_activate_service failed: %d", ret);
11269 goto err_close_cesium;
11270 }
11271
11272 spectral_scan_activate_service(hdd_ctx);
11273
11274 return 0;
11275
11276 err_close_cesium:
11277 hdd_close_cesium_nl_sock();
11278 ptt_sock_deactivate_svc();
11279 hdd_deactivate_wifi_pos();
11280 err_nl_srv:
11281 nl_srv_exit();
11282 out:
11283 return ret;
11284 }
11285
11286 #ifdef SHUTDOWN_WLAN_IN_SYSTEM_SUSPEND
11287 static QDF_STATUS
hdd_shutdown_wlan_in_suspend_prepare(struct hdd_context * hdd_ctx)11288 hdd_shutdown_wlan_in_suspend_prepare(struct hdd_context *hdd_ctx)
11289 {
11290 #define SHUTDOWN_IN_SUSPEND_RETRY 30
11291
11292 int count = 0;
11293 enum pmo_suspend_mode mode;
11294
11295 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
11296 hdd_debug("Driver Modules not Enabled ");
11297 return 0;
11298 }
11299
11300 mode = ucfg_pmo_get_suspend_mode(hdd_ctx->psoc);
11301 hdd_debug("suspend mode is %d", mode);
11302
11303 if (mode == PMO_SUSPEND_NONE || mode == PMO_SUSPEND_LEGENCY) {
11304 hdd_debug("needn't shutdown in suspend");
11305 return 0;
11306 }
11307
11308 if (!hdd_is_any_interface_open(hdd_ctx)) {
11309 return pld_idle_shutdown(hdd_ctx->parent_dev,
11310 hdd_psoc_idle_shutdown);
11311 } else {
11312 if (mode == PMO_SUSPEND_WOW)
11313 return 0;
11314 }
11315
11316 /*try to wait interface down for PMO_SUSPEND_SHUTDOWN mode*/
11317 while (hdd_is_any_interface_open(hdd_ctx) &&
11318 count < SHUTDOWN_IN_SUSPEND_RETRY) {
11319 count++;
11320 hdd_debug_rl("sleep 50ms to wait adapters stopped, #%d", count);
11321 msleep(50);
11322 }
11323 if (count >= SHUTDOWN_IN_SUSPEND_RETRY) {
11324 hdd_err("some adapters not stopped");
11325 return -EBUSY;
11326 }
11327 return pld_idle_shutdown(hdd_ctx->parent_dev, hdd_psoc_idle_shutdown);
11328 }
11329
hdd_pm_notify(struct notifier_block * b,unsigned long event,void * p)11330 static int hdd_pm_notify(struct notifier_block *b,
11331 unsigned long event, void *p)
11332 {
11333 struct hdd_context *hdd_ctx = container_of(b, struct hdd_context,
11334 pm_notifier);
11335
11336 if (wlan_hdd_validate_context(hdd_ctx) != 0)
11337 return NOTIFY_STOP;
11338
11339 hdd_debug("got PM event: %lu", event);
11340
11341 switch (event) {
11342 case PM_SUSPEND_PREPARE:
11343 case PM_HIBERNATION_PREPARE:
11344 if (0 != hdd_shutdown_wlan_in_suspend_prepare(hdd_ctx))
11345 return NOTIFY_STOP;
11346 break;
11347 case PM_POST_SUSPEND:
11348 case PM_POST_HIBERNATION:
11349 break;
11350 }
11351
11352 return NOTIFY_DONE;
11353 }
11354
hdd_pm_notifier_init(struct hdd_context * hdd_ctx)11355 static void hdd_pm_notifier_init(struct hdd_context *hdd_ctx)
11356 {
11357 hdd_ctx->pm_notifier.notifier_call = hdd_pm_notify;
11358 register_pm_notifier(&hdd_ctx->pm_notifier);
11359 }
11360
hdd_pm_notifier_deinit(struct hdd_context * hdd_ctx)11361 static void hdd_pm_notifier_deinit(struct hdd_context *hdd_ctx)
11362 {
11363 unregister_pm_notifier(&hdd_ctx->pm_notifier);
11364 }
11365 #else
hdd_pm_notifier_init(struct hdd_context * hdd_ctx)11366 static inline void hdd_pm_notifier_init(struct hdd_context *hdd_ctx)
11367 {
11368 }
11369
hdd_pm_notifier_deinit(struct hdd_context * hdd_ctx)11370 static inline void hdd_pm_notifier_deinit(struct hdd_context *hdd_ctx)
11371 {
11372 }
11373 #endif
11374
11375 /**
11376 * hdd_context_deinit() - Deinitialize HDD context
11377 * @hdd_ctx: HDD context.
11378 *
11379 * Deinitialize HDD context along with all the feature specific contexts but
11380 * do not free hdd context itself. Caller of this API is supposed to free
11381 * HDD context.
11382 *
11383 * return: 0 on success and errno on failure.
11384 */
hdd_context_deinit(struct hdd_context * hdd_ctx)11385 static int hdd_context_deinit(struct hdd_context *hdd_ctx)
11386 {
11387 hdd_lpc_delete_work(hdd_ctx);
11388
11389 qdf_wake_lock_destroy(&hdd_ctx->monitor_mode_wakelock);
11390
11391 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
11392
11393 ucfg_dp_bbm_context_deinit(hdd_ctx->psoc);
11394
11395 hdd_sap_context_destroy(hdd_ctx);
11396
11397 hdd_scan_context_destroy(hdd_ctx);
11398
11399 qdf_list_destroy(&hdd_ctx->hdd_adapters);
11400
11401 return 0;
11402 }
11403
hdd_context_destroy(struct hdd_context * hdd_ctx)11404 void hdd_context_destroy(struct hdd_context *hdd_ctx)
11405 {
11406 wlan_hdd_sar_timers_deinit(hdd_ctx);
11407
11408 cds_set_context(QDF_MODULE_ID_HDD, NULL);
11409
11410 hdd_exit_netlink_services(hdd_ctx);
11411
11412 hdd_context_deinit(hdd_ctx);
11413
11414 hdd_objmgr_release_and_destroy_psoc(hdd_ctx);
11415
11416 qdf_mem_free(hdd_ctx->config);
11417 hdd_ctx->config = NULL;
11418 cfg_release();
11419
11420 hdd_pm_notifier_deinit(hdd_ctx);
11421 qdf_delayed_work_destroy(&hdd_ctx->psoc_idle_timeout_work);
11422 wiphy_free(hdd_ctx->wiphy);
11423 }
11424
11425 /**
11426 * wlan_destroy_bug_report_lock() - Destroy bug report lock
11427 *
11428 * This function is used to destroy bug report lock
11429 *
11430 * Return: None
11431 */
wlan_destroy_bug_report_lock(void)11432 static void wlan_destroy_bug_report_lock(void)
11433 {
11434 struct cds_context *p_cds_context;
11435
11436 p_cds_context = cds_get_global_context();
11437 if (!p_cds_context) {
11438 hdd_err("cds context is NULL");
11439 return;
11440 }
11441
11442 qdf_spinlock_destroy(&p_cds_context->bug_report_lock);
11443 }
11444
11445 #ifdef DISABLE_CHANNEL_LIST
wlan_hdd_cache_chann_mutex_destroy(struct hdd_context * hdd_ctx)11446 static void wlan_hdd_cache_chann_mutex_destroy(struct hdd_context *hdd_ctx)
11447 {
11448 qdf_mutex_destroy(&hdd_ctx->cache_channel_lock);
11449 }
11450 #else
wlan_hdd_cache_chann_mutex_destroy(struct hdd_context * hdd_ctx)11451 static void wlan_hdd_cache_chann_mutex_destroy(struct hdd_context *hdd_ctx)
11452 {
11453 }
11454 #endif
11455
hdd_wlan_exit(struct hdd_context * hdd_ctx)11456 void hdd_wlan_exit(struct hdd_context *hdd_ctx)
11457 {
11458 struct wiphy *wiphy = hdd_ctx->wiphy;
11459
11460 hdd_enter();
11461
11462 ucfg_dp_wait_complete_tasks();
11463 wlan_hdd_destroy_mib_stats_lock();
11464 hdd_debugfs_ini_config_deinit(hdd_ctx);
11465 hdd_debugfs_mws_coex_info_deinit(hdd_ctx);
11466 hdd_psoc_idle_timer_stop(hdd_ctx);
11467 hdd_regulatory_deinit(hdd_ctx);
11468
11469 /*
11470 * Powersave Offload Case
11471 * Disable Idle Power Save Mode
11472 */
11473 hdd_set_idle_ps_config(hdd_ctx, false);
11474 /* clear the scan queue in all the scenarios */
11475 wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, NULL);
11476
11477 if (hdd_ctx->driver_status != DRIVER_MODULES_CLOSED) {
11478 hdd_unregister_wext_all_adapters(hdd_ctx, false);
11479 /*
11480 * Cancel any outstanding scan requests. We are about to close
11481 * all of our adapters, but an adapter structure is what SME
11482 * passes back to our callback function. Hence if there
11483 * are any outstanding scan requests then there is a
11484 * race condition between when the adapter is closed and
11485 * when the callback is invoked. We try to resolve that
11486 * race condition here by canceling any outstanding scans
11487 * before we close the adapters.
11488 * Note that the scans may be cancelled in an asynchronous
11489 * manner, so ideally there needs to be some kind of
11490 * synchronization. Rather than introduce a new
11491 * synchronization here, we will utilize the fact that we are
11492 * about to Request Full Power, and since that is synchronized,
11493 * the expectation is that by the time Request Full Power has
11494 * completed, all scans will be cancelled
11495 */
11496 hdd_abort_mac_scan_all_adapters(hdd_ctx);
11497 hdd_abort_sched_scan_all_adapters(hdd_ctx);
11498
11499 hdd_stop_all_adapters(hdd_ctx);
11500 hdd_deinit_all_adapters(hdd_ctx, false);
11501 }
11502
11503 unregister_netdevice_notifier(&hdd_netdev_notifier);
11504
11505 qdf_dp_trace_deinit();
11506
11507 hdd_wlan_stop_modules(hdd_ctx, false);
11508
11509 hdd_driver_memdump_deinit();
11510
11511 qdf_nbuf_deinit_replenish_timer();
11512
11513 if (QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
11514 hdd_info("Release wakelock for monitor mode!");
11515 qdf_wake_lock_release(&hdd_ctx->monitor_mode_wakelock,
11516 WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);
11517 }
11518
11519 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
11520 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
11521 wlan_hdd_cache_chann_mutex_destroy(hdd_ctx);
11522
11523 osif_request_manager_deinit();
11524
11525 hdd_close_all_adapters(hdd_ctx, false);
11526
11527 wlansap_global_deinit();
11528 /*
11529 * If there is re_init failure wiphy would have already de-registered
11530 * check the wiphy status before un-registering again
11531 */
11532 if (wiphy && wiphy->registered) {
11533 wiphy_unregister(wiphy);
11534 wlan_hdd_cfg80211_deinit(wiphy);
11535 hdd_lpass_notify_stop(hdd_ctx);
11536 }
11537
11538 hdd_deinit_regulatory_update_event(hdd_ctx);
11539 hdd_exit_netlink_services(hdd_ctx);
11540 #ifdef FEATURE_WLAN_CH_AVOID
11541 mutex_destroy(&hdd_ctx->avoid_freq_lock);
11542 #endif
11543
11544 /* This function should be invoked at the end of this api*/
11545 hdd_dump_func_call_map();
11546 }
11547
11548 /**
11549 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
11550 * @state: state
11551 *
11552 * This function notifies FW with modem power status
11553 *
11554 * Return: 0 if successful, error number otherwise
11555 */
hdd_wlan_notify_modem_power_state(int state)11556 int hdd_wlan_notify_modem_power_state(int state)
11557 {
11558 int status;
11559 QDF_STATUS qdf_status;
11560 struct hdd_context *hdd_ctx;
11561 mac_handle_t mac_handle;
11562
11563 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11564 status = wlan_hdd_validate_context(hdd_ctx);
11565 if (status)
11566 return status;
11567
11568 mac_handle = hdd_ctx->mac_handle;
11569 if (!mac_handle)
11570 return -EINVAL;
11571
11572 qdf_status = sme_notify_modem_power_state(mac_handle, state);
11573 if (QDF_STATUS_SUCCESS != qdf_status) {
11574 hdd_err("Fail to send notification with modem power state %d",
11575 state);
11576 return -EINVAL;
11577 }
11578 return 0;
11579 }
11580
11581 /**
11582 * hdd_post_cds_enable_config() - HDD post cds start config helper
11583 * @hdd_ctx: Pointer to the HDD
11584 *
11585 * Return: None
11586 */
hdd_post_cds_enable_config(struct hdd_context * hdd_ctx)11587 QDF_STATUS hdd_post_cds_enable_config(struct hdd_context *hdd_ctx)
11588 {
11589 QDF_STATUS qdf_ret_status;
11590
11591 /*
11592 * Send ready indication to the HDD. This will kick off the MAC
11593 * into a 'running' state and should kick off an initial scan.
11594 */
11595 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->mac_handle);
11596 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
11597 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
11598 qdf_ret_status, qdf_ret_status);
11599 return QDF_STATUS_E_FAILURE;
11600 }
11601
11602 return QDF_STATUS_SUCCESS;
11603 }
11604
hdd_get_first_valid_adapter(struct hdd_context * hdd_ctx)11605 struct hdd_adapter *hdd_get_first_valid_adapter(struct hdd_context *hdd_ctx)
11606 {
11607 struct hdd_adapter *adapter, *next_adapter = NULL;
11608 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_FIRST_VALID_ADAPTER;
11609
11610 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
11611 dbgid) {
11612 if (adapter && adapter->magic == WLAN_HDD_ADAPTER_MAGIC) {
11613 hdd_adapter_dev_put_debug(adapter, dbgid);
11614 if (next_adapter)
11615 hdd_adapter_dev_put_debug(next_adapter,
11616 dbgid);
11617 return adapter;
11618 }
11619 hdd_adapter_dev_put_debug(adapter, dbgid);
11620 }
11621
11622 return NULL;
11623 }
11624
11625 /* wake lock APIs for HDD */
hdd_prevent_suspend(uint32_t reason)11626 void hdd_prevent_suspend(uint32_t reason)
11627 {
11628 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
11629 }
11630
hdd_allow_suspend(uint32_t reason)11631 void hdd_allow_suspend(uint32_t reason)
11632 {
11633 qdf_wake_lock_release(&wlan_wake_lock, reason);
11634 }
11635
hdd_prevent_suspend_timeout(uint32_t timeout,uint32_t reason)11636 void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
11637 {
11638 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
11639 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
11640 }
11641
11642 /* Initialize channel list in sme based on the country code */
hdd_set_sme_chan_list(struct hdd_context * hdd_ctx)11643 QDF_STATUS hdd_set_sme_chan_list(struct hdd_context *hdd_ctx)
11644 {
11645 return sme_init_chan_list(hdd_ctx->mac_handle,
11646 hdd_ctx->reg.cc_src);
11647 }
11648
11649 /**
11650 * hdd_is_5g_supported() - check if hardware supports 5GHz
11651 * @hdd_ctx: Pointer to the hdd context
11652 *
11653 * HDD function to know if hardware supports 5GHz
11654 *
11655 * Return: true if hardware supports 5GHz
11656 */
hdd_is_5g_supported(struct hdd_context * hdd_ctx)11657 bool hdd_is_5g_supported(struct hdd_context *hdd_ctx)
11658 {
11659 if (!hdd_ctx)
11660 return true;
11661
11662 if (hdd_ctx->curr_band != BAND_2G)
11663 return true;
11664 else
11665 return false;
11666 }
11667
hdd_is_2g_supported(struct hdd_context * hdd_ctx)11668 bool hdd_is_2g_supported(struct hdd_context *hdd_ctx)
11669 {
11670 if (!hdd_ctx)
11671 return false;
11672
11673 if (hdd_ctx->curr_band != BAND_5G)
11674 return true;
11675 else
11676 return false;
11677 }
11678
hdd_wiphy_init(struct hdd_context * hdd_ctx)11679 static int hdd_wiphy_init(struct hdd_context *hdd_ctx)
11680 {
11681 struct wiphy *wiphy;
11682 int ret_val;
11683 uint32_t channel_bonding_mode;
11684
11685 wiphy = hdd_ctx->wiphy;
11686
11687 /*
11688 * The channel information in
11689 * wiphy needs to be initialized before wiphy registration
11690 */
11691 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
11692 if (ret_val) {
11693 hdd_err("regulatory init failed");
11694 return ret_val;
11695 }
11696
11697 if (ucfg_pmo_get_suspend_mode(hdd_ctx->psoc) == PMO_SUSPEND_WOW) {
11698 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
11699 wiphy->wowlan = &wowlan_support_reg_init;
11700 #else
11701 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
11702 WIPHY_WOWLAN_MAGIC_PKT |
11703 WIPHY_WOWLAN_DISCONNECT |
11704 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
11705 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
11706 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
11707 WIPHY_WOWLAN_4WAY_HANDSHAKE |
11708 WIPHY_WOWLAN_RFKILL_RELEASE;
11709
11710 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
11711 WOW_MAX_FILTERS_PER_LIST);
11712 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
11713 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
11714 #endif
11715 }
11716
11717 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
11718 &channel_bonding_mode);
11719 if (hdd_ctx->obss_scan_offload) {
11720 hdd_debug("wmi_service_obss_scan supported");
11721 } else if (channel_bonding_mode) {
11722 hdd_debug("enable wpa_supp obss_scan");
11723 wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN;
11724 }
11725
11726 if (hdd_ctx->num_rf_chains == HDD_ANTENNA_MODE_2X2 &&
11727 ucfg_mlme_is_chain_mask_supported(hdd_ctx->psoc)) {
11728 wiphy->available_antennas_tx = HDD_CHAIN_MODE_2X2;
11729 wiphy->available_antennas_rx = HDD_CHAIN_MODE_2X2;
11730 }
11731 /* registration of wiphy dev with cfg80211 */
11732 ret_val = wlan_hdd_cfg80211_register(wiphy);
11733 if (0 > ret_val) {
11734 hdd_err("wiphy registration failed");
11735 return ret_val;
11736 }
11737
11738 /* Check the kernel version for upstream commit aced43ce780dc5 that
11739 * has support for processing user cell_base hints when wiphy is
11740 * self managed or check the backport flag for the same.
11741 */
11742 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
11743 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
11744 hdd_send_wiphy_regd_sync_event(hdd_ctx);
11745 #endif
11746
11747 pld_increment_driver_load_cnt(hdd_ctx->parent_dev);
11748
11749 return ret_val;
11750 }
11751
11752 #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH
11753 #ifdef CLD_PM_QOS
11754 #define PLD_REMOVE_PM_QOS(x)
11755 #define PLD_REQUEST_PM_QOS(x, y)
11756 #define HDD_PM_QOS_HIGH_TPUT_LATENCY_US 1
11757
11758 /**
11759 * hdd_pm_qos_update_cpu_mask() - Prepare CPU mask for PM_qos voting
11760 * @mask: return variable of cpumask for the TPUT
11761 * @enable_perf_cluster: Enable PERF cluster or not
11762 *
11763 * By default, the function sets CPU mask for silver cluster unless
11764 * enable_perf_cluster is set as true.
11765 *
11766 * Return: none
11767 */
hdd_pm_qos_update_cpu_mask(cpumask_t * mask,bool enable_perf_cluster)11768 static inline void hdd_pm_qos_update_cpu_mask(cpumask_t *mask,
11769 bool enable_perf_cluster)
11770 {
11771 cpumask_set_cpu(0, mask);
11772 cpumask_set_cpu(1, mask);
11773 cpumask_set_cpu(2, mask);
11774 cpumask_set_cpu(3, mask);
11775
11776 if (enable_perf_cluster) {
11777 cpumask_set_cpu(4, mask);
11778 cpumask_set_cpu(5, mask);
11779 cpumask_set_cpu(6, mask);
11780 }
11781 }
11782
11783 #ifdef MSM_PLATFORM
11784 #define COPY_CPU_MASK(a, b) cpumask_copy(a, b)
11785 #define DUMP_CPU_AFFINE() hdd_info("Set cpu_mask %*pb for affine_cores", \
11786 cpumask_pr_args(&hdd_ctx->pm_qos_req.cpus_affine))
11787 #else
11788 #define COPY_CPU_MASK(a, b) /* no-op*/
11789 #define DUMP_CPU_AFFINE() /* no-op*/
11790 #endif
11791
11792 #ifdef CLD_DEV_PM_QOS
11793
_hdd_pm_qos_update_request(struct hdd_context * hdd_ctx,cpumask_t * pm_qos_cpu_mask,unsigned int latency)11794 static inline void _hdd_pm_qos_update_request(struct hdd_context *hdd_ctx,
11795 cpumask_t *pm_qos_cpu_mask,
11796 unsigned int latency)
11797 {
11798 int cpu;
11799 uint32_t default_latency;
11800
11801 default_latency = wlan_hdd_get_default_pm_qos_cpu_latency();
11802 qdf_cpumask_copy(&hdd_ctx->qos_cpu_mask, pm_qos_cpu_mask);
11803
11804 if (qdf_cpumask_empty(pm_qos_cpu_mask)) {
11805 for_each_present_cpu(cpu) {
11806 dev_pm_qos_update_request(
11807 &hdd_ctx->pm_qos_req[cpu],
11808 default_latency);
11809 }
11810 hdd_debug("Empty mask %*pb: Set latency %u",
11811 qdf_cpumask_pr_args(&hdd_ctx->qos_cpu_mask),
11812 default_latency);
11813 } else { /* Set latency to default for CPUs not included in mask */
11814 qdf_for_each_cpu_not(cpu, &hdd_ctx->qos_cpu_mask) {
11815 dev_pm_qos_update_request(
11816 &hdd_ctx->pm_qos_req[cpu],
11817 default_latency);
11818 }
11819 /* Set latency for CPUs included in mask */
11820 qdf_for_each_cpu(cpu, &hdd_ctx->qos_cpu_mask) {
11821 dev_pm_qos_update_request(
11822 &hdd_ctx->pm_qos_req[cpu],
11823 latency);
11824 }
11825 hdd_debug("For qos_cpu_mask %*pb set latency %u",
11826 qdf_cpumask_pr_args(&hdd_ctx->qos_cpu_mask),
11827 latency);
11828 }
11829 }
11830
11831 /**
11832 * hdd_pm_qos_update_request() - API to request for pm_qos
11833 * @hdd_ctx: handle to hdd context
11834 * @pm_qos_cpu_mask: cpu_mask to apply
11835 *
11836 * Return: none
11837 */
hdd_pm_qos_update_request(struct hdd_context * hdd_ctx,cpumask_t * pm_qos_cpu_mask)11838 static void hdd_pm_qos_update_request(struct hdd_context *hdd_ctx,
11839 cpumask_t *pm_qos_cpu_mask)
11840 {
11841 unsigned int latency;
11842
11843 if (qdf_cpumask_empty(pm_qos_cpu_mask))
11844 latency = wlan_hdd_get_default_pm_qos_cpu_latency();
11845 else
11846 latency = HDD_PM_QOS_HIGH_TPUT_LATENCY_US;
11847
11848 _hdd_pm_qos_update_request(hdd_ctx, pm_qos_cpu_mask, latency);
11849 }
11850
hdd_pm_qos_add_request(struct hdd_context * hdd_ctx)11851 static inline void hdd_pm_qos_add_request(struct hdd_context *hdd_ctx)
11852 {
11853 struct device *cpu_dev;
11854 int cpu;
11855 uint32_t default_latency = wlan_hdd_get_default_pm_qos_cpu_latency();
11856
11857
11858 qdf_cpumask_clear(&hdd_ctx->qos_cpu_mask);
11859 hdd_pm_qos_update_cpu_mask(&hdd_ctx->qos_cpu_mask, false);
11860
11861 for_each_present_cpu(cpu) {
11862 cpu_dev = get_cpu_device(cpu);
11863 dev_pm_qos_add_request(cpu_dev, &hdd_ctx->pm_qos_req[cpu],
11864 DEV_PM_QOS_RESUME_LATENCY,
11865 default_latency);
11866 hdd_debug("Set qos_cpu_mask %*pb for affine_cores",
11867 cpumask_pr_args(&hdd_ctx->qos_cpu_mask));
11868 }
11869 }
11870
hdd_pm_qos_remove_request(struct hdd_context * hdd_ctx)11871 static inline void hdd_pm_qos_remove_request(struct hdd_context *hdd_ctx)
11872 {
11873 int cpu;
11874
11875 for_each_present_cpu(cpu) {
11876 dev_pm_qos_remove_request(&hdd_ctx->pm_qos_req[cpu]);
11877 hdd_debug("Remove dev_pm_qos_request for all cpus: %d", cpu);
11878 }
11879 qdf_cpumask_clear(&hdd_ctx->qos_cpu_mask);
11880 }
11881
11882 #else /* CLD_DEV_PM_QOS */
11883
11884 #if defined(CONFIG_SMP) && defined(MSM_PLATFORM)
11885 /**
11886 * hdd_set_default_pm_qos_mask() - Update PM_qos request for AFFINE_CORES
11887 * @hdd_ctx: handle to hdd context
11888 *
11889 * Return: none
11890 */
hdd_set_default_pm_qos_mask(struct hdd_context * hdd_ctx)11891 static inline void hdd_set_default_pm_qos_mask(struct hdd_context *hdd_ctx)
11892 {
11893 hdd_ctx->pm_qos_req.type = PM_QOS_REQ_AFFINE_CORES;
11894 qdf_cpumask_clear(&hdd_ctx->pm_qos_req.cpus_affine);
11895 hdd_pm_qos_update_cpu_mask(&hdd_ctx->pm_qos_req.cpus_affine, false);
11896 }
11897 #else
hdd_set_default_pm_qos_mask(struct hdd_context * hdd_ctx)11898 static inline void hdd_set_default_pm_qos_mask(struct hdd_context *hdd_ctx)
11899 {
11900 }
11901 #endif
11902
11903 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
11904 /**
11905 * hdd_pm_qos_update_request() - API to request for pm_qos
11906 * @hdd_ctx: handle to hdd context
11907 * @pm_qos_cpu_mask: cpu_mask to apply
11908 *
11909 * Return: none
11910 */
hdd_pm_qos_update_request(struct hdd_context * hdd_ctx,cpumask_t * pm_qos_cpu_mask)11911 static inline void hdd_pm_qos_update_request(struct hdd_context *hdd_ctx,
11912 cpumask_t *pm_qos_cpu_mask)
11913 {
11914 COPY_CPU_MASK(&hdd_ctx->pm_qos_req.cpus_affine, pm_qos_cpu_mask);
11915
11916 if (cpumask_empty(pm_qos_cpu_mask))
11917 cpu_latency_qos_update_request(&hdd_ctx->pm_qos_req,
11918 PM_QOS_DEFAULT_VALUE);
11919 else
11920 cpu_latency_qos_update_request(&hdd_ctx->pm_qos_req, 1);
11921 }
11922
hdd_pm_qos_add_request(struct hdd_context * hdd_ctx)11923 static inline void hdd_pm_qos_add_request(struct hdd_context *hdd_ctx)
11924 {
11925 hdd_set_default_pm_qos_mask(hdd_ctx);
11926 cpu_latency_qos_add_request(&hdd_ctx->pm_qos_req, PM_QOS_DEFAULT_VALUE);
11927 DUMP_CPU_AFFINE();
11928 }
11929
hdd_pm_qos_remove_request(struct hdd_context * hdd_ctx)11930 static inline void hdd_pm_qos_remove_request(struct hdd_context *hdd_ctx)
11931 {
11932 cpu_latency_qos_remove_request(&hdd_ctx->pm_qos_req);
11933 }
11934 #else
hdd_pm_qos_update_request(struct hdd_context * hdd_ctx,cpumask_t * pm_qos_cpu_mask)11935 static inline void hdd_pm_qos_update_request(struct hdd_context *hdd_ctx,
11936 cpumask_t *pm_qos_cpu_mask)
11937 {
11938 COPY_CPU_MASK(&hdd_ctx->pm_qos_req.cpus_affine, pm_qos_cpu_mask);
11939
11940 if (cpumask_empty(pm_qos_cpu_mask))
11941 pm_qos_update_request(&hdd_ctx->pm_qos_req,
11942 PM_QOS_DEFAULT_VALUE);
11943 else
11944 pm_qos_update_request(&hdd_ctx->pm_qos_req, 1);
11945 }
11946
hdd_pm_qos_add_request(struct hdd_context * hdd_ctx)11947 static inline void hdd_pm_qos_add_request(struct hdd_context *hdd_ctx)
11948 {
11949 hdd_set_default_pm_qos_mask(hdd_ctx);
11950 pm_qos_add_request(&hdd_ctx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
11951 PM_QOS_DEFAULT_VALUE);
11952 DUMP_CPU_AFFINE();
11953 }
11954
hdd_pm_qos_remove_request(struct hdd_context * hdd_ctx)11955 static inline void hdd_pm_qos_remove_request(struct hdd_context *hdd_ctx)
11956 {
11957 pm_qos_remove_request(&hdd_ctx->pm_qos_req);
11958 }
11959 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) */
11960 #endif /* CLD_DEV_PM_QOS */
11961
11962 #else /* CLD_PM_QOS */
11963 #define PLD_REMOVE_PM_QOS(x) pld_remove_pm_qos(x)
11964 #define PLD_REQUEST_PM_QOS(x, y) pld_request_pm_qos(x, y)
11965
hdd_pm_qos_add_request(struct hdd_context * hdd_ctx)11966 static inline void hdd_pm_qos_add_request(struct hdd_context *hdd_ctx)
11967 {
11968 }
11969
hdd_pm_qos_remove_request(struct hdd_context * hdd_ctx)11970 static inline void hdd_pm_qos_remove_request(struct hdd_context *hdd_ctx)
11971 {
11972 }
11973
hdd_pm_qos_update_cpu_mask(cpumask_t * mask,bool high_throughput)11974 static inline void hdd_pm_qos_update_cpu_mask(cpumask_t *mask,
11975 bool high_throughput)
11976 {
11977 }
11978
hdd_pm_qos_update_request(struct hdd_context * hdd_ctx,cpumask_t * pm_qos_cpu_mask)11979 static inline void hdd_pm_qos_update_request(struct hdd_context *hdd_ctx,
11980 cpumask_t *pm_qos_cpu_mask)
11981 {
11982 }
11983 #endif /* CLD_PM_QOS */
11984
11985 #if defined(CLD_PM_QOS)
11986 #if defined(CLD_DEV_PM_QOS)
wlan_hdd_set_pm_qos_request(struct hdd_context * hdd_ctx,bool pm_qos_request)11987 void wlan_hdd_set_pm_qos_request(struct hdd_context *hdd_ctx,
11988 bool pm_qos_request)
11989 {
11990 cpumask_t pm_qos_cpu_mask;
11991
11992 cpumask_clear(&pm_qos_cpu_mask);
11993 if (pm_qos_request) {
11994 hdd_ctx->pm_qos_request = true;
11995 if (!hdd_ctx->hbw_requested) {
11996 hdd_pm_qos_update_cpu_mask(&pm_qos_cpu_mask, true);
11997 hdd_pm_qos_update_request(hdd_ctx, &pm_qos_cpu_mask);
11998 hdd_ctx->hbw_requested = true;
11999 }
12000 } else {
12001 if (hdd_ctx->hbw_requested) {
12002 hdd_pm_qos_update_cpu_mask(&pm_qos_cpu_mask, false);
12003 hdd_pm_qos_update_request(hdd_ctx, &pm_qos_cpu_mask);
12004 hdd_ctx->hbw_requested = false;
12005 }
12006 hdd_ctx->pm_qos_request = false;
12007 }
12008 }
12009 #else /* CLD_DEV_PM_QOS */
12010 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
wlan_hdd_set_pm_qos_request(struct hdd_context * hdd_ctx,bool pm_qos_request)12011 void wlan_hdd_set_pm_qos_request(struct hdd_context *hdd_ctx,
12012 bool pm_qos_request)
12013 {
12014 if (pm_qos_request) {
12015 hdd_ctx->pm_qos_request = true;
12016 if (!hdd_ctx->hbw_requested) {
12017 cpumask_setall(&hdd_ctx->pm_qos_req.cpus_affine);
12018 cpu_latency_qos_update_request(
12019 &hdd_ctx->pm_qos_req,
12020 DISABLE_KRAIT_IDLE_PS_VAL);
12021 hdd_ctx->hbw_requested = true;
12022 }
12023 } else {
12024 if (hdd_ctx->hbw_requested) {
12025 cpumask_clear(&hdd_ctx->pm_qos_req.cpus_affine);
12026 cpu_latency_qos_update_request(&hdd_ctx->pm_qos_req,
12027 PM_QOS_DEFAULT_VALUE);
12028 hdd_ctx->hbw_requested = false;
12029 }
12030 hdd_ctx->pm_qos_request = false;
12031 }
12032 }
12033 #else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) */
wlan_hdd_set_pm_qos_request(struct hdd_context * hdd_ctx,bool pm_qos_request)12034 void wlan_hdd_set_pm_qos_request(struct hdd_context *hdd_ctx,
12035 bool pm_qos_request)
12036 {
12037 if (pm_qos_request) {
12038 hdd_ctx->pm_qos_request = true;
12039 if (!hdd_ctx->hbw_requested) {
12040 cpumask_setall(&hdd_ctx->pm_qos_req.cpus_affine);
12041 pm_qos_update_request(&hdd_ctx->pm_qos_req,
12042 DISABLE_KRAIT_IDLE_PS_VAL);
12043 hdd_ctx->hbw_requested = true;
12044 }
12045 } else {
12046 if (hdd_ctx->hbw_requested) {
12047 cpumask_clear(&hdd_ctx->pm_qos_req.cpus_affine);
12048 pm_qos_update_request(&hdd_ctx->pm_qos_req,
12049 PM_QOS_DEFAULT_VALUE);
12050 hdd_ctx->hbw_requested = false;
12051 }
12052 hdd_ctx->pm_qos_request = false;
12053 }
12054 }
12055 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) */
12056 #endif /* CLD_DEV_PM_QOS*/
12057 #endif /* CLD_PM_QOS */
12058
12059 #define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
12060
12061 #ifdef WLAN_FEATURE_MSCS
12062
12063 static
hdd_send_mscs_action_frame(struct wlan_hdd_link_info * link_info)12064 void hdd_send_mscs_action_frame(struct wlan_hdd_link_info *link_info)
12065 {
12066 struct hdd_context *hdd_ctx = link_info->adapter->hdd_ctx;
12067 uint64_t mscs_vo_pkt_delta;
12068 unsigned long tx_vo_pkts = 0;
12069 unsigned int cpu;
12070 struct hdd_tx_rx_stats *stats = &link_info->hdd_stats.tx_rx_stats;
12071 uint32_t bus_bw_compute_interval;
12072
12073 /*
12074 * To disable MSCS feature in driver set mscs_pkt_threshold = 0
12075 * in ini file.
12076 */
12077 if (!hdd_ctx->config->mscs_pkt_threshold)
12078 return;
12079
12080 for (cpu = 0; cpu < NUM_CPUS; cpu++)
12081 tx_vo_pkts += stats->per_cpu[cpu].tx_classified_ac[SME_AC_VO];
12082
12083 if (!link_info->mscs_counter)
12084 link_info->mscs_prev_tx_vo_pkts = tx_vo_pkts;
12085
12086 link_info->mscs_counter++;
12087 bus_bw_compute_interval =
12088 ucfg_dp_get_bus_bw_compute_interval(hdd_ctx->psoc);
12089 if (link_info->mscs_counter * bus_bw_compute_interval >=
12090 hdd_ctx->config->mscs_voice_interval * 1000) {
12091 link_info->mscs_counter = 0;
12092 mscs_vo_pkt_delta =
12093 HDD_BW_GET_DIFF(tx_vo_pkts,
12094 link_info->mscs_prev_tx_vo_pkts);
12095 if (mscs_vo_pkt_delta > hdd_ctx->config->mscs_pkt_threshold &&
12096 !mlme_get_is_mscs_req_sent(link_info->vdev))
12097 sme_send_mscs_action_frame(link_info->vdev_id);
12098 }
12099 }
12100 #else
12101 static inline
hdd_send_mscs_action_frame(struct wlan_hdd_link_info * link_info)12102 void hdd_send_mscs_action_frame(struct wlan_hdd_link_info *link_info)
12103 {
12104 }
12105 #endif
12106 #endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/
12107
12108 /**
12109 * wlan_hdd_sta_get_dot11mode() - GET AP client count
12110 * @context: HDD context
12111 * @netdev: netdev
12112 * @dot11_mode: variable in which mode need to update.
12113 *
12114 * Return: true on success else false
12115 */
12116 static inline
wlan_hdd_sta_get_dot11mode(hdd_cb_handle context,qdf_netdev_t netdev,enum qca_wlan_802_11_mode * dot11_mode)12117 bool wlan_hdd_sta_get_dot11mode(hdd_cb_handle context, qdf_netdev_t netdev,
12118 enum qca_wlan_802_11_mode *dot11_mode)
12119 {
12120 struct hdd_context *hdd_ctx;
12121 struct wlan_hdd_link_info *link_info;
12122 struct hdd_station_ctx *sta_ctx;
12123 struct hdd_adapter *adapter;
12124 enum csr_cfgdot11mode mode;
12125
12126 hdd_ctx = hdd_cb_handle_to_context(context);
12127 if (!hdd_ctx)
12128 return false;
12129
12130 adapter = WLAN_HDD_GET_PRIV_PTR(netdev);
12131 if (!adapter)
12132 return false;
12133
12134 link_info = adapter->deflink;
12135
12136 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
12137 mode = sta_ctx->conn_info.dot11mode;
12138 *dot11_mode = hdd_convert_cfgdot11mode_to_80211mode(mode);
12139 return true;
12140 }
12141
12142 /**
12143 * wlan_hdd_get_ap_client_count() - GET AP client count
12144 * @context: HDD context
12145 * @netdev: netdev
12146 * @client_count: variable in which number of client need to update.
12147 *
12148 * Return: true on success else false
12149 */
12150 static inline
wlan_hdd_get_ap_client_count(hdd_cb_handle context,qdf_netdev_t netdev,uint16_t * client_count)12151 bool wlan_hdd_get_ap_client_count(hdd_cb_handle context, qdf_netdev_t netdev,
12152 uint16_t *client_count)
12153 {
12154 struct hdd_context *hdd_ctx;
12155 struct wlan_hdd_link_info *link_info;
12156 struct hdd_adapter *adapter;
12157 struct hdd_ap_ctx *ap_ctx;
12158 enum qca_wlan_802_11_mode i;
12159
12160 hdd_ctx = hdd_cb_handle_to_context(context);
12161 if (!hdd_ctx) {
12162 hdd_err("hdd ctx is null");
12163 return false;
12164 }
12165
12166 adapter = WLAN_HDD_GET_PRIV_PTR(netdev);
12167 if (!adapter) {
12168 hdd_err("adapter is null");
12169 return false;
12170 }
12171
12172 link_info = adapter->deflink;
12173 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
12174 if (!ap_ctx->ap_active)
12175 return false;
12176
12177 for (i = QCA_WLAN_802_11_MODE_11B; i < QCA_WLAN_802_11_MODE_INVALID;
12178 i++)
12179 client_count[i] = ap_ctx->client_count[i];
12180
12181 return true;
12182 }
12183
12184 /**
12185 * wlan_hdd_sta_ndi_connected() - Check if NDI connected
12186 * @context: HDD context
12187 * @netdev: netdev
12188 *
12189 * Return: true if NDI connected else false
12190 */
12191 static inline
wlan_hdd_sta_ndi_connected(hdd_cb_handle context,qdf_netdev_t netdev)12192 bool wlan_hdd_sta_ndi_connected(hdd_cb_handle context, qdf_netdev_t netdev)
12193 {
12194 struct hdd_adapter *adapter;
12195 struct hdd_context *hdd_ctx;
12196 struct wlan_hdd_link_info *link_info;
12197 struct hdd_station_ctx *sta_ctx;
12198
12199 hdd_ctx = hdd_cb_handle_to_context(context);
12200 if (!hdd_ctx) {
12201 hdd_err("hdd_ctx is null");
12202 return false;
12203 }
12204
12205 adapter = WLAN_HDD_GET_PRIV_PTR(netdev);
12206 if (!adapter) {
12207 hdd_err("adapter is null");
12208 return false;
12209 }
12210
12211 link_info = adapter->deflink;
12212
12213 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
12214 if (sta_ctx->conn_info.conn_state != eConnectionState_NdiConnected)
12215 return false;
12216
12217 return true;
12218 }
12219
12220 /**
12221 * wlan_hdd_pktlog_enable_disable() - Enable/Disable packet logging
12222 * @context: HDD context
12223 * @enable_disable_flag: Flag to enable/disable
12224 * @user_triggered: triggered through iwpriv
12225 * @size: buffer size to be used for packetlog
12226 *
12227 * Return: 0 on success; error number otherwise
12228 */
12229 static inline
wlan_hdd_pktlog_enable_disable(hdd_cb_handle context,bool enable_disable_flag,uint8_t user_triggered,int size)12230 int wlan_hdd_pktlog_enable_disable(hdd_cb_handle context,
12231 bool enable_disable_flag,
12232 uint8_t user_triggered, int size)
12233 {
12234 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
12235
12236 if (!hdd_ctx) {
12237 hdd_err("hdd_ctx is null");
12238 return -EINVAL;
12239 }
12240 return hdd_pktlog_enable_disable(hdd_ctx, enable_disable_flag,
12241 user_triggered, size);
12242 }
12243
12244 /**
12245 * wlan_hdd_is_roaming_in_progress() - Check if roaming is in progress
12246 * @context: HDD context
12247 *
12248 * Return: true if roaming is in progress else false
12249 */
wlan_hdd_is_roaming_in_progress(hdd_cb_handle context)12250 static inline bool wlan_hdd_is_roaming_in_progress(hdd_cb_handle context)
12251 {
12252 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
12253
12254 if (!hdd_ctx) {
12255 hdd_err("hdd_ctx is null");
12256 return false;
12257 }
12258 return hdd_is_roaming_in_progress(hdd_ctx);
12259 }
12260
12261 /**
12262 * hdd_is_ap_active() - Check if AP is active
12263 * @context: HDD context
12264 * @netdev: netdev
12265 *
12266 * Return: true if AP active else false
12267 */
hdd_is_ap_active(hdd_cb_handle context,qdf_netdev_t netdev)12268 static inline bool hdd_is_ap_active(hdd_cb_handle context, qdf_netdev_t netdev)
12269 {
12270 struct hdd_adapter *adapter;
12271 struct hdd_context *hdd_ctx;
12272 struct wlan_hdd_link_info *link_info;
12273
12274 hdd_ctx = hdd_cb_handle_to_context(context);
12275 if (!hdd_ctx) {
12276 hdd_err("hdd_ctx is null");
12277 return false;
12278 }
12279
12280 adapter = WLAN_HDD_GET_PRIV_PTR(netdev);
12281 if (!adapter) {
12282 hdd_err("adapter is null");
12283 return false;
12284 }
12285
12286 link_info = adapter->deflink;
12287 return WLAN_HDD_GET_AP_CTX_PTR(link_info)->ap_active;
12288 }
12289
12290 /**
12291 * wlan_hdd_napi_apply_throughput_policy() - Apply NAPI policy
12292 * @context: HDD context
12293 * @tx_packets: tx_packets
12294 * @rx_packets: rx_packets
12295 *
12296 * Return: 0 on success else error code
12297 */
12298 static inline
wlan_hdd_napi_apply_throughput_policy(hdd_cb_handle context,uint64_t tx_packets,uint64_t rx_packets)12299 int wlan_hdd_napi_apply_throughput_policy(hdd_cb_handle context,
12300 uint64_t tx_packets,
12301 uint64_t rx_packets)
12302 {
12303 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
12304 int rc = 0;
12305
12306 if (!hdd_ctx) {
12307 hdd_err("hdd_ctx is null");
12308 return 0;
12309 }
12310 if (hdd_ctx->config->napi_cpu_affinity_mask)
12311 rc = hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets,
12312 rx_packets);
12313 return rc;
12314 }
12315
12316 /**
12317 * hdd_is_link_adapter() - Check if adapter is link adapter
12318 * @context: HDD context
12319 * @vdev_id: Vdev ID
12320 *
12321 * Return: true if link adapter else false
12322 */
hdd_is_link_adapter(hdd_cb_handle context,uint8_t vdev_id)12323 static inline bool hdd_is_link_adapter(hdd_cb_handle context, uint8_t vdev_id)
12324 {
12325 struct hdd_context *hdd_ctx;
12326 struct wlan_hdd_link_info *link_info;
12327
12328 hdd_ctx = hdd_cb_handle_to_context(context);
12329 if (!hdd_ctx) {
12330 hdd_err("hdd_ctx is null");
12331 return false;
12332 }
12333
12334 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
12335 if (!link_info) {
12336 hdd_err("Invalid vdev");
12337 return false;
12338 }
12339 return hdd_adapter_is_link_adapter(link_info->adapter);
12340 }
12341
12342 /**
12343 * hdd_get_pause_map() - Get pause map value
12344 * @context: HDD context
12345 * @netdev: netdev
12346 *
12347 * Return: pause map value
12348 */
12349 static inline
hdd_get_pause_map(hdd_cb_handle context,qdf_netdev_t netdev)12350 uint32_t hdd_get_pause_map(hdd_cb_handle context, qdf_netdev_t netdev)
12351 {
12352 struct hdd_adapter *adapter;
12353
12354 adapter = WLAN_HDD_GET_PRIV_PTR(netdev);
12355 if (!adapter) {
12356 hdd_err("adapter is null");
12357 return 0;
12358 }
12359
12360 return adapter->pause_map;
12361 }
12362
12363 /**
12364 * hdd_any_adapter_connected() - Check if any adapter connected.
12365 * @context: HDD context
12366 *
12367 * Return: True if connected else false.
12368 */
hdd_any_adapter_connected(hdd_cb_handle context)12369 static inline bool hdd_any_adapter_connected(hdd_cb_handle context)
12370 {
12371 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
12372
12373 if (!hdd_ctx) {
12374 hdd_err("hdd_ctx is null");
12375 return false;
12376 }
12377
12378 return hdd_is_any_adapter_connected(hdd_ctx);
12379 }
12380
12381 #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH
12382 /**
12383 * hdd_pld_request_pm_qos() - Request PLD PM QoS request
12384 * @context: HDD context
12385 *
12386 * Return: None
12387 */
hdd_pld_request_pm_qos(hdd_cb_handle context)12388 static inline void hdd_pld_request_pm_qos(hdd_cb_handle context)
12389 {
12390 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
12391
12392 if (!hdd_ctx) {
12393 hdd_err("hdd_ctx is null");
12394 return;
12395 }
12396
12397 if (!hdd_ctx->hbw_requested) {
12398 PLD_REQUEST_PM_QOS(hdd_ctx->parent_dev, 1);
12399 hdd_ctx->hbw_requested = true;
12400 }
12401 }
12402
12403 /**
12404 * hdd_pld_remove_pm_qos() - Remove PLD PM QoS request
12405 * @context: HDD context
12406 *
12407 * Return: None
12408 */
hdd_pld_remove_pm_qos(hdd_cb_handle context)12409 static inline void hdd_pld_remove_pm_qos(hdd_cb_handle context)
12410 {
12411 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
12412
12413 if (!hdd_ctx) {
12414 hdd_err("hdd_ctx is null");
12415 return;
12416 }
12417
12418 if (hdd_ctx->hbw_requested &&
12419 !hdd_ctx->pm_qos_request) {
12420 PLD_REMOVE_PM_QOS(hdd_ctx->parent_dev);
12421 hdd_ctx->hbw_requested = false;
12422 }
12423 }
12424
12425 /**
12426 * wlan_hdd_pm_qos_update_request() - Update PM QoS request
12427 * @context: HDD context
12428 * @pm_qos_cpu_mask: CPU mask
12429 *
12430 * Return: None
12431 */
12432 static inline void
wlan_hdd_pm_qos_update_request(hdd_cb_handle context,cpumask_t * pm_qos_cpu_mask)12433 wlan_hdd_pm_qos_update_request(hdd_cb_handle context,
12434 cpumask_t *pm_qos_cpu_mask)
12435 {
12436 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
12437
12438 if (!hdd_ctx) {
12439 hdd_err("hdd_ctx is null");
12440 return;
12441 }
12442
12443 if (!hdd_ctx->pm_qos_request)
12444 hdd_pm_qos_update_request(hdd_ctx, pm_qos_cpu_mask);
12445 }
12446
12447 /**
12448 * wlan_hdd_pm_qos_add_request() - Add PM QoS request
12449 * @context: HDD context
12450 *
12451 * Return: None
12452 */
wlan_hdd_pm_qos_add_request(hdd_cb_handle context)12453 static inline void wlan_hdd_pm_qos_add_request(hdd_cb_handle context)
12454 {
12455 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
12456
12457 if (!hdd_ctx) {
12458 hdd_err("hdd_ctx is null");
12459 return;
12460 }
12461
12462 hdd_pm_qos_add_request(hdd_ctx);
12463 }
12464
12465 /**
12466 * wlan_hdd_pm_qos_remove_request() - remove PM QoS request
12467 * @context: HDD context
12468 *
12469 * Return: None
12470 */
wlan_hdd_pm_qos_remove_request(hdd_cb_handle context)12471 static inline void wlan_hdd_pm_qos_remove_request(hdd_cb_handle context)
12472 {
12473 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
12474
12475 if (!hdd_ctx) {
12476 hdd_err("hdd_ctx is null");
12477 return;
12478 }
12479
12480 hdd_pm_qos_remove_request(hdd_ctx);
12481 }
12482
12483 /**
12484 * wlan_hdd_send_mscs_action_frame() - Send MSCS action frame
12485 * @context: HDD context
12486 * @netdev: netdev
12487 *
12488 * Return: None
12489 */
wlan_hdd_send_mscs_action_frame(hdd_cb_handle context,qdf_netdev_t netdev)12490 static inline void wlan_hdd_send_mscs_action_frame(hdd_cb_handle context,
12491 qdf_netdev_t netdev)
12492 {
12493 struct hdd_adapter *adapter;
12494 struct wlan_hdd_link_info *link_info;
12495
12496 adapter = WLAN_HDD_GET_PRIV_PTR(netdev);
12497 if (!adapter) {
12498 hdd_err("adapter is null");
12499 return;
12500 }
12501
12502 link_info = adapter->deflink;
12503 hdd_send_mscs_action_frame(link_info);
12504 }
12505
12506 #else
hdd_pld_remove_pm_qos(hdd_cb_handle context)12507 static inline void hdd_pld_remove_pm_qos(hdd_cb_handle context)
12508 {
12509 }
12510
hdd_pld_request_pm_qos(hdd_cb_handle context)12511 static inline void hdd_pld_request_pm_qos(hdd_cb_handle context)
12512 {
12513 }
12514
12515 static inline void
wlan_hdd_pm_qos_update_request(hdd_cb_handle context,cpumask_t * pm_qos_cpu_mask)12516 wlan_hdd_pm_qos_update_request(hdd_cb_handle context,
12517 cpumask_t *pm_qos_cpu_mask)
12518 {
12519 }
12520
wlan_hdd_pm_qos_add_request(hdd_cb_handle context)12521 static inline void wlan_hdd_pm_qos_add_request(hdd_cb_handle context)
12522 {
12523 }
12524
wlan_hdd_pm_qos_remove_request(hdd_cb_handle context)12525 static inline void wlan_hdd_pm_qos_remove_request(hdd_cb_handle context)
12526 {
12527 }
12528
wlan_hdd_send_mscs_action_frame(hdd_cb_handle context,qdf_netdev_t netdev)12529 static inline void wlan_hdd_send_mscs_action_frame(hdd_cb_handle context,
12530 qdf_netdev_t netdev)
12531 {
12532 }
12533 #endif
12534
12535 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && \
12536 defined(FEATURE_RX_LINKSPEED_ROAM_TRIGGER)
wlan_hdd_link_speed_update(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,bool is_link_speed_good)12537 void wlan_hdd_link_speed_update(struct wlan_objmgr_psoc *psoc,
12538 uint8_t vdev_id,
12539 bool is_link_speed_good)
12540 {
12541 ucfg_cm_roam_link_speed_update(psoc, vdev_id, is_link_speed_good);
12542 }
12543 #endif
12544
12545 /**
12546 * hdd_dp_register_callbacks() - Register DP callbacks with HDD
12547 * @hdd_ctx: HDD context
12548 *
12549 * Return: None
12550 */
hdd_dp_register_callbacks(struct hdd_context * hdd_ctx)12551 static void hdd_dp_register_callbacks(struct hdd_context *hdd_ctx)
12552 {
12553 struct wlan_dp_psoc_callbacks cb_obj = {0};
12554
12555 cb_obj.callback_ctx = (hdd_cb_handle)hdd_ctx;
12556 cb_obj.wlan_dp_sta_get_dot11mode = wlan_hdd_sta_get_dot11mode;
12557 cb_obj.wlan_dp_get_ap_client_count = wlan_hdd_get_ap_client_count;
12558 cb_obj.wlan_dp_sta_ndi_connected = wlan_hdd_sta_ndi_connected;
12559 cb_obj.dp_any_adapter_connected = hdd_any_adapter_connected;
12560 cb_obj.dp_send_svc_nlink_msg = wlan_hdd_send_svc_nlink_msg;
12561 cb_obj.dp_pld_remove_pm_qos = hdd_pld_remove_pm_qos;
12562 cb_obj.dp_pld_request_pm_qos = hdd_pld_request_pm_qos;
12563 cb_obj.dp_pktlog_enable_disable = wlan_hdd_pktlog_enable_disable;
12564 cb_obj.dp_pm_qos_update_request = wlan_hdd_pm_qos_update_request;
12565 cb_obj.dp_pm_qos_add_request = wlan_hdd_pm_qos_add_request;
12566 cb_obj.dp_pm_qos_remove_request = wlan_hdd_pm_qos_remove_request;
12567 cb_obj.dp_send_mscs_action_frame = wlan_hdd_send_mscs_action_frame;
12568 cb_obj.dp_is_roaming_in_progress = wlan_hdd_is_roaming_in_progress;
12569 cb_obj.wlan_dp_display_tx_multiq_stats =
12570 wlan_hdd_display_tx_multiq_stats;
12571 cb_obj.wlan_dp_display_netif_queue_history =
12572 wlan_hdd_display_netif_queue_history;
12573 cb_obj.dp_is_ap_active = hdd_is_ap_active;
12574 cb_obj.dp_napi_apply_throughput_policy =
12575 wlan_hdd_napi_apply_throughput_policy;
12576 cb_obj.dp_is_link_adapter = hdd_is_link_adapter;
12577 cb_obj.dp_nud_failure_work = hdd_nud_failure_work;
12578 cb_obj.dp_get_pause_map = hdd_get_pause_map;
12579
12580 cb_obj.dp_get_netdev_by_vdev_mac =
12581 hdd_get_netdev_by_vdev_mac;
12582 cb_obj.dp_get_tx_resource = hdd_get_tx_resource;
12583 cb_obj.dp_get_tx_flow_low_watermark = hdd_get_tx_flow_low_watermark;
12584 cb_obj.dp_get_tsf_time = hdd_get_tsf_time_cb;
12585 cb_obj.dp_tsf_timestamp_rx = hdd_tsf_timestamp_rx;
12586 cb_obj.dp_gro_rx_legacy_get_napi = hdd_legacy_gro_get_napi;
12587 cb_obj.link_monitoring_cb = wlan_hdd_link_speed_update;
12588
12589 os_if_dp_register_hdd_callbacks(hdd_ctx->psoc, &cb_obj);
12590 }
12591
12592 /**
12593 * __hdd_adapter_param_update_work() - Gist of the work to process
12594 * netdev feature update.
12595 * @adapter: pointer to adapter structure
12596 *
12597 * This function assumes that the adapter pointer is always valid.
12598 * So the caller should always validate adapter pointer before calling
12599 * this function
12600 *
12601 * Returns: None
12602 */
12603 static inline void
__hdd_adapter_param_update_work(struct hdd_adapter * adapter)12604 __hdd_adapter_param_update_work(struct hdd_adapter *adapter)
12605 {
12606 /**
12607 * This check is needed in case the work got scheduled after the
12608 * interface got disconnected.
12609 * Netdev features update is to be done only after the connection,
12610 * since the connection mode plays an important role in identifying
12611 * the features that are to be updated.
12612 * So in case of interface disconnect skip feature update.
12613 */
12614 if (!hdd_cm_is_vdev_associated(adapter->deflink))
12615 return;
12616
12617 hdd_netdev_update_features(adapter);
12618 }
12619
12620 /**
12621 * hdd_adapter_param_update_work() - work to process the netdev features
12622 * update.
12623 * @arg: private data passed to work
12624 *
12625 * Returns: None
12626 */
hdd_adapter_param_update_work(void * arg)12627 static void hdd_adapter_param_update_work(void *arg)
12628 {
12629 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12630 struct hdd_adapter *adapter = arg;
12631 struct osif_vdev_sync *vdev_sync;
12632 int errno;
12633
12634 if (!hdd_ctx)
12635 return;
12636
12637 hdd_adapter_ops_record_event(hdd_ctx,
12638 WLAN_HDD_ADAPTER_OPS_WORK_SCHED,
12639 WLAN_INVALID_VDEV_ID);
12640
12641 if (hdd_validate_adapter(adapter))
12642 return;
12643
12644 errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
12645 if (errno)
12646 return;
12647
12648 __hdd_adapter_param_update_work(adapter);
12649
12650 osif_vdev_sync_op_stop(vdev_sync);
12651 }
12652
hdd_init_adapter_ops_wq(struct hdd_context * hdd_ctx)12653 QDF_STATUS hdd_init_adapter_ops_wq(struct hdd_context *hdd_ctx)
12654 {
12655 hdd_enter();
12656
12657 hdd_ctx->adapter_ops_wq =
12658 qdf_alloc_high_prior_ordered_workqueue("hdd_adapter_ops_wq");
12659 if (!hdd_ctx->adapter_ops_wq)
12660 return QDF_STATUS_E_NOMEM;
12661
12662 hdd_exit();
12663
12664 return QDF_STATUS_SUCCESS;
12665 }
12666
hdd_deinit_adapter_ops_wq(struct hdd_context * hdd_ctx)12667 void hdd_deinit_adapter_ops_wq(struct hdd_context *hdd_ctx)
12668 {
12669 hdd_enter();
12670
12671 qdf_flush_workqueue(0, hdd_ctx->adapter_ops_wq);
12672 qdf_destroy_workqueue(0, hdd_ctx->adapter_ops_wq);
12673
12674 hdd_exit();
12675 }
12676
hdd_adapter_feature_update_work_init(struct hdd_adapter * adapter)12677 QDF_STATUS hdd_adapter_feature_update_work_init(struct hdd_adapter *adapter)
12678 {
12679 QDF_STATUS status;
12680
12681 hdd_enter();
12682
12683 status = qdf_create_work(0, &adapter->netdev_features_update_work,
12684 hdd_adapter_param_update_work, adapter);
12685 adapter->netdev_features_update_work_status = HDD_WORK_INITIALIZED;
12686
12687 hdd_exit();
12688
12689 return status;
12690 }
12691
hdd_adapter_feature_update_work_deinit(struct hdd_adapter * adapter)12692 void hdd_adapter_feature_update_work_deinit(struct hdd_adapter *adapter)
12693 {
12694 hdd_enter();
12695
12696 if (adapter->netdev_features_update_work_status !=
12697 HDD_WORK_INITIALIZED) {
12698 hdd_debug("work not yet init");
12699 return;
12700 }
12701 qdf_cancel_work(&adapter->netdev_features_update_work);
12702 qdf_flush_work(&adapter->netdev_features_update_work);
12703 adapter->netdev_features_update_work_status = HDD_WORK_UNINITIALIZED;
12704
12705 hdd_exit();
12706 }
12707
12708 #define HDD_DUMP_STAT_HELP(STAT_ID) \
12709 hdd_nofl_debug("%u -- %s", STAT_ID, (# STAT_ID))
12710 /**
12711 * hdd_display_stats_help() - print statistics help
12712 *
12713 * Return: none
12714 */
hdd_display_stats_help(void)12715 static void hdd_display_stats_help(void)
12716 {
12717 hdd_nofl_debug("iwpriv wlan0 dumpStats [option] - dump statistics");
12718 hdd_nofl_debug("iwpriv wlan0 clearStats [option] - clear statistics");
12719 hdd_nofl_debug("options:");
12720 HDD_DUMP_STAT_HELP(CDP_TXRX_PATH_STATS);
12721 HDD_DUMP_STAT_HELP(CDP_TXRX_HIST_STATS);
12722 HDD_DUMP_STAT_HELP(CDP_TXRX_TSO_STATS);
12723 HDD_DUMP_STAT_HELP(CDP_HDD_NETIF_OPER_HISTORY);
12724 HDD_DUMP_STAT_HELP(CDP_DUMP_TX_FLOW_POOL_INFO);
12725 HDD_DUMP_STAT_HELP(CDP_TXRX_DESC_STATS);
12726 HDD_DUMP_STAT_HELP(CDP_HIF_STATS);
12727 HDD_DUMP_STAT_HELP(CDP_NAPI_STATS);
12728 HDD_DUMP_STAT_HELP(CDP_DP_NAPI_STATS);
12729 HDD_DUMP_STAT_HELP(CDP_DP_RX_THREAD_STATS);
12730 }
12731
hdd_wlan_dump_stats(struct hdd_adapter * adapter,int stats_id)12732 int hdd_wlan_dump_stats(struct hdd_adapter *adapter, int stats_id)
12733 {
12734 int ret = 0;
12735 QDF_STATUS status;
12736 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
12737
12738 hdd_debug("stats_id %d", stats_id);
12739
12740 switch (stats_id) {
12741 case CDP_TXRX_HIST_STATS:
12742 ucfg_wlan_dp_display_tx_rx_histogram(hdd_ctx->psoc);
12743 break;
12744 case CDP_HDD_NETIF_OPER_HISTORY:
12745 wlan_hdd_display_adapter_netif_queue_history(adapter);
12746 break;
12747 case CDP_HIF_STATS:
12748 hdd_display_hif_stats();
12749 break;
12750 case CDP_NAPI_STATS:
12751 if (hdd_display_napi_stats()) {
12752 hdd_err("error displaying napi stats");
12753 ret = -EFAULT;
12754 }
12755 break;
12756 case CDP_DP_RX_THREAD_STATS:
12757 ucfg_dp_txrx_ext_dump_stats(cds_get_context(QDF_MODULE_ID_SOC),
12758 CDP_DP_RX_THREAD_STATS);
12759 break;
12760 case CDP_DISCONNECT_STATS:
12761 sme_display_disconnect_stats(hdd_ctx->mac_handle,
12762 adapter->deflink->vdev_id);
12763 break;
12764 default:
12765 status = cdp_display_stats(cds_get_context(QDF_MODULE_ID_SOC),
12766 stats_id,
12767 QDF_STATS_VERBOSITY_LEVEL_HIGH);
12768 if (status == QDF_STATUS_E_INVAL) {
12769 hdd_display_stats_help();
12770 ret = -EINVAL;
12771 }
12772 break;
12773 }
12774 return ret;
12775 }
12776
hdd_wlan_clear_stats(struct hdd_adapter * adapter,int stats_id)12777 int hdd_wlan_clear_stats(struct hdd_adapter *adapter, int stats_id)
12778 {
12779 QDF_STATUS status = QDF_STATUS_SUCCESS;
12780
12781 hdd_debug("stats_id %d", stats_id);
12782
12783 switch (stats_id) {
12784 case CDP_HDD_STATS:
12785 ucfg_dp_clear_net_dev_stats(adapter->dev);
12786 memset(&adapter->deflink->hdd_stats, 0,
12787 sizeof(adapter->deflink->hdd_stats));
12788 break;
12789 case CDP_TXRX_HIST_STATS:
12790 ucfg_wlan_dp_clear_tx_rx_histogram(adapter->hdd_ctx->psoc);
12791 break;
12792 case CDP_HDD_NETIF_OPER_HISTORY:
12793 wlan_hdd_clear_netif_queue_history(adapter->hdd_ctx);
12794 break;
12795 case CDP_HIF_STATS:
12796 hdd_clear_hif_stats();
12797 break;
12798 case CDP_NAPI_STATS:
12799 hdd_clear_napi_stats();
12800 break;
12801 default:
12802 status = cdp_clear_stats(cds_get_context(QDF_MODULE_ID_SOC),
12803 OL_TXRX_PDEV_ID,
12804 stats_id);
12805 if (status != QDF_STATUS_SUCCESS)
12806 hdd_debug("Failed to dump stats for stats_id: %d",
12807 stats_id);
12808 break;
12809 }
12810
12811 return qdf_status_to_os_return(status);
12812 }
12813
12814 /* length of the netif queue log needed per adapter */
12815 #define ADAP_NETIFQ_LOG_LEN ((20 * WLAN_REASON_TYPE_MAX) + 50)
12816
12817 /**
12818 * hdd_display_netif_queue_history_compact() - display compact netifq history
12819 * @hdd_ctx: hdd context
12820 *
12821 * Return: none
12822 */
12823 static void
hdd_display_netif_queue_history_compact(struct hdd_context * hdd_ctx)12824 hdd_display_netif_queue_history_compact(struct hdd_context *hdd_ctx)
12825 {
12826 int adapter_num = 0;
12827 int i;
12828 int bytes_written;
12829 u32 tbytes;
12830 qdf_time_t total, pause, unpause, curr_time, delta;
12831 char temp_str[20 * WLAN_REASON_TYPE_MAX];
12832 char *comb_log_str;
12833 uint32_t comb_log_str_size;
12834 struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
12835 wlan_net_dev_ref_dbgid dbgid =
12836 NET_DEV_HOLD_DISPLAY_NETIF_QUEUE_HISTORY_COMPACT;
12837
12838 comb_log_str_size = (ADAP_NETIFQ_LOG_LEN * WLAN_MAX_VDEVS) + 1;
12839 comb_log_str = qdf_mem_malloc(comb_log_str_size);
12840 if (!comb_log_str)
12841 return;
12842
12843 bytes_written = 0;
12844
12845 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
12846 dbgid) {
12847 curr_time = qdf_system_ticks();
12848 total = curr_time - adapter->start_time;
12849 delta = curr_time - adapter->last_time;
12850
12851 if (adapter->pause_map) {
12852 pause = adapter->total_pause_time + delta;
12853 unpause = adapter->total_unpause_time;
12854 } else {
12855 unpause = adapter->total_unpause_time + delta;
12856 pause = adapter->total_pause_time;
12857 }
12858
12859 tbytes = 0;
12860 qdf_mem_zero(temp_str, sizeof(temp_str));
12861 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
12862 if (adapter->queue_oper_stats[i].pause_count == 0)
12863 continue;
12864 tbytes +=
12865 snprintf(
12866 &temp_str[tbytes],
12867 (tbytes >= sizeof(temp_str) ?
12868 0 : sizeof(temp_str) - tbytes),
12869 "%d(%d,%d) ",
12870 i,
12871 adapter->queue_oper_stats[i].
12872 pause_count,
12873 adapter->queue_oper_stats[i].
12874 unpause_count);
12875 }
12876 if (tbytes >= sizeof(temp_str))
12877 hdd_warn("log truncated");
12878
12879 bytes_written += snprintf(&comb_log_str[bytes_written],
12880 bytes_written >= comb_log_str_size ? 0 :
12881 comb_log_str_size - bytes_written,
12882 "[%d %d] (%d) %u/%ums %s|",
12883 adapter->deflink->vdev_id, adapter->device_mode,
12884 adapter->pause_map,
12885 qdf_system_ticks_to_msecs(pause),
12886 qdf_system_ticks_to_msecs(total),
12887 temp_str);
12888
12889 adapter_num++;
12890 /* dev_put has to be done here */
12891 hdd_adapter_dev_put_debug(adapter, dbgid);
12892 }
12893
12894 /* using QDF_TRACE to avoid printing function name */
12895 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO_LOW,
12896 "STATS |%s", comb_log_str);
12897
12898 if (bytes_written >= comb_log_str_size)
12899 hdd_warn("log string truncated");
12900
12901 qdf_mem_free(comb_log_str);
12902 }
12903
12904 /* Max size of a single netdev tx queue state string. e.g. "1: 0x1" */
12905 #define HDD_NETDEV_TX_Q_STATE_STRLEN 15
12906 /**
12907 * wlan_hdd_display_adapter_netif_queue_stats() - display adapter based
12908 * netif queue stats
12909 * @adapter: hdd adapter
12910 *
12911 * Return: none
12912 */
12913 static void
wlan_hdd_display_adapter_netif_queue_stats(struct hdd_adapter * adapter)12914 wlan_hdd_display_adapter_netif_queue_stats(struct hdd_adapter *adapter)
12915 {
12916 int i;
12917 qdf_time_t total, pause, unpause, curr_time, delta;
12918 struct hdd_netif_queue_history *q_hist_ptr;
12919 char q_status_buf[NUM_TX_QUEUES * HDD_NETDEV_TX_Q_STATE_STRLEN] = {0};
12920
12921 hdd_nofl_debug("Netif queue operation statistics:");
12922 hdd_nofl_debug("vdev_id %d device mode %d",
12923 adapter->deflink->vdev_id, adapter->device_mode);
12924 hdd_nofl_debug("Current pause_map %x", adapter->pause_map);
12925 curr_time = qdf_system_ticks();
12926 total = curr_time - adapter->start_time;
12927 delta = curr_time - adapter->last_time;
12928 if (adapter->pause_map) {
12929 pause = adapter->total_pause_time + delta;
12930 unpause = adapter->total_unpause_time;
12931 } else {
12932 unpause = adapter->total_unpause_time + delta;
12933 pause = adapter->total_pause_time;
12934 }
12935 hdd_nofl_debug("Total: %ums Pause: %ums Unpause: %ums",
12936 qdf_system_ticks_to_msecs(total),
12937 qdf_system_ticks_to_msecs(pause),
12938 qdf_system_ticks_to_msecs(unpause));
12939 hdd_nofl_debug("reason_type: pause_cnt: unpause_cnt: pause_time");
12940
12941 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
12942 qdf_time_t pause_delta = 0;
12943
12944 if (adapter->pause_map & (1 << i))
12945 pause_delta = delta;
12946
12947 /* using hdd_log to avoid printing function name */
12948 hdd_nofl_debug("%s: %d: %d: %ums",
12949 hdd_reason_type_to_string(i),
12950 adapter->queue_oper_stats[i].pause_count,
12951 adapter->queue_oper_stats[i].
12952 unpause_count,
12953 qdf_system_ticks_to_msecs(
12954 adapter->queue_oper_stats[i].
12955 total_pause_time + pause_delta));
12956 }
12957
12958 hdd_nofl_debug("Netif queue operation history: Total entries: %d current index %d(-1) time %u",
12959 WLAN_HDD_MAX_HISTORY_ENTRY,
12960 adapter->history_index,
12961 qdf_system_ticks_to_msecs(qdf_system_ticks()));
12962
12963 hdd_nofl_debug("%2s%20s%50s%30s%10s %s",
12964 "#", "time(ms)", "action_type", "reason_type",
12965 "pause_map", "netdev-queue-status");
12966
12967 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
12968 /* using hdd_log to avoid printing function name */
12969 if (adapter->queue_oper_history[i].time == 0)
12970 continue;
12971 q_hist_ptr = &adapter->queue_oper_history[i];
12972 wlan_hdd_dump_queue_history_state(q_hist_ptr,
12973 q_status_buf,
12974 sizeof(q_status_buf));
12975 hdd_nofl_debug("%2d%20u%50s%30s%10x %s",
12976 i, qdf_system_ticks_to_msecs(
12977 adapter->queue_oper_history[i].time),
12978 hdd_action_type_to_string(
12979 adapter->queue_oper_history[i].
12980 netif_action),
12981 hdd_reason_type_to_string(
12982 adapter->queue_oper_history[i].
12983 netif_reason),
12984 adapter->queue_oper_history[i].pause_map,
12985 q_status_buf);
12986 }
12987 }
12988
12989 void
wlan_hdd_display_adapter_netif_queue_history(struct hdd_adapter * adapter)12990 wlan_hdd_display_adapter_netif_queue_history(struct hdd_adapter *adapter)
12991 {
12992 wlan_hdd_display_adapter_netif_queue_stats(adapter);
12993 }
12994
12995 /**
12996 * wlan_hdd_display_netif_queue_history() - display netif queue history
12997 * @context: hdd context
12998 * @verb_lvl: verbosity level
12999 *
13000 * Return: none
13001 */
13002 void
wlan_hdd_display_netif_queue_history(hdd_cb_handle context,enum qdf_stats_verbosity_level verb_lvl)13003 wlan_hdd_display_netif_queue_history(hdd_cb_handle context,
13004 enum qdf_stats_verbosity_level verb_lvl)
13005 {
13006 struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
13007 struct hdd_context *hdd_ctx = hdd_cb_handle_to_context(context);
13008 wlan_net_dev_ref_dbgid dbgid =
13009 NET_DEV_HOLD_DISPLAY_NETIF_QUEUE_HISTORY;
13010
13011 if (!hdd_ctx) {
13012 hdd_err("hdd_ctx is null");
13013 return;
13014 }
13015
13016 if (verb_lvl == QDF_STATS_VERBOSITY_LEVEL_LOW) {
13017 hdd_display_netif_queue_history_compact(hdd_ctx);
13018 return;
13019 }
13020
13021 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
13022 dbgid) {
13023 if (adapter->deflink->vdev_id == CDP_INVALID_VDEV_ID) {
13024 hdd_adapter_dev_put_debug(adapter, dbgid);
13025 continue;
13026 }
13027 wlan_hdd_display_adapter_netif_queue_stats(adapter);
13028 /* dev_put has to be done here */
13029 hdd_adapter_dev_put_debug(adapter, dbgid);
13030 }
13031 }
13032
13033 /**
13034 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
13035 * @hdd_ctx: hdd context
13036 *
13037 * Return: none
13038 */
wlan_hdd_clear_netif_queue_history(struct hdd_context * hdd_ctx)13039 void wlan_hdd_clear_netif_queue_history(struct hdd_context *hdd_ctx)
13040 {
13041 struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
13042 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_CLEAR_NETIF_QUEUE_HISTORY;
13043
13044 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
13045 dbgid) {
13046 qdf_mem_zero(adapter->queue_oper_stats,
13047 sizeof(adapter->queue_oper_stats));
13048 qdf_mem_zero(adapter->queue_oper_history,
13049 sizeof(adapter->queue_oper_history));
13050 adapter->history_index = 0;
13051 adapter->start_time = adapter->last_time = qdf_system_ticks();
13052 adapter->total_pause_time = 0;
13053 adapter->total_unpause_time = 0;
13054 hdd_adapter_dev_put_debug(adapter, dbgid);
13055 }
13056 }
13057
13058 #ifdef WLAN_FEATURE_OFFLOAD_PACKETS
13059 /**
13060 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
13061 * @hdd_ctx: hdd global context
13062 *
13063 * Return: none
13064 */
hdd_init_offloaded_packets_ctx(struct hdd_context * hdd_ctx)13065 static void hdd_init_offloaded_packets_ctx(struct hdd_context *hdd_ctx)
13066 {
13067 uint8_t i;
13068
13069 mutex_init(&hdd_ctx->op_ctx.op_lock);
13070 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
13071 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
13072 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
13073 }
13074 }
13075 #else
hdd_init_offloaded_packets_ctx(struct hdd_context * hdd_ctx)13076 static void hdd_init_offloaded_packets_ctx(struct hdd_context *hdd_ctx)
13077 {
13078 }
13079 #endif
13080
13081 #ifdef WLAN_FEATURE_WOW_PULSE
13082 /**
13083 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
13084 * @hdd_ctx: struct hdd_context structure pointer
13085 * @enable: enable or disable this behaviour
13086 *
13087 * Return: int
13088 */
wlan_hdd_set_wow_pulse(struct hdd_context * hdd_ctx,bool enable)13089 static int wlan_hdd_set_wow_pulse(struct hdd_context *hdd_ctx, bool enable)
13090 {
13091 struct wow_pulse_mode wow_pulse_set_info;
13092 QDF_STATUS status;
13093
13094 hdd_debug("wow pulse enable flag is %d", enable);
13095
13096 if (!ucfg_pmo_is_wow_pulse_enabled(hdd_ctx->psoc))
13097 return 0;
13098
13099 /* prepare the request to send to SME */
13100 if (enable == true) {
13101 wow_pulse_set_info.wow_pulse_enable = true;
13102 wow_pulse_set_info.wow_pulse_pin =
13103 ucfg_pmo_get_wow_pulse_pin(hdd_ctx->psoc);
13104
13105 wow_pulse_set_info.wow_pulse_interval_high =
13106 ucfg_pmo_get_wow_pulse_interval_high(hdd_ctx->psoc);
13107
13108 wow_pulse_set_info.wow_pulse_interval_low =
13109 ucfg_pmo_get_wow_pulse_interval_low(hdd_ctx->psoc);
13110
13111 wow_pulse_set_info.wow_pulse_repeat_count =
13112 ucfg_pmo_get_wow_pulse_repeat_count(hdd_ctx->psoc);
13113
13114 wow_pulse_set_info.wow_pulse_init_state =
13115 ucfg_pmo_get_wow_pulse_init_state(hdd_ctx->psoc);
13116 } else {
13117 wow_pulse_set_info.wow_pulse_enable = false;
13118 wow_pulse_set_info.wow_pulse_pin = 0;
13119 wow_pulse_set_info.wow_pulse_interval_low = 0;
13120 wow_pulse_set_info.wow_pulse_interval_high = 0;
13121 wow_pulse_set_info.wow_pulse_repeat_count = 0;
13122 wow_pulse_set_info.wow_pulse_init_state = 0;
13123 }
13124 hdd_debug("enable %d pin %d low %d high %d count %d init %d",
13125 wow_pulse_set_info.wow_pulse_enable,
13126 wow_pulse_set_info.wow_pulse_pin,
13127 wow_pulse_set_info.wow_pulse_interval_low,
13128 wow_pulse_set_info.wow_pulse_interval_high,
13129 wow_pulse_set_info.wow_pulse_repeat_count,
13130 wow_pulse_set_info.wow_pulse_init_state);
13131
13132 status = sme_set_wow_pulse(&wow_pulse_set_info);
13133 if (QDF_STATUS_E_FAILURE == status) {
13134 hdd_debug("sme_set_wow_pulse failure!");
13135 return -EIO;
13136 }
13137 hdd_debug("sme_set_wow_pulse success!");
13138 return 0;
13139 }
13140 #else
wlan_hdd_set_wow_pulse(struct hdd_context * hdd_ctx,bool enable)13141 static inline int wlan_hdd_set_wow_pulse(struct hdd_context *hdd_ctx, bool enable)
13142 {
13143 return 0;
13144 }
13145 #endif
13146
13147 #ifdef WLAN_FEATURE_FASTPATH
13148
13149 /**
13150 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
13151 * @hdd_ctx: hdd context
13152 * @context: lower layer context
13153 *
13154 * Return: none
13155 */
hdd_enable_fastpath(struct hdd_context * hdd_ctx,void * context)13156 void hdd_enable_fastpath(struct hdd_context *hdd_ctx,
13157 void *context)
13158 {
13159 if (cfg_get(hdd_ctx->psoc, CFG_DP_ENABLE_FASTPATH))
13160 hif_enable_fastpath(context);
13161 }
13162 #endif
13163
13164 #if defined(FEATURE_WLAN_CH_AVOID)
13165 /**
13166 * hdd_set_thermal_level_cb() - set thermal level callback function
13167 * @hdd_handle: opaque handle for the hdd context
13168 * @level: thermal level
13169 *
13170 * Change IPA data path to SW path when the thermal throttle level greater
13171 * than 0, and restore the original data path when throttle level is 0
13172 *
13173 * Return: none
13174 */
hdd_set_thermal_level_cb(hdd_handle_t hdd_handle,u_int8_t level)13175 static void hdd_set_thermal_level_cb(hdd_handle_t hdd_handle, u_int8_t level)
13176 {
13177 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
13178
13179 /* Change IPA to SW path when throttle level greater than 0 */
13180 if (level > THROTTLE_LEVEL_0)
13181 ucfg_ipa_send_mcc_scc_msg(hdd_ctx->pdev, true);
13182 else
13183 /* restore original concurrency mode */
13184 ucfg_ipa_send_mcc_scc_msg(hdd_ctx->pdev, hdd_ctx->mcc_mode);
13185 }
13186 #else
13187 /**
13188 * hdd_set_thermal_level_cb() - set thermal level callback function
13189 * @hdd_handle: opaque handle for the hdd context
13190 * @level: thermal level
13191 *
13192 * Change IPA data path to SW path when the thermal throttle level greater
13193 * than 0, and restore the original data path when throttle level is 0
13194 *
13195 * Return: none
13196 */
hdd_set_thermal_level_cb(hdd_handle_t hdd_handle,u_int8_t level)13197 static void hdd_set_thermal_level_cb(hdd_handle_t hdd_handle, u_int8_t level)
13198 {
13199 }
13200 #endif
13201
hdd_switch_sap_channel(struct wlan_hdd_link_info * link_info,uint8_t channel,bool forced)13202 QDF_STATUS hdd_switch_sap_channel(struct wlan_hdd_link_info *link_info,
13203 uint8_t channel, bool forced)
13204 {
13205 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
13206 mac_handle_t mac_handle;
13207 struct sap_config *sap_cfg;
13208 qdf_freq_t freq;
13209
13210 mac_handle = hdd_adapter_get_mac_handle(link_info->adapter);
13211 if (!mac_handle) {
13212 hdd_err("invalid MAC handle");
13213 return QDF_STATUS_E_INVAL;
13214 }
13215
13216 freq = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, channel);
13217 sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(link_info)->sap_config);
13218 hdd_debug("chan:%d width:%d", channel, sap_cfg->ch_width_orig);
13219
13220 return policy_mgr_change_sap_channel_with_csa(hdd_ctx->psoc,
13221 link_info->vdev_id, freq,
13222 sap_cfg->ch_width_orig,
13223 forced);
13224 }
13225
hdd_switch_sap_chan_freq(struct hdd_adapter * adapter,qdf_freq_t chan_freq,enum phy_ch_width ch_width,bool forced)13226 QDF_STATUS hdd_switch_sap_chan_freq(struct hdd_adapter *adapter,
13227 qdf_freq_t chan_freq,
13228 enum phy_ch_width ch_width,
13229 bool forced)
13230 {
13231 struct hdd_ap_ctx *hdd_ap_ctx;
13232 struct hdd_context *hdd_ctx;
13233
13234 if (hdd_validate_adapter(adapter))
13235 return QDF_STATUS_E_INVAL;
13236
13237 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
13238
13239 if(wlan_hdd_validate_context(hdd_ctx))
13240 return QDF_STATUS_E_INVAL;
13241
13242 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
13243
13244 hdd_debug("chan freq:%d width:%d org bw %d",
13245 chan_freq, ch_width, hdd_ap_ctx->sap_config.ch_width_orig);
13246
13247 return policy_mgr_change_sap_channel_with_csa(hdd_ctx->psoc,
13248 adapter->deflink->vdev_id,
13249 chan_freq,
13250 ch_width,
13251 forced);
13252 }
13253
hdd_update_acs_timer_reason(struct hdd_adapter * adapter,uint8_t reason)13254 int hdd_update_acs_timer_reason(struct hdd_adapter *adapter, uint8_t reason)
13255 {
13256 struct hdd_external_acs_timer_context *timer_context;
13257 int status;
13258 QDF_STATUS qdf_status;
13259 qdf_mc_timer_t *vendor_acs_timer;
13260
13261 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->deflink->link_flags);
13262
13263 vendor_acs_timer = &adapter->deflink->session.ap.vendor_acs_timer;
13264 if (QDF_TIMER_STATE_RUNNING ==
13265 qdf_mc_timer_get_current_state(vendor_acs_timer)) {
13266 qdf_mc_timer_stop(vendor_acs_timer);
13267 }
13268 timer_context =
13269 (struct hdd_external_acs_timer_context *)vendor_acs_timer->user_data;
13270 timer_context->reason = reason;
13271 qdf_status =
13272 qdf_mc_timer_start(vendor_acs_timer, WLAN_VENDOR_ACS_WAIT_TIME);
13273 if (qdf_status != QDF_STATUS_SUCCESS) {
13274 hdd_err("failed to start external acs timer");
13275 return -ENOSPC;
13276 }
13277 /* Update config to application */
13278 status = hdd_cfg80211_update_acs_config(adapter, reason);
13279 hdd_info("Updated ACS config to nl with reason %d", reason);
13280
13281 return status;
13282 }
13283
13284 #ifdef FEATURE_WLAN_CH_AVOID_EXT
wlan_hdd_get_restriction_mask(struct hdd_context * hdd_ctx)13285 uint32_t wlan_hdd_get_restriction_mask(struct hdd_context *hdd_ctx)
13286 {
13287 return hdd_ctx->restriction_mask;
13288 }
13289
wlan_hdd_set_restriction_mask(struct hdd_context * hdd_ctx)13290 void wlan_hdd_set_restriction_mask(struct hdd_context *hdd_ctx)
13291 {
13292 hdd_ctx->restriction_mask =
13293 hdd_ctx->coex_avoid_freq_list.restriction_mask;
13294 }
13295 #else
wlan_hdd_get_restriction_mask(struct hdd_context * hdd_ctx)13296 uint32_t wlan_hdd_get_restriction_mask(struct hdd_context *hdd_ctx)
13297 {
13298 return -EINVAL;
13299 }
13300
wlan_hdd_set_restriction_mask(struct hdd_context * hdd_ctx)13301 void wlan_hdd_set_restriction_mask(struct hdd_context *hdd_ctx)
13302 {
13303 }
13304 #endif
13305
13306 #if defined(FEATURE_WLAN_CH_AVOID)
13307 /**
13308 * hdd_store_sap_restart_channel() - store sap restart channel
13309 * @restart_chan: restart channel
13310 * @restart_chan_store: pointer to restart channel store
13311 *
13312 * The function will store new sap restart channel.
13313 *
13314 * Return - none
13315 */
13316 static void
hdd_store_sap_restart_channel(qdf_freq_t restart_chan,qdf_freq_t * restart_chan_store)13317 hdd_store_sap_restart_channel(qdf_freq_t restart_chan, qdf_freq_t *restart_chan_store)
13318 {
13319 uint8_t i;
13320
13321 for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
13322 if (*(restart_chan_store + i) == restart_chan)
13323 return;
13324
13325 if (*(restart_chan_store + i))
13326 continue;
13327
13328 *(restart_chan_store + i) = restart_chan;
13329 return;
13330 }
13331 }
13332
13333 /**
13334 * hdd_check_chn_bw_boundary_unsafe() - check channel range unsafe
13335 * @hdd_ctxt: hdd context pointer
13336 * @adapter: hdd adapter pointer
13337 *
13338 * hdd_check_chn_bw_boundary_unsafe check SAP channel range with certain
13339 * bandwidth whether cover all unsafe channel list.
13340 *
13341 * Return - bool
13342 */
13343 static bool
hdd_check_chn_bw_boundary_unsafe(struct hdd_context * hdd_ctxt,struct hdd_adapter * adapter)13344 hdd_check_chn_bw_boundary_unsafe(struct hdd_context *hdd_ctxt,
13345 struct hdd_adapter *adapter)
13346 {
13347 uint32_t freq;
13348 uint32_t start_freq = 0;
13349 uint32_t end_freq = 0;
13350 uint32_t i;
13351 uint8_t ch_width;
13352 const struct bonded_channel_freq *bonded_chan_ptr_ptr = NULL;
13353
13354 freq = adapter->deflink->session.ap.operating_chan_freq;
13355 ch_width = adapter->deflink->session.ap.sap_config.acs_cfg.ch_width;
13356
13357 if (ch_width > CH_WIDTH_20MHZ)
13358 bonded_chan_ptr_ptr =
13359 wlan_reg_get_bonded_chan_entry(freq, ch_width, 0);
13360
13361 if (bonded_chan_ptr_ptr) {
13362 start_freq = bonded_chan_ptr_ptr->start_freq;
13363 end_freq = bonded_chan_ptr_ptr->end_freq;
13364 }
13365
13366 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
13367 if ((freq == hdd_ctxt->unsafe_channel_list[i]) ||
13368 (start_freq <= hdd_ctxt->unsafe_channel_list[i] &&
13369 hdd_ctxt->unsafe_channel_list[i] <= end_freq)) {
13370 hdd_debug("op chn freq:%u is unsafe for chn list:%u",
13371 freq, hdd_ctxt->unsafe_channel_list[i]);
13372 return true;
13373 }
13374 }
13375
13376 return false;
13377 }
13378
13379 /**
13380 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
13381 * @hdd_ctx: hdd context pointer
13382 *
13383 * hdd_unsafe_channel_restart_sap check all unsafe channel list
13384 * and if ACS is enabled, driver will ask userspace to restart the
13385 * sap. User space on LTE coex indication restart driver.
13386 *
13387 * Return - none
13388 */
hdd_unsafe_channel_restart_sap(struct hdd_context * hdd_ctx)13389 QDF_STATUS hdd_unsafe_channel_restart_sap(struct hdd_context *hdd_ctx)
13390 {
13391 struct hdd_adapter *adapter, *next_adapter = NULL;
13392 struct hdd_ap_ctx *ap_ctx;
13393 uint32_t i;
13394 bool found = false;
13395 qdf_freq_t restart_chan_store[SAP_MAX_NUM_SESSION] = {0};
13396 uint8_t scc_on_lte_coex = 0;
13397 uint32_t restart_freq, ap_chan_freq;
13398 bool value;
13399 QDF_STATUS status;
13400 bool is_acs_support_for_dfs_ltecoex = cfg_default(CFG_USER_ACS_DFS_LTE);
13401 bool is_vendor_acs_support =
13402 cfg_default(CFG_USER_AUTO_CHANNEL_SELECTION);
13403 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_UNSAFE_CHANNEL_RESTART_SAP;
13404 enum phy_ch_width ch_width;
13405 struct wlan_hdd_link_info *link_info;
13406
13407 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
13408 dbgid) {
13409 if (adapter->device_mode != QDF_SAP_MODE) {
13410 hdd_debug_rl("skip device mode:%d",
13411 adapter->device_mode);
13412 hdd_adapter_dev_put_debug(adapter, dbgid);
13413 continue;
13414 }
13415
13416 hdd_adapter_for_each_active_link_info(adapter, link_info) {
13417 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
13418 if (!ap_ctx->sap_config.acs_cfg.acs_mode) {
13419 hdd_debug_rl("skip acs:%d",
13420 ap_ctx->sap_config.acs_cfg.acs_mode);
13421 continue;
13422 }
13423
13424 ap_chan_freq = ap_ctx->operating_chan_freq;
13425 ch_width = ap_ctx->sap_config.ch_width_orig;
13426 found = false;
13427 status =
13428 ucfg_policy_mgr_get_sta_sap_scc_lte_coex_chnl(hdd_ctx->psoc,
13429 &scc_on_lte_coex);
13430 if (!QDF_IS_STATUS_SUCCESS(status))
13431 hdd_err("can't get scc on lte coex chnl, use def");
13432 /*
13433 * If STA+SAP is doing SCC &
13434 * g_sta_sap_scc_on_lte_coex_chan is set,
13435 * no need to move SAP.
13436 */
13437 if ((policy_mgr_is_sta_sap_scc(hdd_ctx->psoc,
13438 ap_chan_freq) &&
13439 scc_on_lte_coex) ||
13440 policy_mgr_nan_sap_scc_on_unsafe_ch_chk(hdd_ctx->psoc,
13441 ap_chan_freq))
13442 hdd_debug("SAP allowed in unsafe SCC channel");
13443 else
13444 found = hdd_check_chn_bw_boundary_unsafe(hdd_ctx,
13445 adapter);
13446 if (!found) {
13447 hdd_store_sap_restart_channel(ap_chan_freq,
13448 restart_chan_store);
13449 hdd_debug("ch freq:%d is safe. no need to change channel",
13450 ap_chan_freq);
13451 continue;
13452 }
13453
13454 status = ucfg_mlme_get_acs_support_for_dfs_ltecoex(
13455 hdd_ctx->psoc,
13456 &is_acs_support_for_dfs_ltecoex);
13457 if (!QDF_IS_STATUS_SUCCESS(status))
13458 hdd_err("get_acs_support_for_dfs_ltecoex failed,set def");
13459
13460 status = ucfg_mlme_get_vendor_acs_support(
13461 hdd_ctx->psoc,
13462 &is_vendor_acs_support);
13463 if (!QDF_IS_STATUS_SUCCESS(status))
13464 hdd_err("get_vendor_acs_support failed, set default");
13465
13466 if (is_vendor_acs_support &&
13467 is_acs_support_for_dfs_ltecoex) {
13468 hdd_update_acs_timer_reason(adapter,
13469 QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX);
13470 continue;
13471 }
13472
13473 restart_freq = 0;
13474 for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
13475 if (!restart_chan_store[i])
13476 continue;
13477
13478 if (policy_mgr_is_force_scc(hdd_ctx->psoc) &&
13479 WLAN_REG_IS_SAME_BAND_FREQS(
13480 restart_chan_store[i],
13481 ap_chan_freq)) {
13482 restart_freq = restart_chan_store[i];
13483 break;
13484 }
13485 }
13486 if (!restart_freq) {
13487 restart_freq =
13488 wlansap_get_safe_channel_from_pcl_and_acs_range(
13489 WLAN_HDD_GET_SAP_CTX_PTR(link_info),
13490 &ch_width);
13491 }
13492 if (!restart_freq) {
13493 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc,
13494 link_info->vdev_id,
13495 CSA_REASON_UNSAFE_CHANNEL);
13496 hdd_err("Unable to find safe chan, Stop the SAP if restriction mask is set else set txpower");
13497 hdd_stop_sap_set_tx_power(hdd_ctx->psoc, adapter);
13498 continue;
13499 }
13500 /*
13501 * SAP restart due to unsafe channel. While
13502 * restarting the SAP, make sure to clear
13503 * acs_channel, channel to reset to
13504 * 0. Otherwise these settings will override
13505 * the ACS while restart.
13506 */
13507 hdd_ctx->acs_policy.acs_chan_freq =
13508 AUTO_CHANNEL_SELECT;
13509 ucfg_mlme_get_sap_internal_restart(hdd_ctx->psoc,
13510 &value);
13511 if (value) {
13512 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc,
13513 link_info->vdev_id,
13514 CSA_REASON_UNSAFE_CHANNEL);
13515 status = hdd_switch_sap_chan_freq(adapter,
13516 restart_freq,
13517 ch_width,
13518 true);
13519 if (QDF_IS_STATUS_SUCCESS(status)) {
13520 hdd_adapter_dev_put_debug(adapter,
13521 dbgid);
13522 if (next_adapter)
13523 hdd_adapter_dev_put_debug(
13524 next_adapter,
13525 dbgid);
13526 return QDF_STATUS_E_PENDING;
13527 } else {
13528 hdd_debug("CSA failed, check next SAP");
13529 }
13530 } else {
13531 hdd_debug("sending coex indication");
13532 wlan_hdd_send_svc_nlink_msg(
13533 hdd_ctx->radio_index,
13534 WLAN_SVC_LTE_COEX_IND, NULL, 0);
13535 hdd_adapter_dev_put_debug(adapter, dbgid);
13536 if (next_adapter)
13537 hdd_adapter_dev_put_debug(next_adapter,
13538 dbgid);
13539 return QDF_STATUS_SUCCESS;
13540 }
13541 }
13542 /* dev_put has to be done here */
13543 hdd_adapter_dev_put_debug(adapter, dbgid);
13544 }
13545
13546 return QDF_STATUS_SUCCESS;
13547 }
13548
13549 /**
13550 * hdd_init_channel_avoidance() - Initialize channel avoidance
13551 * @hdd_ctx: HDD global context
13552 *
13553 * Initialize the channel avoidance logic by retrieving the unsafe
13554 * channel list from the platform driver and plumbing the data
13555 * down to the lower layers. Then subscribe to subsequent channel
13556 * avoidance events.
13557 *
13558 * Return: None
13559 */
hdd_init_channel_avoidance(struct hdd_context * hdd_ctx)13560 static void hdd_init_channel_avoidance(struct hdd_context *hdd_ctx)
13561 {
13562 uint16_t unsafe_channel_count;
13563 int index;
13564 qdf_freq_t *unsafe_freq_list;
13565
13566 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
13567 hdd_ctx->unsafe_channel_list,
13568 &(hdd_ctx->unsafe_channel_count),
13569 sizeof(uint16_t) * NUM_CHANNELS);
13570
13571 hdd_debug("num of unsafe channels is %d",
13572 hdd_ctx->unsafe_channel_count);
13573
13574 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
13575 (uint16_t)NUM_CHANNELS);
13576
13577 if (!unsafe_channel_count)
13578 return;
13579
13580 unsafe_freq_list = qdf_mem_malloc(
13581 unsafe_channel_count * sizeof(*unsafe_freq_list));
13582
13583 if (!unsafe_freq_list)
13584 return;
13585
13586 for (index = 0; index < unsafe_channel_count; index++) {
13587 hdd_debug("channel frequency %d is not safe",
13588 hdd_ctx->unsafe_channel_list[index]);
13589 unsafe_freq_list[index] =
13590 (qdf_freq_t)hdd_ctx->unsafe_channel_list[index];
13591 }
13592
13593 ucfg_policy_mgr_init_chan_avoidance(
13594 hdd_ctx->psoc,
13595 unsafe_freq_list,
13596 unsafe_channel_count);
13597
13598 qdf_mem_free(unsafe_freq_list);
13599 }
13600
hdd_lte_coex_restart_sap(struct hdd_adapter * adapter,struct hdd_context * hdd_ctx)13601 static void hdd_lte_coex_restart_sap(struct hdd_adapter *adapter,
13602 struct hdd_context *hdd_ctx)
13603 {
13604 uint8_t restart_chan;
13605 uint32_t restart_freq;
13606
13607 restart_freq = wlansap_get_safe_channel_from_pcl_and_acs_range(
13608 WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
13609 NULL);
13610
13611 restart_chan = wlan_reg_freq_to_chan(hdd_ctx->pdev,
13612 restart_freq);
13613
13614 if (!restart_chan) {
13615 hdd_alert("fail to restart SAP");
13616 return;
13617 }
13618
13619 /* SAP restart due to unsafe channel. While restarting
13620 * the SAP, make sure to clear acs_channel, channel to
13621 * reset to 0. Otherwise these settings will override
13622 * the ACS while restart.
13623 */
13624 hdd_ctx->acs_policy.acs_chan_freq = AUTO_CHANNEL_SELECT;
13625
13626 hdd_debug("sending coex indication");
13627
13628 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
13629 WLAN_SVC_LTE_COEX_IND, NULL, 0);
13630 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->deflink->vdev_id,
13631 CSA_REASON_LTE_COEX);
13632 hdd_switch_sap_channel(adapter->deflink, restart_chan, true);
13633 }
13634
hdd_clone_local_unsafe_chan(struct hdd_context * hdd_ctx,uint16_t ** local_unsafe_list,uint16_t * local_unsafe_list_count)13635 int hdd_clone_local_unsafe_chan(struct hdd_context *hdd_ctx,
13636 uint16_t **local_unsafe_list, uint16_t *local_unsafe_list_count)
13637 {
13638 uint32_t size;
13639 uint16_t *unsafe_list;
13640 uint16_t chan_count;
13641
13642 if (!hdd_ctx || !local_unsafe_list_count || !local_unsafe_list_count)
13643 return -EINVAL;
13644
13645 chan_count = QDF_MIN(hdd_ctx->unsafe_channel_count,
13646 NUM_CHANNELS);
13647 if (chan_count) {
13648 size = chan_count * sizeof(hdd_ctx->unsafe_channel_list[0]);
13649 unsafe_list = qdf_mem_malloc(size);
13650 if (!unsafe_list)
13651 return -ENOMEM;
13652 qdf_mem_copy(unsafe_list, hdd_ctx->unsafe_channel_list, size);
13653 } else {
13654 unsafe_list = NULL;
13655 }
13656
13657 *local_unsafe_list = unsafe_list;
13658 *local_unsafe_list_count = chan_count;
13659
13660 return 0;
13661 }
13662
hdd_local_unsafe_channel_updated(struct hdd_context * hdd_ctx,uint16_t * local_unsafe_list,uint16_t local_unsafe_list_count,uint32_t restriction_mask)13663 bool hdd_local_unsafe_channel_updated(
13664 struct hdd_context *hdd_ctx, uint16_t *local_unsafe_list,
13665 uint16_t local_unsafe_list_count, uint32_t restriction_mask)
13666 {
13667 int i, j;
13668
13669 if (local_unsafe_list_count != hdd_ctx->unsafe_channel_count)
13670 return true;
13671 if (local_unsafe_list_count == 0)
13672 return false;
13673 for (i = 0; i < local_unsafe_list_count; i++) {
13674 for (j = 0; j < local_unsafe_list_count; j++)
13675 if (local_unsafe_list[i] ==
13676 hdd_ctx->unsafe_channel_list[j])
13677 break;
13678 if (j >= local_unsafe_list_count)
13679 break;
13680 }
13681
13682 if (ucfg_mlme_get_coex_unsafe_chan_nb_user_prefer(hdd_ctx->psoc)) {
13683 /* Return false if current channel list is same as previous
13684 * and restriction mask is not altered
13685 */
13686 if (i >= local_unsafe_list_count &&
13687 (restriction_mask ==
13688 wlan_hdd_get_restriction_mask(hdd_ctx))) {
13689 hdd_info("unsafe chan list same");
13690 return false;
13691 }
13692 } else if (i >= local_unsafe_list_count) {
13693 hdd_info("unsafe chan list same");
13694 return false;
13695 }
13696
13697 return true;
13698 }
13699 #else
hdd_init_channel_avoidance(struct hdd_context * hdd_ctx)13700 static void hdd_init_channel_avoidance(struct hdd_context *hdd_ctx)
13701 {
13702 }
13703
hdd_lte_coex_restart_sap(struct hdd_adapter * adapter,struct hdd_context * hdd_ctx)13704 static inline void hdd_lte_coex_restart_sap(struct hdd_adapter *adapter,
13705 struct hdd_context *hdd_ctx)
13706 {
13707 hdd_debug("Channel avoidance is not enabled; Abort SAP restart");
13708 }
13709 #endif /* defined(FEATURE_WLAN_CH_AVOID) */
13710
13711 struct wlan_hdd_link_info *
wlan_hdd_get_link_info_from_objmgr(struct wlan_objmgr_vdev * vdev)13712 wlan_hdd_get_link_info_from_objmgr(struct wlan_objmgr_vdev *vdev)
13713 {
13714 if (!vdev) {
13715 hdd_err("null vdev object");
13716 return NULL;
13717 }
13718
13719 if (vdev->vdev_nif.osdev)
13720 return vdev->vdev_nif.osdev->legacy_osif_priv;
13721
13722 return NULL;
13723 }
13724
13725 /**
13726 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
13727 * user space
13728 * @frame_ind: Management frame data to be informed.
13729 *
13730 * This function is used to indicate management frame to
13731 * user space
13732 *
13733 * Return: None
13734 *
13735 */
hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd * frame_ind)13736 void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
13737 {
13738 struct hdd_context *hdd_ctx = NULL;
13739 struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
13740 int i, num_adapters;
13741 uint8_t vdev_id[WLAN_MAX_VDEVS + WLAN_MAX_ML_VDEVS];
13742 struct ieee80211_mgmt *mgmt =
13743 (struct ieee80211_mgmt *)frame_ind->frameBuf;
13744 struct wlan_objmgr_vdev *vdev;
13745 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_INDICATE_MGMT_FRAME;
13746 struct wlan_hdd_link_info *link_info;
13747
13748 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13749 if (wlan_hdd_validate_context(hdd_ctx))
13750 return;
13751
13752 if (frame_ind->frame_len < ieee80211_hdrlen(mgmt->frame_control)) {
13753 hdd_err(" Invalid frame length");
13754 return;
13755 }
13756
13757 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
13758 for (i = 0; i < WLAN_MAX_VDEVS; i++) {
13759 link_info = hdd_get_link_info_by_vdev(hdd_ctx, i);
13760 if (link_info) {
13761 adapter = link_info->adapter;
13762 break;
13763 }
13764 }
13765 } else if (SME_SESSION_ID_BROADCAST == frame_ind->sessionId) {
13766 num_adapters = 0;
13767 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter,
13768 next_adapter, dbgid) {
13769 hdd_adapter_for_each_active_link_info(adapter,
13770 link_info) {
13771 vdev_id[num_adapters] = link_info->vdev_id;
13772 num_adapters++;
13773 }
13774 /* dev_put has to be done here */
13775 hdd_adapter_dev_put_debug(adapter, dbgid);
13776 }
13777
13778 adapter = NULL;
13779
13780 for (i = 0; i < num_adapters; i++) {
13781 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
13782 hdd_ctx->psoc,
13783 vdev_id[i],
13784 WLAN_OSIF_ID);
13785
13786 if (!vdev)
13787 continue;
13788
13789 link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
13790 if (!link_info) {
13791 wlan_objmgr_vdev_release_ref(vdev,
13792 WLAN_OSIF_ID);
13793 continue;
13794 }
13795
13796 hdd_indicate_mgmt_frame_to_user(link_info->adapter,
13797 frame_ind->frame_len,
13798 frame_ind->frameBuf,
13799 frame_ind->frameType,
13800 frame_ind->rx_freq,
13801 frame_ind->rxRssi,
13802 frame_ind->rx_flags);
13803 wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
13804 }
13805
13806 adapter = NULL;
13807 } else {
13808 link_info = hdd_get_link_info_by_vdev(hdd_ctx,
13809 frame_ind->sessionId);
13810
13811 if (!link_info) {
13812 hdd_err("Invalid vdev");
13813 return;
13814 }
13815
13816 adapter = link_info->adapter;
13817 }
13818
13819 if ((adapter) &&
13820 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
13821 hdd_indicate_mgmt_frame_to_user(adapter,
13822 frame_ind->frame_len,
13823 frame_ind->frameBuf,
13824 frame_ind->frameType,
13825 frame_ind->rx_freq,
13826 frame_ind->rxRssi,
13827 frame_ind->rx_flags);
13828 }
13829
hdd_acs_response_timeout_handler(void * context)13830 void hdd_acs_response_timeout_handler(void *context)
13831 {
13832 struct hdd_external_acs_timer_context *timer_context =
13833 (struct hdd_external_acs_timer_context *)context;
13834 struct hdd_adapter *adapter;
13835 struct hdd_context *hdd_ctx;
13836 uint8_t reason;
13837 struct sap_context *sap_context;
13838 struct wlan_hdd_link_info *link_info;
13839
13840 hdd_enter();
13841 if (!timer_context) {
13842 hdd_err("invalid timer context");
13843 return;
13844 }
13845 adapter = timer_context->adapter;
13846 reason = timer_context->reason;
13847
13848 if (!adapter || adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
13849 hdd_err("invalid adapter or adapter has invalid magic");
13850 return;
13851 }
13852
13853 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
13854 if (wlan_hdd_validate_context(hdd_ctx))
13855 return;
13856
13857 link_info = adapter->deflink;
13858 if (!test_bit(VENDOR_ACS_RESPONSE_PENDING, &link_info->link_flags))
13859 return;
13860
13861 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &link_info->link_flags);
13862
13863 hdd_err("ACS timeout happened for %s reason %d",
13864 adapter->dev->name, reason);
13865
13866 sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
13867 switch (reason) {
13868 /* SAP init case */
13869 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
13870 wlan_sap_set_vendor_acs(sap_context, false);
13871 wlan_hdd_cfg80211_start_acs(link_info);
13872 break;
13873 /* DFS detected on current channel */
13874 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
13875 wlan_sap_update_next_channel(sap_context, 0, 0);
13876 sme_update_new_channel_event(hdd_ctx->mac_handle,
13877 link_info->vdev_id);
13878 break;
13879 /* LTE coex event on current channel */
13880 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
13881 hdd_lte_coex_restart_sap(adapter, hdd_ctx);
13882 break;
13883 default:
13884 hdd_info("invalid reason for timer invoke");
13885 }
13886 }
13887
13888 /**
13889 * hdd_override_ini_config - Override INI config
13890 * @hdd_ctx: HDD context
13891 *
13892 * Override INI config based on module parameter.
13893 *
13894 * Return: None
13895 */
hdd_override_ini_config(struct hdd_context * hdd_ctx)13896 static void hdd_override_ini_config(struct hdd_context *hdd_ctx)
13897 {
13898 QDF_STATUS status;
13899
13900 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
13901 ucfg_scan_cfg_set_dfs_chan_scan_allowed(hdd_ctx->psoc,
13902 enable_dfs_chan_scan);
13903 hdd_debug("Module enable_dfs_chan_scan set to %d",
13904 enable_dfs_chan_scan);
13905 }
13906 if (0 == enable_11d || 1 == enable_11d) {
13907 status = ucfg_mlme_set_11d_enabled(hdd_ctx->psoc, enable_11d);
13908 if (!QDF_IS_STATUS_SUCCESS(status))
13909 hdd_err("Failed to set 11d_enable flag");
13910 }
13911 }
13912
13913 #ifdef ENABLE_MTRACE_LOG
hdd_set_mtrace_for_each(struct hdd_context * hdd_ctx)13914 static void hdd_set_mtrace_for_each(struct hdd_context *hdd_ctx)
13915 {
13916 uint8_t module_id = 0;
13917 int qdf_print_idx = -1;
13918
13919 qdf_print_idx = qdf_get_pidx();
13920 for (module_id = 0; module_id < QDF_MODULE_ID_MAX; module_id++)
13921 qdf_print_set_category_verbose(
13922 qdf_print_idx,
13923 module_id, QDF_TRACE_LEVEL_TRACE,
13924 hdd_ctx->config->enable_mtrace);
13925 }
13926 #else
hdd_set_mtrace_for_each(struct hdd_context * hdd_ctx)13927 static void hdd_set_mtrace_for_each(struct hdd_context *hdd_ctx)
13928 {
13929 }
13930
13931 #endif
13932
13933 /**
13934 * hdd_log_level_to_bitmask() - user space log level to host log bitmask
13935 * @user_log_level: user space log level
13936 *
13937 * Convert log level from user space to host log level bitmask.
13938 *
13939 * Return: Bitmask of log levels to be enabled
13940 */
hdd_log_level_to_bitmask(enum host_log_level user_log_level)13941 static uint32_t hdd_log_level_to_bitmask(enum host_log_level user_log_level)
13942 {
13943 QDF_TRACE_LEVEL host_trace_level;
13944 uint32_t bitmask;
13945
13946 switch (user_log_level) {
13947 case HOST_LOG_LEVEL_NONE:
13948 host_trace_level = QDF_TRACE_LEVEL_NONE;
13949 break;
13950 case HOST_LOG_LEVEL_FATAL:
13951 host_trace_level = QDF_TRACE_LEVEL_FATAL;
13952 break;
13953 case HOST_LOG_LEVEL_ERROR:
13954 host_trace_level = QDF_TRACE_LEVEL_ERROR;
13955 break;
13956 case HOST_LOG_LEVEL_WARN:
13957 host_trace_level = QDF_TRACE_LEVEL_WARN;
13958 break;
13959 case HOST_LOG_LEVEL_INFO:
13960 host_trace_level = QDF_TRACE_LEVEL_INFO_LOW;
13961 break;
13962 case HOST_LOG_LEVEL_DEBUG:
13963 host_trace_level = QDF_TRACE_LEVEL_DEBUG;
13964 break;
13965 case HOST_LOG_LEVEL_TRACE:
13966 host_trace_level = QDF_TRACE_LEVEL_TRACE;
13967 break;
13968 default:
13969 host_trace_level = QDF_TRACE_LEVEL_TRACE;
13970 break;
13971 }
13972
13973 bitmask = (1 << (host_trace_level + 1)) - 1;
13974
13975 return bitmask;
13976 }
13977
13978 /**
13979 * hdd_set_trace_level_for_each - Set trace level for each INI config
13980 * @hdd_ctx: HDD context
13981 *
13982 * Set trace level for each module based on INI config.
13983 *
13984 * Return: None
13985 */
hdd_set_trace_level_for_each(struct hdd_context * hdd_ctx)13986 static void hdd_set_trace_level_for_each(struct hdd_context *hdd_ctx)
13987 {
13988 uint8_t host_module_log[QDF_MODULE_ID_MAX * 2];
13989 qdf_size_t host_module_log_num = 0;
13990 QDF_MODULE_ID module_id;
13991 uint32_t bitmask;
13992 uint32_t i;
13993
13994 qdf_uint8_array_parse(cfg_get(hdd_ctx->psoc,
13995 CFG_ENABLE_HOST_MODULE_LOG_LEVEL),
13996 host_module_log,
13997 QDF_MODULE_ID_MAX * 2,
13998 &host_module_log_num);
13999
14000 for (i = 0; i + 1 < host_module_log_num; i += 2) {
14001 module_id = host_module_log[i];
14002 bitmask = hdd_log_level_to_bitmask(host_module_log[i + 1]);
14003 if (module_id < QDF_MODULE_ID_MAX &&
14004 module_id >= QDF_MODULE_ID_MIN)
14005 hdd_qdf_trace_enable(module_id, bitmask);
14006 }
14007
14008 hdd_set_mtrace_for_each(hdd_ctx);
14009 }
14010
14011 /**
14012 * hdd_context_init() - Initialize HDD context
14013 * @hdd_ctx: HDD context.
14014 *
14015 * Initialize HDD context along with all the feature specific contexts.
14016 *
14017 * return: 0 on success and errno on failure.
14018 */
hdd_context_init(struct hdd_context * hdd_ctx)14019 static int hdd_context_init(struct hdd_context *hdd_ctx)
14020 {
14021 int ret;
14022
14023 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
14024 hdd_ctx->max_intf_count = WLAN_MAX_VDEVS;
14025
14026 init_completion(&hdd_ctx->mc_sus_event_var);
14027 init_completion(&hdd_ctx->ready_to_suspend);
14028
14029 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
14030 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
14031
14032 qdf_list_create(&hdd_ctx->hdd_adapters, 0);
14033
14034 ret = hdd_scan_context_init(hdd_ctx);
14035 if (ret)
14036 goto list_destroy;
14037
14038 ret = hdd_sap_context_init(hdd_ctx);
14039 if (ret)
14040 goto scan_destroy;
14041
14042 ret = ucfg_dp_bbm_context_init(hdd_ctx->psoc);
14043 if (ret)
14044 goto sap_destroy;
14045
14046 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
14047
14048 hdd_init_offloaded_packets_ctx(hdd_ctx);
14049
14050 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
14051 hdd_ctx->config);
14052 if (ret)
14053 goto bbm_destroy;
14054
14055 qdf_wake_lock_create(&hdd_ctx->monitor_mode_wakelock,
14056 "monitor_mode_wakelock");
14057 hdd_lp_create_work(hdd_ctx);
14058
14059 return 0;
14060
14061 bbm_destroy:
14062 ucfg_dp_bbm_context_deinit(hdd_ctx->psoc);
14063
14064 sap_destroy:
14065 hdd_sap_context_destroy(hdd_ctx);
14066
14067 scan_destroy:
14068 hdd_scan_context_destroy(hdd_ctx);
14069 list_destroy:
14070 qdf_list_destroy(&hdd_ctx->hdd_adapters);
14071
14072 return ret;
14073 }
14074
14075 #ifdef SHUTDOWN_WLAN_IN_SYSTEM_SUSPEND
hdd_idle_timer_in_active(uint32_t timeout_ms)14076 static void hdd_idle_timer_in_active(uint32_t timeout_ms)
14077 {
14078 /* do nothing because idle shutdown will be called in system
14079 * suspend prepare
14080 */
14081 }
14082 #else
14083 /* ensure idle shutdown can be called/finished once timer started */
hdd_idle_timer_in_active(uint32_t timeout_ms)14084 static void hdd_idle_timer_in_active(uint32_t timeout_ms)
14085 {
14086 uint32_t suspend_timeout_ms;
14087 enum wake_lock_reason reason =
14088 WIFI_POWER_EVENT_WAKELOCK_IFACE_CHANGE_TIMER;
14089
14090 suspend_timeout_ms = timeout_ms + HDD_PSOC_IDLE_SHUTDOWN_SUSPEND_DELAY;
14091 hdd_prevent_suspend_timeout(suspend_timeout_ms, reason);
14092 }
14093 #endif
14094
hdd_psoc_idle_timer_start(struct hdd_context * hdd_ctx)14095 void hdd_psoc_idle_timer_start(struct hdd_context *hdd_ctx)
14096 {
14097 uint32_t timeout_ms = hdd_ctx->config->iface_change_wait_time;
14098
14099 if (!timeout_ms) {
14100 hdd_info("psoc idle timer is disabled");
14101 return;
14102 }
14103
14104 hdd_debug("Starting psoc idle timer");
14105
14106 /* If PCIe gen speed change is requested, reduce idle shutdown
14107 * timeout to 100 ms
14108 */
14109 if (hdd_ctx->current_pcie_gen_speed) {
14110 timeout_ms = HDD_PCIE_GEN_SPEED_CHANGE_TIMEOUT_MS;
14111 hdd_info("pcie gen speed change requested");
14112 }
14113
14114 qdf_delayed_work_start(&hdd_ctx->psoc_idle_timeout_work, timeout_ms);
14115 hdd_idle_timer_in_active(timeout_ms);
14116 }
14117
hdd_psoc_idle_timer_stop(struct hdd_context * hdd_ctx)14118 void hdd_psoc_idle_timer_stop(struct hdd_context *hdd_ctx)
14119 {
14120 qdf_delayed_work_stop_sync(&hdd_ctx->psoc_idle_timeout_work);
14121 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_IFACE_CHANGE_TIMER);
14122 hdd_debug("Stopped psoc idle timer");
14123 }
14124
14125
14126 /**
14127 * __hdd_psoc_idle_shutdown() - perform an idle shutdown on the given psoc
14128 * @hdd_ctx: the hdd context which should be shutdown
14129 *
14130 * When no interfaces are "up" on a psoc, an idle shutdown timer is started.
14131 * If no interfaces are brought up before the timer expires, we do an
14132 * "idle shutdown," cutting power to the physical SoC to save power. This is
14133 * done completely transparently from the perspective of userspace.
14134 *
14135 * Return: None
14136 */
__hdd_psoc_idle_shutdown(struct hdd_context * hdd_ctx)14137 static int __hdd_psoc_idle_shutdown(struct hdd_context *hdd_ctx)
14138 {
14139 struct osif_psoc_sync *psoc_sync;
14140 int errno;
14141
14142 hdd_enter();
14143
14144 hdd_reg_wait_for_country_change(hdd_ctx);
14145
14146 errno = osif_psoc_sync_trans_start(hdd_ctx->parent_dev, &psoc_sync);
14147 if (errno) {
14148 hdd_info("psoc busy, abort idle shutdown; errno:%d", errno);
14149 errno = -EAGAIN;
14150 goto exit;
14151 }
14152
14153 osif_psoc_sync_wait_for_ops(psoc_sync);
14154 /*
14155 * This is to handle scenario in which platform driver triggers
14156 * idle_shutdown if Deep Sleep/Hibernate entry notification is
14157 * received from modem subsystem in wearable devices
14158 */
14159 if (hdd_is_any_interface_open(hdd_ctx)) {
14160 hdd_err_rl("all interfaces are not down, ignore idle shutdown");
14161 errno = -EAGAIN;
14162 } else {
14163 errno = hdd_wlan_stop_modules(hdd_ctx, false);
14164 }
14165
14166 osif_psoc_sync_trans_stop(psoc_sync);
14167
14168 exit:
14169 hdd_exit();
14170 return errno;
14171 }
14172
__hdd_mode_change_psoc_idle_shutdown(struct hdd_context * hdd_ctx)14173 static int __hdd_mode_change_psoc_idle_shutdown(struct hdd_context *hdd_ctx)
14174 {
14175 is_mode_change_psoc_idle_shutdown = false;
14176 return hdd_wlan_stop_modules(hdd_ctx, true);
14177 }
14178
hdd_psoc_idle_shutdown(struct device * dev)14179 int hdd_psoc_idle_shutdown(struct device *dev)
14180 {
14181 int ret;
14182 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14183
14184 if (!hdd_ctx)
14185 return -EINVAL;
14186
14187 if (is_mode_change_psoc_idle_shutdown)
14188 ret = __hdd_mode_change_psoc_idle_shutdown(hdd_ctx);
14189 else {
14190 ret = __hdd_psoc_idle_shutdown(hdd_ctx);
14191 }
14192
14193 return ret;
14194 }
14195
__hdd_psoc_idle_restart(struct hdd_context * hdd_ctx)14196 static int __hdd_psoc_idle_restart(struct hdd_context *hdd_ctx)
14197 {
14198 int ret;
14199
14200 ret = hdd_soc_idle_restart_lock(hdd_ctx->parent_dev);
14201 if (ret)
14202 return ret;
14203
14204 ret = hdd_wlan_start_modules(hdd_ctx, false);
14205
14206 if (!qdf_is_fw_down())
14207 cds_set_recovery_in_progress(false);
14208
14209 hdd_soc_idle_restart_unlock();
14210
14211 return ret;
14212 }
14213
hdd_psoc_idle_restart(struct device * dev)14214 int hdd_psoc_idle_restart(struct device *dev)
14215 {
14216 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14217
14218 if (!hdd_ctx)
14219 return -EINVAL;
14220
14221 return __hdd_psoc_idle_restart(hdd_ctx);
14222 }
14223
hdd_trigger_psoc_idle_restart(struct hdd_context * hdd_ctx)14224 int hdd_trigger_psoc_idle_restart(struct hdd_context *hdd_ctx)
14225 {
14226 int ret;
14227
14228 QDF_BUG(rtnl_is_locked());
14229
14230 hdd_psoc_idle_timer_stop(hdd_ctx);
14231 if (hdd_ctx->driver_status == DRIVER_MODULES_ENABLED) {
14232 hdd_nofl_debug("Driver modules already Enabled");
14233 return 0;
14234 }
14235
14236 ret = hdd_soc_idle_restart_lock(hdd_ctx->parent_dev);
14237 if (ret)
14238 return ret;
14239
14240 if (hdd_ctx->current_pcie_gen_speed) {
14241 hdd_info("request pcie gen speed change to %d",
14242 hdd_ctx->current_pcie_gen_speed);
14243
14244 /* call pld api for pcie gen speed change */
14245 ret = pld_set_pcie_gen_speed(hdd_ctx->parent_dev,
14246 hdd_ctx->current_pcie_gen_speed);
14247 if (ret)
14248 hdd_err_rl("failed to set pcie gen speed");
14249
14250 hdd_ctx->current_pcie_gen_speed = 0;
14251 }
14252
14253 qdf_event_reset(&hdd_ctx->regulatory_update_event);
14254 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
14255 hdd_ctx->is_regulatory_update_in_progress = true;
14256 qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
14257
14258 ret = pld_idle_restart(hdd_ctx->parent_dev, hdd_psoc_idle_restart);
14259 hdd_soc_idle_restart_unlock();
14260
14261 return ret;
14262 }
14263
14264 /**
14265 * hdd_psoc_idle_timeout_callback() - Handler for psoc idle timeout
14266 * @priv: pointer to hdd context
14267 *
14268 * Return: None
14269 */
hdd_psoc_idle_timeout_callback(void * priv)14270 static void hdd_psoc_idle_timeout_callback(void *priv)
14271 {
14272 int ret;
14273 struct hdd_context *hdd_ctx = priv;
14274 void *hif_ctx;
14275
14276 if (wlan_hdd_validate_context(hdd_ctx))
14277 return;
14278
14279 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
14280 if (hif_ctx) {
14281 /*
14282 * Trigger runtime sync resume before psoc_idle_shutdown
14283 * such that resume can happen successfully
14284 */
14285 qdf_rtpm_sync_resume();
14286 }
14287
14288 hdd_info("Psoc idle timeout elapsed; starting psoc shutdown");
14289
14290 ret = pld_idle_shutdown(hdd_ctx->parent_dev, hdd_psoc_idle_shutdown);
14291 if (-EAGAIN == ret || hdd_ctx->is_wiphy_suspended) {
14292 hdd_debug("System suspend in progress. Restart idle shutdown timer");
14293 hdd_psoc_idle_timer_start(hdd_ctx);
14294 }
14295
14296 /* Clear the recovery flag for PCIe discrete soc after idle shutdown*/
14297 if (PLD_BUS_TYPE_PCIE == pld_get_bus_type(hdd_ctx->parent_dev) &&
14298 -EBUSY != ret)
14299 cds_set_recovery_in_progress(false);
14300 }
14301
14302 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
hdd_set_wlan_logging(struct hdd_context * hdd_ctx)14303 static void hdd_set_wlan_logging(struct hdd_context *hdd_ctx)
14304 {
14305 wlan_set_console_log_levels(hdd_ctx->config->wlan_console_log_levels);
14306 wlan_logging_set_active(hdd_ctx->config->wlan_logging_enable);
14307 }
14308 #else
hdd_set_wlan_logging(struct hdd_context * hdd_ctx)14309 static void hdd_set_wlan_logging(struct hdd_context *hdd_ctx)
14310 { }
14311 #endif
14312
14313 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
hdd_init_wlan_logging_params(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14314 static void hdd_init_wlan_logging_params(struct hdd_config *config,
14315 struct wlan_objmgr_psoc *psoc)
14316 {
14317 config->wlan_logging_enable = cfg_get(psoc, CFG_WLAN_LOGGING_SUPPORT);
14318
14319 config->wlan_console_log_levels =
14320 cfg_get(psoc, CFG_WLAN_LOGGING_CONSOLE_SUPPORT);
14321 config->host_log_custom_nl_proto =
14322 cfg_get(psoc, CFG_HOST_LOG_CUSTOM_NETLINK_PROTO);
14323 }
14324 #else
hdd_init_wlan_logging_params(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14325 static void hdd_init_wlan_logging_params(struct hdd_config *config,
14326 struct wlan_objmgr_psoc *psoc)
14327 {
14328 }
14329 #endif
14330
14331 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
hdd_init_wlan_auto_shutdown(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14332 static void hdd_init_wlan_auto_shutdown(struct hdd_config *config,
14333 struct wlan_objmgr_psoc *psoc)
14334 {
14335 config->wlan_auto_shutdown = cfg_get(psoc, CFG_WLAN_AUTO_SHUTDOWN);
14336 }
14337 #else
hdd_init_wlan_auto_shutdown(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14338 static void hdd_init_wlan_auto_shutdown(struct hdd_config *config,
14339 struct wlan_objmgr_psoc *psoc)
14340 {
14341 }
14342 #endif
14343
14344 #ifndef REMOVE_PKT_LOG
hdd_init_packet_log(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14345 static void hdd_init_packet_log(struct hdd_config *config,
14346 struct wlan_objmgr_psoc *psoc)
14347 {
14348 config->enable_packet_log = cfg_get(psoc, CFG_ENABLE_PACKET_LOG);
14349 }
14350 #else
hdd_init_packet_log(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14351 static void hdd_init_packet_log(struct hdd_config *config,
14352 struct wlan_objmgr_psoc *psoc)
14353 {
14354 }
14355 #endif
14356
14357 #ifdef ENABLE_MTRACE_LOG
hdd_init_mtrace_log(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14358 static void hdd_init_mtrace_log(struct hdd_config *config,
14359 struct wlan_objmgr_psoc *psoc)
14360 {
14361 config->enable_mtrace = cfg_get(psoc, CFG_ENABLE_MTRACE);
14362 }
14363 #else
hdd_init_mtrace_log(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14364 static void hdd_init_mtrace_log(struct hdd_config *config,
14365 struct wlan_objmgr_psoc *psoc)
14366 {
14367 }
14368 #endif
14369
14370 #ifdef FEATURE_RUNTIME_PM
hdd_init_runtime_pm(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14371 static void hdd_init_runtime_pm(struct hdd_config *config,
14372 struct wlan_objmgr_psoc *psoc)
14373 {
14374 config->runtime_pm = cfg_get(psoc, CFG_ENABLE_RUNTIME_PM);
14375 }
14376
hdd_is_runtime_pm_enabled(struct hdd_context * hdd_ctx)14377 bool hdd_is_runtime_pm_enabled(struct hdd_context *hdd_ctx)
14378 {
14379 return hdd_ctx->config->runtime_pm != hdd_runtime_pm_disabled;
14380 }
14381 #else
hdd_init_runtime_pm(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14382 static void hdd_init_runtime_pm(struct hdd_config *config,
14383 struct wlan_objmgr_psoc *psoc)
14384
14385 {
14386 }
14387
hdd_is_runtime_pm_enabled(struct hdd_context * hdd_ctx)14388 bool hdd_is_runtime_pm_enabled(struct hdd_context *hdd_ctx)
14389 {
14390 return false;
14391 }
14392 #endif
14393
14394 #ifdef WLAN_FEATURE_WMI_SEND_RECV_QMI
hdd_init_qmi_stats(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14395 static void hdd_init_qmi_stats(struct hdd_config *config,
14396 struct wlan_objmgr_psoc *psoc)
14397 {
14398 config->is_qmi_stats_enabled = cfg_get(psoc, CFG_ENABLE_QMI_STATS);
14399 }
14400 #else
hdd_init_qmi_stats(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14401 static void hdd_init_qmi_stats(struct hdd_config *config,
14402 struct wlan_objmgr_psoc *psoc)
14403
14404 {
14405 }
14406 #endif
14407
14408 #ifdef FEATURE_WLAN_DYNAMIC_CVM
hdd_init_vc_mode_cfg_bitmap(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14409 static void hdd_init_vc_mode_cfg_bitmap(struct hdd_config *config,
14410 struct wlan_objmgr_psoc *psoc)
14411 {
14412 config->vc_mode_cfg_bitmap = cfg_get(psoc, CFG_VC_MODE_BITMAP);
14413 }
14414 #else
hdd_init_vc_mode_cfg_bitmap(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14415 static void hdd_init_vc_mode_cfg_bitmap(struct hdd_config *config,
14416 struct wlan_objmgr_psoc *psoc)
14417 {
14418 }
14419 #endif
14420
14421 #ifdef DHCP_SERVER_OFFLOAD
14422 static void
hdd_init_dhcp_server_ip(struct hdd_context * hdd_ctx)14423 hdd_init_dhcp_server_ip(struct hdd_context *hdd_ctx)
14424 {
14425 uint8_t num_entries;
14426
14427 hdd_ctx->config->dhcp_server_ip.is_dhcp_server_ip_valid = true;
14428 hdd_string_to_u8_array(cfg_get(hdd_ctx->psoc, CFG_DHCP_SERVER_IP_NAME),
14429 hdd_ctx->config->dhcp_server_ip.dhcp_server_ip,
14430 &num_entries, IPADDR_NUM_ENTRIES);
14431
14432 if (num_entries != IPADDR_NUM_ENTRIES) {
14433 hdd_err("Incorrect IP address (%s) assigned for DHCP server!",
14434 cfg_get(hdd_ctx->psoc, CFG_DHCP_SERVER_IP_NAME));
14435 hdd_config->dhcp_server_ip.is_dhcp_server_ip_valid = false;
14436 }
14437 }
14438 #else
14439 static void
hdd_init_dhcp_server_ip(struct hdd_context * hdd_ctx)14440 hdd_init_dhcp_server_ip(struct hdd_context *hdd_ctx)
14441 {
14442 }
14443 #endif
14444
14445 #ifdef SAR_SAFETY_FEATURE
hdd_sar_cfg_update(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14446 static void hdd_sar_cfg_update(struct hdd_config *config,
14447 struct wlan_objmgr_psoc *psoc)
14448 {
14449 config->sar_safety_timeout = cfg_get(psoc, CFG_SAR_SAFETY_TIMEOUT);
14450 config->sar_safety_unsolicited_timeout =
14451 cfg_get(psoc, CFG_SAR_SAFETY_UNSOLICITED_TIMEOUT);
14452 config->sar_safety_req_resp_timeout =
14453 cfg_get(psoc, CFG_SAR_SAFETY_REQ_RESP_TIMEOUT);
14454 config->sar_safety_req_resp_retry =
14455 cfg_get(psoc, CFG_SAR_SAFETY_REQ_RESP_RETRIES);
14456 config->sar_safety_index = cfg_get(psoc, CFG_SAR_SAFETY_INDEX);
14457 config->sar_safety_sleep_index =
14458 cfg_get(psoc, CFG_SAR_SAFETY_SLEEP_INDEX);
14459 config->enable_sar_safety =
14460 cfg_get(psoc, CFG_ENABLE_SAR_SAFETY_FEATURE);
14461 config->config_sar_safety_sleep_index =
14462 cfg_get(psoc, CFG_CONFIG_SAR_SAFETY_SLEEP_MODE_INDEX);
14463 }
14464
hdd_set_sar_init_index(struct hdd_context * hdd_ctx)14465 void hdd_set_sar_init_index(struct hdd_context *hdd_ctx)
14466 {
14467 uint32_t index, enable = 0;
14468
14469 if (!hdd_ctx) {
14470 hdd_err("hdd_ctx NULL");
14471 return;
14472 }
14473 if (hdd_ctx->sar_version == SAR_VERSION_1) {
14474 hdd_nofl_debug("FW SAR version: %d", hdd_ctx->sar_version);
14475 return;
14476 }
14477
14478 enable = hdd_ctx->config->enable_sar_safety;
14479 index = hdd_ctx->config->sar_safety_index;
14480 if (enable & SAR_SAFETY_ENABLED_INIT)
14481 hdd_configure_sar_index(hdd_ctx, index);
14482 }
14483 #else
hdd_sar_cfg_update(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14484 static void hdd_sar_cfg_update(struct hdd_config *config,
14485 struct wlan_objmgr_psoc *psoc)
14486 {
14487 }
14488 #endif
14489
14490 #ifdef FEATURE_SET
14491 /**
14492 * hdd_get_wifi_features_cfg_update() - Initialize get wifi features cfg
14493 * @config: Pointer to HDD config
14494 * @psoc: psoc pointer
14495 *
14496 * Return: None
14497 */
hdd_get_wifi_features_cfg_update(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14498 static void hdd_get_wifi_features_cfg_update(struct hdd_config *config,
14499 struct wlan_objmgr_psoc *psoc)
14500 {
14501 config->get_wifi_features = cfg_get(psoc, CFG_GET_WIFI_FEATURES);
14502 }
14503 #else
hdd_get_wifi_features_cfg_update(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14504 static void hdd_get_wifi_features_cfg_update(struct hdd_config *config,
14505 struct wlan_objmgr_psoc *psoc)
14506 {
14507 }
14508 #endif
14509
14510 #ifdef FEATURE_RUNTIME_PM
14511 /**
14512 * hdd_init_cpu_cxpc_threshold_cfg() - Initialize cpu cxpc threshold cfg
14513 * @config: Pointer to HDD config
14514 * @psoc: psoc pointer
14515 *
14516 * Return: None
14517 */
hdd_init_cpu_cxpc_threshold_cfg(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14518 static void hdd_init_cpu_cxpc_threshold_cfg(struct hdd_config *config,
14519 struct wlan_objmgr_psoc *psoc)
14520 {
14521 config->cpu_cxpc_threshold = cfg_get(psoc, CFG_CPU_CXPC_THRESHOLD);
14522 }
14523 #else
hdd_init_cpu_cxpc_threshold_cfg(struct hdd_config * config,struct wlan_objmgr_psoc * psoc)14524 static void hdd_init_cpu_cxpc_threshold_cfg(struct hdd_config *config,
14525 struct wlan_objmgr_psoc *psoc)
14526 {
14527 }
14528 #endif
14529
14530 /**
14531 * hdd_cfg_params_init() - Initialize hdd params in hdd_config structure
14532 * @hdd_ctx: Pointer to HDD context
14533 *
14534 * Return: None
14535 */
hdd_cfg_params_init(struct hdd_context * hdd_ctx)14536 static void hdd_cfg_params_init(struct hdd_context *hdd_ctx)
14537 {
14538 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
14539 struct hdd_config *config = hdd_ctx->config;
14540 if (!psoc) {
14541 hdd_err("Invalid psoc");
14542 return;
14543 }
14544
14545 if (!config) {
14546 hdd_err("Invalid hdd config");
14547 return;
14548 }
14549
14550 config->dot11Mode = cfg_get(psoc, CFG_HDD_DOT11_MODE);
14551 config->bug_on_reinit_failure = cfg_get(psoc,
14552 CFG_BUG_ON_REINIT_FAILURE);
14553
14554 config->is_ramdump_enabled = cfg_get(psoc,
14555 CFG_ENABLE_RAMDUMP_COLLECTION);
14556
14557 config->iface_change_wait_time = cfg_get(psoc,
14558 CFG_INTERFACE_CHANGE_WAIT);
14559
14560 config->multicast_host_fw_msgs = cfg_get(psoc,
14561 CFG_MULTICAST_HOST_FW_MSGS);
14562
14563 config->private_wext_control = cfg_get(psoc, CFG_PRIVATE_WEXT_CONTROL);
14564 config->enablefwprint = cfg_get(psoc, CFG_ENABLE_FW_UART_PRINT);
14565 config->enable_fw_log = cfg_get(psoc, CFG_ENABLE_FW_LOG);
14566 config->operating_chan_freq = cfg_get(psoc, CFG_OPERATING_FREQUENCY);
14567 config->num_vdevs = cfg_get(psoc, CFG_NUM_VDEV_ENABLE);
14568 qdf_str_lcopy(config->enable_concurrent_sta,
14569 cfg_get(psoc, CFG_ENABLE_CONCURRENT_STA),
14570 CFG_CONCURRENT_IFACE_MAX_LEN);
14571 qdf_str_lcopy(config->dbs_scan_selection,
14572 cfg_get(psoc, CFG_DBS_SCAN_SELECTION),
14573 CFG_DBS_SCAN_PARAM_LENGTH);
14574 config->inform_bss_rssi_raw = cfg_get(psoc, CFG_INFORM_BSS_RSSI_RAW);
14575 config->mac_provision = cfg_get(psoc, CFG_ENABLE_MAC_PROVISION);
14576 config->provisioned_intf_pool =
14577 cfg_get(psoc, CFG_PROVISION_INTERFACE_POOL);
14578 config->derived_intf_pool = cfg_get(psoc, CFG_DERIVED_INTERFACE_POOL);
14579 config->advertise_concurrent_operation =
14580 cfg_get(psoc,
14581 CFG_ADVERTISE_CONCURRENT_OPERATION);
14582 config->is_unit_test_framework_enabled =
14583 cfg_get(psoc, CFG_ENABLE_UNIT_TEST_FRAMEWORK);
14584 config->disable_channel = cfg_get(psoc, CFG_ENABLE_DISABLE_CHANNEL);
14585 config->enable_sar_conversion = cfg_get(psoc, CFG_SAR_CONVERSION);
14586 config->nb_commands_interval =
14587 cfg_get(psoc, CFG_NB_COMMANDS_RATE_LIMIT);
14588
14589 hdd_init_vc_mode_cfg_bitmap(config, psoc);
14590 hdd_init_runtime_pm(config, psoc);
14591 hdd_init_wlan_auto_shutdown(config, psoc);
14592 hdd_init_wlan_logging_params(config, psoc);
14593 hdd_init_packet_log(config, psoc);
14594 hdd_init_mtrace_log(config, psoc);
14595 hdd_init_dhcp_server_ip(hdd_ctx);
14596 hdd_dp_cfg_update(psoc, hdd_ctx);
14597 hdd_sar_cfg_update(config, psoc);
14598 hdd_init_qmi_stats(config, psoc);
14599 hdd_club_ll_stats_in_get_sta_cfg_update(config, psoc);
14600 config->read_mac_addr_from_mac_file =
14601 cfg_get(psoc, CFG_READ_MAC_ADDR_FROM_MAC_FILE);
14602
14603 hdd_get_wifi_features_cfg_update(config, psoc);
14604 hdd_init_cpu_cxpc_threshold_cfg(config, psoc);
14605
14606 config->exclude_selftx_from_cca_busy =
14607 cfg_get(psoc, CFG_EXCLUDE_SELFTX_FROM_CCA_BUSY_TIME);
14608 hdd_init_link_state_cfg(config, psoc);
14609 }
14610
14611 #ifdef CONNECTION_ROAMING_CFG
hdd_cfg_parse_connection_roaming_cfg(void)14612 static QDF_STATUS hdd_cfg_parse_connection_roaming_cfg(void)
14613 {
14614 QDF_STATUS status = QDF_STATUS_E_INVAL;
14615 bool is_valid;
14616
14617 is_valid = cfg_valid_ini_check(WLAN_CONNECTION_ROAMING_INI_FILE);
14618
14619 if (is_valid)
14620 status = cfg_parse(WLAN_CONNECTION_ROAMING_INI_FILE);
14621 if (QDF_IS_STATUS_ERROR(status)) {
14622 is_valid = cfg_valid_ini_check(WLAN_CONNECTION_ROAMING_BACKUP_INI_FILE);
14623 if (is_valid)
14624 status = cfg_parse(WLAN_CONNECTION_ROAMING_BACKUP_INI_FILE);
14625 }
14626 return status;
14627 }
14628 #else
hdd_cfg_parse_connection_roaming_cfg(void)14629 static inline QDF_STATUS hdd_cfg_parse_connection_roaming_cfg(void)
14630 {
14631 return QDF_STATUS_E_NOSUPPORT;
14632 }
14633 #endif
14634
hdd_context_create(struct device * dev)14635 struct hdd_context *hdd_context_create(struct device *dev)
14636 {
14637 QDF_STATUS status;
14638 int ret = 0;
14639 struct hdd_context *hdd_ctx;
14640
14641 hdd_enter();
14642
14643 hdd_ctx = hdd_cfg80211_wiphy_alloc();
14644 if (!hdd_ctx) {
14645 ret = -ENOMEM;
14646 goto err_out;
14647 }
14648
14649 status = qdf_delayed_work_create(&hdd_ctx->psoc_idle_timeout_work,
14650 hdd_psoc_idle_timeout_callback,
14651 hdd_ctx);
14652 if (QDF_IS_STATUS_ERROR(status)) {
14653 ret = qdf_status_to_os_return(status);
14654 goto wiphy_dealloc;
14655 }
14656
14657 hdd_pm_notifier_init(hdd_ctx);
14658
14659 hdd_ctx->parent_dev = dev;
14660 hdd_ctx->last_scan_reject_vdev_id = WLAN_UMAC_VDEV_ID_MAX;
14661
14662 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
14663 if (!hdd_ctx->config) {
14664 ret = -ENOMEM;
14665 goto err_free_hdd_context;
14666 }
14667
14668 status = cfg_parse(WLAN_INI_FILE);
14669 if (QDF_IS_STATUS_ERROR(status)) {
14670 hdd_err("Failed to parse cfg %s; status:%d\n",
14671 WLAN_INI_FILE, status);
14672 /* Assert if failed to parse at least one INI parameter */
14673 QDF_BUG(status != QDF_STATUS_E_INVAL);
14674 ret = qdf_status_to_os_return(status);
14675 goto err_free_config;
14676 }
14677
14678 status = hdd_cfg_parse_connection_roaming_cfg();
14679
14680 ret = hdd_objmgr_create_and_store_psoc(hdd_ctx, DEFAULT_PSOC_ID);
14681 if (ret) {
14682 QDF_DEBUG_PANIC("Psoc creation fails!");
14683 goto err_release_store;
14684 }
14685
14686 if (QDF_IS_STATUS_SUCCESS(status))
14687 ucfg_mlme_set_connection_roaming_ini_present(hdd_ctx->psoc,
14688 true);
14689
14690 hdd_cfg_params_init(hdd_ctx);
14691
14692 /* apply multiplier config, if not already set via module parameter */
14693 if (qdf_timer_get_multiplier() == 1)
14694 qdf_timer_set_multiplier(cfg_get(hdd_ctx->psoc,
14695 CFG_TIMER_MULTIPLIER));
14696 hdd_debug("set timer multiplier: %u", qdf_timer_get_multiplier());
14697
14698 cds_set_fatal_event(cfg_get(hdd_ctx->psoc,
14699 CFG_ENABLE_FATAL_EVENT_TRIGGER));
14700
14701 hdd_override_ini_config(hdd_ctx);
14702
14703 ret = hdd_context_init(hdd_ctx);
14704
14705 if (ret)
14706 goto err_hdd_objmgr_destroy;
14707
14708 if (hdd_get_conparam() == QDF_GLOBAL_EPPING_MODE)
14709 goto skip_multicast_logging;
14710
14711 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
14712 ret = hdd_init_netlink_services(hdd_ctx);
14713 if (ret)
14714 goto err_deinit_hdd_context;
14715
14716 hdd_set_wlan_logging(hdd_ctx);
14717 qdf_atomic_init(&hdd_ctx->adapter_ops_history.index);
14718
14719 skip_multicast_logging:
14720 hdd_set_trace_level_for_each(hdd_ctx);
14721
14722 cds_set_context(QDF_MODULE_ID_HDD, hdd_ctx);
14723
14724 wlan_hdd_sar_timers_init(hdd_ctx);
14725
14726 hdd_exit();
14727
14728 return hdd_ctx;
14729
14730 err_deinit_hdd_context:
14731 hdd_context_deinit(hdd_ctx);
14732
14733 err_hdd_objmgr_destroy:
14734 hdd_objmgr_release_and_destroy_psoc(hdd_ctx);
14735
14736 err_release_store:
14737 cfg_release();
14738
14739 err_free_config:
14740 qdf_mem_free(hdd_ctx->config);
14741
14742 err_free_hdd_context:
14743 qdf_delayed_work_destroy(&hdd_ctx->psoc_idle_timeout_work);
14744
14745 wiphy_dealloc:
14746 wiphy_free(hdd_ctx->wiphy);
14747
14748 err_out:
14749 return ERR_PTR(ret);
14750 }
14751
14752 #ifdef MULTI_CLIENT_LL_SUPPORT
14753 /**
14754 * wlan_hdd_init_multi_client_info_table()- Initialize the multi client info
14755 * table
14756 * @adapter: hdd adapter
14757 *
14758 * Return: none
14759 */
14760 static void
wlan_hdd_init_multi_client_info_table(struct hdd_adapter * adapter)14761 wlan_hdd_init_multi_client_info_table(struct hdd_adapter *adapter)
14762 {
14763 uint8_t i;
14764
14765 for (i = 0; i < WLM_MAX_HOST_CLIENT; i++) {
14766 adapter->client_info[i].client_id = i;
14767 adapter->client_info[i].port_id = 0;
14768 adapter->client_info[i].in_use = false;
14769 }
14770 }
14771
wlan_hdd_deinit_multi_client_info_table(struct hdd_adapter * adapter)14772 void wlan_hdd_deinit_multi_client_info_table(struct hdd_adapter *adapter)
14773 {
14774 uint8_t i;
14775
14776 hdd_debug("deinitializing the client info table");
14777 /* de-initialize the table for host driver client */
14778 for (i = 0; i < WLM_MAX_HOST_CLIENT; i++) {
14779 if (adapter->client_info[i].in_use) {
14780 adapter->client_info[i].port_id = 0;
14781 adapter->client_info[i].client_id = i;
14782 adapter->client_info[i].in_use = false;
14783 }
14784 }
14785 }
14786
14787 /**
14788 * wlan_hdd_get_host_driver_port_id()- get host driver port id
14789 * @port_id: argument to be filled
14790 *
14791 * Return: none
14792 */
wlan_hdd_get_host_driver_port_id(uint32_t * port_id)14793 static void wlan_hdd_get_host_driver_port_id(uint32_t *port_id)
14794 {
14795 *port_id = WLAM_WLM_HOST_DRIVER_PORT_ID;
14796 }
14797
14798 #else
14799 static inline void
wlan_hdd_init_multi_client_info_table(struct hdd_adapter * adapter)14800 wlan_hdd_init_multi_client_info_table(struct hdd_adapter *adapter)
14801 {
14802 }
14803
wlan_hdd_get_host_driver_port_id(uint32_t * port_id)14804 static inline void wlan_hdd_get_host_driver_port_id(uint32_t *port_id)
14805 {
14806 }
14807 #endif
14808
14809 static void
hdd_adapter_set_wlm_client_latency_level(struct hdd_adapter * adapter)14810 hdd_adapter_set_wlm_client_latency_level(struct hdd_adapter *adapter)
14811 {
14812 QDF_STATUS status;
14813 bool reset;
14814 uint32_t port_id;
14815 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14816
14817 if (!hdd_ctx)
14818 return;
14819
14820 status = ucfg_mlme_cfg_get_wlm_reset(hdd_ctx->psoc, &reset);
14821 if (QDF_IS_STATUS_ERROR(status)) {
14822 hdd_err("could not get the wlm reset flag");
14823 reset = false;
14824 }
14825
14826 if (reset)
14827 goto out;
14828
14829 if (hdd_get_multi_client_ll_support(adapter)) {
14830 wlan_hdd_get_host_driver_port_id(&port_id);
14831 status = wlan_hdd_set_wlm_client_latency_level(
14832 adapter, port_id,
14833 adapter->latency_level);
14834 if (QDF_IS_STATUS_ERROR(status))
14835 hdd_warn("Fail to set latency level:%u", status);
14836 } else {
14837 status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
14838 adapter->deflink->vdev_id,
14839 adapter->latency_level,
14840 0, false);
14841 if (QDF_IS_STATUS_ERROR(status))
14842 hdd_warn("set wlm mode failed, %u", status);
14843 }
14844 out:
14845 hdd_debug("wlm initial mode %u", adapter->latency_level);
14846 }
14847
14848 #ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
14849 struct qdf_mac_addr *
hdd_adapter_get_link_mac_addr(struct wlan_hdd_link_info * link_info)14850 hdd_adapter_get_link_mac_addr(struct wlan_hdd_link_info *link_info)
14851 {
14852 struct hdd_adapter *adapter;
14853
14854 if (!link_info)
14855 return NULL;
14856
14857 adapter = link_info->adapter;
14858 if (!hdd_adapter_is_ml_adapter(adapter) ||
14859 qdf_is_macaddr_zero(&link_info->link_addr) ||
14860 !wlan_vdev_mlme_is_mlo_vdev(link_info->vdev))
14861 return &adapter->mac_addr;
14862
14863 return &link_info->link_addr;
14864 }
14865 #else
14866 struct qdf_mac_addr *
hdd_adapter_get_link_mac_addr(struct wlan_hdd_link_info * link_info)14867 hdd_adapter_get_link_mac_addr(struct wlan_hdd_link_info *link_info)
14868 {
14869 if (!link_info)
14870 return NULL;
14871
14872 return &link_info->adapter->mac_addr;
14873 }
14874 #endif
14875
14876 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
14877 defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
hdd_adapter_check_duplicate_session(struct hdd_adapter * adapter)14878 QDF_STATUS hdd_adapter_check_duplicate_session(struct hdd_adapter *adapter)
14879 {
14880 int i = 0;
14881 QDF_STATUS status;
14882 uint8_t *addr_list[WLAN_MAX_MLD + 2] = {0};
14883 struct wlan_hdd_link_info *link_info;
14884
14885 if (!hdd_adapter_is_ml_adapter(adapter) ||
14886 adapter->device_mode == QDF_SAP_MODE)
14887 goto netdev_addr;
14888
14889 hdd_adapter_for_each_active_link_info(adapter, link_info)
14890 addr_list[i++] = &link_info->link_addr.bytes[0];
14891
14892 netdev_addr:
14893 addr_list[i] = &adapter->mac_addr.bytes[0];
14894 status = sme_check_for_duplicate_session(adapter->hdd_ctx->mac_handle,
14895 &addr_list[0]);
14896 return status;
14897 }
14898
hdd_adapter_fill_link_address(struct hdd_adapter * adapter)14899 QDF_STATUS hdd_adapter_fill_link_address(struct hdd_adapter *adapter)
14900 {
14901 int i = 0;
14902 QDF_STATUS status;
14903 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14904 enum QDF_OPMODE opmode = adapter->device_mode;
14905 struct qdf_mac_addr link_addrs[WLAN_MAX_ML_BSS_LINKS] = {0};
14906 struct wlan_hdd_link_info *link_info;
14907
14908 if (opmode != QDF_STA_MODE && opmode != QDF_SAP_MODE)
14909 return QDF_STATUS_SUCCESS;
14910
14911 if (opmode == QDF_SAP_MODE) {
14912 link_info = adapter->deflink;
14913 qdf_copy_macaddr(&link_info->link_addr, &adapter->mac_addr);
14914 return QDF_STATUS_SUCCESS;
14915 }
14916
14917 if (!hdd_adapter_is_ml_adapter(adapter))
14918 return QDF_STATUS_SUCCESS;
14919
14920 status = hdd_derive_link_address_from_mld(hdd_ctx->psoc,
14921 &adapter->mac_addr,
14922 &link_addrs[0],
14923 WLAN_MAX_ML_BSS_LINKS);
14924 if (QDF_IS_STATUS_ERROR(status))
14925 return status;
14926
14927 hdd_adapter_for_each_link_info(adapter, link_info)
14928 qdf_copy_macaddr(&link_info->link_addr, &link_addrs[i++]);
14929
14930 return status;
14931 }
14932 #elif defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
hdd_adapter_check_duplicate_session(struct hdd_adapter * adapter)14933 QDF_STATUS hdd_adapter_check_duplicate_session(struct hdd_adapter *adapter)
14934 {
14935 int i;
14936 QDF_STATUS status;
14937 uint8_t *addr_list[WLAN_MAX_MLD + 1] = {0};
14938 struct hdd_adapter *link_adapter;
14939 struct hdd_mlo_adapter_info *mlo_adapter_info;
14940 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
14941
14942 if (hdd_adapter_is_ml_adapter(adapter) &&
14943 adapter->device_mode == QDF_STA_MODE) {
14944 addr_list[0] = &adapter->mld_addr.bytes[0];
14945 mlo_adapter_info = &adapter->mlo_adapter_info;
14946 for (i = 0; i < WLAN_MAX_MLD; i++) {
14947 link_adapter = mlo_adapter_info->link_adapter[i];
14948 if (!link_adapter)
14949 continue;
14950 if (hdd_adapter_is_associated_with_ml_adapter(
14951 link_adapter)) {
14952 addr_list[1] = &link_adapter->mac_addr.bytes[0];
14953 }
14954 }
14955 } else {
14956 addr_list[0] = &adapter->mac_addr.bytes[0];
14957 }
14958
14959 status = sme_check_for_duplicate_session(mac_handle, &addr_list[0]);
14960 return status;
14961 }
14962 #else
hdd_adapter_check_duplicate_session(struct hdd_adapter * adapter)14963 QDF_STATUS hdd_adapter_check_duplicate_session(struct hdd_adapter *adapter)
14964 {
14965 QDF_STATUS status;
14966 uint8_t *addr_list[2] = {0};
14967 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
14968
14969 addr_list[0] = &adapter->mac_addr.bytes[0];
14970 status = sme_check_for_duplicate_session(mac_handle, &addr_list[0]);
14971
14972 return status;
14973 }
14974 #endif
14975
hdd_restore_info_for_ssr(struct hdd_adapter * adapter)14976 static void hdd_restore_info_for_ssr(struct hdd_adapter *adapter)
14977 {
14978 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14979
14980 if (cds_is_driver_recovering()) {
14981 /* ssr happens, recover the info */
14982 hdd_set_vdev_phy_mode(adapter, adapter->user_phy_mode);
14983 wlan_mlme_restore_user_set_link_num(hdd_ctx->psoc);
14984 } else {
14985 /* intf down/up happens, reset default info */
14986 hdd_set_vdev_phy_mode(adapter, QCA_WLAN_VENDOR_PHY_MODE_AUTO);
14987 wlan_mlme_clear_user_set_link_num(hdd_ctx->psoc);
14988 }
14989 }
14990
hdd_adapter_reset_station_ctx(struct hdd_adapter * adapter)14991 void hdd_adapter_reset_station_ctx(struct hdd_adapter *adapter)
14992 {
14993 struct wlan_hdd_link_info *link_info;
14994 struct hdd_station_ctx *sta_ctx;
14995
14996 hdd_adapter_for_each_link_info(adapter, link_info) {
14997 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
14998 qdf_mem_zero(&sta_ctx->conn_info.bssid, QDF_MAC_ADDR_SIZE);
14999
15000 hdd_cm_clear_ieee_link_id(link_info);
15001 sta_ctx->user_cfg_chn_width = CH_WIDTH_INVALID;
15002 }
15003 }
15004
hdd_start_station_adapter(struct hdd_adapter * adapter)15005 int hdd_start_station_adapter(struct hdd_adapter *adapter)
15006 {
15007 QDF_STATUS status;
15008 int ret;
15009 struct wlan_hdd_link_info *link_info;
15010
15011 hdd_enter_dev(adapter->dev);
15012 if (test_bit(SME_SESSION_OPENED, &adapter->deflink->link_flags)) {
15013 hdd_err("session is already opened, %d",
15014 adapter->deflink->vdev_id);
15015 return qdf_status_to_os_return(QDF_STATUS_SUCCESS);
15016 }
15017
15018 if ((adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
15019 (adapter->device_mode == QDF_NAN_DISC_MODE))
15020 wlan_hdd_lpc_del_monitor_interface(adapter->hdd_ctx, false);
15021
15022 status = hdd_adapter_fill_link_address(adapter);
15023 if (QDF_IS_STATUS_ERROR(status)) {
15024 hdd_debug("Link address derive failed");
15025 return qdf_status_to_os_return(status);
15026 }
15027
15028 status = hdd_adapter_check_duplicate_session(adapter);
15029 if (QDF_IS_STATUS_ERROR(status)) {
15030 hdd_err("Duplicate session is existing with same mac address");
15031 return qdf_status_to_os_return(status);
15032 }
15033
15034 hdd_adapter_for_each_active_link_info(adapter, link_info) {
15035 ret = hdd_vdev_create(link_info);
15036 if (ret) {
15037 hdd_err("failed to create vdev: %d", ret);
15038 goto fail;
15039 }
15040
15041 status = hdd_init_station_mode(link_info);
15042 if (QDF_STATUS_SUCCESS != status) {
15043 hdd_err("Error Initializing station mode: %d", status);
15044 ret = qdf_status_to_os_return(status);
15045 goto fail;
15046 }
15047 }
15048
15049 hdd_adapter_reset_station_ctx(adapter);
15050
15051 hdd_register_wext(adapter->dev);
15052 hdd_set_netdev_flags(adapter);
15053
15054 hdd_register_tx_flow_control(adapter,
15055 hdd_tx_resume_timer_expired_handler,
15056 hdd_tx_resume_cb,
15057 hdd_tx_flow_control_is_pause);
15058
15059 hdd_register_hl_netdev_fc_timer(adapter,
15060 hdd_tx_resume_timer_expired_handler);
15061
15062 if (hdd_get_multi_client_ll_support(adapter))
15063 wlan_hdd_init_multi_client_info_table(adapter);
15064
15065 hdd_adapter_set_wlm_client_latency_level(adapter);
15066 hdd_adapter_update_mlo_mgr_mac_addr(adapter);
15067 hdd_restore_info_for_ssr(adapter);
15068
15069 hdd_exit();
15070 return 0;
15071
15072 fail:
15073 hdd_adapter_for_each_active_link_info(adapter, link_info)
15074 hdd_vdev_destroy(link_info);
15075
15076 return ret;
15077 }
15078
hdd_start_ap_adapter(struct hdd_adapter * adapter,bool rtnl_held)15079 int hdd_start_ap_adapter(struct hdd_adapter *adapter, bool rtnl_held)
15080 {
15081 QDF_STATUS status;
15082 bool is_ssr = false;
15083 int ret;
15084 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15085 struct sap_context *sap_ctx;
15086 struct wlan_hdd_link_info *link_info = adapter->deflink;
15087
15088 hdd_enter();
15089
15090 if (test_bit(SME_SESSION_OPENED, &link_info->link_flags)) {
15091 hdd_err("session is already opened, %d",
15092 link_info->vdev_id);
15093 return qdf_status_to_os_return(QDF_STATUS_SUCCESS);
15094 }
15095
15096 status = hdd_adapter_fill_link_address(adapter);
15097 if (QDF_IS_STATUS_ERROR(status)) {
15098 hdd_debug("Link address derive failed");
15099 return qdf_status_to_os_return(status);
15100 }
15101
15102 status = hdd_adapter_check_duplicate_session(adapter);
15103 if (QDF_IS_STATUS_ERROR(status)) {
15104 hdd_err("Duplicate session is existing with same mac address");
15105 return qdf_status_to_os_return(status);
15106 }
15107
15108 /*
15109 * In SSR case no need to create new sap context.
15110 * Otherwise create sap context first and then create
15111 * vdev as while creating the vdev, driver needs to
15112 * register SAP callback and that callback uses sap context
15113 */
15114 if (WLAN_HDD_GET_SAP_CTX_PTR(link_info)) {
15115 is_ssr = true;
15116 } else if (!hdd_sap_create_ctx(adapter)) {
15117 hdd_err("sap creation failed");
15118 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
15119 }
15120
15121 ret = hdd_vdev_create(link_info);
15122 if (ret) {
15123 hdd_err("failed to create vdev, status:%d", ret);
15124 goto sap_destroy_ctx;
15125 }
15126
15127 sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
15128 status = sap_acquire_vdev_ref(hdd_ctx->psoc, sap_ctx,
15129 link_info->vdev_id);
15130 if (!QDF_IS_STATUS_SUCCESS(status)) {
15131 hdd_err("Failed to get vdev ref for sap for session_id: %u",
15132 link_info->vdev_id);
15133 ret = qdf_status_to_os_return(status);
15134 goto sap_vdev_destroy;
15135 }
15136
15137 if (adapter->device_mode == QDF_SAP_MODE) {
15138 status = hdd_vdev_configure_rtt_params(sap_ctx->vdev);
15139 if (QDF_IS_STATUS_ERROR(status))
15140 goto sap_release_ref;
15141 }
15142
15143 status = hdd_init_ap_mode(adapter, is_ssr, rtnl_held);
15144 if (QDF_STATUS_SUCCESS != status) {
15145 hdd_err("Error Initializing the AP mode: %d", status);
15146 ret = qdf_status_to_os_return(status);
15147 goto sap_release_ref;
15148 }
15149
15150 hdd_register_tx_flow_control(adapter,
15151 hdd_softap_tx_resume_timer_expired_handler,
15152 hdd_softap_tx_resume_cb,
15153 hdd_tx_flow_control_is_pause);
15154
15155 hdd_register_hl_netdev_fc_timer(adapter,
15156 hdd_tx_resume_timer_expired_handler);
15157
15158 if (cds_is_driver_recovering())
15159 hdd_medium_assess_ssr_reinit();
15160
15161 hdd_exit();
15162 return 0;
15163
15164 sap_release_ref:
15165 sap_release_vdev_ref(sap_ctx);
15166 sap_vdev_destroy:
15167 hdd_vdev_destroy(link_info);
15168 sap_destroy_ctx:
15169 hdd_sap_destroy_ctx(link_info);
15170 return ret;
15171 }
15172
15173 #if defined(QCA_LL_TX_FLOW_CONTROL_V2) || defined(QCA_LL_PDEV_TX_FLOW_CONTROL)
15174 /**
15175 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
15176 * @cds_cfg: CDS Configuration
15177 * @hdd_ctx: Pointer to hdd context
15178 *
15179 * Return: none
15180 */
hdd_txrx_populate_cds_config(struct cds_config_info * cds_cfg,struct hdd_context * hdd_ctx)15181 static inline void hdd_txrx_populate_cds_config(struct cds_config_info
15182 *cds_cfg,
15183 struct hdd_context *hdd_ctx)
15184 {
15185 cds_cfg->tx_flow_stop_queue_th =
15186 cfg_get(hdd_ctx->psoc, CFG_DP_TX_FLOW_STOP_QUEUE_TH);
15187 cds_cfg->tx_flow_start_queue_offset =
15188 cfg_get(hdd_ctx->psoc, CFG_DP_TX_FLOW_START_QUEUE_OFFSET);
15189 /* configuration for DP RX Threads */
15190 cds_cfg->enable_dp_rx_threads =
15191 ucfg_dp_is_rx_threads_enabled(hdd_ctx->psoc);
15192 }
15193 #else
hdd_txrx_populate_cds_config(struct cds_config_info * cds_cfg,struct hdd_context * hdd_ctx)15194 static inline void hdd_txrx_populate_cds_config(struct cds_config_info
15195 *cds_cfg,
15196 struct hdd_context *hdd_ctx)
15197 {
15198 }
15199 #endif
15200
15201 /**
15202 * hdd_update_cds_config() - API to update cds configuration parameters
15203 * @hdd_ctx: HDD Context
15204 *
15205 * Return: 0 for Success, errno on failure
15206 */
hdd_update_cds_config(struct hdd_context * hdd_ctx)15207 static int hdd_update_cds_config(struct hdd_context *hdd_ctx)
15208 {
15209 struct cds_config_info *cds_cfg;
15210 int value;
15211 uint8_t band_capability;
15212 uint32_t band_bitmap;
15213 uint8_t ito_repeat_count;
15214 bool crash_inject;
15215 bool self_recovery;
15216 bool fw_timeout_crash;
15217 QDF_STATUS status;
15218
15219 cds_cfg = qdf_mem_malloc(sizeof(*cds_cfg));
15220 if (!cds_cfg)
15221 return -ENOMEM;
15222
15223 cds_cfg->driver_type = QDF_DRIVER_TYPE_PRODUCTION;
15224 ucfg_mlme_get_sap_max_modulated_dtim(hdd_ctx->psoc,
15225 &cds_cfg->sta_maxlimod_dtim);
15226
15227 ucfg_mlme_get_max_modulated_dtim_ms(hdd_ctx->psoc,
15228 &cds_cfg->sta_maxlimod_dtim_ms);
15229
15230 status = ucfg_mlme_get_crash_inject(hdd_ctx->psoc, &crash_inject);
15231 if (QDF_IS_STATUS_ERROR(status)) {
15232 hdd_err("Failed to get crash inject ini config");
15233 goto exit;
15234 }
15235
15236 status = ucfg_mlme_get_self_recovery(hdd_ctx->psoc, &self_recovery);
15237 if (QDF_IS_STATUS_ERROR(status)) {
15238 hdd_err("Failed to get self recovery ini config");
15239 goto exit;
15240 }
15241
15242 status = ucfg_mlme_get_fw_timeout_crash(hdd_ctx->psoc,
15243 &fw_timeout_crash);
15244 if (QDF_IS_STATUS_ERROR(status)) {
15245 hdd_err("Failed to get fw timeout crash ini config");
15246 goto exit;
15247 }
15248
15249 status = ucfg_mlme_get_ito_repeat_count(hdd_ctx->psoc,
15250 &ito_repeat_count);
15251 if (QDF_IS_STATUS_ERROR(status)) {
15252 hdd_err("Failed to get ITO repeat count ini config");
15253 goto exit;
15254 }
15255
15256 cds_cfg->force_target_assert_enabled = crash_inject;
15257
15258 ucfg_mlme_get_sap_max_offload_peers(hdd_ctx->psoc, &value);
15259 cds_cfg->ap_maxoffload_peers = value;
15260 ucfg_mlme_get_sap_max_offload_reorder_buffs(hdd_ctx->psoc,
15261 &value);
15262 cds_cfg->ap_maxoffload_reorderbuffs = value;
15263
15264 cds_cfg->reorder_offload = DP_REORDER_OFFLOAD_SUPPORT;
15265
15266 /* IPA micro controller data path offload resource config item */
15267 cds_cfg->uc_offload_enabled = ucfg_ipa_uc_is_enabled();
15268
15269 cds_cfg->enable_rxthread =
15270 ucfg_dp_is_rx_common_thread_enabled(hdd_ctx->psoc);
15271 ucfg_mlme_get_sap_max_peers(hdd_ctx->psoc, &value);
15272 cds_cfg->max_station = value;
15273 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
15274 cds_cfg->max_msdus_per_rxinorderind =
15275 cfg_get(hdd_ctx->psoc, CFG_DP_MAX_MSDUS_PER_RXIND);
15276 cds_cfg->self_recovery_enabled = self_recovery;
15277 cds_cfg->fw_timeout_crash = fw_timeout_crash;
15278
15279 cds_cfg->ito_repeat_count = ito_repeat_count;
15280
15281 status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_bitmap);
15282 if (QDF_IS_STATUS_ERROR(status))
15283 goto exit;
15284
15285 band_capability = wlan_reg_band_bitmap_to_band_info(band_bitmap);
15286 cds_cfg->bandcapability = band_capability;
15287 cds_cfg->num_vdevs = hdd_ctx->config->num_vdevs;
15288 cds_cfg->enable_tx_compl_tsf64 =
15289 hdd_tsf_is_tsf64_tx_set(hdd_ctx);
15290 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
15291 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
15292 cds_init_ini_config(cds_cfg);
15293 return 0;
15294
15295 exit:
15296 qdf_mem_free(cds_cfg);
15297 return -EINVAL;
15298 }
15299
15300 /**
15301 * hdd_update_user_config() - API to update user configuration
15302 * parameters to obj mgr which are used by multiple components
15303 * @hdd_ctx: HDD Context
15304 *
15305 * Return: 0 for Success, errno on failure
15306 */
hdd_update_user_config(struct hdd_context * hdd_ctx)15307 static int hdd_update_user_config(struct hdd_context *hdd_ctx)
15308 {
15309 struct wlan_objmgr_psoc_user_config *user_config;
15310 uint8_t band_capability;
15311 uint32_t band_bitmap;
15312 QDF_STATUS status;
15313 bool value = false;
15314
15315 status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_bitmap);
15316 if (QDF_IS_STATUS_ERROR(status))
15317 return -EIO;
15318
15319 user_config = qdf_mem_malloc(sizeof(*user_config));
15320 if (!user_config)
15321 return -ENOMEM;
15322
15323 user_config->dot11_mode = hdd_ctx->config->dot11Mode;
15324 status = ucfg_mlme_is_11d_enabled(hdd_ctx->psoc, &value);
15325 if (!QDF_IS_STATUS_SUCCESS(status))
15326 hdd_err("Invalid 11d_enable flag");
15327 user_config->is_11d_support_enabled = value;
15328
15329 value = false;
15330 status = ucfg_mlme_is_11h_enabled(hdd_ctx->psoc, &value);
15331 if (!QDF_IS_STATUS_SUCCESS(status))
15332 hdd_err("Invalid 11h_enable flag");
15333 user_config->is_11h_support_enabled = value;
15334 band_capability = wlan_reg_band_bitmap_to_band_info(band_bitmap);
15335 user_config->band_capability = band_capability;
15336 wlan_objmgr_psoc_set_user_config(hdd_ctx->psoc, user_config);
15337
15338 qdf_mem_free(user_config);
15339 return 0;
15340 }
15341
15342 /**
15343 * hdd_init_thermal_info - Initialize thermal level
15344 * @hdd_ctx: HDD context
15345 *
15346 * Initialize thermal level at SME layer and set the thermal level callback
15347 * which would be called when a configured thermal threshold is hit.
15348 *
15349 * Return: 0 on success and errno on failure
15350 */
hdd_init_thermal_info(struct hdd_context * hdd_ctx)15351 static int hdd_init_thermal_info(struct hdd_context *hdd_ctx)
15352 {
15353 QDF_STATUS status;
15354 mac_handle_t mac_handle = hdd_ctx->mac_handle;
15355
15356 status = sme_init_thermal_info(mac_handle);
15357
15358 if (!QDF_IS_STATUS_SUCCESS(status))
15359 return qdf_status_to_os_return(status);
15360
15361 sme_add_set_thermal_level_callback(mac_handle,
15362 hdd_set_thermal_level_cb);
15363
15364 return 0;
15365
15366 }
15367
15368 #if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
15369 /**
15370 * hdd_hold_rtnl_lock - Hold RTNL lock
15371 *
15372 * Hold RTNL lock
15373 *
15374 * Return: True if held and false otherwise
15375 */
hdd_hold_rtnl_lock(void)15376 static inline bool hdd_hold_rtnl_lock(void)
15377 {
15378 rtnl_lock();
15379 return true;
15380 }
15381
15382 /**
15383 * hdd_release_rtnl_lock - Release RTNL lock
15384 *
15385 * Release RTNL lock
15386 *
15387 * Return: None
15388 */
hdd_release_rtnl_lock(void)15389 static inline void hdd_release_rtnl_lock(void)
15390 {
15391 rtnl_unlock();
15392 }
15393 #else
hdd_hold_rtnl_lock(void)15394 static inline bool hdd_hold_rtnl_lock(void) { return false; }
hdd_release_rtnl_lock(void)15395 static inline void hdd_release_rtnl_lock(void) { }
15396 #endif
15397
15398 #if !defined(REMOVE_PKT_LOG)
15399
15400 /* MAX iwpriv command support */
15401 #define PKTLOG_SET_BUFF_SIZE 3
15402 #define PKTLOG_CLEAR_BUFF 4
15403 /* Set Maximum pktlog file size to 64MB */
15404 #define MAX_PKTLOG_SIZE 64
15405
15406 /**
15407 * hdd_pktlog_set_buff_size() - set pktlog buffer size
15408 * @hdd_ctx: hdd context
15409 * @set_value2: pktlog buffer size value
15410 *
15411 *
15412 * Return: 0 for success or error.
15413 */
hdd_pktlog_set_buff_size(struct hdd_context * hdd_ctx,int set_value2)15414 static int hdd_pktlog_set_buff_size(struct hdd_context *hdd_ctx, int set_value2)
15415 {
15416 struct sir_wifi_start_log start_log = { 0 };
15417 QDF_STATUS status;
15418
15419 start_log.ring_id = RING_ID_PER_PACKET_STATS;
15420 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
15421 start_log.ini_triggered = cds_is_packet_log_enabled();
15422 start_log.user_triggered = 1;
15423 start_log.size = set_value2;
15424 start_log.is_pktlog_buff_clear = false;
15425
15426 status = sme_wifi_start_logger(hdd_ctx->mac_handle, start_log);
15427 if (!QDF_IS_STATUS_SUCCESS(status)) {
15428 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
15429 hdd_exit();
15430 return -EINVAL;
15431 }
15432
15433 return 0;
15434 }
15435
15436 /**
15437 * hdd_pktlog_clear_buff() - clear pktlog buffer
15438 * @hdd_ctx: hdd context
15439 *
15440 * Return: 0 for success or error.
15441 */
hdd_pktlog_clear_buff(struct hdd_context * hdd_ctx)15442 static int hdd_pktlog_clear_buff(struct hdd_context *hdd_ctx)
15443 {
15444 struct sir_wifi_start_log start_log;
15445 QDF_STATUS status;
15446
15447 start_log.ring_id = RING_ID_PER_PACKET_STATS;
15448 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
15449 start_log.ini_triggered = cds_is_packet_log_enabled();
15450 start_log.user_triggered = 1;
15451 start_log.size = 0;
15452 start_log.is_pktlog_buff_clear = true;
15453
15454 status = sme_wifi_start_logger(hdd_ctx->mac_handle, start_log);
15455 if (!QDF_IS_STATUS_SUCCESS(status)) {
15456 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
15457 hdd_exit();
15458 return -EINVAL;
15459 }
15460
15461 return 0;
15462 }
15463
15464
15465 /**
15466 * hdd_process_pktlog_command() - process pktlog command
15467 * @hdd_ctx: hdd context
15468 * @set_value: value set by user
15469 * @set_value2: pktlog buffer size value
15470 *
15471 * This function process pktlog command.
15472 * set_value2 only matters when set_value is 3 (set buff size)
15473 * otherwise we ignore it.
15474 *
15475 * Return: 0 for success or error.
15476 */
hdd_process_pktlog_command(struct hdd_context * hdd_ctx,uint32_t set_value,int set_value2)15477 int hdd_process_pktlog_command(struct hdd_context *hdd_ctx, uint32_t set_value,
15478 int set_value2)
15479 {
15480 int ret;
15481 bool enable;
15482 uint8_t user_triggered = 0;
15483
15484 ret = wlan_hdd_validate_context(hdd_ctx);
15485 if (0 != ret)
15486 return ret;
15487
15488 hdd_debug("set pktlog %d, set size %d", set_value, set_value2);
15489
15490 if (set_value > PKTLOG_CLEAR_BUFF) {
15491 hdd_err("invalid pktlog value %d", set_value);
15492 return -EINVAL;
15493 }
15494
15495 if (set_value == PKTLOG_SET_BUFF_SIZE) {
15496 if (set_value2 <= 0) {
15497 hdd_err("invalid pktlog size %d", set_value2);
15498 return -EINVAL;
15499 } else if (set_value2 > MAX_PKTLOG_SIZE) {
15500 hdd_err_rl("Pktlog size is large. max value is %uMB.",
15501 MAX_PKTLOG_SIZE);
15502 return -EINVAL;
15503 }
15504 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
15505 } else if (set_value == PKTLOG_CLEAR_BUFF) {
15506 return hdd_pktlog_clear_buff(hdd_ctx);
15507 }
15508
15509 /*
15510 * set_value = 0 then disable packetlog
15511 * set_value = 1 enable packetlog forcefully
15512 * set_value = 2 then disable packetlog if disabled through ini or
15513 * enable packetlog with AUTO type.
15514 */
15515 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
15516 true : false;
15517
15518 if (1 == set_value) {
15519 enable = true;
15520 user_triggered = 1;
15521 }
15522
15523 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
15524 }
15525
15526 /**
15527 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
15528 * @hdd_ctx: HDD context
15529 * @enable_disable_flag: Flag to enable/disable
15530 * @user_triggered: triggered through iwpriv
15531 * @size: buffer size to be used for packetlog
15532 *
15533 * Return: 0 on success; error number otherwise
15534 */
hdd_pktlog_enable_disable(struct hdd_context * hdd_ctx,bool enable_disable_flag,uint8_t user_triggered,int size)15535 int hdd_pktlog_enable_disable(struct hdd_context *hdd_ctx,
15536 bool enable_disable_flag,
15537 uint8_t user_triggered, int size)
15538 {
15539 struct sir_wifi_start_log start_log;
15540 QDF_STATUS status;
15541
15542 if (hdd_ctx->is_pktlog_enabled && enable_disable_flag)
15543 return 0;
15544
15545 if ((!hdd_ctx->is_pktlog_enabled) && (!enable_disable_flag))
15546 return 0;
15547
15548 start_log.ring_id = RING_ID_PER_PACKET_STATS;
15549 start_log.verbose_level =
15550 enable_disable_flag ?
15551 WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
15552 start_log.ini_triggered = cds_is_packet_log_enabled();
15553 start_log.user_triggered = user_triggered;
15554 start_log.size = size;
15555 start_log.is_pktlog_buff_clear = false;
15556 /*
15557 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
15558 * commands. Host uses this flag to decide whether to send pktlog
15559 * disable command to fw without sending pktlog enable command
15560 * previously. For eg, If vendor sends pktlog disable command without
15561 * sending pktlog enable command, then host discards the packet
15562 * but for iwpriv command, host will send it to fw.
15563 */
15564 start_log.is_iwpriv_command = 1;
15565
15566 status = sme_wifi_start_logger(hdd_ctx->mac_handle, start_log);
15567 if (!QDF_IS_STATUS_SUCCESS(status)) {
15568 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
15569 hdd_exit();
15570 return -EINVAL;
15571 }
15572
15573 hdd_ctx->is_pktlog_enabled = enable_disable_flag;
15574
15575 return 0;
15576 }
15577 #endif /* REMOVE_PKT_LOG */
15578
hdd_free_mac_address_lists(struct hdd_context * hdd_ctx)15579 void hdd_free_mac_address_lists(struct hdd_context *hdd_ctx)
15580 {
15581 hdd_debug("Resetting MAC address lists");
15582 qdf_mem_zero(hdd_ctx->provisioned_mac_addr,
15583 sizeof(hdd_ctx->provisioned_mac_addr));
15584 qdf_mem_zero(hdd_ctx->derived_mac_addr,
15585 sizeof(hdd_ctx->derived_mac_addr));
15586 hdd_ctx->num_provisioned_addr = 0;
15587 hdd_ctx->num_derived_addr = 0;
15588 hdd_ctx->provisioned_intf_addr_mask = 0;
15589 hdd_ctx->derived_intf_addr_mask = 0;
15590 }
15591
15592 /**
15593 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
15594 * for MAC address
15595 * @dev: Device Pointer
15596 * @num: Number of Valid Mac address
15597 *
15598 * Return: Pointer to MAC address buffer
15599 */
hdd_get_platform_wlan_mac_buff(struct device * dev,uint32_t * num)15600 static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
15601 uint32_t *num)
15602 {
15603 return pld_get_wlan_mac_address(dev, num);
15604 }
15605
15606 /**
15607 * hdd_get_platform_wlan_derived_mac_buff() - API to query platform driver
15608 * for derived MAC address
15609 * @dev: Device Pointer
15610 * @num: Number of Valid Mac address
15611 *
15612 * Return: Pointer to MAC address buffer
15613 */
hdd_get_platform_wlan_derived_mac_buff(struct device * dev,uint32_t * num)15614 static uint8_t *hdd_get_platform_wlan_derived_mac_buff(struct device *dev,
15615 uint32_t *num)
15616 {
15617 return pld_get_wlan_derived_mac_address(dev, num);
15618 }
15619
15620 /**
15621 * hdd_populate_random_mac_addr() - API to populate random mac addresses
15622 * @hdd_ctx: HDD Context
15623 * @num: Number of random mac addresses needed
15624 *
15625 * Generate random addresses using bit manipulation on the base mac address
15626 *
15627 * Return: None
15628 */
hdd_populate_random_mac_addr(struct hdd_context * hdd_ctx,uint32_t num)15629 void hdd_populate_random_mac_addr(struct hdd_context *hdd_ctx, uint32_t num)
15630 {
15631 uint32_t idx = hdd_ctx->num_derived_addr;
15632 uint32_t iter;
15633 uint8_t *buf = NULL;
15634 uint8_t macaddr_b3, tmp_br3;
15635 /*
15636 * Consider first provisioned mac address as source address to derive
15637 * remaining addresses
15638 */
15639
15640 uint8_t *src = hdd_ctx->provisioned_mac_addr[0].bytes;
15641
15642 for (iter = 0; iter < num; ++iter, ++idx) {
15643 buf = hdd_ctx->derived_mac_addr[idx].bytes;
15644 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
15645 macaddr_b3 = buf[3];
15646 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + idx) &
15647 INTF_MACADDR_MASK;
15648 macaddr_b3 += tmp_br3;
15649 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
15650 buf[0] |= 0x02;
15651 buf[3] = macaddr_b3;
15652 hdd_debug(QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(buf));
15653 hdd_ctx->num_derived_addr++;
15654 }
15655 }
15656
15657 /**
15658 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
15659 * @hdd_ctx: HDD Context
15660 *
15661 * API to get mac addresses from platform driver and update the driver
15662 * structures and configure FW with the base mac address.
15663 * Return: int
15664 */
hdd_platform_wlan_mac(struct hdd_context * hdd_ctx)15665 static int hdd_platform_wlan_mac(struct hdd_context *hdd_ctx)
15666 {
15667 uint32_t no_of_mac_addr, iter;
15668 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
15669 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
15670 uint8_t *addr, *buf;
15671 struct device *dev = hdd_ctx->parent_dev;
15672 tSirMacAddr mac_addr;
15673 QDF_STATUS status;
15674
15675 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
15676
15677 if (no_of_mac_addr == 0 || !addr) {
15678 hdd_debug("No mac configured from platform driver");
15679 return -EINVAL;
15680 }
15681
15682 hdd_free_mac_address_lists(hdd_ctx);
15683
15684 if (no_of_mac_addr > max_mac_addr)
15685 no_of_mac_addr = max_mac_addr;
15686
15687 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
15688
15689 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
15690 buf = hdd_ctx->provisioned_mac_addr[iter].bytes;
15691 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
15692 hdd_info("provisioned MAC Addr [%d] "QDF_MAC_ADDR_FMT, iter,
15693 QDF_MAC_ADDR_REF(buf));
15694 }
15695
15696 hdd_ctx->num_provisioned_addr = no_of_mac_addr;
15697
15698 if (hdd_ctx->config->mac_provision) {
15699 addr = hdd_get_platform_wlan_derived_mac_buff(dev,
15700 &no_of_mac_addr);
15701
15702 if (no_of_mac_addr == 0 || !addr)
15703 hdd_warn("No derived address from platform driver");
15704 else if (no_of_mac_addr >
15705 (max_mac_addr - hdd_ctx->num_provisioned_addr))
15706 no_of_mac_addr = (max_mac_addr -
15707 hdd_ctx->num_provisioned_addr);
15708
15709 for (iter = 0; iter < no_of_mac_addr; ++iter,
15710 addr += mac_addr_size) {
15711 buf = hdd_ctx->derived_mac_addr[iter].bytes;
15712 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
15713 hdd_debug("derived MAC Addr [%d] "QDF_MAC_ADDR_FMT, iter,
15714 QDF_MAC_ADDR_REF(buf));
15715 }
15716 hdd_ctx->num_derived_addr = no_of_mac_addr;
15717 }
15718
15719 no_of_mac_addr = hdd_ctx->num_provisioned_addr +
15720 hdd_ctx->num_derived_addr;
15721 if (no_of_mac_addr < max_mac_addr)
15722 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
15723 no_of_mac_addr);
15724
15725 status = sme_set_custom_mac_addr(mac_addr);
15726 if (!QDF_IS_STATUS_SUCCESS(status))
15727 return -EAGAIN;
15728
15729 return 0;
15730 }
15731
15732 /**
15733 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
15734 * @hdd_ctx: HDD Context
15735 *
15736 * Update MAC address to FW. If MAC address passed by FW is invalid, host
15737 * will generate its own MAC and update it to FW.
15738 *
15739 * Return: 0 for success
15740 * Non-zero error code for failure
15741 */
hdd_update_mac_addr_to_fw(struct hdd_context * hdd_ctx)15742 static int hdd_update_mac_addr_to_fw(struct hdd_context *hdd_ctx)
15743 {
15744 tSirMacAddr custom_mac_addr;
15745 QDF_STATUS status;
15746
15747 if (hdd_ctx->num_provisioned_addr)
15748 qdf_mem_copy(&custom_mac_addr,
15749 &hdd_ctx->provisioned_mac_addr[0].bytes[0],
15750 sizeof(tSirMacAddr));
15751 else
15752 qdf_mem_copy(&custom_mac_addr,
15753 &hdd_ctx->derived_mac_addr[0].bytes[0],
15754 sizeof(tSirMacAddr));
15755 status = sme_set_custom_mac_addr(custom_mac_addr);
15756 if (!QDF_IS_STATUS_SUCCESS(status))
15757 return -EAGAIN;
15758 return 0;
15759 }
15760
15761 /**
15762 * hdd_initialize_mac_address() - API to get wlan mac addresses
15763 * @hdd_ctx: HDD Context
15764 *
15765 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
15766 * is provisioned with mac addresses, driver uses it, else it will use
15767 * wlan_mac.bin to update HW MAC addresses.
15768 *
15769 * Return: None
15770 */
hdd_initialize_mac_address(struct hdd_context * hdd_ctx)15771 static int hdd_initialize_mac_address(struct hdd_context *hdd_ctx)
15772 {
15773 QDF_STATUS status;
15774 int ret;
15775
15776 ret = hdd_platform_wlan_mac(hdd_ctx);
15777 if (!ret) {
15778 hdd_info("using MAC address from platform driver");
15779 return ret;
15780 } else if (hdd_ctx->config->mac_provision) {
15781 hdd_err("getting MAC address from platform driver failed");
15782 return ret;
15783 }
15784
15785 status = hdd_update_mac_config(hdd_ctx);
15786 if (QDF_IS_STATUS_SUCCESS(status)) {
15787 hdd_info("using MAC address from wlan_mac.bin");
15788 return 0;
15789 }
15790
15791 hdd_info("using default MAC address");
15792
15793 /* Use fw provided MAC */
15794 if (!qdf_is_macaddr_zero(&hdd_ctx->hw_macaddr)) {
15795 hdd_update_macaddr(hdd_ctx, hdd_ctx->hw_macaddr, false);
15796 return 0;
15797 } else if (hdd_generate_macaddr_auto(hdd_ctx) != 0) {
15798 struct qdf_mac_addr mac_addr;
15799
15800 hdd_err("MAC failure from device serial no.");
15801 qdf_get_random_bytes(&mac_addr, sizeof(mac_addr));
15802 /*
15803 * Reset multicast bit (bit-0) and set
15804 * locally-administered bit
15805 */
15806 mac_addr.bytes[0] = 0x2;
15807 hdd_update_macaddr(hdd_ctx, mac_addr, true);
15808 }
15809
15810 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
15811 if (ret)
15812 hdd_err("MAC address out-of-sync, ret:%d", ret);
15813 return ret;
15814 }
15815
15816 /* params being sent:
15817 * wmi_pdev_param_tx_chain_mask_1ss
15818 * wmi_pdev_param_mgmt_retry_limit
15819 * wmi_pdev_param_default_6ghz_rate
15820 * wmi_pdev_param_pdev_stats_tx_xretry_ext
15821 * wmi_pdev_param_smart_chainmask_scheme
15822 * wmi_pdev_param_alternative_chainmask_scheme
15823 * wmi_pdev_param_ani_enable
15824 * wmi_pdev_param_pcie_config
15825 */
15826 /**
15827 * hdd_pre_enable_configure() - Configurations prior to cds_enable
15828 * @hdd_ctx: HDD context
15829 *
15830 * Pre configurations to be done at lower layer before calling cds enable.
15831 *
15832 * Return: 0 on success and errno on failure.
15833 */
hdd_pre_enable_configure(struct hdd_context * hdd_ctx)15834 static int hdd_pre_enable_configure(struct hdd_context *hdd_ctx)
15835 {
15836 int ret;
15837 uint8_t val = 0;
15838 uint8_t max_retry = 0;
15839 bool enable_he_mcs0_for_6ghz_mgmt = false;
15840 uint32_t tx_retry_multiplier;
15841 QDF_STATUS status;
15842 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
15843 struct dev_set_param setparam[MAX_PDEV_PRE_ENABLE_PARAMS] = {};
15844 bool check_value;
15845 uint8_t index = 0;
15846
15847 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
15848 hdd_tx_latency_register_cb(soc);
15849
15850 /* Register HL netdev flow control callback */
15851 cdp_hl_fc_register(soc, OL_TXRX_PDEV_ID, wlan_hdd_txrx_pause_cb);
15852 /* Register rx mic error indication handler */
15853 ucfg_dp_register_rx_mic_error_ind_handler(soc);
15854
15855 /*
15856 * Note that the cds_pre_enable() sequence triggers the cfg download.
15857 * The cfg download must occur before we update the SME config
15858 * since the SME config operation must access the cfg database
15859 */
15860 status = hdd_set_sme_config(hdd_ctx);
15861
15862 if (QDF_STATUS_SUCCESS != status) {
15863 hdd_err("Failed hdd_set_sme_config: %d", status);
15864 ret = qdf_status_to_os_return(status);
15865 goto out;
15866 }
15867
15868 status = hdd_set_policy_mgr_user_cfg(hdd_ctx);
15869 if (QDF_STATUS_SUCCESS != status) {
15870 hdd_alert("Failed hdd_set_policy_mgr_user_cfg: %d", status);
15871 ret = qdf_status_to_os_return(status);
15872 goto out;
15873 }
15874
15875 status = ucfg_mlme_get_tx_chainmask_1ss(hdd_ctx->psoc, &val);
15876 if (QDF_STATUS_SUCCESS != status) {
15877 hdd_err("Get tx_chainmask_1ss from mlme failed");
15878 ret = qdf_status_to_os_return(status);
15879 goto out;
15880 }
15881 ret = mlme_check_index_setparam(setparam,
15882 wmi_pdev_param_tx_chain_mask_1ss,
15883 val, index++,
15884 MAX_PDEV_PRE_ENABLE_PARAMS);
15885 if (QDF_IS_STATUS_ERROR(ret)) {
15886 hdd_err("failed at wmi_pdev_param_tx_chain_mask_1ss");
15887 goto out;
15888
15889 }
15890
15891 wlan_mlme_get_mgmt_max_retry(hdd_ctx->psoc, &max_retry);
15892 ret = mlme_check_index_setparam(setparam,
15893 wmi_pdev_param_mgmt_retry_limit,
15894 max_retry, index++,
15895 MAX_PDEV_PRE_ENABLE_PARAMS);
15896 if (QDF_IS_STATUS_ERROR(ret)) {
15897 hdd_err("failed at wmi_pdev_param_mgmt_retry_limit");
15898 goto out;
15899 }
15900
15901 wlan_mlme_get_mgmt_6ghz_rate_support(hdd_ctx->psoc,
15902 &enable_he_mcs0_for_6ghz_mgmt);
15903 if (enable_he_mcs0_for_6ghz_mgmt) {
15904 hdd_debug("HE rates for 6GHz mgmt frames are supported");
15905 ret = mlme_check_index_setparam(
15906 setparam,
15907 wmi_pdev_param_default_6ghz_rate,
15908 MGMT_DEFAULT_DATA_RATE_6GHZ, index++,
15909 MAX_PDEV_PRE_ENABLE_PARAMS);
15910 if (QDF_IS_STATUS_ERROR(ret)) {
15911 hdd_err("wmi_pdev_param_default_6ghz_rate failed %d",
15912 ret);
15913 goto out;
15914 }
15915 }
15916
15917 wlan_mlme_get_tx_retry_multiplier(hdd_ctx->psoc,
15918 &tx_retry_multiplier);
15919 ret = mlme_check_index_setparam(setparam,
15920 wmi_pdev_param_pdev_stats_tx_xretry_ext,
15921 tx_retry_multiplier, index++,
15922 MAX_PDEV_PRE_ENABLE_PARAMS);
15923 if (QDF_IS_STATUS_ERROR(ret)) {
15924 hdd_err("failed at wmi_pdev_param_pdev_stats_tx_xretry_ext");
15925 goto out;
15926 }
15927
15928 ret = ucfg_get_smart_chainmask_enabled(hdd_ctx->psoc,
15929 &check_value);
15930 if (QDF_IS_STATUS_SUCCESS(ret)) {
15931 ret = mlme_check_index_setparam(
15932 setparam,
15933 wmi_pdev_param_smart_chainmask_scheme,
15934 (int)check_value, index++,
15935 MAX_PDEV_PRE_ENABLE_PARAMS);
15936 if (QDF_IS_STATUS_ERROR(ret)) {
15937 hdd_err("failed to set wmi_pdev_param_smart_chainmask_scheme");
15938 goto out;
15939 }
15940 }
15941
15942 ret = ucfg_get_alternative_chainmask_enabled(hdd_ctx->psoc,
15943 &check_value);
15944 if (QDF_IS_STATUS_SUCCESS(ret)) {
15945 ret = mlme_check_index_setparam(
15946 setparam,
15947 wmi_pdev_param_alternative_chainmask_scheme,
15948 (int)check_value, index++,
15949 MAX_PDEV_PRE_ENABLE_PARAMS);
15950 if (QDF_IS_STATUS_ERROR(ret)) {
15951 hdd_err("failed to set wmi_pdev_param_alternative_chainmask_scheme");
15952 goto out;
15953 }
15954 }
15955
15956 ret = ucfg_fwol_get_ani_enabled(hdd_ctx->psoc, &check_value);
15957 if (QDF_IS_STATUS_SUCCESS(ret)) {
15958 ret = mlme_check_index_setparam(setparam,
15959 wmi_pdev_param_ani_enable,
15960 (int)check_value, index++,
15961 MAX_PDEV_PRE_ENABLE_PARAMS);
15962 if (QDF_IS_STATUS_ERROR(ret)) {
15963 hdd_err("failed to set wmi_pdev_param_ani_enable");
15964 goto out;
15965 }
15966 }
15967
15968 ret = hdd_set_pcie_params(hdd_ctx, index, setparam);
15969 if (QDF_IS_STATUS_ERROR(ret))
15970 goto out;
15971 else
15972 index++;
15973 ret = sme_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
15974 WMI_PDEV_ID_SOC, setparam,
15975 index);
15976 if (QDF_IS_STATUS_ERROR(ret)) {
15977 hdd_err("failed to send pdev set params");
15978 goto out;
15979 }
15980
15981 /* Configure global firmware params */
15982 ret = ucfg_fwol_configure_global_params(hdd_ctx->psoc, hdd_ctx->pdev);
15983 if (ret)
15984 goto out;
15985
15986 status = hdd_set_sme_chan_list(hdd_ctx);
15987 if (status != QDF_STATUS_SUCCESS) {
15988 hdd_err("Failed to init channel list: %d", status);
15989 ret = qdf_status_to_os_return(status);
15990 goto out;
15991 }
15992
15993 if (!hdd_update_config_cfg(hdd_ctx)) {
15994 hdd_err("config update failed");
15995 ret = -EINVAL;
15996 goto out;
15997 }
15998 hdd_init_channel_avoidance(hdd_ctx);
15999
16000 out:
16001 return ret;
16002 }
16003
16004 #ifdef FEATURE_P2P_LISTEN_OFFLOAD
16005 /**
16006 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
16007 * @context: context registered with sme_register_p2p_lo_event(). HDD
16008 * always registers a hdd context pointer
16009 * @evt:event structure pointer
16010 *
16011 * This is the p2p listen offload stop event handler, it sends vendor
16012 * event back to supplicant to notify the stop reason.
16013 *
16014 * Return: None
16015 */
wlan_hdd_p2p_lo_event_callback(void * context,struct sir_p2p_lo_event * evt)16016 static void wlan_hdd_p2p_lo_event_callback(void *context,
16017 struct sir_p2p_lo_event *evt)
16018 {
16019 struct hdd_context *hdd_ctx = context;
16020 struct sk_buff *vendor_event;
16021 enum qca_nl80211_vendor_subcmds_index index =
16022 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX;
16023 struct wlan_hdd_link_info *link_info;
16024
16025 hdd_enter();
16026
16027 if (!hdd_ctx) {
16028 hdd_err("Invalid HDD context pointer");
16029 return;
16030 }
16031
16032 link_info = hdd_get_link_info_by_vdev(hdd_ctx, evt->vdev_id);
16033 if (!link_info) {
16034 hdd_err("Cannot find adapter by vdev_id = %d",
16035 evt->vdev_id);
16036 return;
16037 }
16038
16039 vendor_event =
16040 wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
16041 &link_info->adapter->wdev,
16042 sizeof(uint32_t) +
16043 NLMSG_HDRLEN,
16044 index, GFP_KERNEL);
16045 if (!vendor_event) {
16046 hdd_err("wlan_cfg80211_vendor_event_alloc failed");
16047 return;
16048 }
16049
16050 if (nla_put_u32(vendor_event,
16051 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
16052 evt->reason_code)) {
16053 hdd_err("nla put failed");
16054 wlan_cfg80211_vendor_free_skb(vendor_event);
16055 return;
16056 }
16057
16058 wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
16059 hdd_debug("Sent P2P_LISTEN_OFFLOAD_STOP event for vdev_id = %d",
16060 evt->vdev_id);
16061 }
16062 #else
wlan_hdd_p2p_lo_event_callback(void * context,struct sir_p2p_lo_event * evt)16063 static void wlan_hdd_p2p_lo_event_callback(void *context,
16064 struct sir_p2p_lo_event *evt)
16065 {
16066 }
16067 #endif
16068
16069 #ifdef FEATURE_WLAN_DYNAMIC_CVM
hdd_set_vc_mode_config(struct hdd_context * hdd_ctx)16070 static inline int hdd_set_vc_mode_config(struct hdd_context *hdd_ctx)
16071 {
16072 return sme_set_vc_mode_config(hdd_ctx->config->vc_mode_cfg_bitmap);
16073 }
16074 #else
hdd_set_vc_mode_config(struct hdd_context * hdd_ctx)16075 static inline int hdd_set_vc_mode_config(struct hdd_context *hdd_ctx)
16076 {
16077 return QDF_STATUS_SUCCESS;
16078 }
16079 #endif
16080
16081 /**
16082 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
16083 * @hdd_ctx: HDD context
16084 *
16085 * This function sends the adaptive dwell time config configuration to the
16086 * firmware via WMA
16087 *
16088 * Return: 0 - success, < 0 - failure
16089 */
hdd_adaptive_dwelltime_init(struct hdd_context * hdd_ctx)16090 static int hdd_adaptive_dwelltime_init(struct hdd_context *hdd_ctx)
16091 {
16092 QDF_STATUS status;
16093 struct adaptive_dwelltime_params dwelltime_params;
16094
16095 status = ucfg_fwol_get_all_adaptive_dwelltime_params(hdd_ctx->psoc,
16096 &dwelltime_params);
16097 status = ucfg_fwol_set_adaptive_dwelltime_config(&dwelltime_params);
16098
16099 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
16100 if (!QDF_IS_STATUS_SUCCESS(status)) {
16101 hdd_err("Failed to send Adaptive Dwelltime configuration!");
16102 return -EAGAIN;
16103 }
16104 return 0;
16105 }
16106
hdd_dbs_scan_selection_init(struct hdd_context * hdd_ctx)16107 int hdd_dbs_scan_selection_init(struct hdd_context *hdd_ctx)
16108 {
16109 QDF_STATUS status;
16110 struct wmi_dbs_scan_sel_params dbs_scan_params;
16111 uint32_t i = 0;
16112 uint8_t count = 0, numentries = 0;
16113 uint8_t dual_mac_feature;
16114 uint8_t dbs_scan_config[CDS_DBS_SCAN_PARAM_PER_CLIENT
16115 * CDS_DBS_SCAN_CLIENTS_MAX];
16116
16117 status = ucfg_policy_mgr_get_dual_mac_feature(hdd_ctx->psoc,
16118 &dual_mac_feature);
16119
16120 if (status != QDF_STATUS_SUCCESS) {
16121 hdd_err("can't get dual mac feature flag");
16122 return -EINVAL;
16123 }
16124 /* check if DBS is enabled or supported */
16125 if ((dual_mac_feature == DISABLE_DBS_CXN_AND_SCAN) ||
16126 (dual_mac_feature == ENABLE_DBS_CXN_AND_DISABLE_DBS_SCAN))
16127 return -EINVAL;
16128
16129 hdd_string_to_u8_array(hdd_ctx->config->dbs_scan_selection,
16130 dbs_scan_config, &numentries,
16131 (CDS_DBS_SCAN_PARAM_PER_CLIENT
16132 * CDS_DBS_SCAN_CLIENTS_MAX));
16133
16134 if (!numentries) {
16135 hdd_debug("Do not send scan_selection_config");
16136 return 0;
16137 }
16138
16139 /* hdd_set_fw_log_params */
16140 dbs_scan_params.num_clients = 0;
16141 while (count < (numentries - 2)) {
16142 dbs_scan_params.module_id[i] = dbs_scan_config[count];
16143 dbs_scan_params.num_dbs_scans[i] = dbs_scan_config[count + 1];
16144 dbs_scan_params.num_non_dbs_scans[i] =
16145 dbs_scan_config[count + 2];
16146 dbs_scan_params.num_clients++;
16147 hdd_debug("module:%d NDS:%d NNDS:%d",
16148 dbs_scan_params.module_id[i],
16149 dbs_scan_params.num_dbs_scans[i],
16150 dbs_scan_params.num_non_dbs_scans[i]);
16151 count += CDS_DBS_SCAN_PARAM_PER_CLIENT;
16152 i++;
16153 }
16154
16155 dbs_scan_params.pdev_id = 0;
16156
16157 hdd_debug("clients:%d pdev:%d",
16158 dbs_scan_params.num_clients, dbs_scan_params.pdev_id);
16159
16160 status = sme_set_dbs_scan_selection_config(hdd_ctx->mac_handle,
16161 &dbs_scan_params);
16162 hdd_debug("Sending DBS Scan Selection Configuration to fw");
16163 if (!QDF_IS_STATUS_SUCCESS(status)) {
16164 hdd_err("Failed to send DBS Scan selection configuration!");
16165 return -EAGAIN;
16166 }
16167 return 0;
16168 }
16169
16170 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
16171 /**
16172 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
16173 * @hdd_ctx: HDD context
16174 *
16175 * Set auto shutdown callback to get indications from firmware to indicate
16176 * userspace to shutdown WLAN after a configured amount of inactivity.
16177 *
16178 * Return: 0 on success and errno on failure.
16179 */
hdd_set_auto_shutdown_cb(struct hdd_context * hdd_ctx)16180 static int hdd_set_auto_shutdown_cb(struct hdd_context *hdd_ctx)
16181 {
16182 QDF_STATUS status;
16183
16184 if (!hdd_ctx->config->wlan_auto_shutdown)
16185 return 0;
16186
16187 status = sme_set_auto_shutdown_cb(hdd_ctx->mac_handle,
16188 wlan_hdd_auto_shutdown_cb);
16189 if (status != QDF_STATUS_SUCCESS)
16190 hdd_err("Auto shutdown feature could not be enabled: %d",
16191 status);
16192
16193 return qdf_status_to_os_return(status);
16194 }
16195 #else
hdd_set_auto_shutdown_cb(struct hdd_context * hdd_ctx)16196 static int hdd_set_auto_shutdown_cb(struct hdd_context *hdd_ctx)
16197 {
16198 return 0;
16199 }
16200 #endif
16201
16202 #ifdef MWS_COEX
16203 #define MAX_PDEV_MWSCOEX_PARAMS 4
16204 /* params being sent:
16205 * wmi_pdev_param_mwscoex_4g_allow_quick_ftdm
16206 * wmi_pdev_param_mwscoex_set_5gnr_pwr_limit
16207 * wmi_pdev_param_mwscoex_pcc_chavd_delay
16208 * wmi_pdev_param_mwscoex_scc_chavd_delay
16209 */
16210
16211 /**
16212 * hdd_init_mws_coex() - Initialize MWS coex configurations
16213 * @hdd_ctx: HDD context
16214 *
16215 * This function sends MWS-COEX 4G quick FTDM and
16216 * MWS-COEX 5G-NR power limit to FW
16217 *
16218 * Return: 0 on success and errno on failure.
16219 */
hdd_init_mws_coex(struct hdd_context * hdd_ctx)16220 static int hdd_init_mws_coex(struct hdd_context *hdd_ctx)
16221 {
16222 int ret = 0;
16223 uint32_t mws_coex_4g_quick_tdm = 0, mws_coex_5g_nr_pwr_limit = 0;
16224 uint32_t mws_coex_pcc_channel_avoid_delay = 0;
16225 uint32_t mws_coex_scc_channel_avoid_delay = 0;
16226 struct dev_set_param setparam[MAX_PDEV_MWSCOEX_PARAMS] = {};
16227 uint8_t index = 0;
16228
16229 ucfg_mlme_get_mws_coex_4g_quick_tdm(hdd_ctx->psoc,
16230 &mws_coex_4g_quick_tdm);
16231 ret = mlme_check_index_setparam(
16232 setparam,
16233 wmi_pdev_param_mwscoex_4g_allow_quick_ftdm,
16234 mws_coex_4g_quick_tdm, index++,
16235 MAX_PDEV_MWSCOEX_PARAMS);
16236 if (QDF_IS_STATUS_ERROR(ret)) {
16237 hdd_err("failed at wmi_pdev_param_mwscoex_4g_allow_quick_ftdm");
16238 goto error;
16239 }
16240
16241 ucfg_mlme_get_mws_coex_5g_nr_pwr_limit(hdd_ctx->psoc,
16242 &mws_coex_5g_nr_pwr_limit);
16243 ret = mlme_check_index_setparam(
16244 setparam,
16245 wmi_pdev_param_mwscoex_set_5gnr_pwr_limit,
16246 mws_coex_5g_nr_pwr_limit, index++,
16247 MAX_PDEV_MWSCOEX_PARAMS);
16248 if (QDF_IS_STATUS_ERROR(ret)) {
16249 hdd_err("failed at wmi_pdev_param_mwscoex_set_5gnr_pwr_limit");
16250 goto error;
16251 }
16252
16253 ucfg_mlme_get_mws_coex_pcc_channel_avoid_delay(
16254 hdd_ctx->psoc,
16255 &mws_coex_pcc_channel_avoid_delay);
16256 ret = mlme_check_index_setparam(setparam,
16257 wmi_pdev_param_mwscoex_pcc_chavd_delay,
16258 mws_coex_pcc_channel_avoid_delay,
16259 index++, MAX_PDEV_MWSCOEX_PARAMS);
16260 if (QDF_IS_STATUS_ERROR(ret)) {
16261 hdd_err("failed at wmi_pdev_param_mwscoex_pcc_chavd_delay");
16262 goto error;
16263 }
16264
16265 ucfg_mlme_get_mws_coex_scc_channel_avoid_delay(
16266 hdd_ctx->psoc,
16267 &mws_coex_scc_channel_avoid_delay);
16268 ret = mlme_check_index_setparam(setparam,
16269 wmi_pdev_param_mwscoex_scc_chavd_delay,
16270 mws_coex_scc_channel_avoid_delay,
16271 index++, MAX_PDEV_MWSCOEX_PARAMS);
16272 if (QDF_IS_STATUS_ERROR(ret)) {
16273 hdd_err("failed at wmi_pdev_param_mwscoex_scc_chavd_delay");
16274 goto error;
16275 }
16276 ret = sme_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
16277 WMI_PDEV_ID_SOC, setparam,
16278 index);
16279 if (QDF_IS_STATUS_ERROR(ret))
16280 hdd_err("failed to send pdev MWSCOEX set params");
16281 error:
16282 return ret;
16283 }
16284 #else
hdd_init_mws_coex(struct hdd_context * hdd_ctx)16285 static int hdd_init_mws_coex(struct hdd_context *hdd_ctx)
16286 {
16287 return 0;
16288 }
16289 #endif
16290
16291 #ifdef THERMAL_STATS_SUPPORT
hdd_thermal_stats_cmd_init(struct hdd_context * hdd_ctx)16292 static void hdd_thermal_stats_cmd_init(struct hdd_context *hdd_ctx)
16293 {
16294 hdd_send_get_thermal_stats_cmd(hdd_ctx, thermal_stats_init, NULL, NULL);
16295 }
16296 #else
hdd_thermal_stats_cmd_init(struct hdd_context * hdd_ctx)16297 static void hdd_thermal_stats_cmd_init(struct hdd_context *hdd_ctx)
16298 {
16299 }
16300 #endif
16301
16302 #ifdef WLAN_FEATURE_CAL_FAILURE_TRIGGER
16303 /**
16304 * hdd_cal_fail_send_event()- send calibration failure information
16305 * @cal_type: calibration type
16306 * @reason: reason for calibration failure
16307 *
16308 * This Function sends calibration failure diag event
16309 *
16310 * Return: void.
16311 */
hdd_cal_fail_send_event(uint8_t cal_type,uint8_t reason)16312 static void hdd_cal_fail_send_event(uint8_t cal_type, uint8_t reason)
16313 {
16314 /*
16315 * For now we are going with the print. Once CST APK has support to
16316 * read the diag events then we will add the diag event here.
16317 */
16318 hdd_debug("Received cal failure event with cal_type:%x reason:%x",
16319 cal_type, reason);
16320 }
16321 #else
hdd_cal_fail_send_event(uint8_t cal_type,uint8_t reason)16322 static inline void hdd_cal_fail_send_event(uint8_t cal_type, uint8_t reason)
16323 {
16324 }
16325 #endif
16326
16327 /**
16328 * hdd_features_init() - Init features
16329 * @hdd_ctx: HDD context
16330 *
16331 * Initialize features and their feature context after WLAN firmware is up.
16332 *
16333 * Return: 0 on success and errno on failure.
16334 */
hdd_features_init(struct hdd_context * hdd_ctx)16335 static int hdd_features_init(struct hdd_context *hdd_ctx)
16336 {
16337 struct tx_power_limit hddtxlimit;
16338 QDF_STATUS status;
16339 int ret;
16340 mac_handle_t mac_handle;
16341 bool b_cts2self, is_imps_enabled;
16342 bool rf_test_mode;
16343 bool std_6ghz_conn_policy;
16344 uint32_t fw_data_stall_evt;
16345 bool disable_vlp_sta_conn_sp_ap;
16346
16347 hdd_enter();
16348
16349 ret = hdd_init_mws_coex(hdd_ctx);
16350 if (ret)
16351 hdd_warn("Error initializing mws-coex");
16352
16353 /* FW capabilities received, Set the Dot11 mode */
16354 mac_handle = hdd_ctx->mac_handle;
16355 sme_setdef_dot11mode(mac_handle);
16356
16357 ucfg_mlme_is_imps_enabled(hdd_ctx->psoc, &is_imps_enabled);
16358 hdd_set_idle_ps_config(hdd_ctx, is_imps_enabled);
16359
16360 fw_data_stall_evt = ucfg_dp_fw_data_stall_evt_enabled();
16361
16362 /* Send Enable/Disable data stall detection cmd to FW */
16363 sme_cli_set_command(0, wmi_pdev_param_data_stall_detect_enable,
16364 fw_data_stall_evt, PDEV_CMD);
16365
16366 ucfg_mlme_get_go_cts2self_for_sta(hdd_ctx->psoc, &b_cts2self);
16367 if (b_cts2self)
16368 sme_set_cts2self_for_p2p_go(mac_handle);
16369
16370 if (hdd_set_vc_mode_config(hdd_ctx))
16371 hdd_warn("Error in setting Voltage Corner mode config to FW");
16372
16373 if (ucfg_dp_rx_ol_init(hdd_ctx->psoc, hdd_ctx->is_wifi3_0_target))
16374 hdd_err("Unable to initialize Rx LRO/GRO in fw");
16375
16376 if (hdd_adaptive_dwelltime_init(hdd_ctx))
16377 hdd_err("Unable to send adaptive dwelltime setting to FW");
16378
16379 if (hdd_dbs_scan_selection_init(hdd_ctx))
16380 hdd_err("Unable to send DBS scan selection setting to FW");
16381
16382 ret = hdd_init_thermal_info(hdd_ctx);
16383 if (ret) {
16384 hdd_err("Error while initializing thermal information");
16385 return ret;
16386 }
16387
16388 /**
16389 * In case of SSR/PDR, if pktlog was enabled manually before
16390 * SSR/PDR, then enable it again automatically after Wlan
16391 * device up.
16392 * During SSR/PDR, pktlog will be disabled as part of
16393 * hdd_features_deinit if pktlog is enabled in ini.
16394 * Re-enable pktlog in SSR case, if pktlog is enabled in ini.
16395 */
16396 if (hdd_get_conparam() != QDF_GLOBAL_MONITOR_MODE &&
16397 (cds_is_packet_log_enabled() ||
16398 (cds_is_driver_recovering() && hdd_ctx->is_pktlog_enabled)))
16399 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
16400
16401 hddtxlimit.txPower2g = ucfg_get_tx_power(hdd_ctx->psoc, BAND_2G);
16402 hddtxlimit.txPower5g = ucfg_get_tx_power(hdd_ctx->psoc, BAND_5G);
16403 status = sme_txpower_limit(mac_handle, &hddtxlimit);
16404 if (!QDF_IS_STATUS_SUCCESS(status))
16405 hdd_err("Error setting txlimit in sme: %d", status);
16406
16407 wlan_hdd_tsf_init(hdd_ctx);
16408
16409 status = sme_enable_disable_chanavoidind_event(mac_handle, 0);
16410 if (QDF_IS_STATUS_ERROR(status) && (status != QDF_STATUS_E_NOSUPPORT)) {
16411 hdd_err("Failed to disable Chan Avoidance Indication");
16412 return -EINVAL;
16413 }
16414
16415 /* register P2P Listen Offload event callback */
16416 if (wma_is_p2p_lo_capable())
16417 sme_register_p2p_lo_event(mac_handle, hdd_ctx,
16418 wlan_hdd_p2p_lo_event_callback);
16419 wlan_hdd_register_mcc_quota_event_callback(hdd_ctx);
16420 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
16421
16422 if (ret)
16423 return -EINVAL;
16424
16425 wlan_hdd_init_chan_info(hdd_ctx);
16426 wlan_hdd_twt_init(hdd_ctx);
16427 wlan_hdd_gpio_wakeup_init(hdd_ctx);
16428
16429 status = ucfg_mlme_is_rf_test_mode_enabled(hdd_ctx->psoc,
16430 &rf_test_mode);
16431 if (!QDF_IS_STATUS_SUCCESS(status)) {
16432 hdd_err("Get rf test mode failed");
16433 return QDF_STATUS_E_FAILURE;
16434 }
16435
16436 if (rf_test_mode) {
16437 wlan_cm_set_check_6ghz_security(hdd_ctx->psoc, false);
16438 wlan_cm_set_6ghz_key_mgmt_mask(hdd_ctx->psoc,
16439 DEFAULT_KEYMGMT_6G_MASK);
16440 }
16441
16442 status = ucfg_mlme_is_standard_6ghz_conn_policy_enabled(hdd_ctx->psoc,
16443 &std_6ghz_conn_policy);
16444
16445 if (!QDF_IS_STATUS_SUCCESS(status)) {
16446 hdd_err("Get 6ghz standard connection policy failed");
16447 return QDF_STATUS_E_FAILURE;
16448 }
16449 if (std_6ghz_conn_policy)
16450 wlan_cm_set_standard_6ghz_conn_policy(hdd_ctx->psoc, true);
16451
16452 status = ucfg_mlme_is_disable_vlp_sta_conn_to_sp_ap_enabled(
16453 hdd_ctx->psoc,
16454 &disable_vlp_sta_conn_sp_ap);
16455 if (!QDF_IS_STATUS_SUCCESS(status)) {
16456 hdd_err("Get disable vlp sta conn to sp flag failed");
16457 return QDF_STATUS_E_FAILURE;
16458 }
16459
16460 if (disable_vlp_sta_conn_sp_ap)
16461 wlan_cm_set_disable_vlp_sta_conn_to_sp_ap(hdd_ctx->psoc, true);
16462
16463 hdd_thermal_stats_cmd_init(hdd_ctx);
16464 sme_set_cal_failure_event_cb(hdd_ctx->mac_handle,
16465 hdd_cal_fail_send_event);
16466
16467 hdd_exit();
16468 return 0;
16469 }
16470
16471 /**
16472 * hdd_register_bcn_cb() - register scan beacon callback
16473 * @hdd_ctx: Pointer to the HDD context
16474 *
16475 * Return: QDF_STATUS
16476 */
hdd_register_bcn_cb(struct hdd_context * hdd_ctx)16477 static inline QDF_STATUS hdd_register_bcn_cb(struct hdd_context *hdd_ctx)
16478 {
16479 QDF_STATUS status;
16480
16481 status = ucfg_scan_register_bcn_cb(hdd_ctx->psoc,
16482 wlan_cfg80211_inform_bss_frame,
16483 SCAN_CB_TYPE_INFORM_BCN);
16484 if (!QDF_IS_STATUS_SUCCESS(status)) {
16485 hdd_err("failed to register SCAN_CB_TYPE_INFORM_BCN with status code %08d [x%08x]",
16486 status, status);
16487 return status;
16488 }
16489
16490 status = ucfg_scan_register_bcn_cb(hdd_ctx->psoc,
16491 wlan_cfg80211_unlink_bss_list,
16492 SCAN_CB_TYPE_UNLINK_BSS);
16493 if (!QDF_IS_STATUS_SUCCESS(status)) {
16494 hdd_err("failed to refister SCAN_CB_TYPE_FLUSH_BSS with status code %08d [x%08x]",
16495 status, status);
16496 return status;
16497 }
16498
16499 return QDF_STATUS_SUCCESS;
16500 }
16501
16502 /**
16503 * hdd_v2_flow_pool_map() - Flow pool create callback when vdev is active
16504 * @vdev_id: vdev_id, corresponds to flow_pool
16505 *
16506 * Return: none.
16507 */
hdd_v2_flow_pool_map(int vdev_id)16508 static void hdd_v2_flow_pool_map(int vdev_id)
16509 {
16510 QDF_STATUS status;
16511 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16512 struct wlan_objmgr_vdev *vdev;
16513
16514 if (!hdd_ctx) {
16515 hdd_err("HDD context null");
16516 return;
16517 }
16518
16519 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(hdd_ctx->psoc, vdev_id,
16520 WLAN_OSIF_ID);
16521 if (!vdev) {
16522 hdd_err("Invalid VDEV %d", vdev_id);
16523 return;
16524 }
16525
16526 if (wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev) ||
16527 policy_mgr_is_set_link_in_progress(wlan_vdev_get_psoc(vdev))) {
16528 hdd_info_rl("Link switch/set_link is ongoing, do not invoke flow pool map");
16529 goto release_ref;
16530 }
16531
16532 status = cdp_flow_pool_map(cds_get_context(QDF_MODULE_ID_SOC),
16533 OL_TXRX_PDEV_ID, vdev_id);
16534 /*
16535 * For Adrastea flow control v2 is based on FW MAP events,
16536 * so this above callback is not implemented.
16537 * Hence this is not actual failure. Dont return failure
16538 */
16539 if ((status != QDF_STATUS_SUCCESS) &&
16540 (status != QDF_STATUS_E_INVAL)) {
16541 hdd_err("vdev_id: %d, failed to create flow pool status %d",
16542 vdev_id, status);
16543 }
16544
16545 release_ref:
16546 wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
16547 }
16548
16549 /**
16550 * hdd_v2_flow_pool_unmap() - Flow pool create callback when vdev is not active
16551 * @vdev_id: vdev_id, corresponds to flow_pool
16552 *
16553 * Return: none.
16554 */
hdd_v2_flow_pool_unmap(int vdev_id)16555 static void hdd_v2_flow_pool_unmap(int vdev_id)
16556 {
16557 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16558 struct wlan_objmgr_vdev *vdev;
16559
16560 if (!hdd_ctx) {
16561 hdd_err("HDD context null");
16562 return;
16563 }
16564
16565 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(hdd_ctx->psoc, vdev_id,
16566 WLAN_OSIF_ID);
16567 if (!vdev) {
16568 hdd_err("Invalid VDEV %d", vdev_id);
16569 return;
16570 }
16571
16572 if (wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev)) {
16573 hdd_info("Link switch ongoing do not invoke flow pool unmap");
16574 goto release_ref;
16575 }
16576
16577 cdp_flow_pool_unmap(cds_get_context(QDF_MODULE_ID_SOC),
16578 OL_TXRX_PDEV_ID, vdev_id);
16579 release_ref:
16580 wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
16581 }
16582
hdd_hastings_bt_war_initialize(struct hdd_context * hdd_ctx)16583 static void hdd_hastings_bt_war_initialize(struct hdd_context *hdd_ctx)
16584 {
16585 if (hdd_ctx->config->iface_change_wait_time)
16586 hdd_hastings_bt_war_disable_fw(hdd_ctx);
16587 else
16588 hdd_hastings_bt_war_enable_fw(hdd_ctx);
16589 }
16590
16591 #define MAX_PDEV_CFG_CDS_PARAMS 8
16592 /* params being sent:
16593 * wmi_pdev_param_set_iot_pattern
16594 * wmi_pdev_param_max_mpdus_in_ampdu
16595 * wmi_pdev_param_enable_rts_sifs_bursting
16596 * wmi_pdev_param_peer_stats_info_enable
16597 * wmi_pdev_param_abg_mode_tx_chain_num
16598 * wmi_pdev_param_gcmp_support_enable
16599 * wmi_pdev_auto_detect_power_failure
16600 * wmi_pdev_param_fast_pwr_transition
16601 */
16602
16603 /**
16604 * hdd_configure_cds() - Configure cds modules
16605 * @hdd_ctx: HDD context
16606 *
16607 * Enable Cds modules after WLAN firmware is up.
16608 *
16609 * Return: 0 on success and errno on failure.
16610 */
hdd_configure_cds(struct hdd_context * hdd_ctx)16611 int hdd_configure_cds(struct hdd_context *hdd_ctx)
16612 {
16613 int ret;
16614 QDF_STATUS status;
16615 int set_value;
16616 mac_handle_t mac_handle;
16617 bool enable_rts_sifsbursting;
16618 uint8_t enable_phy_reg_retention;
16619 uint8_t max_mpdus_inampdu, is_force_1x1 = 0;
16620 uint32_t num_abg_tx_chains = 0;
16621 uint16_t num_11b_tx_chains = 0;
16622 uint16_t num_11ag_tx_chains = 0;
16623 struct policy_mgr_dp_cbacks dp_cbs = {0};
16624 bool value;
16625 enum pmo_auto_pwr_detect_failure_mode auto_power_fail_mode;
16626 bool bval = false;
16627 uint8_t max_index = MAX_PDEV_CFG_CDS_PARAMS;
16628 struct dev_set_param setparam[MAX_PDEV_CFG_CDS_PARAMS] = {};
16629 uint8_t index = 0;
16630 uint8_t next_index = 0;
16631 mac_handle = hdd_ctx->mac_handle;
16632
16633 status = ucfg_policy_mgr_get_force_1x1(hdd_ctx->psoc, &is_force_1x1);
16634 if (status != QDF_STATUS_SUCCESS) {
16635 hdd_err("Failed to get force 1x1 value");
16636 goto out;
16637 }
16638 if (is_force_1x1) {
16639 status = mlme_check_index_setparam(
16640 setparam,
16641 wmi_pdev_param_set_iot_pattern,
16642 1, index++,
16643 max_index);
16644 if (QDF_IS_STATUS_ERROR(status)) {
16645 hdd_err("failed at wmi_pdev_param_set_iot_pattern");
16646 goto out;
16647 }
16648 }
16649 /* set chip power save failure detected callback */
16650 sme_set_chip_pwr_save_fail_cb(mac_handle,
16651 hdd_chip_pwr_save_fail_detected_cb);
16652
16653 status = ucfg_get_max_mpdus_inampdu(hdd_ctx->psoc,
16654 &max_mpdus_inampdu);
16655 if (status) {
16656 hdd_err("Failed to get max mpdus in ampdu value");
16657 goto out;
16658 }
16659
16660 if (max_mpdus_inampdu) {
16661 set_value = max_mpdus_inampdu;
16662 status = mlme_check_index_setparam(
16663 setparam,
16664 wmi_pdev_param_max_mpdus_in_ampdu,
16665 set_value, index++,
16666 max_index);
16667 if (QDF_IS_STATUS_ERROR(status)) {
16668 hdd_err("failed at wmi_pdev_param_max_mpdus_in_ampdu");
16669 goto out;
16670 }
16671 }
16672
16673 status = ucfg_get_enable_rts_sifsbursting(hdd_ctx->psoc,
16674 &enable_rts_sifsbursting);
16675 if (status) {
16676 hdd_err("Failed to get rts sifs bursting value");
16677 goto out;
16678 }
16679
16680 if (enable_rts_sifsbursting) {
16681 set_value = enable_rts_sifsbursting;
16682 status = mlme_check_index_setparam(
16683 setparam,
16684 wmi_pdev_param_enable_rts_sifs_bursting,
16685 set_value, index++,
16686 max_index);
16687 if (QDF_IS_STATUS_ERROR(status)) {
16688 hdd_err("Failed at wmi_pdev_param_enable_rts_sifs_bursting");
16689 goto out;
16690 }
16691 }
16692
16693 ucfg_mlme_get_sap_get_peer_info(hdd_ctx->psoc, &value);
16694 if (value) {
16695 set_value = value;
16696 status = mlme_check_index_setparam(
16697 setparam,
16698 wmi_pdev_param_peer_stats_info_enable,
16699 set_value, index++,
16700 max_index);
16701 if (QDF_IS_STATUS_ERROR(status)) {
16702 hdd_err("Failed at wmi_pdev_param_peer_stats_info_enable");
16703 goto out;
16704 }
16705 }
16706
16707 status = ucfg_mlme_get_num_11b_tx_chains(hdd_ctx->psoc,
16708 &num_11b_tx_chains);
16709 if (status != QDF_STATUS_SUCCESS) {
16710 hdd_err("Failed to get num_11b_tx_chains");
16711 goto out;
16712 }
16713
16714 status = ucfg_mlme_get_num_11ag_tx_chains(hdd_ctx->psoc,
16715 &num_11ag_tx_chains);
16716 if (status != QDF_STATUS_SUCCESS) {
16717 hdd_err("Failed to get num_11ag_tx_chains");
16718 goto out;
16719 }
16720
16721 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval);
16722 if (!QDF_IS_STATUS_SUCCESS(status))
16723 hdd_err("unable to get vht_enable2x2");
16724
16725 if (!bval) {
16726 if (num_11b_tx_chains > 1)
16727 num_11b_tx_chains = 1;
16728 if (num_11ag_tx_chains > 1)
16729 num_11ag_tx_chains = 1;
16730 }
16731 WMI_PDEV_PARAM_SET_11B_TX_CHAIN_NUM(num_abg_tx_chains,
16732 num_11b_tx_chains);
16733 WMI_PDEV_PARAM_SET_11AG_TX_CHAIN_NUM(num_abg_tx_chains,
16734 num_11ag_tx_chains);
16735 status = mlme_check_index_setparam(setparam,
16736 wmi_pdev_param_abg_mode_tx_chain_num,
16737 num_abg_tx_chains, index++,
16738 max_index);
16739 if (QDF_IS_STATUS_ERROR(status)) {
16740 hdd_err("Failed at wmi_pdev_param_abg_mode_tx_chain_num");
16741 goto out;
16742 }
16743 /* Send some pdev params to maintain legacy order of pdev set params
16744 * at hdd_pre_enable_configure
16745 */
16746 status = sme_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
16747 WMI_PDEV_ID_SOC, setparam,
16748 index);
16749 if (QDF_IS_STATUS_ERROR(status)) {
16750 hdd_err("Failed to send 1st set of pdev params");
16751 goto out;
16752 }
16753 if (!ucfg_reg_is_regdb_offloaded(hdd_ctx->psoc))
16754 ucfg_reg_program_default_cc(hdd_ctx->pdev,
16755 hdd_ctx->reg.reg_domain);
16756
16757 ret = hdd_pre_enable_configure(hdd_ctx);
16758 if (ret) {
16759 hdd_err("Failed to pre-configure cds");
16760 goto out;
16761 }
16762
16763 /* Always get latest IPA resources allocated from cds_open and configure
16764 * IPA module before configuring them to FW. Sequence required as crash
16765 * observed otherwise.
16766 */
16767
16768 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16769 ipa_disable_register_cb();
16770 } else {
16771 status = ipa_register_is_ipa_ready(hdd_ctx->pdev);
16772 if (!QDF_IS_STATUS_SUCCESS(status)) {
16773 hdd_err("ipa_register_is_ipa_ready failed");
16774 goto out;
16775 }
16776 }
16777
16778 /*
16779 * Start CDS which starts up the SME/MAC/HAL modules and everything
16780 * else
16781 */
16782 status = cds_enable(hdd_ctx->psoc);
16783
16784 if (!QDF_IS_STATUS_SUCCESS(status)) {
16785 hdd_err("cds_enable failed");
16786 goto out;
16787 }
16788
16789 status = hdd_post_cds_enable_config(hdd_ctx);
16790 if (!QDF_IS_STATUS_SUCCESS(status)) {
16791 hdd_err("hdd_post_cds_enable_config failed");
16792 goto cds_disable;
16793 }
16794 status = hdd_register_bcn_cb(hdd_ctx);
16795 if (!QDF_IS_STATUS_SUCCESS(status)) {
16796 hdd_err("hdd_register_bcn_cb failed");
16797 goto cds_disable;
16798 }
16799
16800 ret = hdd_features_init(hdd_ctx);
16801 if (ret)
16802 goto cds_disable;
16803
16804 /*
16805 * Donot disable rx offload on concurrency for lithium and
16806 * beryllium based targets
16807 */
16808 if (!hdd_ctx->is_wifi3_0_target)
16809 if (ucfg_dp_is_ol_enabled(hdd_ctx->psoc))
16810 dp_cbs.hdd_disable_rx_ol_in_concurrency =
16811 hdd_disable_rx_ol_in_concurrency;
16812 dp_cbs.hdd_set_rx_mode_rps_cb = ucfg_dp_set_rx_mode_rps;
16813 dp_cbs.hdd_ipa_set_mcc_mode_cb = hdd_ipa_set_mcc_mode;
16814 dp_cbs.hdd_v2_flow_pool_map = hdd_v2_flow_pool_map;
16815 dp_cbs.hdd_v2_flow_pool_unmap = hdd_v2_flow_pool_unmap;
16816 if (ucfg_ipa_set_perf_level_bw_enabled(hdd_ctx->pdev))
16817 dp_cbs.hdd_ipa_set_perf_level_bw = hdd_ipa_set_perf_level_bw;
16818 status = policy_mgr_register_dp_cb(hdd_ctx->psoc, &dp_cbs);
16819 if (!QDF_IS_STATUS_SUCCESS(status)) {
16820 hdd_debug("Failed to register DP cb with Policy Manager");
16821 goto cds_disable;
16822 }
16823 status = policy_mgr_register_mode_change_cb(hdd_ctx->psoc,
16824 wlan_hdd_send_mode_change_event);
16825 if (!QDF_IS_STATUS_SUCCESS(status)) {
16826 hdd_debug("Failed to register mode change cb with Policy Manager");
16827 goto cds_disable;
16828 }
16829
16830 if (hdd_green_ap_enable_egap(hdd_ctx))
16831 hdd_debug("enhance green ap is not enabled");
16832
16833 hdd_register_green_ap_callback(hdd_ctx->pdev);
16834
16835 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
16836 hdd_debug("Failed to set wow pulse");
16837
16838 max_index = max_index - index;
16839 status = mlme_check_index_setparam(
16840 setparam + index,
16841 wmi_pdev_param_gcmp_support_enable,
16842 ucfg_fwol_get_gcmp_enable(hdd_ctx->psoc),
16843 next_index++, max_index);
16844 if (QDF_IS_STATUS_ERROR(status)) {
16845 hdd_err("failed at wmi_pdev_param_gcmp_support_enable");
16846 goto out;
16847 }
16848
16849 auto_power_fail_mode =
16850 ucfg_pmo_get_auto_power_fail_mode(hdd_ctx->psoc);
16851 status = mlme_check_index_setparam(
16852 setparam + index,
16853 wmi_pdev_auto_detect_power_failure,
16854 auto_power_fail_mode,
16855 next_index++, max_index);
16856 if (QDF_IS_STATUS_ERROR(status)) {
16857 hdd_err("failed at wmi_pdev_auto_detect_power_failure");
16858 goto out;
16859 }
16860
16861 status = ucfg_get_enable_phy_reg_retention(hdd_ctx->psoc,
16862 &enable_phy_reg_retention);
16863
16864 if (QDF_IS_STATUS_ERROR(status))
16865 return -EINVAL;
16866
16867 if (enable_phy_reg_retention) {
16868 status = mlme_check_index_setparam(
16869 setparam + index,
16870 wmi_pdev_param_fast_pwr_transition,
16871 enable_phy_reg_retention,
16872 next_index++, max_index);
16873 if (QDF_IS_STATUS_ERROR(status)) {
16874 hdd_err("failed at wmi_pdev_param_fast_pwr_transition");
16875 goto out;
16876 }
16877 }
16878 /*Send remaining pdev setparams from array*/
16879 status = sme_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
16880 WMI_PDEV_ID_SOC,
16881 setparam + index,
16882 next_index);
16883 if (QDF_IS_STATUS_ERROR(status)) {
16884 hdd_err("failed to send 2nd set of pdev set params");
16885 goto out;
16886 }
16887
16888 hdd_hastings_bt_war_initialize(hdd_ctx);
16889
16890 wlan_hdd_hang_event_notifier_register(hdd_ctx);
16891 return 0;
16892
16893 cds_disable:
16894 cds_disable(hdd_ctx->psoc);
16895
16896 out:
16897 return -EINVAL;
16898 }
16899
16900 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
hdd_deregister_policy_manager_callback(struct wlan_objmgr_psoc * psoc)16901 static void hdd_deregister_policy_manager_callback(
16902 struct wlan_objmgr_psoc *psoc)
16903 {
16904 if (QDF_STATUS_SUCCESS !=
16905 policy_mgr_deregister_hdd_cb(psoc)) {
16906 hdd_err("HDD callback deregister with policy manager failed");
16907 }
16908 }
16909 #else
hdd_deregister_policy_manager_callback(struct wlan_objmgr_psoc * psoc)16910 static void hdd_deregister_policy_manager_callback(
16911 struct wlan_objmgr_psoc *psoc)
16912 {
16913 }
16914 #endif
16915
hdd_wlan_stop_modules(struct hdd_context * hdd_ctx,bool ftm_mode)16916 int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode)
16917 {
16918 void *hif_ctx;
16919 qdf_device_t qdf_ctx;
16920 QDF_STATUS qdf_status;
16921 bool is_recovery_stop = cds_is_driver_recovering();
16922 int ret = 0;
16923 int debugfs_threads;
16924 struct target_psoc_info *tgt_hdl;
16925 struct bbm_params param = {0};
16926
16927 hdd_enter();
16928 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
16929 if (!qdf_ctx)
16930 return -EINVAL;
16931
16932 cds_set_driver_state_module_stop(true);
16933
16934 debugfs_threads = hdd_return_debugfs_threads_count();
16935
16936 if (debugfs_threads > 0 || hdd_ctx->is_wiphy_suspended) {
16937 hdd_warn("Debugfs threads %d, wiphy suspend %d",
16938 debugfs_threads, hdd_ctx->is_wiphy_suspended);
16939
16940 if (IS_IDLE_STOP && !ftm_mode) {
16941 hdd_psoc_idle_timer_start(hdd_ctx);
16942 cds_set_driver_state_module_stop(false);
16943
16944 ucfg_dp_bus_bw_compute_timer_stop(hdd_ctx->psoc);
16945 return -EAGAIN;
16946 }
16947 }
16948
16949 ucfg_dp_bus_bw_compute_timer_stop(hdd_ctx->psoc);
16950 hdd_deregister_policy_manager_callback(hdd_ctx->psoc);
16951
16952 /* free user wowl patterns */
16953 hdd_free_user_wowl_ptrns();
16954
16955 switch (hdd_ctx->driver_status) {
16956 case DRIVER_MODULES_UNINITIALIZED:
16957 hdd_debug("Modules not initialized just return");
16958 goto done;
16959 case DRIVER_MODULES_CLOSED:
16960 hdd_debug("Modules already closed");
16961 goto done;
16962 case DRIVER_MODULES_ENABLED:
16963 hdd_debug("Wlan transitioning (CLOSED <- ENABLED)");
16964
16965 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
16966 hdd_disable_power_management(hdd_ctx);
16967 break;
16968 }
16969
16970 if (hdd_get_conparam() == QDF_GLOBAL_EPPING_MODE)
16971 break;
16972
16973 hdd_skip_acs_scan_timer_deinit(hdd_ctx);
16974
16975 hdd_disable_power_management(hdd_ctx);
16976
16977 if (hdd_get_conparam() == QDF_GLOBAL_MISSION_MODE)
16978 ucfg_dp_direct_link_deinit(hdd_ctx->psoc,
16979 is_recovery_stop);
16980
16981 if (hdd_deconfigure_cds(hdd_ctx)) {
16982 hdd_err("Failed to de-configure CDS");
16983 QDF_ASSERT(0);
16984 ret = -EINVAL;
16985 }
16986 hdd_debug("successfully Disabled the CDS modules!");
16987
16988 break;
16989 default:
16990 QDF_DEBUG_PANIC("Unknown driver state:%d",
16991 hdd_ctx->driver_status);
16992 ret = -EINVAL;
16993 goto done;
16994 }
16995
16996 hdd_destroy_sysfs_files();
16997 hdd_debug("Closing CDS modules!");
16998
16999 if (hdd_get_conparam() != QDF_GLOBAL_EPPING_MODE) {
17000 qdf_status = cds_post_disable();
17001 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
17002 hdd_err("Failed to process post CDS disable! :%d",
17003 qdf_status);
17004 ret = -EINVAL;
17005 QDF_ASSERT(0);
17006 }
17007
17008 hdd_unregister_notifiers(hdd_ctx);
17009 /* De-register the SME callbacks */
17010 hdd_deregister_cb(hdd_ctx);
17011
17012 hdd_runtime_suspend_context_deinit(hdd_ctx);
17013
17014 qdf_status = cds_dp_close(hdd_ctx->psoc);
17015 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
17016 hdd_warn("Failed to stop CDS DP: %d", qdf_status);
17017 ret = -EINVAL;
17018 QDF_ASSERT(0);
17019 }
17020
17021 hdd_component_pdev_close(hdd_ctx->pdev);
17022 dispatcher_pdev_close(hdd_ctx->pdev);
17023 ret = hdd_objmgr_release_and_destroy_pdev(hdd_ctx);
17024 if (ret) {
17025 hdd_err("Failed to destroy pdev; errno:%d", ret);
17026 QDF_ASSERT(0);
17027 }
17028
17029 qdf_status = cds_close(hdd_ctx->psoc);
17030 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
17031 hdd_warn("Failed to stop CDS: %d", qdf_status);
17032 ret = -EINVAL;
17033 QDF_ASSERT(0);
17034 }
17035
17036 qdf_status = wbuff_module_deinit();
17037 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
17038 hdd_err("WBUFF de-init unsuccessful; status: %d",
17039 qdf_status);
17040
17041 hdd_component_psoc_close(hdd_ctx->psoc);
17042 /* pdev close and destroy use tx rx ops so call this here */
17043 wlan_global_lmac_if_close(hdd_ctx->psoc);
17044 }
17045
17046 /*
17047 * Reset total mac phy during module stop such that during
17048 * next module start same psoc is used to populate new service
17049 * ready data
17050 */
17051 tgt_hdl = wlan_psoc_get_tgt_if_handle(hdd_ctx->psoc);
17052 if (tgt_hdl)
17053 target_psoc_set_total_mac_phy_cnt(tgt_hdl, 0);
17054
17055
17056 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
17057 if (!hif_ctx)
17058 ret = -EINVAL;
17059
17060 if (hdd_get_conparam() == QDF_GLOBAL_EPPING_MODE) {
17061 epping_disable();
17062 epping_close();
17063 }
17064
17065 wlan_connectivity_logging_stop();
17066
17067 ucfg_ipa_component_config_free();
17068
17069 hdd_hif_close(hdd_ctx, hif_ctx);
17070
17071 ol_cds_free();
17072
17073 if (IS_IDLE_STOP) {
17074 ret = pld_power_off(qdf_ctx->dev);
17075 if (ret)
17076 hdd_err("Failed to power down device; errno:%d", ret);
17077 }
17078
17079 /* Free the cache channels of the command SET_DISABLE_CHANNEL_LIST */
17080 wlan_hdd_free_cache_channels(hdd_ctx);
17081 hdd_driver_mem_cleanup();
17082
17083 /* Free the resources allocated while storing SAR config. These needs
17084 * to be freed only in the case when it is not SSR. As in the case of
17085 * SSR, the values needs to be intact so that it can be restored during
17086 * reinit path.
17087 */
17088 if (!is_recovery_stop)
17089 wlan_hdd_free_sar_config(hdd_ctx);
17090
17091 hdd_sap_destroy_ctx_all(hdd_ctx, is_recovery_stop);
17092 hdd_sta_destroy_ctx_all(hdd_ctx);
17093
17094 /*
17095 * Reset the driver mode specific bus bw level
17096 */
17097 param.policy = BBM_DRIVER_MODE_POLICY;
17098 param.policy_info.driver_mode = QDF_GLOBAL_MAX_MODE;
17099 ucfg_dp_bbm_apply_independent_policy(hdd_ctx->psoc, ¶m);
17100
17101 hdd_deinit_adapter_ops_wq(hdd_ctx);
17102 hdd_deinit_qdf_ctx(hdd_debug_domain_get());
17103
17104 hdd_check_for_leaks(hdd_ctx, is_recovery_stop);
17105 hdd_debug_domain_set(QDF_DEBUG_DOMAIN_INIT);
17106 hdd_deinit_qdf_ctx(hdd_debug_domain_get());
17107 qdf_dma_invalid_buf_list_deinit();
17108
17109 /* Restore PS params for monitor mode */
17110 if (hdd_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
17111 hdd_restore_all_ps(hdd_ctx);
17112
17113 /* Once the firmware sequence is completed reset this flag */
17114 hdd_ctx->imps_enabled = false;
17115 hdd_ctx->is_dual_mac_cfg_updated = false;
17116 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
17117 hdd_ctx->is_fw_dbg_log_levels_configured = false;
17118 hdd_debug("Wlan transitioned (now CLOSED)");
17119
17120 done:
17121 hdd_exit();
17122
17123 return ret;
17124 }
17125
17126 #ifdef WLAN_FEATURE_MEMDUMP_ENABLE
17127 /**
17128 * hdd_state_info_dump() - prints state information of hdd layer
17129 * @buf_ptr: buffer pointer
17130 * @size: size of buffer to be filled
17131 *
17132 * This function is used to dump state information of hdd layer
17133 *
17134 * Return: None
17135 */
hdd_state_info_dump(char ** buf_ptr,uint16_t * size)17136 static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
17137 {
17138 struct hdd_context *hdd_ctx;
17139 struct hdd_station_ctx *sta_ctx;
17140 struct hdd_adapter *adapter, *next_adapter = NULL;
17141 uint16_t len = 0;
17142 char *buf = *buf_ptr;
17143 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_STATE_INFO_DUMP;
17144 struct wlan_hdd_link_info *link_info;
17145
17146 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17147 if (!hdd_ctx)
17148 return;
17149
17150 hdd_debug("size of buffer: %d", *size);
17151
17152 len += scnprintf(buf + len, *size - len, "\n is_wiphy_suspended %d",
17153 hdd_ctx->is_wiphy_suspended);
17154 len += scnprintf(buf + len, *size - len, "\n is_scheduler_suspended %d",
17155 hdd_ctx->is_scheduler_suspended);
17156
17157 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
17158 dbgid) {
17159 hdd_adapter_for_each_active_link_info(adapter, link_info) {
17160 len +=
17161 scnprintf(buf + len, *size - len, "\n device name: %s",
17162 adapter->dev->name);
17163 len +=
17164 scnprintf(buf + len, *size - len, "\n device_mode: %d",
17165 adapter->device_mode);
17166 switch (adapter->device_mode) {
17167 case QDF_STA_MODE:
17168 case QDF_P2P_CLIENT_MODE:
17169 sta_ctx =
17170 WLAN_HDD_GET_STATION_CTX_PTR(link_info);
17171 len += scnprintf(buf + len, *size - len,
17172 "\n conn_state: %d",
17173 sta_ctx->conn_info.conn_state);
17174 break;
17175 default:
17176 break;
17177 }
17178 }
17179 hdd_adapter_dev_put_debug(adapter, dbgid);
17180 }
17181
17182 *size -= len;
17183 *buf_ptr += len;
17184 }
17185
17186 /**
17187 * hdd_register_debug_callback() - registration function for hdd layer
17188 * to print hdd state information
17189 *
17190 * Return: None
17191 */
hdd_register_debug_callback(void)17192 static void hdd_register_debug_callback(void)
17193 {
17194 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
17195 }
17196 #else /* WLAN_FEATURE_MEMDUMP_ENABLE */
hdd_register_debug_callback(void)17197 static void hdd_register_debug_callback(void)
17198 {
17199 }
17200 #endif /* WLAN_FEATURE_MEMDUMP_ENABLE */
17201
17202 /*
17203 * wlan_init_bug_report_lock() - Initialize bug report lock
17204 *
17205 * This function is used to create bug report lock
17206 *
17207 * Return: None
17208 */
wlan_init_bug_report_lock(void)17209 static void wlan_init_bug_report_lock(void)
17210 {
17211 struct cds_context *p_cds_context;
17212
17213 p_cds_context = cds_get_global_context();
17214 if (!p_cds_context) {
17215 hdd_err("cds context is NULL");
17216 return;
17217 }
17218
17219 qdf_spinlock_create(&p_cds_context->bug_report_lock);
17220 }
17221
17222 #ifdef DISABLE_CHANNEL_LIST
wlan_hdd_cache_chann_mutex_create(struct hdd_context * hdd_ctx)17223 static QDF_STATUS wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx)
17224 {
17225 return qdf_mutex_create(&hdd_ctx->cache_channel_lock);
17226 }
17227 #else
wlan_hdd_cache_chann_mutex_create(struct hdd_context * hdd_ctx)17228 static QDF_STATUS wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx)
17229 {
17230 return QDF_STATUS_SUCCESS;
17231 }
17232 #endif
17233
hdd_open_adapter_no_trans(struct hdd_context * hdd_ctx,enum QDF_OPMODE op_mode,const char * iface_name,uint8_t * mac_addr_bytes,struct hdd_adapter_create_param * params)17234 QDF_STATUS hdd_open_adapter_no_trans(struct hdd_context *hdd_ctx,
17235 enum QDF_OPMODE op_mode,
17236 const char *iface_name,
17237 uint8_t *mac_addr_bytes,
17238 struct hdd_adapter_create_param *params)
17239 {
17240 struct osif_vdev_sync *vdev_sync;
17241 struct hdd_adapter *adapter;
17242 QDF_STATUS status;
17243 int errno;
17244
17245 QDF_BUG(rtnl_is_locked());
17246
17247 errno = osif_vdev_sync_create(hdd_ctx->parent_dev, &vdev_sync);
17248 if (errno)
17249 return qdf_status_from_os_return(errno);
17250
17251 adapter = hdd_open_adapter(hdd_ctx, op_mode, iface_name,
17252 mac_addr_bytes, NET_NAME_UNKNOWN, true,
17253 params);
17254 if (!adapter) {
17255 status = QDF_STATUS_E_INVAL;
17256 goto destroy_sync;
17257 }
17258
17259 osif_vdev_sync_register(adapter->dev, vdev_sync);
17260
17261 return QDF_STATUS_SUCCESS;
17262
17263 destroy_sync:
17264 osif_vdev_sync_destroy(vdev_sync);
17265
17266 return status;
17267 }
17268
17269 #ifdef WLAN_OPEN_P2P_INTERFACE
17270 /**
17271 * hdd_open_p2p_interface - Open P2P interface
17272 * @hdd_ctx: HDD context
17273 *
17274 * Return: QDF_STATUS
17275 */
hdd_open_p2p_interface(struct hdd_context * hdd_ctx)17276 static QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx)
17277 {
17278 QDF_STATUS status;
17279 bool p2p_dev_addr_admin;
17280 bool is_p2p_locally_administered = false;
17281 struct hdd_adapter_create_param params = {0};
17282
17283 cfg_p2p_get_device_addr_admin(hdd_ctx->psoc, &p2p_dev_addr_admin);
17284
17285 if (p2p_dev_addr_admin) {
17286 if (hdd_ctx->num_provisioned_addr &&
17287 !(hdd_ctx->provisioned_mac_addr[0].bytes[0] & 0x02)) {
17288 hdd_ctx->p2p_device_address =
17289 hdd_ctx->provisioned_mac_addr[0];
17290
17291 /*
17292 * Generate the P2P Device Address. This consists of
17293 * the device's primary MAC address with the locally
17294 * administered bit set.
17295 */
17296
17297 hdd_ctx->p2p_device_address.bytes[0] |= 0x02;
17298 is_p2p_locally_administered = true;
17299 } else if (!(hdd_ctx->derived_mac_addr[0].bytes[0] & 0x02)) {
17300 hdd_ctx->p2p_device_address =
17301 hdd_ctx->derived_mac_addr[0];
17302 /*
17303 * Generate the P2P Device Address. This consists of
17304 * the device's primary MAC address with the locally
17305 * administered bit set.
17306 */
17307 hdd_ctx->p2p_device_address.bytes[0] |= 0x02;
17308 is_p2p_locally_administered = true;
17309 }
17310 }
17311 if (!is_p2p_locally_administered) {
17312 uint8_t *p2p_dev_addr;
17313
17314 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx,
17315 QDF_P2P_DEVICE_MODE);
17316 if (!p2p_dev_addr) {
17317 hdd_err("Failed to get MAC address for new p2p device");
17318 return QDF_STATUS_E_INVAL;
17319 }
17320
17321 qdf_mem_copy(hdd_ctx->p2p_device_address.bytes,
17322 p2p_dev_addr, QDF_MAC_ADDR_SIZE);
17323 }
17324
17325 status = hdd_open_adapter_no_trans(hdd_ctx, QDF_P2P_DEVICE_MODE,
17326 "p2p%d",
17327 hdd_ctx->p2p_device_address.bytes,
17328 ¶ms);
17329 if (QDF_IS_STATUS_ERROR(status)) {
17330 if (!is_p2p_locally_administered)
17331 wlan_hdd_release_intf_addr(hdd_ctx,
17332 hdd_ctx->p2p_device_address.bytes);
17333 hdd_err("Failed to open p2p interface");
17334 return QDF_STATUS_E_INVAL;
17335 }
17336
17337 return QDF_STATUS_SUCCESS;
17338 }
17339 #else
hdd_open_p2p_interface(struct hdd_context * hdd_ctx)17340 static inline QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx)
17341 {
17342 return QDF_STATUS_SUCCESS;
17343 }
17344 #endif
17345
hdd_open_ocb_interface(struct hdd_context * hdd_ctx)17346 static QDF_STATUS hdd_open_ocb_interface(struct hdd_context *hdd_ctx)
17347 {
17348 QDF_STATUS status;
17349 uint8_t *mac_addr;
17350 struct hdd_adapter_create_param params = {0};
17351
17352 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_OCB_MODE);
17353 if (!mac_addr)
17354 return QDF_STATUS_E_INVAL;
17355
17356 status = hdd_open_adapter_no_trans(hdd_ctx, QDF_OCB_MODE,
17357 "wlanocb%d", mac_addr,
17358 ¶ms);
17359 if (QDF_IS_STATUS_ERROR(status)) {
17360 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
17361 hdd_err("Failed to open 802.11p interface");
17362 }
17363
17364 return status;
17365 }
17366
hdd_open_concurrent_interface(struct hdd_context * hdd_ctx)17367 static QDF_STATUS hdd_open_concurrent_interface(struct hdd_context *hdd_ctx)
17368 {
17369 QDF_STATUS status;
17370 const char *iface_name;
17371 uint8_t *mac_addr;
17372 struct hdd_adapter_create_param params = {0};
17373
17374 if (qdf_str_eq(hdd_ctx->config->enable_concurrent_sta, ""))
17375 return QDF_STATUS_SUCCESS;
17376
17377 iface_name = hdd_ctx->config->enable_concurrent_sta;
17378 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_STA_MODE);
17379 if (!mac_addr)
17380 return QDF_STATUS_E_INVAL;
17381
17382 status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE,
17383 iface_name, mac_addr,
17384 ¶ms);
17385 if (QDF_IS_STATUS_ERROR(status)) {
17386 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
17387 hdd_err("Failed to open concurrent station interface");
17388 }
17389
17390 return status;
17391 }
17392
17393 #ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
17394 static inline void
hdd_adapter_open_set_max_active_links(struct hdd_adapter_create_param * params)17395 hdd_adapter_open_set_max_active_links(struct hdd_adapter_create_param *params)
17396 {
17397 if (params->is_add_virtual_iface || !params->is_ml_adapter)
17398 params->num_sessions = 1;
17399 else
17400 params->num_sessions = 2;
17401 }
17402 #else
17403 static inline void
hdd_adapter_open_set_max_active_links(struct hdd_adapter_create_param * params)17404 hdd_adapter_open_set_max_active_links(struct hdd_adapter_create_param *params)
17405 {
17406 params->num_sessions = 1;
17407 }
17408 #endif
17409
17410 static QDF_STATUS
hdd_open_adapters_for_mission_mode(struct hdd_context * hdd_ctx)17411 hdd_open_adapters_for_mission_mode(struct hdd_context *hdd_ctx)
17412 {
17413 enum dot11p_mode dot11p_mode;
17414 QDF_STATUS status;
17415 uint8_t *mac_addr;
17416 struct hdd_adapter_create_param params = {0};
17417 bool eht_capab = 0;
17418
17419 ucfg_mlme_get_dot11p_mode(hdd_ctx->psoc, &dot11p_mode);
17420 ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
17421
17422 /* Create only 802.11p interface? */
17423 if (dot11p_mode == CFG_11P_STANDALONE)
17424 return hdd_open_ocb_interface(hdd_ctx);
17425
17426 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_STA_MODE);
17427 if (!mac_addr)
17428 return QDF_STATUS_E_INVAL;
17429
17430 if (eht_capab) {
17431 params.is_ml_adapter = true;
17432 hdd_adapter_open_set_max_active_links(¶ms);
17433 }
17434
17435 status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE,
17436 "wlan%d", mac_addr,
17437 ¶ms);
17438 if (QDF_IS_STATUS_ERROR(status)) {
17439 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
17440 return status;
17441 }
17442
17443 /* opening concurrent STA is best effort, continue on error */
17444 hdd_open_concurrent_interface(hdd_ctx);
17445
17446 status = hdd_open_p2p_interface(hdd_ctx);
17447 if (status)
17448 goto err_close_adapters;
17449
17450 /*
17451 * Create separate interface (wifi-aware0) for NAN. All NAN commands
17452 * should go on this new interface.
17453 */
17454 if (wlan_hdd_is_vdev_creation_allowed(hdd_ctx->psoc)) {
17455 qdf_mem_zero(¶ms, sizeof(params));
17456 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_NAN_DISC_MODE);
17457 if (!mac_addr)
17458 goto err_close_adapters;
17459
17460 status = hdd_open_adapter_no_trans(hdd_ctx, QDF_NAN_DISC_MODE,
17461 "wifi-aware%d", mac_addr,
17462 ¶ms);
17463 if (status) {
17464 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
17465 goto err_close_adapters;
17466 }
17467 }
17468 /* Open 802.11p Interface */
17469 if (dot11p_mode == CFG_11P_CONCURRENT) {
17470 status = hdd_open_ocb_interface(hdd_ctx);
17471 if (QDF_IS_STATUS_ERROR(status))
17472 goto err_close_adapters;
17473 }
17474
17475 if (eht_capab)
17476 hdd_wlan_register_mlo_interfaces(hdd_ctx);
17477
17478 return QDF_STATUS_SUCCESS;
17479
17480 err_close_adapters:
17481 hdd_close_all_adapters(hdd_ctx, true);
17482
17483 return status;
17484 }
17485
hdd_open_adapters_for_ftm_mode(struct hdd_context * hdd_ctx)17486 static QDF_STATUS hdd_open_adapters_for_ftm_mode(struct hdd_context *hdd_ctx)
17487 {
17488 QDF_STATUS status;
17489 uint8_t *mac_addr;
17490 struct hdd_adapter_create_param params = {0};
17491
17492 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_FTM_MODE);
17493 if (!mac_addr)
17494 return QDF_STATUS_E_INVAL;
17495
17496 status = hdd_open_adapter_no_trans(hdd_ctx, QDF_FTM_MODE,
17497 "wlan%d", mac_addr,
17498 ¶ms);
17499 if (QDF_IS_STATUS_ERROR(status)) {
17500 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
17501 return status;
17502 }
17503
17504 return QDF_STATUS_SUCCESS;
17505 }
17506
17507 static QDF_STATUS
hdd_open_adapters_for_monitor_mode(struct hdd_context * hdd_ctx)17508 hdd_open_adapters_for_monitor_mode(struct hdd_context *hdd_ctx)
17509 {
17510 QDF_STATUS status;
17511 uint8_t *mac_addr;
17512 struct hdd_adapter_create_param params = {0};
17513
17514 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_MONITOR_MODE);
17515 if (!mac_addr)
17516 return QDF_STATUS_E_INVAL;
17517
17518 status = hdd_open_adapter_no_trans(hdd_ctx, QDF_MONITOR_MODE,
17519 "wlan%d", mac_addr,
17520 ¶ms);
17521 if (QDF_IS_STATUS_ERROR(status)) {
17522 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
17523 return status;
17524 }
17525
17526 return QDF_STATUS_SUCCESS;
17527 }
17528
hdd_open_adapters_for_epping_mode(struct hdd_context * hdd_ctx)17529 static QDF_STATUS hdd_open_adapters_for_epping_mode(struct hdd_context *hdd_ctx)
17530 {
17531 epping_enable_adapter();
17532 return QDF_STATUS_SUCCESS;
17533 }
17534
17535 typedef QDF_STATUS (*hdd_open_mode_handler)(struct hdd_context *hdd_ctx);
17536
17537 static const hdd_open_mode_handler
17538 hdd_open_mode_handlers[QDF_GLOBAL_MAX_MODE] = {
17539 [QDF_GLOBAL_MISSION_MODE] = hdd_open_adapters_for_mission_mode,
17540 [QDF_GLOBAL_FTM_MODE] = hdd_open_adapters_for_ftm_mode,
17541 [QDF_GLOBAL_MONITOR_MODE] = hdd_open_adapters_for_monitor_mode,
17542 [QDF_GLOBAL_EPPING_MODE] = hdd_open_adapters_for_epping_mode,
17543 };
17544
hdd_open_adapters_for_mode(struct hdd_context * hdd_ctx,enum QDF_GLOBAL_MODE driver_mode)17545 static QDF_STATUS hdd_open_adapters_for_mode(struct hdd_context *hdd_ctx,
17546 enum QDF_GLOBAL_MODE driver_mode)
17547 {
17548 QDF_STATUS status;
17549
17550 if (driver_mode < 0 ||
17551 driver_mode >= QDF_GLOBAL_MAX_MODE ||
17552 !hdd_open_mode_handlers[driver_mode]) {
17553 hdd_err("Driver mode %d not supported", driver_mode);
17554 return -ENOTSUPP;
17555 }
17556
17557 hdd_hold_rtnl_lock();
17558 status = hdd_open_mode_handlers[driver_mode](hdd_ctx);
17559 hdd_release_rtnl_lock();
17560
17561 return status;
17562 }
17563
hdd_wlan_startup(struct hdd_context * hdd_ctx)17564 int hdd_wlan_startup(struct hdd_context *hdd_ctx)
17565 {
17566 QDF_STATUS status;
17567 int errno;
17568 bool is_imps_enabled;
17569
17570 hdd_enter();
17571
17572 qdf_nbuf_init_replenish_timer();
17573
17574 status = wlan_hdd_cache_chann_mutex_create(hdd_ctx);
17575 if (QDF_IS_STATUS_ERROR(status))
17576 return qdf_status_to_os_return(status);
17577
17578 #ifdef FEATURE_WLAN_CH_AVOID
17579 mutex_init(&hdd_ctx->avoid_freq_lock);
17580 #endif
17581
17582 osif_request_manager_init();
17583 hdd_driver_memdump_init();
17584
17585 errno = hdd_init_regulatory_update_event(hdd_ctx);
17586 if (errno) {
17587 hdd_err("Failed to initialize regulatory update event; errno:%d",
17588 errno);
17589 goto memdump_deinit;
17590 }
17591
17592 errno = hdd_wlan_start_modules(hdd_ctx, false);
17593 if (errno) {
17594 hdd_err("Failed to start modules; errno:%d", errno);
17595 goto memdump_deinit;
17596 }
17597
17598 if (hdd_get_conparam() == QDF_GLOBAL_EPPING_MODE)
17599 return 0;
17600
17601 wlan_hdd_update_wiphy(hdd_ctx);
17602
17603 hdd_ctx->mac_handle = cds_get_context(QDF_MODULE_ID_SME);
17604 if (!hdd_ctx->mac_handle)
17605 goto stop_modules;
17606
17607 errno = hdd_wiphy_init(hdd_ctx);
17608 if (errno) {
17609 hdd_err("Failed to initialize wiphy; errno:%d", errno);
17610 goto stop_modules;
17611 }
17612
17613 errno = hdd_initialize_mac_address(hdd_ctx);
17614 if (errno) {
17615 hdd_err("MAC initializtion failed: %d", errno);
17616 goto unregister_wiphy;
17617 }
17618
17619 errno = register_netdevice_notifier(&hdd_netdev_notifier);
17620 if (errno) {
17621 hdd_err("register_netdevice_notifier failed; errno:%d", errno);
17622 goto unregister_wiphy;
17623 }
17624
17625 wlan_hdd_update_11n_mode(hdd_ctx);
17626
17627 hdd_lpass_notify_wlan_version(hdd_ctx);
17628
17629 status = wlansap_global_init();
17630 if (QDF_IS_STATUS_ERROR(status))
17631 goto unregister_notifiers;
17632
17633 ucfg_mlme_is_imps_enabled(hdd_ctx->psoc, &is_imps_enabled);
17634 hdd_set_idle_ps_config(hdd_ctx, is_imps_enabled);
17635 hdd_debugfs_mws_coex_info_init(hdd_ctx);
17636 hdd_debugfs_ini_config_init(hdd_ctx);
17637 wlan_hdd_debugfs_unit_test_host_create(hdd_ctx);
17638 wlan_hdd_create_mib_stats_lock();
17639 wlan_cfg80211_init_interop_issues_ap(hdd_ctx->pdev);
17640
17641 hdd_exit();
17642
17643 return 0;
17644
17645 unregister_notifiers:
17646 unregister_netdevice_notifier(&hdd_netdev_notifier);
17647
17648 unregister_wiphy:
17649 qdf_dp_trace_deinit();
17650 wiphy_unregister(hdd_ctx->wiphy);
17651
17652 stop_modules:
17653 hdd_wlan_stop_modules(hdd_ctx, false);
17654
17655 memdump_deinit:
17656 hdd_driver_memdump_deinit();
17657 osif_request_manager_deinit();
17658 qdf_nbuf_deinit_replenish_timer();
17659
17660 if (cds_is_fw_down())
17661 hdd_err("Not setting the complete event as fw is down");
17662 else
17663 hdd_start_complete(errno);
17664
17665 hdd_exit();
17666
17667 return errno;
17668 }
17669
hdd_psoc_create_vdevs(struct hdd_context * hdd_ctx)17670 QDF_STATUS hdd_psoc_create_vdevs(struct hdd_context *hdd_ctx)
17671 {
17672 enum QDF_GLOBAL_MODE driver_mode = hdd_get_conparam();
17673 QDF_STATUS status;
17674
17675 status = hdd_open_adapters_for_mode(hdd_ctx, driver_mode);
17676 if (QDF_IS_STATUS_ERROR(status)) {
17677 hdd_err("Failed to create vdevs; status:%d", status);
17678 return status;
17679 }
17680
17681 ucfg_dp_try_set_rps_cpu_mask(hdd_ctx->psoc);
17682
17683 if (driver_mode != QDF_GLOBAL_FTM_MODE &&
17684 driver_mode != QDF_GLOBAL_EPPING_MODE)
17685 hdd_psoc_idle_timer_start(hdd_ctx);
17686
17687 return QDF_STATUS_SUCCESS;
17688 }
17689
17690 /**
17691 * hdd_wlan_update_target_info() - update target type info
17692 * @hdd_ctx: HDD context
17693 * @context: hif context
17694 *
17695 * Update target info received from firmware in hdd context
17696 * Return:None
17697 */
17698
hdd_wlan_update_target_info(struct hdd_context * hdd_ctx,void * context)17699 void hdd_wlan_update_target_info(struct hdd_context *hdd_ctx, void *context)
17700 {
17701 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
17702
17703 if (!tgt_info) {
17704 hdd_err("Target info is Null");
17705 return;
17706 }
17707
17708 hdd_ctx->target_type = tgt_info->target_type;
17709 }
17710
17711 #ifdef WLAN_FEATURE_MOTION_DETECTION
17712 /**
17713 * hdd_md_host_evt_cb - Callback for Motion Detection Event
17714 * @ctx: HDD context
17715 * @event: motion detect event
17716 *
17717 * Callback for Motion Detection Event. Re-enables Motion
17718 * Detection again upon event
17719 *
17720 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and
17721 * QDF_STATUS_E_FAILURE on failure
17722 */
hdd_md_host_evt_cb(void * ctx,struct sir_md_evt * event)17723 QDF_STATUS hdd_md_host_evt_cb(void *ctx, struct sir_md_evt *event)
17724 {
17725 struct hdd_adapter *adapter;
17726 struct hdd_context *hdd_ctx;
17727 struct sme_motion_det_en motion_det;
17728 struct wlan_hdd_link_info *link_info;
17729
17730 if (!ctx || !event)
17731 return QDF_STATUS_E_INVAL;
17732
17733 hdd_ctx = (struct hdd_context *)ctx;
17734 if (wlan_hdd_validate_context(hdd_ctx))
17735 return QDF_STATUS_E_INVAL;
17736
17737 link_info = hdd_get_link_info_by_vdev(hdd_ctx, event->vdev_id);
17738 if (!link_info ||
17739 WLAN_HDD_ADAPTER_MAGIC != link_info->adapter->magic) {
17740 hdd_err("Invalid adapter or adapter has invalid magic");
17741 return QDF_STATUS_E_INVAL;
17742 }
17743
17744 adapter = link_info->adapter;
17745 /* When motion is detected, reset the motion_det_in_progress flag */
17746 if (event->status)
17747 adapter->motion_det_in_progress = false;
17748
17749 hdd_debug("Motion Detection CB vdev_id=%u, status=%u",
17750 event->vdev_id, event->status);
17751
17752 if (adapter->motion_detection_mode) {
17753 motion_det.vdev_id = event->vdev_id;
17754 motion_det.enable = 1;
17755 hdd_debug("Motion Detect CB -> Enable Motion Detection again");
17756 sme_motion_det_enable(hdd_ctx->mac_handle, &motion_det);
17757 }
17758
17759 return QDF_STATUS_SUCCESS;
17760 }
17761
17762 /**
17763 * hdd_md_bl_evt_cb - Callback for Motion Detection Baseline Event
17764 * @ctx: HDD context
17765 * @event: motion detect baseline event
17766 *
17767 * Callback for Motion Detection Baseline completion
17768 *
17769 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and
17770 * QDF_STATUS_E_FAILURE on failure
17771 */
hdd_md_bl_evt_cb(void * ctx,struct sir_md_bl_evt * event)17772 QDF_STATUS hdd_md_bl_evt_cb(void *ctx, struct sir_md_bl_evt *event)
17773 {
17774 struct hdd_context *hdd_ctx;
17775 struct wlan_hdd_link_info *link_info;
17776
17777 if (!ctx || !event)
17778 return QDF_STATUS_E_INVAL;
17779
17780 hdd_ctx = (struct hdd_context *)ctx;
17781 if (wlan_hdd_validate_context(hdd_ctx))
17782 return QDF_STATUS_E_INVAL;
17783
17784 link_info = hdd_get_link_info_by_vdev(hdd_ctx, event->vdev_id);
17785 if (!link_info ||
17786 WLAN_HDD_ADAPTER_MAGIC != link_info->adapter->magic) {
17787 hdd_err("Invalid adapter or adapter has invalid magic");
17788 return QDF_STATUS_E_INVAL;
17789 }
17790
17791 hdd_debug("Motion Detection Baseline CB vdev id=%u, baseline val = %d",
17792 event->vdev_id, event->bl_baseline_value);
17793
17794 link_info->adapter->motion_det_baseline_value =
17795 event->bl_baseline_value;
17796
17797 return QDF_STATUS_SUCCESS;
17798 }
17799 #endif /* WLAN_FEATURE_MOTION_DETECTION */
17800
hdd_ssr_on_pagefault_cb(struct hdd_context * hdd_ctx)17801 static QDF_STATUS hdd_ssr_on_pagefault_cb(struct hdd_context *hdd_ctx)
17802 {
17803 uint32_t ssr_frequency_on_pagefault;
17804 qdf_time_t curr_time, ssr_threshold;
17805
17806 hdd_enter();
17807
17808 if (!hdd_ctx)
17809 return QDF_STATUS_E_NULL_VALUE;
17810
17811 ssr_frequency_on_pagefault =
17812 ucfg_pmo_get_ssr_frequency_on_pagefault(hdd_ctx->psoc);
17813
17814 curr_time = qdf_get_system_uptime();
17815 ssr_threshold = qdf_system_msecs_to_ticks(ssr_frequency_on_pagefault);
17816
17817 if (!hdd_ctx->last_pagefault_ssr_time ||
17818 (curr_time - hdd_ctx->last_pagefault_ssr_time) >= ssr_threshold) {
17819 hdd_info("curr_time %lu last_pagefault_ssr_time %lu ssr_frequency %lu",
17820 curr_time, hdd_ctx->last_pagefault_ssr_time,
17821 ssr_threshold);
17822 hdd_ctx->last_pagefault_ssr_time = curr_time;
17823 cds_trigger_recovery(QDF_HOST_WAKEUP_REASON_PAGEFAULT);
17824
17825 return QDF_STATUS_SUCCESS;
17826 }
17827
17828 return QDF_STATUS_E_AGAIN;
17829 }
17830
17831 #define FW_PAGE_FAULT_IDX QCA_NL80211_VENDOR_SUBCMD_FW_PAGE_FAULT_REPORT_INDEX
hdd_send_pagefault_report_to_user(struct hdd_context * hdd_ctx,void * buf,uint32_t buf_len)17832 static QDF_STATUS hdd_send_pagefault_report_to_user(struct hdd_context *hdd_ctx,
17833 void *buf, uint32_t buf_len)
17834 {
17835 struct sk_buff *event_buf;
17836 int flags = cds_get_gfp_flags();
17837 uint8_t *ev_data = buf;
17838 uint16_t event_len = NLMSG_HDRLEN + buf_len;
17839
17840 event_buf = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
17841 event_len,
17842 FW_PAGE_FAULT_IDX, flags);
17843 if (!event_buf) {
17844 hdd_err("wlan_cfg80211_vendor_event_alloc failed");
17845 return QDF_STATUS_E_NOMEM;
17846 }
17847
17848 if (nla_put(event_buf, QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_DATA,
17849 buf_len, ev_data)) {
17850 hdd_debug("Failed to fill pagefault blob data");
17851 wlan_cfg80211_vendor_free_skb(event_buf);
17852 return QDF_STATUS_E_FAILURE;
17853 }
17854
17855 wlan_cfg80211_vendor_event(event_buf, flags);
17856 return QDF_STATUS_SUCCESS;
17857 }
17858
hdd_pagefault_action_cb(void * buf,uint32_t buf_len)17859 static QDF_STATUS hdd_pagefault_action_cb(void *buf, uint32_t buf_len)
17860 {
17861 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17862
17863 if (!hdd_ctx)
17864 return QDF_STATUS_E_NULL_VALUE;
17865
17866 if (wlan_pmo_enable_ssr_on_page_fault(hdd_ctx->psoc))
17867 return hdd_ssr_on_pagefault_cb(hdd_ctx);
17868
17869 return hdd_send_pagefault_report_to_user(hdd_ctx, buf, buf_len);
17870 }
17871
17872 /**
17873 * hdd_register_cb - Register HDD callbacks.
17874 * @hdd_ctx: HDD context
17875 *
17876 * Register the HDD callbacks to CDS/SME.
17877 *
17878 * Return: 0 for success or Error code for failure
17879 */
hdd_register_cb(struct hdd_context * hdd_ctx)17880 int hdd_register_cb(struct hdd_context *hdd_ctx)
17881 {
17882 QDF_STATUS status;
17883 int ret = 0;
17884 mac_handle_t mac_handle;
17885
17886 hdd_enter();
17887 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17888 hdd_err("in ftm mode, no need to register callbacks");
17889 return ret;
17890 }
17891
17892 mac_handle = hdd_ctx->mac_handle;
17893
17894 sme_register_oem_data_rsp_callback(mac_handle,
17895 hdd_send_oem_data_rsp_msg);
17896
17897 sme_register_mgmt_frame_ind_callback(mac_handle,
17898 hdd_indicate_mgmt_frame);
17899 sme_set_tsfcb(mac_handle, hdd_get_tsf_cb, hdd_ctx);
17900 sme_stats_ext_register_callback(mac_handle,
17901 wlan_hdd_cfg80211_stats_ext_callback);
17902
17903 sme_ext_scan_register_callback(mac_handle,
17904 wlan_hdd_cfg80211_extscan_callback);
17905 sme_stats_ext2_register_callback(mac_handle,
17906 wlan_hdd_cfg80211_stats_ext2_callback);
17907
17908 sme_multi_client_ll_rsp_register_callback(mac_handle,
17909 hdd_latency_level_event_handler_cb);
17910
17911 sme_set_rssi_threshold_breached_cb(mac_handle,
17912 hdd_rssi_threshold_breached);
17913
17914 sme_set_link_layer_stats_ind_cb(mac_handle,
17915 wlan_hdd_cfg80211_link_layer_stats_callback);
17916
17917 sme_rso_cmd_status_cb(mac_handle, wlan_hdd_rso_cmd_status_cb);
17918
17919 sme_set_link_layer_ext_cb(mac_handle,
17920 wlan_hdd_cfg80211_link_layer_stats_ext_callback);
17921 sme_update_hidden_ssid_status_cb(mac_handle,
17922 hdd_hidden_ssid_enable_roaming);
17923
17924 status = sme_set_lost_link_info_cb(mac_handle,
17925 hdd_lost_link_info_cb);
17926
17927 wlan_hdd_register_cp_stats_cb(hdd_ctx);
17928 hdd_dcs_register_cb(hdd_ctx);
17929
17930 hdd_thermal_register_callbacks(hdd_ctx);
17931 /* print error and not block the startup process */
17932 if (!QDF_IS_STATUS_SUCCESS(status))
17933 hdd_err("set lost link info callback failed");
17934
17935 ret = hdd_register_data_stall_detect_cb();
17936 if (ret) {
17937 hdd_err("Register data stall detect detect callback failed.");
17938 return ret;
17939 }
17940
17941 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
17942
17943 sme_register_set_connection_info_cb(mac_handle,
17944 hdd_set_connection_in_progress,
17945 hdd_is_connection_in_progress);
17946
17947 status = sme_set_bt_activity_info_cb(mac_handle,
17948 hdd_bt_activity_cb);
17949 if (!QDF_IS_STATUS_SUCCESS(status))
17950 hdd_err("set bt activity info callback failed");
17951
17952 status = sme_register_tx_queue_cb(mac_handle,
17953 hdd_tx_queue_cb);
17954 if (!QDF_IS_STATUS_SUCCESS(status))
17955 hdd_err("Register tx queue callback failed");
17956
17957 #ifdef WLAN_FEATURE_MOTION_DETECTION
17958 sme_set_md_host_evt_cb(mac_handle, hdd_md_host_evt_cb, (void *)hdd_ctx);
17959 sme_set_md_bl_evt_cb(mac_handle, hdd_md_bl_evt_cb, (void *)hdd_ctx);
17960 #endif /* WLAN_FEATURE_MOTION_DETECTION */
17961
17962 mac_register_session_open_close_cb(hdd_ctx->mac_handle,
17963 hdd_sme_close_session_callback,
17964 hdd_common_roam_callback);
17965
17966 sme_set_roam_scan_ch_event_cb(mac_handle, hdd_get_roam_scan_ch_cb);
17967 status = sme_set_monitor_mode_cb(mac_handle,
17968 hdd_sme_monitor_mode_callback);
17969 if (QDF_IS_STATUS_ERROR(status))
17970 hdd_err_rl("Register monitor mode callback failed");
17971
17972 status = sme_set_beacon_latency_event_cb(mac_handle,
17973 hdd_beacon_latency_event_cb);
17974 if (QDF_IS_STATUS_ERROR(status))
17975 hdd_err_rl("Register beacon latency event callback failed");
17976
17977 sme_async_oem_event_init(mac_handle,
17978 hdd_oem_event_async_cb);
17979
17980 sme_register_pagefault_cb(mac_handle, hdd_pagefault_action_cb);
17981
17982 hdd_exit();
17983
17984 return ret;
17985 }
17986
17987 /**
17988 * hdd_deregister_cb() - De-Register HDD callbacks.
17989 * @hdd_ctx: HDD context
17990 *
17991 * De-Register the HDD callbacks to CDS/SME.
17992 *
17993 * Return: void
17994 */
hdd_deregister_cb(struct hdd_context * hdd_ctx)17995 void hdd_deregister_cb(struct hdd_context *hdd_ctx)
17996 {
17997 QDF_STATUS status;
17998 int ret;
17999 mac_handle_t mac_handle;
18000
18001 hdd_enter();
18002 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18003 hdd_err("in ftm mode, no need to deregister callbacks");
18004 return;
18005 }
18006
18007 mac_handle = hdd_ctx->mac_handle;
18008
18009 sme_deregister_ssr_on_pagefault_cb(mac_handle);
18010
18011 sme_async_oem_event_deinit(mac_handle);
18012
18013 sme_deregister_tx_queue_cb(mac_handle);
18014
18015 sme_reset_link_layer_stats_ind_cb(mac_handle);
18016 sme_reset_rssi_threshold_breached_cb(mac_handle);
18017
18018 sme_stats_ext_deregister_callback(mac_handle);
18019
18020 status = sme_reset_tsfcb(mac_handle);
18021 if (!QDF_IS_STATUS_SUCCESS(status))
18022 hdd_err("Failed to de-register tsfcb the callback:%d",
18023 status);
18024
18025 ret = hdd_deregister_data_stall_detect_cb();
18026 if (ret)
18027 hdd_err("Failed to de-register data stall detect event callback");
18028 hdd_thermal_unregister_callbacks(hdd_ctx);
18029 sme_deregister_oem_data_rsp_callback(mac_handle);
18030 sme_multi_client_ll_rsp_deregister_callback(mac_handle);
18031
18032 hdd_exit();
18033 }
18034
18035 /**
18036 * hdd_softap_sta_deauth() - handle deauth req from HDD
18037 * @adapter: Pointer to the HDD adapter
18038 * @param: Params to the operation
18039 *
18040 * This to take counter measure to handle deauth req from HDD
18041 *
18042 * Return: None
18043 */
hdd_softap_sta_deauth(struct hdd_adapter * adapter,struct csr_del_sta_params * param)18044 QDF_STATUS hdd_softap_sta_deauth(struct hdd_adapter *adapter,
18045 struct csr_del_sta_params *param)
18046 {
18047 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
18048 struct hdd_context *hdd_ctx;
18049 bool is_sap_bcast_deauth_enabled = false;
18050
18051 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18052 if (!hdd_ctx) {
18053 hdd_err("hdd_ctx is NULL");
18054 return QDF_STATUS_E_INVAL;
18055 }
18056
18057 ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc,
18058 &is_sap_bcast_deauth_enabled);
18059
18060 hdd_enter();
18061
18062 hdd_debug("sap_bcast_deauth_enabled %d", is_sap_bcast_deauth_enabled);
18063 /* Ignore request to deauth bcmc station */
18064 if (!is_sap_bcast_deauth_enabled)
18065 if (param->peerMacAddr.bytes[0] & 0x1)
18066 return qdf_status;
18067
18068 qdf_status =
18069 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
18070 param);
18071
18072 hdd_exit();
18073 return qdf_status;
18074 }
18075
18076 /**
18077 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
18078 * @adapter: Pointer to the HDD
18079 * @param: pointer to station deletion parameters
18080 *
18081 * This to take counter measure to handle deauth req from HDD
18082 *
18083 * Return: None
18084 */
hdd_softap_sta_disassoc(struct hdd_adapter * adapter,struct csr_del_sta_params * param)18085 void hdd_softap_sta_disassoc(struct hdd_adapter *adapter,
18086 struct csr_del_sta_params *param)
18087 {
18088 hdd_enter();
18089
18090 /* Ignore request to disassoc bcmc station */
18091 if (param->peerMacAddr.bytes[0] & 0x1)
18092 return;
18093
18094 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
18095 param);
18096 }
18097
18098 void
wlan_hdd_set_roaming_state(struct wlan_hdd_link_info * cur_link_info,enum wlan_cm_rso_control_requestor rso_op_requestor,bool enab_roam)18099 wlan_hdd_set_roaming_state(struct wlan_hdd_link_info *cur_link_info,
18100 enum wlan_cm_rso_control_requestor rso_op_requestor,
18101 bool enab_roam)
18102 {
18103 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(cur_link_info->adapter);
18104 struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
18105 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_DISABLE_ROAMING;
18106 uint8_t vdev_id, cur_vdev_id = cur_link_info->vdev_id;
18107 struct wlan_hdd_link_info *link_info;
18108
18109 if (!policy_mgr_is_sta_active_connection_exists(hdd_ctx->psoc))
18110 return;
18111
18112 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
18113 dbgid) {
18114 hdd_adapter_for_each_active_link_info(adapter, link_info) {
18115 vdev_id = link_info->vdev_id;
18116 if (cur_vdev_id != link_info->vdev_id &&
18117 adapter->device_mode == QDF_STA_MODE &&
18118 hdd_cm_is_vdev_associated(link_info)) {
18119 if (enab_roam) {
18120 hdd_debug("%d Enable roaming", vdev_id);
18121 sme_start_roaming(hdd_ctx->mac_handle,
18122 vdev_id,
18123 REASON_DRIVER_ENABLED,
18124 rso_op_requestor);
18125 } else {
18126 hdd_debug("%d Disable roaming",
18127 vdev_id);
18128 sme_stop_roaming(hdd_ctx->mac_handle,
18129 vdev_id,
18130 REASON_DRIVER_DISABLED,
18131 rso_op_requestor);
18132 }
18133 }
18134 }
18135 hdd_adapter_dev_put_debug(adapter, dbgid);
18136 }
18137 }
18138
18139 /**
18140 * nl_srv_bcast_svc() - Wrapper function to send bcast msgs to SVC mcast group
18141 * @skb: sk buffer pointer
18142 *
18143 * Sends the bcast message to SVC multicast group with generic nl socket
18144 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
18145 *
18146 * Return: None
18147 */
nl_srv_bcast_svc(struct sk_buff * skb)18148 static void nl_srv_bcast_svc(struct sk_buff *skb)
18149 {
18150 #ifdef CNSS_GENL
18151 nl_srv_bcast(skb, CLD80211_MCGRP_SVC_MSGS, WLAN_NL_MSG_SVC);
18152 #else
18153 nl_srv_bcast(skb);
18154 #endif
18155 }
18156
wlan_hdd_send_svc_nlink_msg(int radio,int type,void * data,int len)18157 void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
18158 {
18159 struct sk_buff *skb;
18160 struct nlmsghdr *nlh;
18161 tAniMsgHdr *ani_hdr;
18162 void *nl_data = NULL;
18163 int flags = GFP_KERNEL;
18164 struct radio_index_tlv *radio_info;
18165 int tlv_len;
18166
18167 if (in_interrupt() || irqs_disabled() || in_atomic())
18168 flags = GFP_ATOMIC;
18169
18170 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
18171
18172 if (!skb)
18173 return;
18174
18175 nlh = (struct nlmsghdr *)skb->data;
18176 nlh->nlmsg_pid = 0; /* from kernel */
18177 nlh->nlmsg_flags = 0;
18178 nlh->nlmsg_seq = 0;
18179 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
18180
18181 ani_hdr = NLMSG_DATA(nlh);
18182 ani_hdr->type = type;
18183
18184 switch (type) {
18185 case WLAN_SVC_FW_CRASHED_IND:
18186 case WLAN_SVC_FW_SHUTDOWN_IND:
18187 case WLAN_SVC_LTE_COEX_IND:
18188 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
18189 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
18190 ani_hdr->length = 0;
18191 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
18192 break;
18193 case WLAN_SVC_WLAN_STATUS_IND:
18194 case WLAN_SVC_WLAN_VERSION_IND:
18195 case WLAN_SVC_DFS_CAC_START_IND:
18196 case WLAN_SVC_DFS_CAC_END_IND:
18197 case WLAN_SVC_DFS_RADAR_DETECT_IND:
18198 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
18199 case WLAN_SVC_WLAN_TP_IND:
18200 case WLAN_SVC_WLAN_TP_TX_IND:
18201 case WLAN_SVC_RPS_ENABLE_IND:
18202 case WLAN_SVC_CORE_MINFREQ:
18203 ani_hdr->length = len;
18204 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
18205 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
18206 memcpy(nl_data, data, len);
18207 break;
18208
18209 default:
18210 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
18211 type);
18212 kfree_skb(skb);
18213 return;
18214 }
18215
18216 /*
18217 * Add radio index at the end of the svc event in TLV format
18218 * to maintain the backward compatibility with userspace
18219 * applications.
18220 */
18221
18222 tlv_len = 0;
18223
18224 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
18225 < WLAN_NL_MAX_PAYLOAD) {
18226 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
18227 sizeof(*ani_hdr) + len);
18228 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
18229 radio_info->length = (unsigned short) sizeof(radio_info->radio);
18230 radio_info->radio = radio;
18231 tlv_len = sizeof(*radio_info);
18232 hdd_debug("Added radio index tlv - radio index %d",
18233 radio_info->radio);
18234 }
18235
18236 nlh->nlmsg_len += tlv_len;
18237 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
18238
18239 nl_srv_bcast_svc(skb);
18240 }
18241
18242 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
wlan_hdd_auto_shutdown_cb(void)18243 void wlan_hdd_auto_shutdown_cb(void)
18244 {
18245 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
18246
18247 if (!hdd_ctx)
18248 return;
18249
18250 hdd_debug("Wlan Idle. Sending Shutdown event..");
18251 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
18252 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
18253 }
18254
wlan_hdd_auto_shutdown_enable(struct hdd_context * hdd_ctx,bool enable)18255 void wlan_hdd_auto_shutdown_enable(struct hdd_context *hdd_ctx, bool enable)
18256 {
18257 struct hdd_adapter *adapter, *next_adapter = NULL;
18258 bool ap_connected = false, sta_connected = false;
18259 mac_handle_t mac_handle;
18260 struct wlan_hdd_link_info *link_info;
18261 struct hdd_ap_ctx *ap_ctx;
18262 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_AUTO_SHUTDOWN_ENABLE;
18263
18264 mac_handle = hdd_ctx->mac_handle;
18265 if (!mac_handle)
18266 return;
18267
18268 if (hdd_ctx->config->wlan_auto_shutdown == 0)
18269 return;
18270
18271 if (enable == false) {
18272 if (sme_set_auto_shutdown_timer(mac_handle, 0) !=
18273 QDF_STATUS_SUCCESS) {
18274 hdd_err("Failed to stop wlan auto shutdown timer");
18275 }
18276 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
18277 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
18278 return;
18279 }
18280
18281 /* To enable shutdown timer check conncurrency */
18282 if (!policy_mgr_concurrent_open_sessions_running(hdd_ctx->psoc))
18283 goto start_timer;
18284
18285 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter,
18286 next_adapter, dbgid) {
18287 hdd_adapter_for_each_active_link_info(adapter, link_info) {
18288 if (adapter->device_mode == QDF_STA_MODE &&
18289 hdd_cm_is_vdev_associated(link_info)) {
18290 sta_connected = true;
18291 hdd_adapter_dev_put_debug(adapter, dbgid);
18292 if (next_adapter)
18293 hdd_adapter_dev_put_debug(next_adapter,
18294 dbgid);
18295 break;
18296 }
18297
18298 if (adapter->device_mode == QDF_SAP_MODE) {
18299 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
18300 if (ap_ctx->ap_active == true) {
18301 ap_connected = true;
18302 hdd_adapter_dev_put_debug(adapter,
18303 dbgid);
18304 if (next_adapter)
18305 hdd_adapter_dev_put_debug(
18306 next_adapter,
18307 dbgid);
18308 break;
18309 }
18310 }
18311 }
18312 hdd_adapter_dev_put_debug(adapter, dbgid);
18313 }
18314
18315 start_timer:
18316 if (ap_connected == true || sta_connected == true) {
18317 hdd_debug("CC Session active. Shutdown timer not enabled");
18318 return;
18319 }
18320
18321 if (sme_set_auto_shutdown_timer(mac_handle,
18322 hdd_ctx->config->wlan_auto_shutdown)
18323 != QDF_STATUS_SUCCESS)
18324 hdd_err("Failed to start wlan auto shutdown timer");
18325 else
18326 hdd_info("Auto Shutdown timer for %d seconds enabled",
18327 hdd_ctx->config->wlan_auto_shutdown);
18328 }
18329 #endif
18330
18331 struct hdd_adapter *
hdd_get_con_sap_adapter(struct hdd_adapter * this_sap_adapter,bool check_start_bss)18332 hdd_get_con_sap_adapter(struct hdd_adapter *this_sap_adapter,
18333 bool check_start_bss)
18334 {
18335 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
18336 struct hdd_adapter *adapter, *next_adapter = NULL;
18337 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_CON_SAP_ADAPTER;
18338 struct wlan_hdd_link_info *link_info;
18339
18340 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
18341 dbgid) {
18342 if ((adapter->device_mode == QDF_SAP_MODE ||
18343 adapter->device_mode == QDF_P2P_GO_MODE) &&
18344 adapter != this_sap_adapter) {
18345 hdd_adapter_for_each_active_link_info(adapter,
18346 link_info) {
18347 if (!check_start_bss) {
18348 hdd_adapter_dev_put_debug(adapter,
18349 dbgid);
18350 if (next_adapter)
18351 hdd_adapter_dev_put_debug(
18352 next_adapter,
18353 dbgid);
18354 return adapter;
18355 }
18356 if (test_bit(SOFTAP_BSS_STARTED,
18357 &link_info->link_flags)) {
18358 hdd_adapter_dev_put_debug(adapter,
18359 dbgid);
18360 if (next_adapter)
18361 hdd_adapter_dev_put_debug(
18362 next_adapter,
18363 dbgid);
18364 return adapter;
18365 }
18366 }
18367 }
18368 hdd_adapter_dev_put_debug(adapter, dbgid);
18369 }
18370
18371 return NULL;
18372 }
18373
hdd_adapter_is_sta(struct hdd_adapter * adapter)18374 static inline bool hdd_adapter_is_sta(struct hdd_adapter *adapter)
18375 {
18376 return adapter->device_mode == QDF_STA_MODE ||
18377 adapter->device_mode == QDF_P2P_CLIENT_MODE;
18378 }
18379
hdd_is_any_adapter_connected(struct hdd_context * hdd_ctx)18380 bool hdd_is_any_adapter_connected(struct hdd_context *hdd_ctx)
18381 {
18382 struct hdd_adapter *adapter, *next_adapter = NULL;
18383 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_IS_ANY_ADAPTER_CONNECTED;
18384 struct wlan_hdd_link_info *link_info;
18385
18386 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
18387 dbgid) {
18388 hdd_adapter_for_each_active_link_info(adapter, link_info) {
18389 if (hdd_adapter_is_sta(adapter) &&
18390 hdd_cm_is_vdev_associated(link_info)) {
18391 hdd_adapter_dev_put_debug(adapter, dbgid);
18392 if (next_adapter)
18393 hdd_adapter_dev_put_debug(next_adapter,
18394 dbgid);
18395 return true;
18396 }
18397
18398 if (hdd_adapter_is_ap(adapter) &&
18399 WLAN_HDD_GET_AP_CTX_PTR(link_info)->ap_active) {
18400 hdd_adapter_dev_put_debug(adapter, dbgid);
18401 if (next_adapter)
18402 hdd_adapter_dev_put_debug(next_adapter,
18403 dbgid);
18404 return true;
18405 }
18406
18407 if (adapter->device_mode == QDF_NDI_MODE &&
18408 hdd_cm_is_vdev_associated(link_info)) {
18409 hdd_adapter_dev_put_debug(adapter, dbgid);
18410 if (next_adapter)
18411 hdd_adapter_dev_put_debug(next_adapter,
18412 dbgid);
18413 return true;
18414 }
18415 }
18416 hdd_adapter_dev_put_debug(adapter, dbgid);
18417 }
18418
18419 return false;
18420 }
18421
18422 #if defined MSM_PLATFORM && (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0))
18423 /**
18424 * hdd_inform_stop_sap() - call cfg80211 API to stop SAP
18425 * @adapter: pointer to adapter
18426 *
18427 * This function calls cfg80211 API to stop SAP
18428 *
18429 * Return: None
18430 */
hdd_inform_stop_sap(struct hdd_adapter * adapter)18431 static void hdd_inform_stop_sap(struct hdd_adapter *adapter)
18432 {
18433 hdd_debug("SAP stopped due to invalid channel vdev id %d",
18434 wlan_vdev_get_id(adapter->deflink->vdev));
18435 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
18436 }
18437
18438 #else
hdd_inform_stop_sap(struct hdd_adapter * adapter)18439 static void hdd_inform_stop_sap(struct hdd_adapter *adapter)
18440 {
18441 hdd_debug("SAP stopped due to invalid channel vdev id %d",
18442 wlan_vdev_get_id(adapter->deflink->vdev));
18443 cfg80211_stop_iface(adapter->hdd_ctx->wiphy, &adapter->wdev,
18444 GFP_KERNEL);
18445 }
18446 #endif
18447
18448 /**
18449 * wlan_hdd_stop_sap() - This function stops bss of SAP.
18450 * @ap_adapter: SAP adapter
18451 *
18452 * This function will process the stopping of sap adapter.
18453 *
18454 * Return: None
18455 */
wlan_hdd_stop_sap(struct hdd_adapter * ap_adapter)18456 void wlan_hdd_stop_sap(struct hdd_adapter *ap_adapter)
18457 {
18458 struct hdd_ap_ctx *hdd_ap_ctx;
18459 struct hdd_hostapd_state *hostapd_state;
18460 QDF_STATUS qdf_status;
18461 struct hdd_context *hdd_ctx;
18462
18463 if (!ap_adapter) {
18464 hdd_err("ap_adapter is NULL here");
18465 return;
18466 }
18467
18468 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter->deflink);
18469 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
18470 if (wlan_hdd_validate_context(hdd_ctx))
18471 return;
18472
18473 mutex_lock(&hdd_ctx->sap_lock);
18474 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->deflink->link_flags)) {
18475 wlan_hdd_del_station(ap_adapter, NULL);
18476 hostapd_state =
18477 WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter->deflink);
18478 hdd_debug("Now doing SAP STOPBSS");
18479 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
18480 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
18481 sap_context)) {
18482 qdf_status = qdf_wait_single_event(&hostapd_state->
18483 qdf_stop_bss_event,
18484 SME_CMD_STOP_BSS_TIMEOUT);
18485 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
18486 mutex_unlock(&hdd_ctx->sap_lock);
18487 hdd_err("SAP Stop Failed");
18488 return;
18489 }
18490 }
18491 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->deflink->link_flags);
18492 policy_mgr_decr_session_set_pcl(hdd_ctx->psoc,
18493 ap_adapter->device_mode,
18494 ap_adapter->deflink->vdev_id);
18495 hdd_green_ap_start_state_mc(hdd_ctx, ap_adapter->device_mode,
18496 false);
18497 hdd_inform_stop_sap(ap_adapter);
18498 hdd_debug("SAP Stop Success");
18499 } else {
18500 hdd_err("Can't stop ap because its not started");
18501 }
18502 mutex_unlock(&hdd_ctx->sap_lock);
18503 }
18504
18505 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
18506 /**
18507 * wlan_hdd_mlo_sap_reinit() - handle mlo scenario for ssr
18508 * @link_info: Pointer of link_info in adapter
18509 *
18510 * Return: QDF_STATUS
18511 */
wlan_hdd_mlo_sap_reinit(struct wlan_hdd_link_info * link_info)18512 static QDF_STATUS wlan_hdd_mlo_sap_reinit(struct wlan_hdd_link_info *link_info)
18513 {
18514 struct hdd_context *hdd_ctx = link_info->adapter->hdd_ctx;
18515 struct sap_config *config = &link_info->session.ap.sap_config;
18516
18517 if (config->mlo_sap) {
18518 if (!mlo_ap_vdev_attach(link_info->vdev, config->link_id,
18519 config->num_link)) {
18520 hdd_err("SAP mlo mgr attach fail");
18521 return QDF_STATUS_E_INVAL;
18522 }
18523 }
18524
18525 if (!policy_mgr_is_mlo_sap_concurrency_allowed(hdd_ctx->psoc,
18526 config->mlo_sap,
18527 wlan_vdev_get_id(link_info->vdev))) {
18528 hdd_err("MLO SAP concurrency check fails");
18529 return QDF_STATUS_E_INVAL;
18530 }
18531
18532 return QDF_STATUS_SUCCESS;
18533 }
18534 #else
18535 static inline QDF_STATUS
wlan_hdd_mlo_sap_reinit(struct wlan_hdd_link_info * link_info)18536 wlan_hdd_mlo_sap_reinit(struct wlan_hdd_link_info *link_info)
18537 {
18538 return QDF_STATUS_SUCCESS;
18539 }
18540 #endif
18541
wlan_hdd_set_sap_beacon_protection(struct hdd_context * hdd_ctx,struct wlan_hdd_link_info * link_info,struct hdd_beacon_data * beacon)18542 void wlan_hdd_set_sap_beacon_protection(struct hdd_context *hdd_ctx,
18543 struct wlan_hdd_link_info *link_info,
18544 struct hdd_beacon_data *beacon)
18545 {
18546 const uint8_t *ie = NULL;
18547 struct s_ext_cap *p_ext_cap;
18548 struct wlan_objmgr_vdev *vdev;
18549 bool target_bigtk_support = false;
18550 uint8_t vdev_id;
18551 uint8_t ie_len;
18552
18553 if (!beacon) {
18554 hdd_err("beacon is null");
18555 return;
18556 }
18557
18558 ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_EXTCAP, beacon->tail,
18559 beacon->tail_len);
18560 if (!ie) {
18561 hdd_err("IE is null");
18562 return;
18563 }
18564
18565 if (ie[1] > DOT11F_IE_EXTCAP_MAX_LEN ||
18566 ie[1] < DOT11F_IE_EXTCAP_MIN_LEN) {
18567 hdd_err("Invalid IEs eid: %d elem_len: %d", ie[0], ie[1]);
18568 return;
18569 }
18570
18571 p_ext_cap = qdf_mem_malloc(sizeof(*p_ext_cap));
18572 if (!p_ext_cap)
18573 return;
18574
18575 ie_len = (ie[1] > sizeof(*p_ext_cap)) ? sizeof(*p_ext_cap) : ie[1];
18576
18577 qdf_mem_copy(p_ext_cap, &ie[2], ie_len);
18578
18579 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_HDD_ID_OBJ_MGR);
18580 if (!vdev) {
18581 hdd_err("vdev is null");
18582 goto end;
18583 }
18584
18585 vdev_id = wlan_vdev_get_id(vdev);
18586
18587 hdd_debug("vdev %d beacon protection %d", vdev_id,
18588 p_ext_cap->beacon_protection_enable);
18589
18590 ucfg_mlme_get_bigtk_support(hdd_ctx->psoc, &target_bigtk_support);
18591
18592 if (target_bigtk_support && p_ext_cap->beacon_protection_enable)
18593 mlme_set_bigtk_support(vdev, true);
18594
18595 hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
18596
18597 end:
18598 qdf_mem_free(p_ext_cap);
18599 }
18600
wlan_hdd_start_sap(struct wlan_hdd_link_info * link_info,bool reinit)18601 void wlan_hdd_start_sap(struct wlan_hdd_link_info *link_info, bool reinit)
18602 {
18603 struct hdd_ap_ctx *ap_ctx;
18604 struct hdd_hostapd_state *hostapd_state;
18605 QDF_STATUS qdf_status;
18606 struct hdd_context *hdd_ctx;
18607 struct sap_config *sap_config;
18608 struct hdd_adapter *ap_adapter = link_info->adapter;
18609
18610 if (QDF_SAP_MODE != ap_adapter->device_mode) {
18611 hdd_err("SoftAp role has not been enabled");
18612 return;
18613 }
18614
18615 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
18616 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
18617 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info);
18618 sap_config = &ap_ctx->sap_config;
18619
18620 mutex_lock(&hdd_ctx->sap_lock);
18621 if (test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags))
18622 goto end;
18623
18624 if (wlan_hdd_cfg80211_update_apies(link_info)) {
18625 hdd_err("SAP Not able to set AP IEs");
18626 goto end;
18627 }
18628 wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
18629 sap_config->chan_freq, 0,
18630 &sap_config->ch_params,
18631 REG_CURRENT_PWR_MODE);
18632 qdf_status = wlan_hdd_mlo_sap_reinit(link_info);
18633 if (QDF_IS_STATUS_ERROR(qdf_status)) {
18634 hdd_err("SAP Not able to do mlo attach");
18635 goto end;
18636 }
18637
18638 qdf_event_reset(&hostapd_state->qdf_event);
18639 qdf_status = wlansap_start_bss(ap_ctx->sap_context,
18640 hdd_hostapd_sap_event_cb, sap_config,
18641 ap_adapter->dev);
18642 if (QDF_IS_STATUS_ERROR(qdf_status))
18643 goto end;
18644
18645 wlan_hdd_set_sap_beacon_protection(hdd_ctx, link_info, ap_ctx->beacon);
18646
18647 hdd_debug("Waiting for SAP to start");
18648 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
18649 SME_CMD_START_BSS_TIMEOUT);
18650 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
18651 hdd_err("SAP Start failed");
18652 goto end;
18653 }
18654 hdd_info("SAP Start Success");
18655
18656 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
18657 set_bit(SOFTAP_BSS_STARTED, &link_info->link_flags);
18658 if (hostapd_state->bss_state == BSS_START) {
18659 policy_mgr_incr_active_session(hdd_ctx->psoc,
18660 ap_adapter->device_mode,
18661 link_info->vdev_id);
18662 hdd_green_ap_start_state_mc(hdd_ctx, ap_adapter->device_mode,
18663 true);
18664 }
18665 mutex_unlock(&hdd_ctx->sap_lock);
18666
18667 return;
18668 end:
18669 wlan_hdd_mlo_reset(link_info);
18670 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
18671 mutex_unlock(&hdd_ctx->sap_lock);
18672 /* SAP context and beacon cleanup will happen during driver unload
18673 * in hdd_stop_adapter
18674 */
18675 hdd_err("SAP restart after SSR failed! Reload WLAN and try SAP again");
18676 /* Free the beacon memory in case of failure in the sap restart */
18677 qdf_mem_free(ap_ctx->beacon);
18678 ap_ctx->beacon = NULL;
18679 }
18680
18681 #ifdef QCA_CONFIG_SMP
18682 /**
18683 * wlan_hdd_get_cpu() - get cpu_index
18684 *
18685 * Return: cpu_index
18686 */
wlan_hdd_get_cpu(void)18687 int wlan_hdd_get_cpu(void)
18688 {
18689 int cpu_index = get_cpu();
18690
18691 put_cpu();
18692 return cpu_index;
18693 }
18694 #endif
18695
18696 /**
18697 * hdd_get_fwpath() - get framework path
18698 *
18699 * This function is used to get the string written by
18700 * userspace to start the wlan driver
18701 *
18702 * Return: string
18703 */
hdd_get_fwpath(void)18704 const char *hdd_get_fwpath(void)
18705 {
18706 return fwpath.string;
18707 }
18708
hdd_state_query_cb(void)18709 static inline int hdd_state_query_cb(void)
18710 {
18711 return !!wlan_hdd_validate_context(cds_get_context(QDF_MODULE_ID_HDD));
18712 }
18713
__hdd_op_protect_cb(void ** out_sync,const char * func)18714 static int __hdd_op_protect_cb(void **out_sync, const char *func)
18715 {
18716 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
18717
18718 if (!hdd_ctx)
18719 return -EAGAIN;
18720
18721 return __osif_psoc_sync_op_start(hdd_ctx->parent_dev,
18722 (struct osif_psoc_sync **)out_sync,
18723 func);
18724 }
18725
__hdd_op_unprotect_cb(void * sync,const char * func)18726 static void __hdd_op_unprotect_cb(void *sync, const char *func)
18727 {
18728 __osif_psoc_sync_op_stop(sync, func);
18729 }
18730
18731 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
18732 /**
18733 * hdd_logging_sock_init_svc() - Initialize logging sock
18734 *
18735 * Return: 0 for success, errno on failure
18736 */
18737 static int
hdd_logging_sock_init_svc(void)18738 hdd_logging_sock_init_svc(void)
18739 {
18740 return wlan_logging_sock_init_svc();
18741 }
18742 #else
18743 static inline int
hdd_logging_sock_init_svc(void)18744 hdd_logging_sock_init_svc(void)
18745 {
18746 return 0;
18747 }
18748 #endif
18749
18750 /**
18751 * hdd_init() - Initialize Driver
18752 *
18753 * This function initializes CDS global context with the help of cds_init. This
18754 * has to be the first function called after probe to get a valid global
18755 * context.
18756 *
18757 * Return: 0 for success, errno on failure
18758 */
hdd_init(void)18759 int hdd_init(void)
18760 {
18761 QDF_STATUS status;
18762
18763 status = cds_init();
18764 if (QDF_IS_STATUS_ERROR(status)) {
18765 hdd_err("Failed to allocate CDS context");
18766 return -ENOMEM;
18767 }
18768
18769 qdf_op_callbacks_register(__hdd_op_protect_cb, __hdd_op_unprotect_cb);
18770
18771 wlan_init_bug_report_lock();
18772
18773 if (hdd_logging_sock_init_svc()) {
18774 hdd_err("logging sock init failed.");
18775 goto err;
18776 }
18777
18778 hdd_trace_init();
18779 hdd_register_debug_callback();
18780 wlan_roam_debug_init();
18781
18782 return 0;
18783
18784 err:
18785 wlan_destroy_bug_report_lock();
18786 qdf_op_callbacks_register(NULL, NULL);
18787 cds_deinit();
18788 return -ENOMEM;
18789 }
18790
18791 /**
18792 * hdd_deinit() - Deinitialize Driver
18793 *
18794 * This function frees CDS global context with the help of cds_deinit. This
18795 * has to be the last function call in remove callback to free the global
18796 * context.
18797 */
hdd_deinit(void)18798 void hdd_deinit(void)
18799 {
18800 wlan_roam_debug_deinit();
18801
18802 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
18803 wlan_logging_sock_deinit_svc();
18804 #endif
18805
18806 wlan_destroy_bug_report_lock();
18807 qdf_op_callbacks_register(NULL, NULL);
18808 cds_deinit();
18809 }
18810
18811 #ifdef QCA_WIFI_EMULATION
18812 #define HDD_WLAN_START_WAIT_TIME ((CDS_WMA_TIMEOUT + 5000) * 100)
18813 #else
18814 #define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
18815 #endif
18816
hdd_init_start_completion(void)18817 void hdd_init_start_completion(void)
18818 {
18819 INIT_COMPLETION(wlan_start_comp);
18820 }
18821
18822 #ifdef WLAN_CTRL_NAME
18823 static unsigned int dev_num = 1;
18824 static struct cdev wlan_hdd_state_cdev;
18825 static struct class *class;
18826 static dev_t device;
18827
hdd_set_adapter_wlm_def_level(struct hdd_context * hdd_ctx)18828 static void hdd_set_adapter_wlm_def_level(struct hdd_context *hdd_ctx)
18829 {
18830 struct hdd_adapter *adapter, *next_adapter = NULL;
18831 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER;
18832 int ret;
18833 QDF_STATUS qdf_status;
18834 uint8_t latency_level;
18835 bool reset;
18836
18837 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
18838 return;
18839
18840 ret = wlan_hdd_validate_context(hdd_ctx);
18841 if (ret != 0)
18842 return;
18843
18844 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
18845 dbgid) {
18846 qdf_status = ucfg_mlme_cfg_get_wlm_level(hdd_ctx->psoc,
18847 &latency_level);
18848 if (QDF_IS_STATUS_ERROR(qdf_status))
18849 adapter->latency_level =
18850 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL;
18851 else
18852 adapter->latency_level = latency_level;
18853 qdf_status = ucfg_mlme_cfg_get_wlm_reset(hdd_ctx->psoc, &reset);
18854 if (QDF_IS_STATUS_ERROR(qdf_status)) {
18855 hdd_err("could not get the wlm reset flag");
18856 reset = false;
18857 }
18858
18859 if (hdd_get_multi_client_ll_support(adapter) && !reset)
18860 wlan_hdd_deinit_multi_client_info_table(adapter);
18861
18862 adapter->upgrade_udp_qos_threshold = QCA_WLAN_AC_BK;
18863 hdd_debug("UDP packets qos reset to: %d",
18864 adapter->upgrade_udp_qos_threshold);
18865 hdd_adapter_dev_put_debug(adapter, dbgid);
18866 }
18867 }
18868
wlan_hdd_state_ctrl_param_open(struct inode * inode,struct file * file)18869 static int wlan_hdd_state_ctrl_param_open(struct inode *inode,
18870 struct file *file)
18871 {
18872 qdf_atomic_inc(&wlan_hdd_state_fops_ref);
18873
18874 return 0;
18875 }
18876
__hdd_inform_wifi_off(void)18877 static void __hdd_inform_wifi_off(void)
18878 {
18879 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
18880 int ret;
18881
18882 ret = wlan_hdd_validate_context(hdd_ctx);
18883 if (ret != 0)
18884 return;
18885
18886 ucfg_dlm_wifi_off(hdd_ctx->pdev);
18887
18888 if (rtnl_trylock()) {
18889 wlan_hdd_lpc_del_monitor_interface(hdd_ctx, false);
18890 rtnl_unlock();
18891 }
18892 }
18893
hdd_inform_wifi_off(void)18894 static void hdd_inform_wifi_off(void)
18895 {
18896 int ret;
18897 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
18898 struct osif_psoc_sync *psoc_sync;
18899
18900 if (!hdd_ctx)
18901 return;
18902
18903 ret = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync);
18904 if (ret)
18905 return;
18906
18907 hdd_set_adapter_wlm_def_level(hdd_ctx);
18908 __hdd_inform_wifi_off();
18909
18910 osif_psoc_sync_op_stop(psoc_sync);
18911 }
18912
18913 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
18914 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
hdd_inform_wifi_on(void)18915 static void hdd_inform_wifi_on(void)
18916 {
18917 int ret;
18918 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
18919 struct osif_psoc_sync *psoc_sync;
18920
18921 hdd_nofl_debug("inform regdomain for wifi on");
18922 ret = wlan_hdd_validate_context(hdd_ctx);
18923 if (ret)
18924 return;
18925 if (!wlan_hdd_validate_modules_state(hdd_ctx))
18926 return;
18927 if (!hdd_ctx->wiphy)
18928 return;
18929 ret = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync);
18930 if (ret)
18931 return;
18932 if (hdd_ctx->wiphy->registered)
18933 hdd_send_wiphy_regd_sync_event(hdd_ctx);
18934
18935 osif_psoc_sync_op_stop(psoc_sync);
18936 }
18937 #else
hdd_inform_wifi_on(void)18938 static void hdd_inform_wifi_on(void)
18939 {
18940 }
18941 #endif
18942
hdd_validate_wlan_string(const char __user * user_buf)18943 static int hdd_validate_wlan_string(const char __user *user_buf)
18944 {
18945 char buf[15];
18946 int i;
18947 static const char * const wlan_str[] = {
18948 [WLAN_OFF_STR] = "OFF",
18949 [WLAN_ON_STR] = "ON",
18950 [WLAN_ENABLE_STR] = "ENABLE",
18951 [WLAN_DISABLE_STR] = "DISABLE",
18952 [WLAN_WAIT_FOR_READY_STR] = "WAIT_FOR_READY",
18953 [WLAN_FORCE_DISABLE_STR] = "FORCE_DISABLE"
18954 };
18955
18956 if (copy_from_user(buf, user_buf, sizeof(buf))) {
18957 pr_err("Failed to read buffer\n");
18958 return -EINVAL;
18959 }
18960
18961 for (i = 0; i < ARRAY_SIZE(wlan_str); i++) {
18962 if (qdf_str_ncmp(buf, wlan_str[i], strlen(wlan_str[i])) == 0)
18963 return i;
18964 }
18965
18966 return -EINVAL;
18967 }
18968
18969 #ifdef FEATURE_CNSS_HW_SECURE_DISABLE
18970 #define WIFI_DISABLE_SLEEP (10)
18971 #define WIFI_DISABLE_MAX_RETRY_ATTEMPTS (10)
18972 static bool g_soft_unload;
18973
hdd_get_wlan_driver_status(void)18974 bool hdd_get_wlan_driver_status(void)
18975 {
18976 return g_soft_unload;
18977 }
18978
hdd_wlan_soft_driver_load(void)18979 static int hdd_wlan_soft_driver_load(void)
18980 {
18981 if (!cds_is_driver_loaded()) {
18982 hdd_debug("\nEnabling CNSS WLAN HW");
18983 pld_wlan_hw_enable();
18984 return 0;
18985 }
18986
18987 if (!g_soft_unload) {
18988 hdd_debug_rl("Enabling WiFi\n");
18989 return -EINVAL;
18990 }
18991
18992 hdd_driver_load();
18993 g_soft_unload = false;
18994 return 0;
18995 }
18996
hdd_wlan_soft_driver_unload(void)18997 static void hdd_wlan_soft_driver_unload(void)
18998 {
18999 if (g_soft_unload) {
19000 hdd_debug_rl("WiFi is already disabled");
19001 return;
19002 }
19003 hdd_debug("Initiating soft driver unload\n");
19004 g_soft_unload = true;
19005 hdd_driver_unload();
19006 }
19007
hdd_wlan_idle_shutdown(struct hdd_context * hdd_ctx)19008 static int hdd_wlan_idle_shutdown(struct hdd_context *hdd_ctx)
19009 {
19010 int ret;
19011 int retries = 0;
19012 void *hif_ctx;
19013
19014 if (!hdd_ctx) {
19015 hdd_err_rl("hdd_ctx is Null");
19016 return -EINVAL;
19017 }
19018
19019 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
19020
19021 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_IDLE_SHUTDOWN);
19022
19023 while (retries < WIFI_DISABLE_MAX_RETRY_ATTEMPTS) {
19024 if (hif_ctx) {
19025 /*
19026 * Trigger runtime sync resume before psoc_idle_shutdown
19027 * such that resume can happen successfully
19028 */
19029 qdf_rtpm_sync_resume();
19030 }
19031 ret = pld_idle_shutdown(hdd_ctx->parent_dev,
19032 hdd_psoc_idle_shutdown);
19033
19034 if (-EAGAIN == ret || hdd_ctx->is_wiphy_suspended) {
19035 hdd_debug("System suspend in progress.Retries done:%d",
19036 retries);
19037 msleep(WIFI_DISABLE_SLEEP);
19038 retries++;
19039 continue;
19040 }
19041 break;
19042 }
19043 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_IDLE_SHUTDOWN);
19044
19045 if (retries > WIFI_DISABLE_MAX_RETRY_ATTEMPTS) {
19046 hdd_debug("Max retries reached");
19047 return -EINVAL;
19048 }
19049 hdd_debug_rl("WiFi is disabled");
19050
19051 return 0;
19052 }
19053
hdd_disable_wifi(struct hdd_context * hdd_ctx)19054 static int hdd_disable_wifi(struct hdd_context *hdd_ctx)
19055 {
19056 int ret;
19057
19058 if (hdd_ctx->is_wlan_disabled) {
19059 hdd_err_rl("Wifi is already disabled");
19060 return 0;
19061 }
19062
19063 hdd_debug("Initiating WLAN idle shutdown");
19064 if (hdd_is_any_interface_open(hdd_ctx)) {
19065 hdd_err("Interfaces still open, cannot process wifi disable");
19066 return -EAGAIN;
19067 }
19068
19069 hdd_ctx->is_wlan_disabled = true;
19070
19071 ret = hdd_wlan_idle_shutdown(hdd_ctx);
19072 if (ret)
19073 hdd_ctx->is_wlan_disabled = false;
19074
19075 return ret;
19076 }
19077 #else
hdd_wlan_soft_driver_load(void)19078 static int hdd_wlan_soft_driver_load(void)
19079 {
19080 return -EINVAL;
19081 }
19082
hdd_wlan_soft_driver_unload(void)19083 static void hdd_wlan_soft_driver_unload(void)
19084 {
19085 }
19086
hdd_disable_wifi(struct hdd_context * hdd_ctx)19087 static int hdd_disable_wifi(struct hdd_context *hdd_ctx)
19088 {
19089 return 0;
19090 }
19091 #endif /* FEATURE_CNSS_HW_SECURE_DISABLE */
19092
wlan_hdd_state_ctrl_param_write(struct file * filp,const char __user * user_buf,size_t count,loff_t * f_pos)19093 static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
19094 const char __user *user_buf,
19095 size_t count,
19096 loff_t *f_pos)
19097 {
19098 int id, ret;
19099 unsigned long rc;
19100 struct hdd_context *hdd_ctx;
19101 bool is_wait_for_ready = false;
19102 bool is_wlan_force_disabled;
19103
19104 hdd_enter();
19105
19106 id = hdd_validate_wlan_string(user_buf);
19107
19108 switch (id) {
19109 case WLAN_OFF_STR:
19110 hdd_info("Wifi turning off from UI\n");
19111 hdd_inform_wifi_off();
19112 goto exit;
19113 case WLAN_ON_STR:
19114 hdd_info("Wifi Turning On from UI\n");
19115 break;
19116 case WLAN_WAIT_FOR_READY_STR:
19117 is_wait_for_ready = true;
19118 hdd_info("Wifi wait for ready from UI\n");
19119 break;
19120 case WLAN_ENABLE_STR:
19121 hdd_nofl_debug("Received WiFi enable from framework\n");
19122 if (!hdd_wlan_soft_driver_load())
19123 goto exit;
19124 pr_info("Enabling WiFi\n");
19125 break;
19126 case WLAN_DISABLE_STR:
19127 hdd_nofl_debug("Received WiFi disable from framework\n");
19128 if (!cds_is_driver_loaded())
19129 goto exit;
19130
19131 is_wlan_force_disabled = hdd_get_wlan_driver_status();
19132 if (is_wlan_force_disabled)
19133 goto exit;
19134 pr_info("Disabling WiFi\n");
19135 break;
19136 case WLAN_FORCE_DISABLE_STR:
19137 hdd_nofl_debug("Received Force WiFi disable from framework\n");
19138 if (!cds_is_driver_loaded())
19139 goto exit;
19140
19141 hdd_wlan_soft_driver_unload();
19142 goto exit;
19143 default:
19144 hdd_err_rl("Invalid value received from framework");
19145 return -EINVAL;
19146 }
19147
19148 hdd_info("is_driver_loaded %d is_driver_recovering %d",
19149 cds_is_driver_loaded(), cds_is_driver_recovering());
19150
19151 if (!cds_is_driver_loaded() || cds_is_driver_recovering()) {
19152 rc = wait_for_completion_timeout(&wlan_start_comp,
19153 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
19154 if (!rc) {
19155 hdd_err("Driver Loading Timed-out!!");
19156 ret = -EINVAL;
19157 return ret;
19158 }
19159 }
19160
19161 if (is_wait_for_ready)
19162 return count;
19163 /*
19164 * Flush idle shutdown work for cases to synchronize the wifi on
19165 * during the idle shutdown.
19166 */
19167 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
19168 if (hdd_ctx)
19169 hdd_psoc_idle_timer_stop(hdd_ctx);
19170
19171 if (id == WLAN_DISABLE_STR) {
19172 if (!hdd_ctx) {
19173 hdd_err_rl("hdd_ctx is Null");
19174 goto exit;
19175 }
19176
19177 ret = hdd_disable_wifi(hdd_ctx);
19178 if (ret)
19179 return ret;
19180 }
19181
19182 if (id == WLAN_ENABLE_STR) {
19183 if (!hdd_ctx) {
19184 hdd_err_rl("hdd_ctx is Null");
19185 goto exit;
19186 }
19187
19188 if (!hdd_ctx->is_wlan_disabled) {
19189 hdd_err_rl("WiFi is already enabled");
19190 goto exit;
19191 }
19192 hdd_ctx->is_wlan_disabled = false;
19193 }
19194
19195 if (id == WLAN_ON_STR)
19196 hdd_inform_wifi_on();
19197 exit:
19198 hdd_exit();
19199 return count;
19200 }
19201
19202 /**
19203 * wlan_hdd_state_ctrl_param_release() - Release callback for /dev/wlan.
19204 *
19205 * @inode: struct inode pointer.
19206 * @file: struct file pointer.
19207 *
19208 * Release callback that would be invoked when the file operations has
19209 * completed fully. This is implemented to provide a reference count mechanism
19210 * via which the driver can wait till all possible usage of the /dev/wlan
19211 * file is completed.
19212 *
19213 * Return: Success
19214 */
wlan_hdd_state_ctrl_param_release(struct inode * inode,struct file * file)19215 static int wlan_hdd_state_ctrl_param_release(struct inode *inode,
19216 struct file *file)
19217 {
19218 qdf_atomic_dec(&wlan_hdd_state_fops_ref);
19219
19220 return 0;
19221 }
19222
19223 const struct file_operations wlan_hdd_state_fops = {
19224 .owner = THIS_MODULE,
19225 .open = wlan_hdd_state_ctrl_param_open,
19226 .write = wlan_hdd_state_ctrl_param_write,
19227 .release = wlan_hdd_state_ctrl_param_release,
19228 };
19229
19230 #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0))
wlan_hdd_class_create(const char * name)19231 static struct class *wlan_hdd_class_create(const char *name)
19232 {
19233 return class_create(THIS_MODULE, name);
19234 }
19235 #else
wlan_hdd_class_create(const char * name)19236 static struct class *wlan_hdd_class_create(const char *name)
19237 {
19238 return class_create(name);
19239 }
19240 #endif
19241
wlan_hdd_state_ctrl_param_create(void)19242 static int wlan_hdd_state_ctrl_param_create(void)
19243 {
19244 unsigned int wlan_hdd_state_major = 0;
19245 int ret;
19246 struct device *dev;
19247
19248 init_completion(&wlan_start_comp);
19249 qdf_atomic_init(&wlan_hdd_state_fops_ref);
19250
19251 device = MKDEV(wlan_hdd_state_major, 0);
19252
19253 ret = alloc_chrdev_region(&device, 0, dev_num, "qcwlanstate");
19254 if (ret) {
19255 pr_err("Failed to register qcwlanstate");
19256 goto dev_alloc_err;
19257 }
19258 wlan_hdd_state_major = MAJOR(device);
19259 class = wlan_hdd_class_create(WLAN_CTRL_NAME);
19260 if (IS_ERR(class)) {
19261 pr_err("wlan_hdd_state class_create error");
19262 goto class_err;
19263 }
19264
19265 dev = device_create(class, NULL, device, NULL, WLAN_CTRL_NAME);
19266 if (IS_ERR(dev)) {
19267 pr_err("wlan_hdd_statedevice_create error");
19268 goto err_class_destroy;
19269 }
19270
19271 cdev_init(&wlan_hdd_state_cdev, &wlan_hdd_state_fops);
19272
19273 wlan_hdd_state_cdev.owner = THIS_MODULE;
19274
19275 ret = cdev_add(&wlan_hdd_state_cdev, device, dev_num);
19276 if (ret) {
19277 pr_err("Failed to add cdev error");
19278 goto cdev_add_err;
19279 }
19280
19281 pr_info("wlan_hdd_state %s major(%d) initialized",
19282 WLAN_CTRL_NAME, wlan_hdd_state_major);
19283
19284 return 0;
19285
19286 cdev_add_err:
19287 device_destroy(class, device);
19288 err_class_destroy:
19289 class_destroy(class);
19290 class_err:
19291 unregister_chrdev_region(device, dev_num);
19292 dev_alloc_err:
19293 return -ENODEV;
19294 }
19295
19296 /*
19297 * When multiple instances of the driver are loaded in parallel, only
19298 * one can create and own the state ctrl param. An instance of the
19299 * driver that creates the state ctrl param will wait for
19300 * HDD_WLAN_START_WAIT_TIME to be probed. If it is probed, then that
19301 * instance of the driver will stay loaded and no other instances of
19302 * the driver can load. But if it is not probed, then that instance of
19303 * the driver will destroy the state ctrl param and exit, and another
19304 * instance of the driver can then create the state ctrl param.
19305 */
19306
19307 /* max number of instances we expect (arbitrary) */
19308 #define WLAN_DRIVER_MAX_INSTANCES 5
19309
19310 /* max amount of time an instance has to wait for all instances */
19311 #define CTRL_PARAM_WAIT (WLAN_DRIVER_MAX_INSTANCES * HDD_WLAN_START_WAIT_TIME)
19312
19313 /* amount of time we sleep for each retry (arbitrary) */
19314 #define CTRL_PARAM_SLEEP 100
19315
wlan_hdd_state_ctrl_param_destroy(void)19316 static void wlan_hdd_state_ctrl_param_destroy(void)
19317 {
19318 cdev_del(&wlan_hdd_state_cdev);
19319 device_destroy(class, device);
19320 class_destroy(class);
19321 unregister_chrdev_region(device, dev_num);
19322
19323 pr_info("Device node unregistered");
19324 }
19325
19326 #else /* WLAN_CTRL_NAME */
19327
wlan_hdd_state_ctrl_param_create(void)19328 static int wlan_hdd_state_ctrl_param_create(void)
19329 {
19330 return 0;
19331 }
19332
wlan_hdd_state_ctrl_param_destroy(void)19333 static void wlan_hdd_state_ctrl_param_destroy(void)
19334 {
19335 }
19336
19337 #endif /* WLAN_CTRL_NAME */
19338
19339 /**
19340 * hdd_send_scan_done_complete_cb() - API to send scan done indication to upper
19341 * layer
19342 * @vdev_id: vdev id
19343 *
19344 * Return: none
19345 */
hdd_send_scan_done_complete_cb(uint8_t vdev_id)19346 static void hdd_send_scan_done_complete_cb(uint8_t vdev_id)
19347 {
19348 struct hdd_context *hdd_ctx;
19349 struct wlan_hdd_link_info *link_info;
19350 struct hdd_adapter *adapter;
19351 struct sk_buff *vendor_event;
19352 uint32_t len;
19353
19354 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
19355 if (!hdd_ctx)
19356 return;
19357
19358 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
19359 if (!link_info) {
19360 hdd_err("Invalid vdev id:%d", vdev_id);
19361 return;
19362 }
19363
19364 adapter = link_info->adapter;
19365 len = NLMSG_HDRLEN;
19366 vendor_event =
19367 wlan_cfg80211_vendor_event_alloc(
19368 hdd_ctx->wiphy, &adapter->wdev, len,
19369 QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS_INDEX,
19370 GFP_KERNEL);
19371
19372 if (!vendor_event) {
19373 hdd_err("wlan_cfg80211_vendor_event_alloc failed");
19374 return;
19375 }
19376
19377 hdd_debug("sending scan done ind to upper layer for vdev_id:%d",
19378 vdev_id);
19379 wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
19380 }
19381
19382 struct osif_vdev_mgr_ops osif_vdev_mgrlegacy_ops = {
19383 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
19384 .osif_vdev_mgr_set_mac_addr_response = hdd_set_mac_addr_event_cb,
19385 #endif
19386 .osif_vdev_mgr_send_scan_done_complete_cb =
19387 hdd_send_scan_done_complete_cb,
19388
19389 };
19390
hdd_vdev_mgr_register_cb(void)19391 static QDF_STATUS hdd_vdev_mgr_register_cb(void)
19392 {
19393 osif_vdev_mgr_set_legacy_cb(&osif_vdev_mgrlegacy_ops);
19394 return osif_vdev_mgr_register_cb();
19395 }
19396
hdd_vdev_mgr_unregister_cb(void)19397 static void hdd_vdev_mgr_unregister_cb(void)
19398 {
19399 osif_vdev_mgr_reset_legacy_cb();
19400 }
19401
19402 /**
19403 * hdd_ll_sap_register_cb() - Register ll_sap osif callbacks
19404 *
19405 * Return: QDF_STATUS
19406 */
hdd_ll_sap_register_cb(void)19407 static QDF_STATUS hdd_ll_sap_register_cb(void)
19408 {
19409 return osif_ll_sap_register_cb();
19410 }
19411
19412 /**
19413 * hdd_ll_sap_unregister_cb() - Un-register ll_sap osif callbacks
19414 *
19415 * Return: void
19416 */
hdd_ll_sap_unregister_cb(void)19417 static void hdd_ll_sap_unregister_cb(void)
19418 {
19419 osif_ll_sap_unregister_cb();
19420 }
19421
19422 /**
19423 * hdd_component_cb_init() - Initialize component callbacks
19424 *
19425 * This function initializes hdd callbacks to different
19426 * components
19427 *
19428 * Context: Any context.
19429 * Return: QDF_STATUS
19430 */
hdd_component_cb_init(void)19431 static QDF_STATUS hdd_component_cb_init(void)
19432 {
19433 QDF_STATUS status;
19434
19435 status = hdd_cm_register_cb();
19436 if (QDF_IS_STATUS_ERROR(status))
19437 return status;
19438
19439 status = hdd_vdev_mgr_register_cb();
19440 if (QDF_IS_STATUS_ERROR(status))
19441 goto cm_unregister_cb;
19442
19443 status = osif_twt_register_cb();
19444 if (QDF_IS_STATUS_ERROR(status))
19445 goto hdd_vdev_mgr_unregister_cb;
19446
19447 status = hdd_pre_cac_register_cb();
19448 if (QDF_IS_STATUS_ERROR(status))
19449 goto hdd_vdev_mgr_unregister_cb;
19450
19451 status = hdd_ll_sap_register_cb();
19452 if (QDF_IS_STATUS_ERROR(status))
19453 goto pre_cac_unregister_cb;
19454
19455 return QDF_STATUS_SUCCESS;
19456
19457 pre_cac_unregister_cb:
19458 hdd_pre_cac_unregister_cb();
19459 hdd_vdev_mgr_unregister_cb:
19460 hdd_vdev_mgr_unregister_cb();
19461 cm_unregister_cb:
19462 hdd_cm_unregister_cb();
19463 return status;
19464 }
19465
19466 /**
19467 * hdd_component_cb_deinit() - De-initialize component callbacks
19468 *
19469 * This function de-initializes hdd callbacks with different components
19470 *
19471 * Context: Any context.
19472 * Return: None`
19473 */
hdd_component_cb_deinit(void)19474 static void hdd_component_cb_deinit(void)
19475 {
19476 hdd_ll_sap_unregister_cb();
19477 hdd_pre_cac_unregister_cb();
19478 hdd_vdev_mgr_unregister_cb();
19479 hdd_cm_unregister_cb();
19480 }
19481
19482 /**
19483 * hdd_component_init() - Initialize all components
19484 *
19485 * Return: QDF_STATUS
19486 */
hdd_component_init(void)19487 static QDF_STATUS hdd_component_init(void)
19488 {
19489 QDF_STATUS status;
19490
19491 /* initialize converged components */
19492
19493 status = ucfg_mlme_global_init();
19494 if (QDF_IS_STATUS_ERROR(status))
19495 return status;
19496
19497 status = dispatcher_init();
19498 if (QDF_IS_STATUS_ERROR(status))
19499 goto mlme_global_deinit;
19500
19501 status = target_if_init(wma_get_psoc_from_scn_handle);
19502 if (QDF_IS_STATUS_ERROR(status))
19503 goto dispatcher_deinit;
19504
19505 /* initialize non-converged components */
19506 status = ucfg_mlme_init();
19507 if (QDF_IS_STATUS_ERROR(status))
19508 goto target_if_deinit;
19509
19510 status = ucfg_fwol_init();
19511 if (QDF_IS_STATUS_ERROR(status))
19512 goto mlme_deinit;
19513
19514 status = disa_init();
19515 if (QDF_IS_STATUS_ERROR(status))
19516 goto fwol_deinit;
19517
19518 status = pmo_init();
19519 if (QDF_IS_STATUS_ERROR(status))
19520 goto disa_deinit;
19521
19522 status = ucfg_ocb_init();
19523 if (QDF_IS_STATUS_ERROR(status))
19524 goto pmo_deinit;
19525
19526 status = ipa_init();
19527 if (QDF_IS_STATUS_ERROR(status))
19528 goto ocb_deinit;
19529
19530 status = ucfg_action_oui_init();
19531 if (QDF_IS_STATUS_ERROR(status))
19532 goto ipa_deinit;
19533
19534 status = nan_init();
19535 if (QDF_IS_STATUS_ERROR(status))
19536 goto action_oui_deinit;
19537
19538 status = ucfg_p2p_init();
19539 if (QDF_IS_STATUS_ERROR(status))
19540 goto nan_deinit;
19541
19542 status = ucfg_interop_issues_ap_init();
19543 if (QDF_IS_STATUS_ERROR(status))
19544 goto p2p_deinit;
19545
19546 status = policy_mgr_init();
19547 if (QDF_IS_STATUS_ERROR(status))
19548 goto interop_issues_ap_deinit;
19549
19550 status = ucfg_tdls_init();
19551 if (QDF_IS_STATUS_ERROR(status))
19552 goto policy_deinit;
19553
19554 status = ucfg_dlm_init();
19555 if (QDF_IS_STATUS_ERROR(status))
19556 goto tdls_deinit;
19557
19558 status = ucfg_pkt_capture_init();
19559 if (QDF_IS_STATUS_ERROR(status))
19560 goto dlm_deinit;
19561
19562 status = ucfg_ftm_time_sync_init();
19563 if (QDF_IS_STATUS_ERROR(status))
19564 goto pkt_capture_deinit;
19565
19566 status = ucfg_pre_cac_init();
19567 if (QDF_IS_STATUS_ERROR(status))
19568 goto pre_cac_deinit;
19569
19570 status = ucfg_dp_init();
19571 if (QDF_IS_STATUS_ERROR(status))
19572 goto pre_cac_deinit;
19573
19574 status = ucfg_qmi_init();
19575 if (QDF_IS_STATUS_ERROR(status))
19576 goto dp_deinit;
19577
19578 status = ucfg_ll_sap_init();
19579 if (QDF_IS_STATUS_ERROR(status))
19580 goto qmi_deinit;
19581
19582 status = ucfg_afc_init();
19583 if (QDF_IS_STATUS_ERROR(status))
19584 goto ll_sap_deinit;
19585
19586 status = hdd_mlo_mgr_register_osif_ops();
19587 if (QDF_IS_STATUS_ERROR(status))
19588 goto afc_deinit;
19589
19590 hdd_register_cstats_ops();
19591
19592 return QDF_STATUS_SUCCESS;
19593
19594 afc_deinit:
19595 ucfg_afc_deinit();
19596 ll_sap_deinit:
19597 ucfg_ll_sap_deinit();
19598 qmi_deinit:
19599 ucfg_qmi_deinit();
19600 dp_deinit:
19601 ucfg_dp_deinit();
19602 pre_cac_deinit:
19603 ucfg_pre_cac_deinit();
19604 pkt_capture_deinit:
19605 ucfg_pkt_capture_deinit();
19606 dlm_deinit:
19607 ucfg_dlm_deinit();
19608 tdls_deinit:
19609 ucfg_tdls_deinit();
19610 policy_deinit:
19611 policy_mgr_deinit();
19612 interop_issues_ap_deinit:
19613 ucfg_interop_issues_ap_deinit();
19614 p2p_deinit:
19615 ucfg_p2p_deinit();
19616 nan_deinit:
19617 nan_deinit();
19618 action_oui_deinit:
19619 ucfg_action_oui_deinit();
19620 ipa_deinit:
19621 ipa_deinit();
19622 ocb_deinit:
19623 ucfg_ocb_deinit();
19624 pmo_deinit:
19625 pmo_deinit();
19626 disa_deinit:
19627 disa_deinit();
19628 fwol_deinit:
19629 ucfg_fwol_deinit();
19630 mlme_deinit:
19631 ucfg_mlme_deinit();
19632 target_if_deinit:
19633 target_if_deinit();
19634 dispatcher_deinit:
19635 dispatcher_deinit();
19636 mlme_global_deinit:
19637 ucfg_mlme_global_deinit();
19638
19639 return status;
19640 }
19641
19642 /**
19643 * hdd_component_deinit() - Deinitialize all components
19644 *
19645 * Return: None
19646 */
hdd_component_deinit(void)19647 static void hdd_component_deinit(void)
19648 {
19649 /* deinitialize non-converged components */
19650 hdd_mlo_mgr_unregister_osif_ops();
19651 ucfg_afc_deinit();
19652 ucfg_ll_sap_deinit();
19653 ucfg_qmi_deinit();
19654 ucfg_dp_deinit();
19655 ucfg_pre_cac_deinit();
19656 ucfg_ftm_time_sync_deinit();
19657 ucfg_pkt_capture_deinit();
19658 ucfg_dlm_deinit();
19659 ucfg_tdls_deinit();
19660 policy_mgr_deinit();
19661 ucfg_interop_issues_ap_deinit();
19662 ucfg_p2p_deinit();
19663 nan_deinit();
19664 ucfg_action_oui_deinit();
19665 ipa_deinit();
19666 ucfg_ocb_deinit();
19667 pmo_deinit();
19668 disa_deinit();
19669 ucfg_fwol_deinit();
19670 ucfg_mlme_deinit();
19671
19672 /* deinitialize converged components */
19673 target_if_deinit();
19674 dispatcher_deinit();
19675 ucfg_mlme_global_deinit();
19676 }
19677
hdd_component_psoc_open(struct wlan_objmgr_psoc * psoc)19678 QDF_STATUS hdd_component_psoc_open(struct wlan_objmgr_psoc *psoc)
19679 {
19680 QDF_STATUS status;
19681
19682 status = ucfg_mlme_psoc_open(psoc);
19683 if (QDF_IS_STATUS_ERROR(status))
19684 return status;
19685
19686 status = ucfg_dlm_psoc_open(psoc);
19687 if (QDF_IS_STATUS_ERROR(status))
19688 goto err_dlm;
19689
19690 status = ucfg_fwol_psoc_open(psoc);
19691 if (QDF_IS_STATUS_ERROR(status))
19692 goto err_fwol;
19693
19694 status = ucfg_pmo_psoc_open(psoc);
19695 if (QDF_IS_STATUS_ERROR(status))
19696 goto err_pmo;
19697
19698 status = ucfg_policy_mgr_psoc_open(psoc);
19699 if (QDF_IS_STATUS_ERROR(status))
19700 goto err_plcy_mgr;
19701
19702 status = ucfg_p2p_psoc_open(psoc);
19703 if (QDF_IS_STATUS_ERROR(status))
19704 goto err_p2p;
19705
19706 status = ucfg_tdls_psoc_open(psoc);
19707 if (QDF_IS_STATUS_ERROR(status))
19708 goto err_tdls;
19709
19710 status = ucfg_nan_psoc_open(psoc);
19711 if (QDF_IS_STATUS_ERROR(status))
19712 goto err_nan;
19713
19714 status = ucfg_twt_psoc_open(psoc);
19715 if (QDF_IS_STATUS_ERROR(status))
19716 goto err_twt;
19717
19718 status = ucfg_wifi_pos_psoc_open(psoc);
19719 if (QDF_IS_STATUS_ERROR(status))
19720 goto err_wifi_pos;
19721
19722 status = ucfg_dp_psoc_open(psoc);
19723 if (QDF_IS_STATUS_ERROR(status))
19724 goto err_dp;
19725
19726 return status;
19727
19728 err_dp:
19729 ucfg_wifi_pos_psoc_close(psoc);
19730 err_wifi_pos:
19731 ucfg_twt_psoc_close(psoc);
19732 err_twt:
19733 ucfg_nan_psoc_close(psoc);
19734 err_nan:
19735 ucfg_tdls_psoc_close(psoc);
19736 err_tdls:
19737 ucfg_p2p_psoc_close(psoc);
19738 err_p2p:
19739 ucfg_policy_mgr_psoc_close(psoc);
19740 err_plcy_mgr:
19741 ucfg_pmo_psoc_close(psoc);
19742 err_pmo:
19743 ucfg_fwol_psoc_close(psoc);
19744 err_fwol:
19745 ucfg_dlm_psoc_close(psoc);
19746 err_dlm:
19747 ucfg_mlme_psoc_close(psoc);
19748
19749 return status;
19750 }
19751
hdd_component_psoc_close(struct wlan_objmgr_psoc * psoc)19752 void hdd_component_psoc_close(struct wlan_objmgr_psoc *psoc)
19753 {
19754 ucfg_dp_psoc_close(psoc);
19755 ucfg_wifi_pos_psoc_close(psoc);
19756 ucfg_twt_psoc_close(psoc);
19757 ucfg_nan_psoc_close(psoc);
19758 ucfg_tdls_psoc_close(psoc);
19759 ucfg_p2p_psoc_close(psoc);
19760 ucfg_policy_mgr_psoc_close(psoc);
19761 ucfg_pmo_psoc_close(psoc);
19762 ucfg_fwol_psoc_close(psoc);
19763 ucfg_dlm_psoc_close(psoc);
19764 ucfg_mlme_psoc_close(psoc);
19765
19766 if (!cds_is_driver_recovering())
19767 ucfg_crypto_flush_entries(psoc);
19768 }
19769
hdd_component_psoc_enable(struct wlan_objmgr_psoc * psoc)19770 void hdd_component_psoc_enable(struct wlan_objmgr_psoc *psoc)
19771 {
19772 ocb_psoc_enable(psoc);
19773 disa_psoc_enable(psoc);
19774 nan_psoc_enable(psoc);
19775 p2p_psoc_enable(psoc);
19776 ucfg_interop_issues_ap_psoc_enable(psoc);
19777 policy_mgr_psoc_enable(psoc);
19778 ucfg_tdls_psoc_enable(psoc);
19779 ucfg_fwol_psoc_enable(psoc);
19780 ucfg_action_oui_psoc_enable(psoc);
19781 ucfg_ll_sap_psoc_enable(psoc);
19782 }
19783
hdd_component_psoc_disable(struct wlan_objmgr_psoc * psoc)19784 void hdd_component_psoc_disable(struct wlan_objmgr_psoc *psoc)
19785 {
19786 ucfg_ll_sap_psoc_disable(psoc);
19787 ucfg_action_oui_psoc_disable(psoc);
19788 ucfg_fwol_psoc_disable(psoc);
19789 ucfg_tdls_psoc_disable(psoc);
19790 policy_mgr_psoc_disable(psoc);
19791 ucfg_interop_issues_ap_psoc_disable(psoc);
19792 p2p_psoc_disable(psoc);
19793 nan_psoc_disable(psoc);
19794 disa_psoc_disable(psoc);
19795 ocb_psoc_disable(psoc);
19796 }
19797
hdd_component_pdev_open(struct wlan_objmgr_pdev * pdev)19798 QDF_STATUS hdd_component_pdev_open(struct wlan_objmgr_pdev *pdev)
19799 {
19800 return ucfg_mlme_pdev_open(pdev);
19801 }
19802
hdd_component_pdev_close(struct wlan_objmgr_pdev * pdev)19803 void hdd_component_pdev_close(struct wlan_objmgr_pdev *pdev)
19804 {
19805 ucfg_mlme_pdev_close(pdev);
19806 }
19807
hdd_qdf_print_init(void)19808 static QDF_STATUS hdd_qdf_print_init(void)
19809 {
19810 QDF_STATUS status;
19811 int qdf_print_idx;
19812
19813 status = qdf_print_setup();
19814 if (QDF_IS_STATUS_ERROR(status)) {
19815 pr_err("Failed qdf_print_setup; status:%u\n", status);
19816 return status;
19817 }
19818
19819 qdf_print_idx = qdf_print_ctrl_register(cinfo, NULL, NULL, "MCL_WLAN");
19820 if (qdf_print_idx < 0) {
19821 pr_err("Failed to register for qdf_print_ctrl\n");
19822 return QDF_STATUS_E_FAILURE;
19823 }
19824
19825 qdf_set_pidx(qdf_print_idx);
19826
19827 return QDF_STATUS_SUCCESS;
19828 }
19829
hdd_qdf_print_deinit(void)19830 static void hdd_qdf_print_deinit(void)
19831 {
19832 int qdf_pidx = qdf_get_pidx();
19833
19834 qdf_set_pidx(-1);
19835 qdf_print_ctrl_cleanup(qdf_pidx);
19836
19837 /* currently, no qdf print 'un-setup'*/
19838 }
19839
hdd_qdf_init(void)19840 static QDF_STATUS hdd_qdf_init(void)
19841 {
19842 QDF_STATUS status;
19843
19844 status = hdd_qdf_print_init();
19845 if (QDF_IS_STATUS_ERROR(status))
19846 goto exit;
19847
19848 status = qdf_debugfs_init();
19849 if (QDF_IS_STATUS_ERROR(status)) {
19850 hdd_err("Failed to init debugfs; status:%u", status);
19851 goto print_deinit;
19852 }
19853
19854 qdf_lock_stats_init();
19855 qdf_mem_init();
19856 qdf_delayed_work_feature_init();
19857 qdf_periodic_work_feature_init();
19858 qdf_wake_lock_feature_init();
19859 qdf_mc_timer_manager_init();
19860 qdf_event_list_init();
19861
19862 status = qdf_talloc_feature_init();
19863 if (QDF_IS_STATUS_ERROR(status)) {
19864 hdd_err("Failed to init talloc; status:%u", status);
19865 goto event_deinit;
19866 }
19867
19868 status = qdf_cpuhp_init();
19869 if (QDF_IS_STATUS_ERROR(status)) {
19870 hdd_err("Failed to init cpuhp; status:%u", status);
19871 goto talloc_deinit;
19872 }
19873
19874 status = qdf_trace_spin_lock_init();
19875 if (QDF_IS_STATUS_ERROR(status)) {
19876 hdd_err("Failed to init spinlock; status:%u", status);
19877 goto cpuhp_deinit;
19878 }
19879
19880 qdf_trace_init();
19881 qdf_minidump_init();
19882 qdf_ssr_driver_dump_init();
19883 qdf_register_debugcb_init();
19884
19885 return QDF_STATUS_SUCCESS;
19886
19887 cpuhp_deinit:
19888 qdf_cpuhp_deinit();
19889 talloc_deinit:
19890 qdf_talloc_feature_deinit();
19891 event_deinit:
19892 qdf_event_list_destroy();
19893 qdf_mc_timer_manager_exit();
19894 qdf_wake_lock_feature_deinit();
19895 qdf_periodic_work_feature_deinit();
19896 qdf_delayed_work_feature_deinit();
19897 qdf_mem_exit();
19898 qdf_lock_stats_deinit();
19899 qdf_debugfs_exit();
19900 print_deinit:
19901 hdd_qdf_print_deinit();
19902
19903 exit:
19904 return status;
19905 }
19906
hdd_qdf_deinit(void)19907 static void hdd_qdf_deinit(void)
19908 {
19909 /* currently, no debugcb deinit */
19910 qdf_ssr_driver_dump_deinit();
19911 qdf_minidump_deinit();
19912 qdf_trace_deinit();
19913
19914 /* currently, no trace spinlock deinit */
19915
19916 qdf_cpuhp_deinit();
19917 qdf_talloc_feature_deinit();
19918 qdf_event_list_destroy();
19919 qdf_mc_timer_manager_exit();
19920 qdf_wake_lock_feature_deinit();
19921 qdf_periodic_work_feature_deinit();
19922 qdf_delayed_work_feature_deinit();
19923 qdf_mem_exit();
19924 qdf_lock_stats_deinit();
19925 qdf_debugfs_exit();
19926 hdd_qdf_print_deinit();
19927 }
19928
19929 #ifdef FEATURE_MONITOR_MODE_SUPPORT
is_monitor_mode_supported(void)19930 static bool is_monitor_mode_supported(void)
19931 {
19932 return true;
19933 }
19934 #else
is_monitor_mode_supported(void)19935 static bool is_monitor_mode_supported(void)
19936 {
19937 pr_err("Monitor mode not supported!");
19938 return false;
19939 }
19940 #endif
19941
19942 #ifdef WLAN_FEATURE_EPPING
is_epping_mode_supported(void)19943 static bool is_epping_mode_supported(void)
19944 {
19945 return true;
19946 }
19947 #else
is_epping_mode_supported(void)19948 static bool is_epping_mode_supported(void)
19949 {
19950 pr_err("Epping mode not supported!");
19951 return false;
19952 }
19953 #endif
19954
19955 #ifdef QCA_WIFI_FTM
is_ftm_mode_supported(void)19956 static bool is_ftm_mode_supported(void)
19957 {
19958 return true;
19959 }
19960 #else
is_ftm_mode_supported(void)19961 static bool is_ftm_mode_supported(void)
19962 {
19963 pr_err("FTM mode not supported!");
19964 return false;
19965 }
19966 #endif
19967
19968 /**
19969 * is_con_mode_valid() - check con mode is valid or not
19970 * @mode: global con mode
19971 *
19972 * Return: TRUE on success FALSE on failure
19973 */
is_con_mode_valid(enum QDF_GLOBAL_MODE mode)19974 static bool is_con_mode_valid(enum QDF_GLOBAL_MODE mode)
19975 {
19976 switch (mode) {
19977 case QDF_GLOBAL_MONITOR_MODE:
19978 return is_monitor_mode_supported();
19979 case QDF_GLOBAL_EPPING_MODE:
19980 return is_epping_mode_supported();
19981 case QDF_GLOBAL_FTM_MODE:
19982 return is_ftm_mode_supported();
19983 case QDF_GLOBAL_MISSION_MODE:
19984 return true;
19985 default:
19986 return false;
19987 }
19988 }
19989
hdd_stop_present_mode(struct hdd_context * hdd_ctx,enum QDF_GLOBAL_MODE curr_mode)19990 static void hdd_stop_present_mode(struct hdd_context *hdd_ctx,
19991 enum QDF_GLOBAL_MODE curr_mode)
19992 {
19993 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED)
19994 return;
19995
19996 switch (curr_mode) {
19997 case QDF_GLOBAL_MONITOR_MODE:
19998 hdd_info("Release wakelock for monitor mode!");
19999 qdf_wake_lock_release(&hdd_ctx->monitor_mode_wakelock,
20000 WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);
20001 fallthrough;
20002 case QDF_GLOBAL_MISSION_MODE:
20003 case QDF_GLOBAL_FTM_MODE:
20004 hdd_abort_mac_scan_all_adapters(hdd_ctx);
20005 wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, NULL);
20006 hdd_stop_all_adapters(hdd_ctx);
20007 hdd_deinit_all_adapters(hdd_ctx, false);
20008
20009 break;
20010 default:
20011 break;
20012 }
20013 }
20014
hdd_cleanup_present_mode(struct hdd_context * hdd_ctx,enum QDF_GLOBAL_MODE curr_mode)20015 static void hdd_cleanup_present_mode(struct hdd_context *hdd_ctx,
20016 enum QDF_GLOBAL_MODE curr_mode)
20017 {
20018 switch (curr_mode) {
20019 case QDF_GLOBAL_MISSION_MODE:
20020 case QDF_GLOBAL_MONITOR_MODE:
20021 case QDF_GLOBAL_FTM_MODE:
20022 hdd_close_all_adapters(hdd_ctx, false);
20023 break;
20024 case QDF_GLOBAL_EPPING_MODE:
20025 epping_disable();
20026 epping_close();
20027 break;
20028 default:
20029 return;
20030 }
20031 }
20032
20033 static int
hdd_parse_driver_mode(const char * mode_str,enum QDF_GLOBAL_MODE * out_mode)20034 hdd_parse_driver_mode(const char *mode_str, enum QDF_GLOBAL_MODE *out_mode)
20035 {
20036 QDF_STATUS status;
20037 uint32_t mode;
20038
20039 *out_mode = QDF_GLOBAL_MAX_MODE;
20040
20041 status = qdf_uint32_parse(mode_str, &mode);
20042 if (QDF_IS_STATUS_ERROR(status))
20043 return qdf_status_to_os_return(status);
20044
20045 if (mode >= QDF_GLOBAL_MAX_MODE)
20046 return -ERANGE;
20047
20048 *out_mode = (enum QDF_GLOBAL_MODE)mode;
20049
20050 return 0;
20051 }
20052
hdd_mode_change_psoc_idle_shutdown(struct device * dev)20053 static int hdd_mode_change_psoc_idle_shutdown(struct device *dev)
20054 {
20055 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
20056
20057 if (!hdd_ctx)
20058 return -EINVAL;
20059
20060 return hdd_wlan_stop_modules(hdd_ctx, true);
20061 }
20062
hdd_mode_change_psoc_idle_restart(struct device * dev)20063 static int hdd_mode_change_psoc_idle_restart(struct device *dev)
20064 {
20065 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
20066 int ret;
20067
20068 if (!hdd_ctx)
20069 return -EINVAL;
20070 ret = hdd_soc_idle_restart_lock(dev);
20071 if (ret)
20072 return ret;
20073 ret = hdd_wlan_start_modules(hdd_ctx, false);
20074 hdd_soc_idle_restart_unlock();
20075
20076 return ret;
20077 }
20078
20079 /**
20080 * __hdd_driver_mode_change() - Handles a driver mode change
20081 * @hdd_ctx: Pointer to the global HDD context
20082 * @next_mode: the driver mode to transition to
20083 *
20084 * This function is invoked when user updates con_mode using sys entry,
20085 * to initialize and bring-up driver in that specific mode.
20086 *
20087 * Return: Errno
20088 */
__hdd_driver_mode_change(struct hdd_context * hdd_ctx,enum QDF_GLOBAL_MODE next_mode)20089 static int __hdd_driver_mode_change(struct hdd_context *hdd_ctx,
20090 enum QDF_GLOBAL_MODE next_mode)
20091 {
20092 enum QDF_GLOBAL_MODE curr_mode;
20093 int errno;
20094 struct bbm_params param = {0};
20095
20096 hdd_info("Driver mode changing to %d", next_mode);
20097
20098 errno = wlan_hdd_validate_context(hdd_ctx);
20099 if (errno)
20100 return errno;
20101
20102 if (!is_con_mode_valid(next_mode)) {
20103 hdd_err_rl("Requested driver mode is invalid");
20104 return -EINVAL;
20105 }
20106
20107 curr_mode = hdd_get_conparam();
20108 if (curr_mode == next_mode) {
20109 hdd_err_rl("Driver is already in the requested mode");
20110 return 0;
20111 }
20112
20113 hdd_psoc_idle_timer_stop(hdd_ctx);
20114
20115 /* ensure adapters are stopped */
20116 hdd_stop_present_mode(hdd_ctx, curr_mode);
20117
20118 if (DRIVER_MODULES_CLOSED != hdd_ctx->driver_status) {
20119 is_mode_change_psoc_idle_shutdown = true;
20120 errno = pld_idle_shutdown(hdd_ctx->parent_dev,
20121 hdd_mode_change_psoc_idle_shutdown);
20122 if (errno) {
20123 is_mode_change_psoc_idle_shutdown = false;
20124 hdd_err("Stop wlan modules failed");
20125 return errno;
20126 }
20127 }
20128
20129 /* Cleanup present mode before switching to new mode */
20130 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
20131
20132 hdd_set_conparam(next_mode);
20133 pld_set_mode(next_mode);
20134
20135 qdf_event_reset(&hdd_ctx->regulatory_update_event);
20136 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
20137 hdd_ctx->is_regulatory_update_in_progress = true;
20138 qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
20139
20140 errno = pld_idle_restart(hdd_ctx->parent_dev,
20141 hdd_mode_change_psoc_idle_restart);
20142 if (errno) {
20143 hdd_err("Start wlan modules failed: %d", errno);
20144 return errno;
20145 }
20146
20147 errno = hdd_open_adapters_for_mode(hdd_ctx, next_mode);
20148 if (errno) {
20149 hdd_err("Failed to open adapters");
20150 return errno;
20151 }
20152
20153 if (next_mode == QDF_GLOBAL_MONITOR_MODE) {
20154 struct hdd_adapter *adapter =
20155 hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
20156
20157 QDF_BUG(adapter);
20158 if (!adapter) {
20159 hdd_err("Failed to get monitor adapter");
20160 return -EINVAL;
20161 }
20162
20163 errno = hdd_start_adapter(adapter, false);
20164 if (errno) {
20165 hdd_err("Failed to start monitor adapter");
20166 return errno;
20167 }
20168
20169 hdd_info("Acquire wakelock for monitor mode");
20170 qdf_wake_lock_acquire(&hdd_ctx->monitor_mode_wakelock,
20171 WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);
20172 }
20173
20174 /* con_mode is a global module parameter */
20175 con_mode = next_mode;
20176 hdd_info("Driver mode successfully changed to %d", next_mode);
20177
20178 param.policy = BBM_DRIVER_MODE_POLICY;
20179 param.policy_info.driver_mode = con_mode;
20180 ucfg_dp_bbm_apply_independent_policy(hdd_ctx->psoc, ¶m);
20181
20182 return 0;
20183 }
20184
hdd_pre_mode_change(enum QDF_GLOBAL_MODE mode)20185 static void hdd_pre_mode_change(enum QDF_GLOBAL_MODE mode)
20186 {
20187 struct osif_psoc_sync *psoc_sync;
20188 struct hdd_context *hdd_ctx;
20189 int errno;
20190 enum QDF_GLOBAL_MODE curr_mode;
20191
20192 curr_mode = hdd_get_conparam();
20193 if (curr_mode != QDF_GLOBAL_MISSION_MODE)
20194 return;
20195
20196 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
20197 errno = wlan_hdd_validate_context(hdd_ctx);
20198 if (errno)
20199 return;
20200
20201 errno = osif_psoc_sync_op_start(hdd_ctx->parent_dev, &psoc_sync);
20202 if (errno) {
20203 hdd_err("psoc op start failed");
20204 return;
20205 }
20206
20207 hdd_debug("cleanup scan queue");
20208 if (hdd_ctx && hdd_ctx->pdev)
20209 wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, NULL);
20210
20211 osif_psoc_sync_op_stop(psoc_sync);
20212 }
20213
hdd_driver_mode_change(enum QDF_GLOBAL_MODE mode)20214 static int hdd_driver_mode_change(enum QDF_GLOBAL_MODE mode)
20215 {
20216 struct osif_driver_sync *driver_sync;
20217 struct hdd_context *hdd_ctx;
20218 QDF_STATUS status;
20219 int errno;
20220
20221 hdd_enter();
20222
20223 hdd_pre_mode_change(mode);
20224
20225 status = osif_driver_sync_trans_start_wait(&driver_sync);
20226 if (QDF_IS_STATUS_ERROR(status)) {
20227 hdd_err("Failed to start 'mode change'; status:%u", status);
20228 errno = qdf_status_to_os_return(status);
20229 goto exit;
20230 }
20231
20232 osif_driver_sync_wait_for_ops(driver_sync);
20233
20234 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
20235 errno = wlan_hdd_validate_context(hdd_ctx);
20236 if (errno)
20237 goto trans_stop;
20238
20239 errno = __hdd_driver_mode_change(hdd_ctx, mode);
20240
20241 trans_stop:
20242 osif_driver_sync_trans_stop(driver_sync);
20243
20244 exit:
20245 hdd_exit();
20246
20247 return errno;
20248 }
20249
hdd_set_con_mode(enum QDF_GLOBAL_MODE mode)20250 static int hdd_set_con_mode(enum QDF_GLOBAL_MODE mode)
20251 {
20252 con_mode = mode;
20253
20254 return 0;
20255 }
20256
20257 static int (*hdd_set_con_mode_cb)(enum QDF_GLOBAL_MODE mode) = hdd_set_con_mode;
20258
hdd_driver_mode_change_register(void)20259 static void hdd_driver_mode_change_register(void)
20260 {
20261 hdd_set_con_mode_cb = hdd_driver_mode_change;
20262 }
20263
hdd_driver_mode_change_unregister(void)20264 static void hdd_driver_mode_change_unregister(void)
20265 {
20266 hdd_set_con_mode_cb = hdd_set_con_mode;
20267 }
20268
con_mode_handler(const char * kmessage,const struct kernel_param * kp)20269 static int con_mode_handler(const char *kmessage, const struct kernel_param *kp)
20270 {
20271 enum QDF_GLOBAL_MODE mode;
20272 int errno;
20273
20274 errno = hdd_parse_driver_mode(kmessage, &mode);
20275 if (errno) {
20276 hdd_err_rl("Failed to parse driver mode '%s'", kmessage);
20277 return errno;
20278 }
20279
20280 return hdd_set_con_mode_cb(mode);
20281 }
20282
20283 /*
20284 * If the wlan_hdd_register_driver will return an error
20285 * if the wlan driver tries to register with the
20286 * platform driver before cnss_probe is completed.
20287 * Depending on the error code, the wlan driver waits
20288 * and retries to register.
20289 */
20290
20291 /* Max number of retries (arbitrary)*/
20292 #define HDD_MAX_PLD_REGISTER_RETRY (50)
20293
20294 /* Max amount of time we sleep before each retry */
20295 #define HDD_PLD_REGISTER_FAIL_SLEEP_DURATION (100)
20296
hdd_register_driver_retry(void)20297 static int hdd_register_driver_retry(void)
20298 {
20299 int count = 0;
20300 int errno;
20301
20302 while (true) {
20303 errno = wlan_hdd_register_driver();
20304 if (errno != -EAGAIN)
20305 return errno;
20306 hdd_nofl_info("Retry Platform Driver Registration; errno:%d count:%d",
20307 errno, count);
20308 if (++count == HDD_MAX_PLD_REGISTER_RETRY)
20309 return errno;
20310 msleep(HDD_PLD_REGISTER_FAIL_SLEEP_DURATION);
20311 continue;
20312 }
20313
20314 return errno;
20315 }
20316
20317 /**
20318 * hdd_create_wifi_feature_interface() - Create wifi feature interface
20319 *
20320 * Return: none
20321 */
hdd_create_wifi_feature_interface(void)20322 static void hdd_create_wifi_feature_interface(void)
20323 {
20324 hdd_sysfs_create_wifi_root_obj();
20325 hdd_create_wifi_feature_interface_sysfs_file();
20326 }
20327
hdd_driver_load(void)20328 int hdd_driver_load(void)
20329 {
20330 struct osif_driver_sync *driver_sync;
20331 QDF_STATUS status;
20332 int errno;
20333 bool soft_load;
20334
20335 pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
20336 g_wlan_driver_version);
20337 hdd_place_marker(NULL, "START LOADING", NULL);
20338
20339 status = hdd_qdf_init();
20340 if (QDF_IS_STATUS_ERROR(status)) {
20341 errno = qdf_status_to_os_return(status);
20342 goto exit;
20343 }
20344
20345 osif_sync_init();
20346
20347 status = osif_driver_sync_create_and_trans(&driver_sync);
20348 if (QDF_IS_STATUS_ERROR(status)) {
20349 hdd_err("Failed to init driver sync; status:%u", status);
20350 errno = qdf_status_to_os_return(status);
20351 goto sync_deinit;
20352 }
20353
20354 errno = hdd_init();
20355 if (errno) {
20356 hdd_err("Failed to init HDD; errno:%d", errno);
20357 goto trans_stop;
20358 }
20359
20360 status = hdd_component_cb_init();
20361 if (QDF_IS_STATUS_ERROR(status)) {
20362 hdd_err("Failed to init component cb; status:%u", status);
20363 errno = qdf_status_to_os_return(status);
20364 goto hdd_deinit;
20365 }
20366
20367 status = hdd_component_init();
20368 if (QDF_IS_STATUS_ERROR(status)) {
20369 hdd_err("Failed to init components; status:%u", status);
20370 errno = qdf_status_to_os_return(status);
20371 goto comp_cb_deinit;
20372 }
20373
20374 status = qdf_wake_lock_create(&wlan_wake_lock, "wlan");
20375 if (QDF_IS_STATUS_ERROR(status)) {
20376 hdd_err("Failed to create wake lock; status:%u", status);
20377 errno = qdf_status_to_os_return(status);
20378 goto comp_deinit;
20379 }
20380
20381 hdd_set_conparam(con_mode);
20382
20383 errno = pld_init();
20384 if (errno) {
20385 hdd_err("Failed to init PLD; errno:%d", errno);
20386 goto wakelock_destroy;
20387 }
20388
20389 /* driver mode pass to cnss2 platform driver*/
20390 errno = pld_set_mode(con_mode);
20391 if (errno)
20392 hdd_err("Failed to set mode in PLD; errno:%d", errno);
20393
20394 hdd_driver_mode_change_register();
20395
20396 osif_driver_sync_register(driver_sync);
20397 osif_driver_sync_trans_stop(driver_sync);
20398
20399 /* psoc probe can happen in registration; do after 'load' transition */
20400 errno = hdd_register_driver_retry();
20401 if (errno) {
20402 hdd_err("Failed to register driver; errno:%d", errno);
20403 goto pld_deinit;
20404 }
20405
20406 /* If a soft unload of driver is done, we don't call
20407 * wlan_hdd_state_ctrl_param_destroy() to maintain sync
20408 * with userspace. In Symmetry, during soft load, avoid
20409 * calling wlan_hdd_state_ctrl_param_create().
20410 */
20411 soft_load = hdd_get_wlan_driver_status();
20412 if (soft_load)
20413 goto out;
20414
20415 errno = wlan_hdd_state_ctrl_param_create();
20416 if (errno) {
20417 hdd_err("Failed to create ctrl param; errno:%d", errno);
20418 goto unregister_driver;
20419 }
20420 hdd_create_wifi_feature_interface();
20421 out:
20422 hdd_debug("%s: driver loaded", WLAN_MODULE_NAME);
20423 hdd_place_marker(NULL, "DRIVER LOADED", NULL);
20424
20425 return 0;
20426
20427 unregister_driver:
20428 wlan_hdd_unregister_driver();
20429 pld_deinit:
20430 status = osif_driver_sync_trans_start(&driver_sync);
20431 QDF_BUG(QDF_IS_STATUS_SUCCESS(status));
20432
20433 osif_driver_sync_unregister();
20434 if (driver_sync)
20435 osif_driver_sync_wait_for_ops(driver_sync);
20436
20437 hdd_driver_mode_change_unregister();
20438 pld_deinit();
20439
20440 hdd_start_complete(errno);
20441 /* Wait for any ref taken on /dev/wlan to be released */
20442 while (qdf_atomic_read(&wlan_hdd_state_fops_ref))
20443 ;
20444 wakelock_destroy:
20445 qdf_wake_lock_destroy(&wlan_wake_lock);
20446 comp_deinit:
20447 hdd_component_deinit();
20448 comp_cb_deinit:
20449 hdd_component_cb_deinit();
20450 hdd_deinit:
20451 hdd_deinit();
20452 trans_stop:
20453 if (driver_sync) {
20454 osif_driver_sync_trans_stop(driver_sync);
20455 osif_driver_sync_destroy(driver_sync);
20456 }
20457 sync_deinit:
20458 osif_sync_deinit();
20459 hdd_qdf_deinit();
20460
20461 exit:
20462 return errno;
20463 }
20464
20465 #ifdef FEATURE_WLAN_RESIDENT_DRIVER
20466 EXPORT_SYMBOL(hdd_driver_load);
20467 #endif
20468
20469 /**
20470 * hdd_distroy_wifi_feature_interface() - Distroy wifi feature interface
20471 *
20472 * Return: none
20473 */
hdd_distroy_wifi_feature_interface(void)20474 static void hdd_distroy_wifi_feature_interface(void)
20475 {
20476 hdd_destroy_wifi_feature_interface_sysfs_file();
20477 hdd_sysfs_destroy_wifi_root_obj();
20478 }
20479
hdd_driver_unload(void)20480 void hdd_driver_unload(void)
20481 {
20482 struct osif_driver_sync *driver_sync;
20483 struct hdd_context *hdd_ctx;
20484 QDF_STATUS status;
20485 void *hif_ctx;
20486 bool soft_unload;
20487
20488 soft_unload = hdd_get_wlan_driver_status();
20489 if (soft_unload) {
20490 pr_info("%s: Soft Unloading driver v%s\n", WLAN_MODULE_NAME,
20491 QWLAN_VERSIONSTR);
20492 } else {
20493 pr_info("%s: Hard Unloading driver v%s\n", WLAN_MODULE_NAME,
20494 QWLAN_VERSIONSTR);
20495 }
20496
20497 hdd_place_marker(NULL, "START UNLOADING", NULL);
20498
20499 /*
20500 * Wait for any trans to complete and then start the driver trans
20501 * for the unload. This will ensure that the driver trans proceeds only
20502 * after all trans have been completed. As a part of this trans, set
20503 * the driver load/unload flag to further ensure that any upcoming
20504 * trans are rejected via wlan_hdd_validate_context.
20505 */
20506 status = osif_driver_sync_trans_start_wait(&driver_sync);
20507 if (QDF_IS_STATUS_ERROR(status) && status != -ETIMEDOUT) {
20508 QDF_BUG(QDF_IS_STATUS_SUCCESS(status));
20509 hdd_err("Unable to unload wlan; status:%u", status);
20510 hdd_place_marker(NULL, "UNLOAD FAILURE", NULL);
20511 return;
20512 }
20513
20514 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
20515 if (hif_ctx) {
20516 /*
20517 * Trigger runtime sync resume before setting unload in progress
20518 * such that resume can happen successfully
20519 */
20520 qdf_rtpm_sync_resume();
20521 }
20522
20523 cds_set_driver_loaded(false);
20524 cds_set_unload_in_progress(true);
20525
20526 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
20527 if (hdd_ctx) {
20528 hdd_psoc_idle_timer_stop(hdd_ctx);
20529 /*
20530 * Runtime PM sync resume may have started the bus bandwidth
20531 * periodic work hence stop it.
20532 */
20533 ucfg_dp_bus_bw_compute_timer_stop(hdd_ctx->psoc);
20534 }
20535
20536 /*
20537 * Stop the trans before calling unregister_driver as that involves a
20538 * call to pld_remove which in itself is a psoc transaction
20539 */
20540 if (driver_sync)
20541 osif_driver_sync_trans_stop(driver_sync);
20542
20543 hdd_distroy_wifi_feature_interface();
20544 if (!soft_unload)
20545 wlan_hdd_state_ctrl_param_destroy();
20546
20547 /* trigger SoC remove */
20548 wlan_hdd_unregister_driver();
20549
20550 status = osif_driver_sync_trans_start_wait(&driver_sync);
20551 if (QDF_IS_STATUS_ERROR(status) && status != -ETIMEDOUT) {
20552 QDF_BUG(QDF_IS_STATUS_SUCCESS(status));
20553 hdd_err("Unable to unload wlan; status:%u", status);
20554 hdd_place_marker(NULL, "UNLOAD FAILURE", NULL);
20555 return;
20556 }
20557
20558 osif_driver_sync_unregister();
20559 if (driver_sync)
20560 osif_driver_sync_wait_for_ops(driver_sync);
20561
20562 hdd_driver_mode_change_unregister();
20563 pld_deinit();
20564 hdd_set_conparam(0);
20565 qdf_wake_lock_destroy(&wlan_wake_lock);
20566 hdd_component_deinit();
20567 hdd_component_cb_deinit();
20568 hdd_deinit();
20569
20570 if (driver_sync) {
20571 osif_driver_sync_trans_stop(driver_sync);
20572 osif_driver_sync_destroy(driver_sync);
20573 }
20574 osif_sync_deinit();
20575
20576 hdd_qdf_deinit();
20577 hdd_place_marker(NULL, "UNLOAD DONE", NULL);
20578 }
20579
20580 #ifdef FEATURE_WLAN_RESIDENT_DRIVER
20581 EXPORT_SYMBOL(hdd_driver_unload);
20582 #endif
20583
20584 #ifndef MODULE
20585 /**
20586 * wlan_boot_cb() - Wlan boot callback
20587 * @kobj: object whose directory we're creating the link in.
20588 * @attr: attribute the user is interacting with
20589 * @buf: the buffer containing the user data
20590 * @count: number of bytes in the buffer
20591 *
20592 * This callback is invoked when the fs is ready to start the
20593 * wlan driver initialization.
20594 *
20595 * Return: 'count' on success or a negative error code in case of failure
20596 */
wlan_boot_cb(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)20597 static ssize_t wlan_boot_cb(struct kobject *kobj,
20598 struct kobj_attribute *attr,
20599 const char *buf,
20600 size_t count)
20601 {
20602
20603 if (wlan_loader->loaded_state) {
20604 hdd_err("wlan driver already initialized");
20605 return -EALREADY;
20606 }
20607
20608 if (hdd_driver_load())
20609 return -EIO;
20610
20611 wlan_loader->loaded_state = MODULE_INITIALIZED;
20612
20613 return count;
20614 }
20615
20616 /**
20617 * hdd_sysfs_cleanup() - cleanup sysfs
20618 *
20619 * Return: None
20620 *
20621 */
hdd_sysfs_cleanup(void)20622 static void hdd_sysfs_cleanup(void)
20623 {
20624 /* remove from group */
20625 if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
20626 sysfs_remove_group(wlan_loader->boot_wlan_obj,
20627 wlan_loader->attr_group);
20628
20629 /* unlink the object from parent */
20630 kobject_del(wlan_loader->boot_wlan_obj);
20631
20632 /* free the object */
20633 kobject_put(wlan_loader->boot_wlan_obj);
20634
20635 kfree(wlan_loader->attr_group);
20636 kfree(wlan_loader);
20637
20638 wlan_loader = NULL;
20639 }
20640
20641 /**
20642 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
20643 * ready
20644 *
20645 * This is creates the syfs entry boot_wlan. Which shall be invoked
20646 * when the filesystem is ready.
20647 *
20648 * QDF API cannot be used here since this function is called even before
20649 * initializing WLAN driver.
20650 *
20651 * Return: 0 for success, errno on failure
20652 */
wlan_init_sysfs(void)20653 static int wlan_init_sysfs(void)
20654 {
20655 int ret = -ENOMEM;
20656
20657 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
20658 if (!wlan_loader)
20659 return -ENOMEM;
20660
20661 wlan_loader->boot_wlan_obj = NULL;
20662 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
20663 GFP_KERNEL);
20664 if (!wlan_loader->attr_group)
20665 goto error_return;
20666
20667 wlan_loader->loaded_state = 0;
20668 wlan_loader->attr_group->attrs = attrs;
20669
20670 wlan_loader->boot_wlan_obj = kobject_create_and_add(WLAN_LOADER_NAME,
20671 kernel_kobj);
20672 if (!wlan_loader->boot_wlan_obj) {
20673 hdd_err("sysfs create and add failed");
20674 goto error_return;
20675 }
20676
20677 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
20678 wlan_loader->attr_group);
20679 if (ret) {
20680 hdd_err("sysfs create group failed; errno:%d", ret);
20681 goto error_return;
20682 }
20683
20684 return 0;
20685
20686 error_return:
20687 hdd_sysfs_cleanup();
20688
20689 return ret;
20690 }
20691
20692 /**
20693 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
20694 *
20695 * Return: 0 on success or errno on failure
20696 */
wlan_deinit_sysfs(void)20697 static int wlan_deinit_sysfs(void)
20698 {
20699 if (!wlan_loader) {
20700 hdd_err("wlan_loader is null");
20701 return -EINVAL;
20702 }
20703
20704 hdd_sysfs_cleanup();
20705 return 0;
20706 }
20707
20708 #endif /* MODULE */
20709
20710 #ifdef MODULE
20711 /**
20712 * hdd_module_init() - Module init helper
20713 *
20714 * Module init helper function used by both module and static driver.
20715 *
20716 * Return: 0 for success, errno on failure
20717 */
20718 #ifdef FEATURE_WLAN_RESIDENT_DRIVER
hdd_module_init(void)20719 static int hdd_module_init(void)
20720 {
20721 return 0;
20722 }
20723 #else
hdd_module_init(void)20724 static int hdd_module_init(void)
20725 {
20726 if (hdd_driver_load())
20727 return -EINVAL;
20728
20729 return 0;
20730 }
20731 #endif
20732 #else
hdd_module_init(void)20733 static int __init hdd_module_init(void)
20734 {
20735 int ret = -EINVAL;
20736
20737 ret = wlan_init_sysfs();
20738 if (ret)
20739 hdd_err("Failed to create sysfs entry");
20740
20741 return ret;
20742 }
20743 #endif
20744
20745
20746 #ifdef MODULE
20747 /**
20748 * hdd_module_exit() - Exit function
20749 *
20750 * This is the driver exit point (invoked when module is unloaded using rmmod)
20751 *
20752 * Return: None
20753 */
20754 #ifdef FEATURE_WLAN_RESIDENT_DRIVER
hdd_module_exit(void)20755 static void __exit hdd_module_exit(void)
20756 {
20757 }
20758 #else
hdd_module_exit(void)20759 static void __exit hdd_module_exit(void)
20760 {
20761 hdd_driver_unload();
20762 }
20763 #endif
20764 #else
hdd_module_exit(void)20765 static void __exit hdd_module_exit(void)
20766 {
20767 hdd_driver_unload();
20768 wlan_deinit_sysfs();
20769 }
20770 #endif
20771
fwpath_changed_handler(const char * kmessage,const struct kernel_param * kp)20772 static int fwpath_changed_handler(const char *kmessage,
20773 const struct kernel_param *kp)
20774 {
20775 return param_set_copystring(kmessage, kp);
20776 }
20777
con_mode_handler_ftm(const char * kmessage,const struct kernel_param * kp)20778 static int con_mode_handler_ftm(const char *kmessage,
20779 const struct kernel_param *kp)
20780 {
20781 int ret;
20782
20783 ret = param_set_int(kmessage, kp);
20784
20785 if (cds_is_driver_loaded() || cds_is_load_or_unload_in_progress()) {
20786 pr_err("Driver already loaded or load/unload in progress");
20787 return -ENOTSUPP;
20788 }
20789
20790 if (con_mode_ftm != QDF_GLOBAL_FTM_MODE) {
20791 pr_err("Only FTM mode supported!");
20792 return -ENOTSUPP;
20793 }
20794
20795 hdd_set_conparam(con_mode_ftm);
20796 con_mode = con_mode_ftm;
20797
20798 return ret;
20799 }
20800
20801 #ifdef WLAN_FEATURE_EPPING
con_mode_handler_epping(const char * kmessage,const struct kernel_param * kp)20802 static int con_mode_handler_epping(const char *kmessage,
20803 const struct kernel_param *kp)
20804 {
20805 int ret;
20806
20807 ret = param_set_int(kmessage, kp);
20808
20809 if (con_mode_epping != QDF_GLOBAL_EPPING_MODE) {
20810 pr_err("Only EPPING mode supported!");
20811 return -ENOTSUPP;
20812 }
20813
20814 hdd_set_conparam(con_mode_epping);
20815 con_mode = con_mode_epping;
20816
20817 return ret;
20818 }
20819 #endif
20820
20821 /**
20822 * hdd_get_conparam() - driver exit point
20823 *
20824 * This is the driver exit point (invoked when module is unloaded using rmmod)
20825 *
20826 * Return: enum QDF_GLOBAL_MODE
20827 */
hdd_get_conparam(void)20828 enum QDF_GLOBAL_MODE hdd_get_conparam(void)
20829 {
20830 return (enum QDF_GLOBAL_MODE) curr_con_mode;
20831 }
20832
hdd_set_conparam(int32_t con_param)20833 void hdd_set_conparam(int32_t con_param)
20834 {
20835 curr_con_mode = con_param;
20836 }
20837
20838 /**
20839 * hdd_svc_fw_crashed_ind() - API to send FW CRASHED IND to Userspace
20840 *
20841 * Return: void
20842 */
hdd_svc_fw_crashed_ind(void)20843 static void hdd_svc_fw_crashed_ind(void)
20844 {
20845 struct hdd_context *hdd_ctx;
20846
20847 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
20848
20849 hdd_ctx ? wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
20850 WLAN_SVC_FW_CRASHED_IND,
20851 NULL, 0) : 0;
20852 }
20853
20854 /**
20855 * hdd_update_ol_config - API to update ol configuration parameters
20856 * @hdd_ctx: HDD context
20857 *
20858 * Return: void
20859 */
hdd_update_ol_config(struct hdd_context * hdd_ctx)20860 static void hdd_update_ol_config(struct hdd_context *hdd_ctx)
20861 {
20862 struct ol_config_info cfg = {0};
20863 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
20864 bool self_recovery = false;
20865 QDF_STATUS status;
20866
20867 if (!ol_ctx)
20868 return;
20869
20870 status = ucfg_mlme_get_self_recovery(hdd_ctx->psoc, &self_recovery);
20871 if (QDF_IS_STATUS_ERROR(status))
20872 hdd_err("Failed to get self recovery ini config");
20873
20874 cfg.enable_self_recovery = self_recovery;
20875 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
20876 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
20877 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
20878 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
20879
20880 ol_init_ini_config(ol_ctx, &cfg);
20881 ol_set_fw_crashed_cb(ol_ctx, hdd_svc_fw_crashed_ind);
20882 }
20883
20884 #ifdef FEATURE_RUNTIME_PM
20885 /**
20886 * hdd_populate_runtime_cfg() - populate runtime configuration
20887 * @hdd_ctx: hdd context
20888 * @cfg: pointer to the configuration memory being populated
20889 *
20890 * Return: void
20891 */
hdd_populate_runtime_cfg(struct hdd_context * hdd_ctx,struct hif_config_info * cfg)20892 static void hdd_populate_runtime_cfg(struct hdd_context *hdd_ctx,
20893 struct hif_config_info *cfg)
20894 {
20895 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
20896 cfg->runtime_pm_delay =
20897 ucfg_pmo_get_runtime_pm_delay(hdd_ctx->psoc);
20898 }
20899 #else
hdd_populate_runtime_cfg(struct hdd_context * hdd_ctx,struct hif_config_info * cfg)20900 static void hdd_populate_runtime_cfg(struct hdd_context *hdd_ctx,
20901 struct hif_config_info *cfg)
20902 {
20903 }
20904 #endif
20905
20906 #ifdef FEATURE_ENABLE_CE_DP_IRQ_AFFINE
20907 /**
20908 * hdd_populate_ce_dp_irq_affine_cfg() - populate ce irq affine configuration
20909 * @hdd_ctx: hdd context
20910 * @cfg: pointer to the configuration memory being populated
20911 *
20912 * Return: void
20913 */
hdd_populate_ce_dp_irq_affine_cfg(struct hdd_context * hdd_ctx,struct hif_config_info * cfg)20914 static void hdd_populate_ce_dp_irq_affine_cfg(struct hdd_context *hdd_ctx,
20915 struct hif_config_info *cfg)
20916 {
20917 cfg->enable_ce_dp_irq_affine = cfg_get(hdd_ctx->psoc,
20918 CFG_ENABLE_CE_DP_IRQ_AFFINE);
20919 }
20920 #else
hdd_populate_ce_dp_irq_affine_cfg(struct hdd_context * hdd_ctx,struct hif_config_info * cfg)20921 static void hdd_populate_ce_dp_irq_affine_cfg(struct hdd_context *hdd_ctx,
20922 struct hif_config_info *cfg)
20923 {
20924 }
20925 #endif
20926
20927 /**
20928 * hdd_update_hif_config - API to update HIF configuration parameters
20929 * @hdd_ctx: HDD Context
20930 *
20931 * Return: void
20932 */
hdd_update_hif_config(struct hdd_context * hdd_ctx)20933 static void hdd_update_hif_config(struct hdd_context *hdd_ctx)
20934 {
20935 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
20936 struct hif_config_info cfg = {0};
20937 bool prevent_link_down = false;
20938 bool self_recovery = false;
20939 QDF_STATUS status;
20940
20941 if (!scn)
20942 return;
20943
20944 status = ucfg_mlme_get_prevent_link_down(hdd_ctx->psoc,
20945 &prevent_link_down);
20946 if (QDF_IS_STATUS_ERROR(status))
20947 hdd_err("Failed to get prevent_link_down config");
20948
20949 status = ucfg_mlme_get_self_recovery(hdd_ctx->psoc, &self_recovery);
20950 if (QDF_IS_STATUS_ERROR(status))
20951 hdd_err("Failed to get self recovery ini config");
20952
20953 cfg.enable_self_recovery = self_recovery;
20954 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
20955 cfg.rx_softirq_max_yield_duration_ns =
20956 ucfg_dp_get_rx_softirq_yield_duration(hdd_ctx->psoc);
20957 hdd_populate_ce_dp_irq_affine_cfg(hdd_ctx, &cfg);
20958
20959 hif_init_ini_config(scn, &cfg);
20960 hif_set_enable_rpm(scn);
20961
20962 if (prevent_link_down)
20963 hif_vote_link_up(scn);
20964 }
20965
20966 /**
20967 * hdd_update_dp_config() - Propagate config parameters to Lithium
20968 * datapath
20969 * @hdd_ctx: HDD Context
20970 *
20971 * Return: 0 for success/errno for failure
20972 */
hdd_update_dp_config(struct hdd_context * hdd_ctx)20973 static int hdd_update_dp_config(struct hdd_context *hdd_ctx)
20974 {
20975 struct wlan_dp_user_config dp_cfg;
20976 QDF_STATUS status;
20977
20978 dp_cfg.ipa_enable = ucfg_ipa_is_enabled();
20979 dp_cfg.arp_connectivity_map = CONNECTIVITY_CHECK_SET_ARP;
20980
20981 status = ucfg_dp_update_config(hdd_ctx->psoc, &dp_cfg);
20982 if (status != QDF_STATUS_SUCCESS) {
20983 hdd_err("failed DP PSOC configuration update");
20984 return -EINVAL;
20985 }
20986
20987 return 0;
20988 }
20989
20990 /**
20991 * hdd_update_config() - Initialize driver per module ini parameters
20992 * @hdd_ctx: HDD Context
20993 *
20994 * API is used to initialize all driver per module configuration parameters
20995 * Return: 0 for success, errno for failure
20996 */
hdd_update_config(struct hdd_context * hdd_ctx)20997 int hdd_update_config(struct hdd_context *hdd_ctx)
20998 {
20999 int ret;
21000
21001 if (ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc))
21002 hdd_ctx->ns_offload_enable = true;
21003
21004 hdd_update_ol_config(hdd_ctx);
21005 hdd_update_hif_config(hdd_ctx);
21006 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
21007 ret = hdd_update_cds_config_ftm(hdd_ctx);
21008 else
21009 ret = hdd_update_cds_config(hdd_ctx);
21010 ret = hdd_update_user_config(hdd_ctx);
21011
21012 hdd_update_regdb_offload_config(hdd_ctx);
21013
21014 return ret;
21015 }
21016
21017 /**
21018 * hdd_update_pmo_config - API to update pmo configuration parameters
21019 * @hdd_ctx: HDD context
21020 *
21021 * Return: void
21022 */
hdd_update_pmo_config(struct hdd_context * hdd_ctx)21023 static int hdd_update_pmo_config(struct hdd_context *hdd_ctx)
21024 {
21025 struct pmo_psoc_cfg psoc_cfg = {0};
21026 QDF_STATUS status;
21027 enum pmo_wow_enable_type wow_enable;
21028
21029 ucfg_pmo_get_psoc_config(hdd_ctx->psoc, &psoc_cfg);
21030
21031 /*
21032 * Value of hdd_ctx->wowEnable can be,
21033 * 0 - Disable both magic pattern match and pattern byte match.
21034 * 1 - Enable magic pattern match on all interfaces.
21035 * 2 - Enable pattern byte match on all interfaces.
21036 * 3 - Enable both magic pattern and pattern byte match on
21037 * all interfaces.
21038 */
21039 wow_enable = ucfg_pmo_get_wow_enable(hdd_ctx->psoc);
21040 psoc_cfg.magic_ptrn_enable = (wow_enable & 0x01) ? true : false;
21041 psoc_cfg.ptrn_match_enable_all_vdev =
21042 (wow_enable & 0x02) ? true : false;
21043 psoc_cfg.ap_arpns_support = hdd_ctx->ap_arpns_support;
21044 psoc_cfg.d0_wow_supported = wma_d0_wow_is_supported();
21045 ucfg_mlme_get_sap_max_modulated_dtim(hdd_ctx->psoc,
21046 &psoc_cfg.sta_max_li_mod_dtim);
21047
21048 hdd_lpass_populate_pmo_config(&psoc_cfg, hdd_ctx);
21049
21050 status = ucfg_pmo_update_psoc_config(hdd_ctx->psoc, &psoc_cfg);
21051 if (QDF_IS_STATUS_ERROR(status))
21052 hdd_err("failed pmo psoc configuration; status:%d", status);
21053
21054 return qdf_status_to_os_return(status);
21055 }
21056
hdd_update_ie_allowlist_attr(struct probe_req_allowlist_attr * ie_allowlist,struct hdd_context * hdd_ctx)21057 void hdd_update_ie_allowlist_attr(struct probe_req_allowlist_attr *ie_allowlist,
21058 struct hdd_context *hdd_ctx)
21059 {
21060 struct wlan_fwol_ie_allowlist allowlist = {0};
21061 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
21062 QDF_STATUS status;
21063 bool is_ie_allowlist_enable = false;
21064 uint8_t i = 0;
21065
21066 status = ucfg_fwol_get_ie_allowlist(psoc, &is_ie_allowlist_enable);
21067 if (QDF_IS_STATUS_ERROR(status)) {
21068 hdd_err("Unable to get IE allowlist param");
21069 return;
21070 }
21071
21072 ie_allowlist->allow_list = is_ie_allowlist_enable;
21073 if (!ie_allowlist->allow_list)
21074 return;
21075
21076 status = ucfg_fwol_get_all_allowlist_params(psoc, &allowlist);
21077 if (QDF_IS_STATUS_ERROR(status)) {
21078 hdd_err("Unable to get all allowlist params");
21079 return;
21080 }
21081
21082 ie_allowlist->ie_bitmap[0] = allowlist.ie_bitmap_0;
21083 ie_allowlist->ie_bitmap[1] = allowlist.ie_bitmap_1;
21084 ie_allowlist->ie_bitmap[2] = allowlist.ie_bitmap_2;
21085 ie_allowlist->ie_bitmap[3] = allowlist.ie_bitmap_3;
21086 ie_allowlist->ie_bitmap[4] = allowlist.ie_bitmap_4;
21087 ie_allowlist->ie_bitmap[5] = allowlist.ie_bitmap_5;
21088 ie_allowlist->ie_bitmap[6] = allowlist.ie_bitmap_6;
21089 ie_allowlist->ie_bitmap[7] = allowlist.ie_bitmap_7;
21090
21091 ie_allowlist->num_vendor_oui = allowlist.no_of_probe_req_ouis;
21092 for (i = 0; i < ie_allowlist->num_vendor_oui; i++)
21093 ie_allowlist->voui[i] = allowlist.probe_req_voui[i];
21094 }
21095
hdd_update_score_config(struct hdd_context * hdd_ctx)21096 QDF_STATUS hdd_update_score_config(struct hdd_context *hdd_ctx)
21097 {
21098 struct hdd_config *cfg = hdd_ctx->config;
21099 eCsrPhyMode phy_mode = hdd_cfg_xlate_to_csr_phy_mode(cfg->dot11Mode);
21100
21101 sme_update_score_config(hdd_ctx->mac_handle, phy_mode,
21102 hdd_ctx->num_rf_chains);
21103
21104 return QDF_STATUS_SUCCESS;
21105 }
21106
21107 /**
21108 * hdd_update_dfs_config() - API to update dfs configuration parameters.
21109 * @hdd_ctx: HDD context
21110 *
21111 * Return: 0 if success else err
21112 */
hdd_update_dfs_config(struct hdd_context * hdd_ctx)21113 static int hdd_update_dfs_config(struct hdd_context *hdd_ctx)
21114 {
21115 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
21116 struct dfs_user_config dfs_cfg = {0};
21117 QDF_STATUS status;
21118
21119 ucfg_mlme_get_dfs_filter_offload(hdd_ctx->psoc,
21120 &dfs_cfg.dfs_is_phyerr_filter_offload);
21121 status = ucfg_dfs_update_config(psoc, &dfs_cfg);
21122 if (QDF_IS_STATUS_ERROR(status)) {
21123 hdd_err("failed dfs psoc configuration");
21124 return -EINVAL;
21125 }
21126
21127 return 0;
21128 }
21129
21130 /**
21131 * hdd_update_scan_config - API to update scan configuration parameters
21132 * @hdd_ctx: HDD context
21133 *
21134 * Return: 0 if success else err
21135 */
hdd_update_scan_config(struct hdd_context * hdd_ctx)21136 int hdd_update_scan_config(struct hdd_context *hdd_ctx)
21137 {
21138 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
21139 struct scan_user_cfg scan_cfg;
21140 QDF_STATUS status;
21141 uint32_t mcast_mcc_rest_time = 0;
21142
21143 qdf_mem_zero(&scan_cfg, sizeof(scan_cfg));
21144 status = ucfg_mlme_get_sta_miracast_mcc_rest_time(hdd_ctx->psoc,
21145 &mcast_mcc_rest_time);
21146 if (!QDF_IS_STATUS_SUCCESS(status)) {
21147 hdd_err("ucfg_mlme_get_sta_miracast_mcc_rest_time, use def");
21148 return -EIO;
21149 }
21150 scan_cfg.sta_miracast_mcc_rest_time = mcast_mcc_rest_time;
21151 hdd_update_ie_allowlist_attr(&scan_cfg.ie_allowlist, hdd_ctx);
21152
21153 status = ucfg_scan_update_user_config(psoc, &scan_cfg);
21154 if (status != QDF_STATUS_SUCCESS) {
21155 hdd_err("failed pmo psoc configuration");
21156 return -EINVAL;
21157 }
21158
21159 return 0;
21160 }
21161
hdd_update_components_config(struct hdd_context * hdd_ctx)21162 int hdd_update_components_config(struct hdd_context *hdd_ctx)
21163 {
21164 int ret;
21165
21166 ret = hdd_update_pmo_config(hdd_ctx);
21167 if (ret)
21168 return ret;
21169
21170 ret = hdd_update_scan_config(hdd_ctx);
21171 if (ret)
21172 return ret;
21173
21174 ret = hdd_update_tdls_config(hdd_ctx);
21175 if (ret)
21176 return ret;
21177
21178 ret = hdd_update_dp_config(hdd_ctx);
21179 if (ret)
21180 return ret;
21181
21182 ret = hdd_update_dfs_config(hdd_ctx);
21183 if (ret)
21184 return ret;
21185
21186 ret = hdd_update_regulatory_config(hdd_ctx);
21187 if (ret)
21188 return ret;
21189
21190 return ret;
21191 }
21192
21193 /**
21194 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
21195 * @mode : cfg80211 DFS mode
21196 *
21197 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
21198 */
wlan_hdd_get_dfs_mode(enum dfs_mode mode)21199 enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
21200 {
21201 switch (mode) {
21202 case DFS_MODE_ENABLE:
21203 return ACS_DFS_MODE_ENABLE;
21204 case DFS_MODE_DISABLE:
21205 return ACS_DFS_MODE_DISABLE;
21206 case DFS_MODE_DEPRIORITIZE:
21207 return ACS_DFS_MODE_DEPRIORITIZE;
21208 default:
21209 hdd_debug("ACS dfs mode is NONE");
21210 return ACS_DFS_MODE_NONE;
21211 }
21212 }
21213
21214 /**
21215 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
21216 * @hdd_ctx: pointer to hdd context
21217 * @set_value: enable/disable
21218 *
21219 * When Host sends vendor command enable, FW will send *ONE* CA ind to
21220 * Host(even though it is duplicate). When Host send vendor command
21221 * disable,FW doesn't perform any action. Whenever any change in
21222 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
21223 *
21224 * return - 0 on success, appropriate error values on failure.
21225 */
hdd_enable_disable_ca_event(struct hdd_context * hdd_ctx,uint8_t set_value)21226 int hdd_enable_disable_ca_event(struct hdd_context *hdd_ctx, uint8_t set_value)
21227 {
21228 QDF_STATUS status;
21229
21230 if (0 != wlan_hdd_validate_context(hdd_ctx))
21231 return -EAGAIN;
21232
21233 status = sme_enable_disable_chanavoidind_event(hdd_ctx->mac_handle,
21234 set_value);
21235 if (!QDF_IS_STATUS_SUCCESS(status)) {
21236 hdd_err("Failed to send chan avoid command to SME");
21237 return -EINVAL;
21238 }
21239 return 0;
21240 }
21241
hdd_is_roaming_in_progress(struct hdd_context * hdd_ctx)21242 bool hdd_is_roaming_in_progress(struct hdd_context *hdd_ctx)
21243 {
21244 struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
21245 uint8_t vdev_id;
21246 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_IS_ROAMING_IN_PROGRESS;
21247 struct wlan_hdd_link_info *link_info;
21248
21249 if (!hdd_ctx) {
21250 hdd_err("HDD context is NULL");
21251 return false;
21252 }
21253
21254 if (!policy_mgr_is_sta_active_connection_exists(hdd_ctx->psoc))
21255 return false;
21256
21257 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
21258 dbgid) {
21259 if (adapter->device_mode != QDF_STA_MODE)
21260 goto adapter_put;
21261
21262 hdd_adapter_for_each_active_link_info(adapter, link_info) {
21263 vdev_id = link_info->vdev_id;
21264 if (test_bit(SME_SESSION_OPENED,
21265 &link_info->link_flags) &&
21266 sme_roaming_in_progress(hdd_ctx->mac_handle,
21267 vdev_id)) {
21268 hdd_debug("Roaming is in progress on:vdev_id:%d",
21269 link_info->vdev_id);
21270 hdd_adapter_dev_put_debug(adapter, dbgid);
21271 if (next_adapter)
21272 hdd_adapter_dev_put_debug(next_adapter,
21273 dbgid);
21274 return true;
21275 }
21276 }
21277 adapter_put:
21278 hdd_adapter_dev_put_debug(adapter, dbgid);
21279 }
21280
21281 return false;
21282 }
21283
21284 /**
21285 * struct hdd_is_connection_in_progress_priv - adapter connection info
21286 * @out_vdev_id: id of vdev where connection is occurring
21287 * @out_reason: scan reject reason
21288 * @connection_in_progress: true if connection is in progress
21289 */
21290 struct hdd_is_connection_in_progress_priv {
21291 uint8_t out_vdev_id;
21292 enum scan_reject_states out_reason;
21293 bool connection_in_progress;
21294 };
21295
21296 /**
21297 * hdd_is_connection_in_progress_iterator() - Check adapter connection based
21298 * on device mode
21299 * @link_info: Link info pointer in HDD adapter
21300 * @ctx: user context supplied
21301 *
21302 * Check if connection is in progress for the current adapter according to the
21303 * device mode
21304 *
21305 * Return:
21306 * * QDF_STATUS_SUCCESS if iteration should continue
21307 * * QDF_STATUS_E_ABORTED if iteration should be aborted
21308 */
21309 static QDF_STATUS
hdd_is_connection_in_progress_iterator(struct wlan_hdd_link_info * link_info,void * ctx)21310 hdd_is_connection_in_progress_iterator(struct wlan_hdd_link_info *link_info,
21311 void *ctx)
21312 {
21313 struct hdd_station_ctx *hdd_sta_ctx;
21314 uint8_t *sta_mac;
21315 struct hdd_context *hdd_ctx;
21316 mac_handle_t mac_handle;
21317 struct hdd_station_info *sta_info, *tmp = NULL;
21318 struct hdd_is_connection_in_progress_priv *context = ctx;
21319 struct hdd_adapter *adapter = link_info->adapter;
21320
21321 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
21322 if (!hdd_ctx)
21323 return QDF_STATUS_E_ABORTED;
21324
21325 mac_handle = hdd_ctx->mac_handle;
21326
21327 if (!test_bit(SME_SESSION_OPENED, &link_info->link_flags) &&
21328 (adapter->device_mode == QDF_STA_MODE ||
21329 adapter->device_mode == QDF_P2P_CLIENT_MODE ||
21330 adapter->device_mode == QDF_P2P_DEVICE_MODE ||
21331 adapter->device_mode == QDF_P2P_GO_MODE ||
21332 adapter->device_mode == QDF_SAP_MODE))
21333 return QDF_STATUS_SUCCESS;
21334
21335 if ((QDF_STA_MODE == adapter->device_mode ||
21336 QDF_P2P_CLIENT_MODE == adapter->device_mode ||
21337 QDF_P2P_DEVICE_MODE == adapter->device_mode) &&
21338 hdd_cm_is_connecting(link_info)) {
21339 hdd_debug("%pK(%d) mode %d Connection is in progress",
21340 WLAN_HDD_GET_STATION_CTX_PTR(link_info),
21341 link_info->vdev_id, adapter->device_mode);
21342
21343 context->out_vdev_id = link_info->vdev_id;
21344 context->out_reason = CONNECTION_IN_PROGRESS;
21345 context->connection_in_progress = true;
21346
21347 return QDF_STATUS_E_ABORTED;
21348 }
21349
21350 if ((QDF_STA_MODE == adapter->device_mode) &&
21351 sme_roaming_in_progress(mac_handle, link_info->vdev_id)) {
21352 hdd_debug("%pK(%d) mode %d Reassociation in progress",
21353 WLAN_HDD_GET_STATION_CTX_PTR(link_info),
21354 link_info->vdev_id, adapter->device_mode);
21355
21356 context->out_vdev_id = link_info->vdev_id;
21357 context->out_reason = REASSOC_IN_PROGRESS;
21358 context->connection_in_progress = true;
21359 return QDF_STATUS_E_ABORTED;
21360 }
21361
21362 if ((QDF_STA_MODE == adapter->device_mode) ||
21363 (QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
21364 (QDF_P2P_DEVICE_MODE == adapter->device_mode)) {
21365 hdd_sta_ctx =
21366 WLAN_HDD_GET_STATION_CTX_PTR(link_info);
21367 if (hdd_cm_is_vdev_associated(link_info)
21368 && sme_is_sta_key_exchange_in_progress(
21369 mac_handle, link_info->vdev_id)) {
21370 sta_mac = (uint8_t *)&(adapter->mac_addr.bytes[0]);
21371 hdd_debug("client " QDF_MAC_ADDR_FMT
21372 " is in middle of WPS/EAPOL exchange.",
21373 QDF_MAC_ADDR_REF(sta_mac));
21374
21375 context->out_vdev_id = link_info->vdev_id;
21376 context->out_reason = EAPOL_IN_PROGRESS;
21377 context->connection_in_progress = true;
21378
21379 return QDF_STATUS_E_ABORTED;
21380 }
21381 } else if ((QDF_SAP_MODE == adapter->device_mode) ||
21382 (QDF_P2P_GO_MODE == adapter->device_mode)) {
21383 hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp,
21384 STA_INFO_CONNECTION_IN_PROGRESS_ITERATOR) {
21385 if (sta_info->peer_state !=
21386 OL_TXRX_PEER_STATE_CONN) {
21387 hdd_put_sta_info_ref(
21388 &adapter->sta_info_list, &sta_info, true,
21389 STA_INFO_CONNECTION_IN_PROGRESS_ITERATOR);
21390 continue;
21391 }
21392
21393 sta_mac = sta_info->sta_mac.bytes;
21394 hdd_debug("client " QDF_MAC_ADDR_FMT
21395 " of SAP/GO is in middle of WPS/EAPOL exchange",
21396 QDF_MAC_ADDR_REF(sta_mac));
21397
21398 context->out_vdev_id = link_info->vdev_id;
21399 context->out_reason = SAP_EAPOL_IN_PROGRESS;
21400 context->connection_in_progress = true;
21401
21402 hdd_put_sta_info_ref(
21403 &adapter->sta_info_list, &sta_info, true,
21404 STA_INFO_CONNECTION_IN_PROGRESS_ITERATOR);
21405 if (tmp)
21406 hdd_put_sta_info_ref(
21407 &adapter->sta_info_list, &tmp, true,
21408 STA_INFO_CONNECTION_IN_PROGRESS_ITERATOR);
21409
21410 return QDF_STATUS_E_ABORTED;
21411 }
21412 if (hdd_ctx->connection_in_progress) {
21413 hdd_debug("AP/GO: vdev %d connection is in progress",
21414 link_info->vdev_id);
21415 context->out_reason = SAP_CONNECTION_IN_PROGRESS;
21416 context->out_vdev_id = link_info->vdev_id;
21417 context->connection_in_progress = true;
21418
21419 return QDF_STATUS_E_ABORTED;
21420 }
21421 }
21422
21423 if (ucfg_nan_is_enable_disable_in_progress(hdd_ctx->psoc)) {
21424 context->out_reason = NAN_ENABLE_DISABLE_IN_PROGRESS;
21425 context->out_vdev_id = NAN_PSEUDO_VDEV_ID;
21426 context->connection_in_progress = true;
21427
21428 return QDF_STATUS_E_ABORTED;
21429 }
21430
21431 return QDF_STATUS_SUCCESS;
21432 }
21433
hdd_is_connection_in_progress(uint8_t * out_vdev_id,enum scan_reject_states * out_reason)21434 bool hdd_is_connection_in_progress(uint8_t *out_vdev_id,
21435 enum scan_reject_states *out_reason)
21436 {
21437 struct hdd_is_connection_in_progress_priv hdd_conn;
21438 hdd_adapter_iterate_cb cb;
21439
21440 hdd_conn.out_vdev_id = 0;
21441 hdd_conn.out_reason = SCAN_REJECT_DEFAULT;
21442 hdd_conn.connection_in_progress = false;
21443
21444 cb = hdd_is_connection_in_progress_iterator;
21445
21446 hdd_adapter_iterate(cb, &hdd_conn);
21447
21448 if (hdd_conn.connection_in_progress && out_vdev_id && out_reason) {
21449 *out_vdev_id = hdd_conn.out_vdev_id;
21450 *out_reason = hdd_conn.out_reason;
21451 }
21452
21453 return hdd_conn.connection_in_progress;
21454 }
21455
hdd_restart_sap(struct wlan_hdd_link_info * link_info)21456 void hdd_restart_sap(struct wlan_hdd_link_info *link_info)
21457 {
21458 struct hdd_hostapd_state *hapd_state;
21459 QDF_STATUS status;
21460 struct hdd_adapter *ap_adapter = link_info->adapter;
21461 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
21462 struct sap_config *sap_config;
21463 void *sap_ctx;
21464
21465 sap_config =
21466 &(WLAN_HDD_GET_AP_CTX_PTR(link_info)->sap_config);
21467 sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
21468
21469 mutex_lock(&hdd_ctx->sap_lock);
21470 if (test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
21471 wlan_hdd_del_station(ap_adapter, NULL);
21472 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info);
21473 qdf_event_reset(&hapd_state->qdf_stop_bss_event);
21474 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) {
21475 status = qdf_wait_single_event(&hapd_state->qdf_stop_bss_event,
21476 SME_CMD_STOP_BSS_TIMEOUT);
21477
21478 if (!QDF_IS_STATUS_SUCCESS(status)) {
21479 hdd_err("SAP Stop Failed");
21480 goto end;
21481 }
21482 }
21483 clear_bit(SOFTAP_BSS_STARTED, &link_info->link_flags);
21484 policy_mgr_decr_session_set_pcl(hdd_ctx->psoc,
21485 ap_adapter->device_mode, link_info->vdev_id);
21486 hdd_green_ap_start_state_mc(hdd_ctx, ap_adapter->device_mode,
21487 false);
21488 hdd_err("SAP Stop Success");
21489
21490 if (0 != wlan_hdd_cfg80211_update_apies(link_info)) {
21491 hdd_err("SAP Not able to set AP IEs");
21492 goto end;
21493 }
21494
21495 status = wlan_hdd_mlo_sap_reinit(link_info);
21496 if (QDF_IS_STATUS_ERROR(status)) {
21497 hdd_err("SAP Not able to do mlo attach");
21498 goto deinit_mlo;
21499 }
21500
21501 qdf_event_reset(&hapd_state->qdf_event);
21502 status = wlansap_start_bss(sap_ctx, hdd_hostapd_sap_event_cb,
21503 sap_config, ap_adapter->dev);
21504 if (QDF_IS_STATUS_ERROR(status)) {
21505 hdd_err("SAP Start Bss fail");
21506 goto deinit_mlo;
21507 }
21508
21509 hdd_info("Waiting for SAP to start");
21510 status = qdf_wait_single_event(&hapd_state->qdf_event,
21511 SME_CMD_START_BSS_TIMEOUT);
21512 if (!QDF_IS_STATUS_SUCCESS(status)) {
21513 hdd_err("SAP Start failed");
21514 goto deinit_mlo;
21515 }
21516 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
21517 hdd_err("SAP Start Success");
21518 set_bit(SOFTAP_BSS_STARTED, &link_info->link_flags);
21519 if (hapd_state->bss_state == BSS_START) {
21520 policy_mgr_incr_active_session(hdd_ctx->psoc,
21521 ap_adapter->device_mode,
21522 link_info->vdev_id);
21523 hdd_green_ap_start_state_mc(hdd_ctx,
21524 ap_adapter->device_mode,
21525 true);
21526 }
21527 }
21528 mutex_unlock(&hdd_ctx->sap_lock);
21529 return;
21530
21531 deinit_mlo:
21532 wlan_hdd_mlo_reset(link_info);
21533 end:
21534 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
21535 mutex_unlock(&hdd_ctx->sap_lock);
21536 }
21537
21538 /**
21539 * hdd_set_connection_in_progress() - to set the connection in
21540 * progress flag
21541 * @value: value to set
21542 *
21543 * This function will set the passed value to connection in progress flag.
21544 * If value is previously being set to true then no need to set it again.
21545 *
21546 * Return: true if value is being set correctly and false otherwise.
21547 */
hdd_set_connection_in_progress(bool value)21548 bool hdd_set_connection_in_progress(bool value)
21549 {
21550 bool status = true;
21551 struct hdd_context *hdd_ctx;
21552
21553 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
21554 if (!hdd_ctx)
21555 return false;
21556
21557 qdf_spin_lock(&hdd_ctx->connection_status_lock);
21558 /*
21559 * if the value is set to true previously and if someone is
21560 * trying to make it true again then it could be some race
21561 * condition being triggered. Avoid this situation by returning
21562 * false
21563 */
21564 if (hdd_ctx->connection_in_progress && value)
21565 status = false;
21566 else
21567 hdd_ctx->connection_in_progress = value;
21568 qdf_spin_unlock(&hdd_ctx->connection_status_lock);
21569 return status;
21570 }
21571
wlan_hdd_send_mcc_vdev_quota(struct hdd_adapter * adapter,int set_value)21572 int wlan_hdd_send_mcc_vdev_quota(struct hdd_adapter *adapter, int set_value)
21573 {
21574 if (!adapter) {
21575 hdd_err("Invalid adapter");
21576 return -EINVAL;
21577 }
21578 hdd_info("send mcc vdev quota to fw: %d", set_value);
21579 sme_cli_set_command(adapter->deflink->vdev_id,
21580 WMA_VDEV_MCC_SET_TIME_QUOTA,
21581 set_value, VDEV_CMD);
21582 return 0;
21583
21584 }
21585
wlan_hdd_send_mcc_latency(struct hdd_adapter * adapter,int set_value)21586 int wlan_hdd_send_mcc_latency(struct hdd_adapter *adapter, int set_value)
21587 {
21588 if (!adapter) {
21589 hdd_err("Invalid adapter");
21590 return -EINVAL;
21591 }
21592
21593 hdd_info("Send MCC latency WMA: %d", set_value);
21594 sme_cli_set_command(adapter->deflink->vdev_id,
21595 WMA_VDEV_MCC_SET_TIME_LATENCY,
21596 set_value, VDEV_CMD);
21597 return 0;
21598 }
21599
21600 struct wlan_hdd_link_info *
wlan_hdd_get_link_info_from_vdev(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id)21601 wlan_hdd_get_link_info_from_vdev(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
21602 {
21603 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
21604 struct wlan_hdd_link_info *link_info;
21605
21606 /*
21607 * Currently PSOC is not being used. But this logic will
21608 * change once we have the converged implementation of
21609 * HDD context per PSOC in place. This would break if
21610 * multiple vdev objects reuse the vdev id.
21611 */
21612 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
21613 if (!link_info) {
21614 hdd_err("Get adapter by vdev id failed");
21615 return NULL;
21616 }
21617
21618 return link_info;
21619 }
21620
hdd_get_rssi_snr_by_bssid(mac_handle_t mac_handle,const uint8_t * bssid,int8_t * rssi,int8_t * snr)21621 int hdd_get_rssi_snr_by_bssid(mac_handle_t mac_handle, const uint8_t *bssid,
21622 int8_t *rssi, int8_t *snr)
21623 {
21624 QDF_STATUS status;
21625
21626 status = sme_get_rssi_snr_by_bssid(mac_handle, bssid, rssi, snr);
21627 if (QDF_IS_STATUS_ERROR(status)) {
21628 hdd_debug("sme_get_rssi_snr_by_bssid failed");
21629 return -EINVAL;
21630 }
21631
21632 return 0;
21633 }
21634
21635 /**
21636 * hdd_reset_limit_off_chan() - reset limit off-channel command parameters
21637 * @adapter: HDD adapter
21638 *
21639 * Return: 0 on success and non zero value on failure
21640 */
hdd_reset_limit_off_chan(struct hdd_adapter * adapter)21641 int hdd_reset_limit_off_chan(struct hdd_adapter *adapter)
21642 {
21643 struct hdd_context *hdd_ctx;
21644 int ret;
21645 QDF_STATUS status;
21646 uint8_t sys_pref = 0;
21647
21648 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21649 ret = wlan_hdd_validate_context(hdd_ctx);
21650 if (ret < 0)
21651 return ret;
21652
21653 ucfg_policy_mgr_get_sys_pref(hdd_ctx->psoc,
21654 &sys_pref);
21655 /* set the system preferece to default */
21656 policy_mgr_set_cur_conc_system_pref(hdd_ctx->psoc, sys_pref);
21657
21658 /* clear the bitmap */
21659 adapter->active_ac = 0;
21660
21661 hdd_debug("reset ac_bitmap for session %hu active_ac %0x",
21662 adapter->deflink->vdev_id, adapter->active_ac);
21663
21664 status = sme_send_limit_off_channel_params(hdd_ctx->mac_handle,
21665 adapter->deflink->vdev_id,
21666 false, 0, 0, false);
21667 if (!QDF_IS_STATUS_SUCCESS(status)) {
21668 hdd_err("failed to reset limit off chan params");
21669 ret = -EINVAL;
21670 }
21671
21672 return ret;
21673 }
21674
hdd_hidden_ssid_enable_roaming(hdd_handle_t hdd_handle,uint8_t vdev_id)21675 void hdd_hidden_ssid_enable_roaming(hdd_handle_t hdd_handle, uint8_t vdev_id)
21676 {
21677 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
21678 struct wlan_hdd_link_info *link_info;
21679
21680 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
21681 if (!link_info) {
21682 hdd_err("Invalid vdev");
21683 return;
21684 }
21685 /* enable roaming on all adapters once hdd get hidden ssid rsp */
21686 wlan_hdd_set_roaming_state(link_info, RSO_START_BSS, true);
21687 }
21688
21689 #ifdef WLAN_FEATURE_PKT_CAPTURE
wlan_hdd_is_mon_concurrency(void)21690 bool wlan_hdd_is_mon_concurrency(void)
21691 {
21692 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
21693
21694 if (!hdd_ctx)
21695 return -EINVAL;
21696
21697 if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
21698 PACKET_CAPTURE_MODE_DISABLE) {
21699 if (policy_mgr_get_concurrency_mode(hdd_ctx->psoc) ==
21700 (QDF_STA_MASK | QDF_MONITOR_MASK)) {
21701 hdd_err("STA + MON mode is UP");
21702 return true;
21703 }
21704 }
21705 return false;
21706 }
21707
wlan_hdd_del_monitor(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,bool rtnl_held)21708 void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
21709 struct hdd_adapter *adapter, bool rtnl_held)
21710 {
21711 wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes);
21712 hdd_stop_adapter(hdd_ctx, adapter);
21713 hdd_close_adapter(hdd_ctx, adapter, true);
21714
21715 hdd_open_p2p_interface(hdd_ctx);
21716 }
21717
21718 void
wlan_hdd_del_p2p_interface(struct hdd_context * hdd_ctx)21719 wlan_hdd_del_p2p_interface(struct hdd_context *hdd_ctx)
21720 {
21721 struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
21722 struct osif_vdev_sync *vdev_sync;
21723
21724 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
21725 NET_DEV_HOLD_DEL_P2P_INTERFACE) {
21726 if (adapter->device_mode == QDF_P2P_CLIENT_MODE ||
21727 adapter->device_mode == QDF_P2P_DEVICE_MODE ||
21728 adapter->device_mode == QDF_P2P_GO_MODE) {
21729 vdev_sync = osif_vdev_sync_unregister(adapter->dev);
21730 if (vdev_sync)
21731 osif_vdev_sync_wait_for_ops(vdev_sync);
21732
21733 hdd_adapter_dev_put_debug(
21734 adapter, NET_DEV_HOLD_DEL_P2P_INTERFACE);
21735
21736 hdd_clean_up_interface(hdd_ctx, adapter);
21737
21738 if (vdev_sync)
21739 osif_vdev_sync_destroy(vdev_sync);
21740 } else
21741 hdd_adapter_dev_put_debug(
21742 adapter, NET_DEV_HOLD_DEL_P2P_INTERFACE);
21743 }
21744 }
21745
21746 #endif /* WLAN_FEATURE_PKT_CAPTURE */
21747
wlan_hdd_is_session_type_monitor(uint8_t session_type)21748 bool wlan_hdd_is_session_type_monitor(uint8_t session_type)
21749 {
21750 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
21751
21752 if (!hdd_ctx) {
21753 cds_err("HDD context is NULL");
21754 return false;
21755 }
21756
21757 if (cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE &&
21758 session_type == QDF_MONITOR_MODE)
21759 return true;
21760 else
21761 return false;
21762 }
21763
21764 int
wlan_hdd_add_monitor_check(struct hdd_context * hdd_ctx,struct hdd_adapter ** adapter,const char * name,bool rtnl_held,unsigned char name_assign_type,bool is_rx_mon)21765 wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
21766 struct hdd_adapter **adapter,
21767 const char *name, bool rtnl_held,
21768 unsigned char name_assign_type, bool is_rx_mon)
21769 {
21770 struct hdd_adapter *sta_adapter;
21771 struct hdd_adapter *mon_adapter;
21772 uint8_t num_open_session = 0;
21773 QDF_STATUS status;
21774 struct hdd_adapter_create_param params = {0};
21775
21776 sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
21777 if (!sta_adapter) {
21778 hdd_err("No station adapter");
21779 return -EINVAL;
21780 }
21781
21782 status = policy_mgr_check_mon_concurrency(hdd_ctx->psoc);
21783
21784 if (QDF_IS_STATUS_ERROR(status))
21785 return -EINVAL;
21786
21787 if (hdd_is_connection_in_progress(NULL, NULL)) {
21788 hdd_err("cannot add monitor mode, Connection in progress");
21789 return -EINVAL;
21790 }
21791
21792 if (is_rx_mon) {
21793 num_open_session = policy_mgr_mode_specific_connection_count(
21794 hdd_ctx->psoc,
21795 PM_STA_MODE,
21796 NULL);
21797
21798 if (num_open_session) {
21799 /* Try disconnecting if already in connected state */
21800 wlan_hdd_cm_issue_disconnect(sta_adapter->deflink,
21801 REASON_UNSPEC_FAILURE,
21802 true);
21803 }
21804 }
21805
21806 if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
21807 PACKET_CAPTURE_MODE_DISABLE)
21808 wlan_hdd_del_p2p_interface(hdd_ctx);
21809
21810 params.is_add_virtual_iface = 1;
21811
21812 mon_adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, name,
21813 wlan_hdd_get_intf_addr(
21814 hdd_ctx,
21815 QDF_MONITOR_MODE),
21816 name_assign_type, rtnl_held, ¶ms);
21817 if (!mon_adapter) {
21818 hdd_err("hdd_open_adapter failed");
21819 if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
21820 PACKET_CAPTURE_MODE_DISABLE)
21821 hdd_open_p2p_interface(hdd_ctx);
21822 return -EINVAL;
21823 }
21824
21825 if (mon_adapter)
21826 hdd_set_idle_ps_config(hdd_ctx, false);
21827
21828 *adapter = mon_adapter;
21829 return 0;
21830 }
21831
21832 #ifdef FEATURE_MONITOR_MODE_SUPPORT
21833
hdd_sme_monitor_mode_callback(uint8_t vdev_id)21834 void hdd_sme_monitor_mode_callback(uint8_t vdev_id)
21835 {
21836 struct hdd_context *hdd_ctx;
21837 struct hdd_adapter *adapter;
21838 struct wlan_hdd_link_info *link_info;
21839
21840 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
21841 if (!hdd_ctx)
21842 return;
21843
21844 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
21845 if (!link_info) {
21846 hdd_err_rl("NULL adapter");
21847 return;
21848 }
21849
21850 adapter = link_info->adapter;
21851 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
21852 hdd_err_rl("Invalid magic");
21853 return;
21854 }
21855
21856 qdf_event_set(&adapter->qdf_monitor_mode_vdev_up_event);
21857
21858 hdd_debug("monitor mode vdev up completed");
21859 adapter->monitor_mode_vdev_up_in_progress = false;
21860 }
21861
hdd_monitor_mode_qdf_create_event(struct hdd_adapter * adapter,uint8_t session_type)21862 QDF_STATUS hdd_monitor_mode_qdf_create_event(struct hdd_adapter *adapter,
21863 uint8_t session_type)
21864 {
21865 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
21866
21867 if (session_type == QDF_MONITOR_MODE) {
21868 qdf_status = qdf_event_create(
21869 &adapter->qdf_monitor_mode_vdev_up_event);
21870 }
21871 return qdf_status;
21872 }
21873
hdd_monitor_mode_vdev_status(struct hdd_adapter * adapter)21874 QDF_STATUS hdd_monitor_mode_vdev_status(struct hdd_adapter *adapter)
21875 {
21876 QDF_STATUS status = QDF_STATUS_SUCCESS;
21877
21878 if (!adapter->monitor_mode_vdev_up_in_progress)
21879 return status;
21880
21881 /* block on a completion variable until vdev up success*/
21882 status = qdf_wait_for_event_completion(
21883 &adapter->qdf_monitor_mode_vdev_up_event,
21884 WLAN_MONITOR_MODE_VDEV_UP_EVT);
21885 if (QDF_IS_STATUS_ERROR(status)) {
21886 hdd_err_rl("monitor mode vdev up event time out vdev id: %d",
21887 adapter->deflink->vdev_id);
21888 if (adapter->qdf_monitor_mode_vdev_up_event.force_set)
21889 /*
21890 * SSR/PDR has caused shutdown, which has
21891 * forcefully set the event.
21892 */
21893 hdd_err_rl("monitor mode vdev up event forcefully set");
21894 else if (status == QDF_STATUS_E_TIMEOUT)
21895 hdd_err_rl("mode vdev up event timed out");
21896 else
21897 hdd_err_rl("Failed to wait for monitor vdev up(status-%d)",
21898 status);
21899
21900 adapter->monitor_mode_vdev_up_in_progress = false;
21901 return status;
21902 }
21903
21904 return QDF_STATUS_SUCCESS;
21905 }
21906 #endif
21907
21908 #if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE)
hdd_beacon_latency_event_cb(uint32_t latency_level)21909 void hdd_beacon_latency_event_cb(uint32_t latency_level)
21910 {
21911 struct hdd_context *hdd_ctx;
21912
21913 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
21914 if (!hdd_ctx)
21915 return;
21916
21917 if (latency_level ==
21918 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW)
21919 wlan_hdd_set_pm_qos_request(hdd_ctx, true);
21920 else
21921 wlan_hdd_set_pm_qos_request(hdd_ctx, false);
21922 }
21923 #endif
21924
21925 #ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT
hdd_crash_inject(struct hdd_adapter * adapter,uint32_t v1,uint32_t v2)21926 int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2)
21927 {
21928 struct hdd_context *hdd_ctx;
21929 int ret;
21930 bool crash_inject;
21931 QDF_STATUS status;
21932
21933 hdd_debug("v1: %d v2: %d", v1, v2);
21934 pr_err("SSR is triggered by CRASH_INJECT: %d %d\n",
21935 v1, v2);
21936 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21937
21938 status = ucfg_mlme_get_crash_inject(hdd_ctx->psoc, &crash_inject);
21939 if (QDF_IS_STATUS_ERROR(status)) {
21940 hdd_err("Failed to get crash inject ini config");
21941 return 0;
21942 }
21943
21944 if (!crash_inject) {
21945 hdd_err("Crash Inject ini disabled, Ignore Crash Inject");
21946 return 0;
21947 }
21948
21949 if (v1 == 3) {
21950 cds_trigger_recovery(QDF_REASON_UNSPECIFIED);
21951 return 0;
21952 }
21953 ret = wma_cli_set2_command(adapter->deflink->vdev_id,
21954 GEN_PARAM_CRASH_INJECT,
21955 v1, v2, GEN_CMD);
21956 return ret;
21957 }
21958 #endif
21959
21960 static const struct hdd_chwidth_info chwidth_info[] = {
21961 [NL80211_CHAN_WIDTH_20_NOHT] = {
21962 .ch_bw = HW_MODE_20_MHZ,
21963 .ch_bw_str = "20MHz",
21964 .phy_chwidth = CH_WIDTH_20MHZ,
21965 },
21966 [NL80211_CHAN_WIDTH_20] = {
21967 .sir_chwidth_valid = true,
21968 .sir_chwidth = eHT_CHANNEL_WIDTH_20MHZ,
21969 .ch_bw = HW_MODE_20_MHZ,
21970 .ch_bw_str = "20MHz",
21971 .phy_chwidth = CH_WIDTH_20MHZ,
21972 .bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE,
21973 },
21974 [NL80211_CHAN_WIDTH_40] = {
21975 .sir_chwidth_valid = true,
21976 .sir_chwidth = eHT_CHANNEL_WIDTH_40MHZ,
21977 .ch_bw = HW_MODE_40_MHZ,
21978 .ch_bw_str = "40MHz",
21979 .phy_chwidth = CH_WIDTH_40MHZ,
21980 .bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE,
21981 },
21982 [NL80211_CHAN_WIDTH_80] = {
21983 .sir_chwidth_valid = true,
21984 .sir_chwidth = eHT_CHANNEL_WIDTH_80MHZ,
21985 .ch_bw = HW_MODE_80_MHZ,
21986 .ch_bw_str = "80MHz",
21987 .phy_chwidth = CH_WIDTH_80MHZ,
21988 .bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE,
21989 },
21990 [NL80211_CHAN_WIDTH_80P80] = {
21991 .sir_chwidth_valid = true,
21992 .sir_chwidth = eHT_CHANNEL_WIDTH_80P80MHZ,
21993 .ch_bw = HW_MODE_80_PLUS_80_MHZ,
21994 .ch_bw_str = "(80 + 80)MHz",
21995 .phy_chwidth = CH_WIDTH_80P80MHZ,
21996 .bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE,
21997 },
21998 [NL80211_CHAN_WIDTH_160] = {
21999 .sir_chwidth_valid = true,
22000 .sir_chwidth = eHT_CHANNEL_WIDTH_160MHZ,
22001 .ch_bw = HW_MODE_160_MHZ,
22002 .ch_bw_str = "160MHz",
22003 .phy_chwidth = CH_WIDTH_160MHZ,
22004 .bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE,
22005 },
22006 [NL80211_CHAN_WIDTH_5] = {
22007 .ch_bw = HW_MODE_5_MHZ,
22008 .ch_bw_str = "5MHz",
22009 .phy_chwidth = CH_WIDTH_5MHZ,
22010 },
22011 [NL80211_CHAN_WIDTH_10] = {
22012 .ch_bw = HW_MODE_10_MHZ,
22013 .ch_bw_str = "10MHz",
22014 .phy_chwidth = CH_WIDTH_10MHZ,
22015 },
22016 #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC)
22017 [NL80211_CHAN_WIDTH_320] = {
22018 .sir_chwidth_valid = true,
22019 .sir_chwidth = eHT_CHANNEL_WIDTH_320MHZ,
22020 .ch_bw = HW_MODE_320_MHZ,
22021 .ch_bw_str = "320MHz",
22022 .phy_chwidth = CH_WIDTH_320MHZ,
22023 .bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE,
22024 },
22025 #endif
22026 };
22027
22028 enum eSirMacHTChannelWidth
hdd_nl80211_chwidth_to_chwidth(uint8_t nl80211_chwidth)22029 hdd_nl80211_chwidth_to_chwidth(uint8_t nl80211_chwidth)
22030 {
22031 if (nl80211_chwidth >= ARRAY_SIZE(chwidth_info) ||
22032 !chwidth_info[nl80211_chwidth].sir_chwidth_valid) {
22033 hdd_err("Unsupported channel width %d", nl80211_chwidth);
22034 return -EINVAL;
22035 }
22036
22037 return chwidth_info[nl80211_chwidth].sir_chwidth;
22038 }
22039
hdd_chwidth_to_nl80211_chwidth(enum eSirMacHTChannelWidth chwidth)22040 uint8_t hdd_chwidth_to_nl80211_chwidth(enum eSirMacHTChannelWidth chwidth)
22041 {
22042 int i;
22043
22044 for (i = 0; i < ARRAY_SIZE(chwidth_info); i++) {
22045 if (chwidth_info[i].sir_chwidth_valid &&
22046 chwidth_info[i].sir_chwidth == chwidth)
22047 return i;
22048 }
22049
22050 hdd_err("Unsupported channel width %d", chwidth);
22051 return 0xFF;
22052 }
22053
hdd_phy_chwidth_to_nl80211_chwidth(enum phy_ch_width chwidth)22054 uint8_t hdd_phy_chwidth_to_nl80211_chwidth(enum phy_ch_width chwidth)
22055 {
22056 int i;
22057
22058 for (i = 0; i < ARRAY_SIZE(chwidth_info); i++) {
22059 if (chwidth_info[i].sir_chwidth_valid &&
22060 chwidth_info[i].phy_chwidth == chwidth)
22061 return i;
22062 }
22063
22064 hdd_err("Unsupported channel width %d", chwidth);
22065 return 0xFF;
22066 }
22067
wlan_hdd_get_channel_bw(enum nl80211_chan_width width)22068 enum hw_mode_bandwidth wlan_hdd_get_channel_bw(enum nl80211_chan_width width)
22069 {
22070 if (width >= ARRAY_SIZE(chwidth_info)) {
22071 hdd_err("Invalid width: %d, using default 20MHz", width);
22072 return HW_MODE_20_MHZ;
22073 }
22074
22075 return chwidth_info[width].ch_bw;
22076 }
22077
hdd_ch_width_str(enum phy_ch_width ch_width)22078 uint8_t *hdd_ch_width_str(enum phy_ch_width ch_width)
22079 {
22080 int i;
22081
22082 for (i = 0; i < ARRAY_SIZE(chwidth_info); i++) {
22083 if (chwidth_info[i].phy_chwidth == ch_width)
22084 return chwidth_info[i].ch_bw_str;
22085 }
22086
22087 return "UNKNOWN";
22088 }
22089
hdd_we_set_ch_width(struct wlan_hdd_link_info * link_info,int ch_width)22090 int hdd_we_set_ch_width(struct wlan_hdd_link_info *link_info, int ch_width)
22091 {
22092 int i;
22093 uint8_t link_id = 0xFF;
22094
22095 /* updating channel bonding only on 5Ghz */
22096 hdd_debug("wmi_vdev_param_chwidth val %d", ch_width);
22097
22098 for (i = 0; i < ARRAY_SIZE(chwidth_info); i++) {
22099 if (!chwidth_info[i].sir_chwidth_valid ||
22100 chwidth_info[i].sir_chwidth != ch_width)
22101 continue;
22102
22103 return hdd_update_channel_width(link_info, ch_width,
22104 chwidth_info[i].bonding_mode,
22105 link_id, false);
22106 }
22107
22108 hdd_err("Invalid ch_width %d", ch_width);
22109 return -EINVAL;
22110 }
22111
22112 /* Register the module init/exit functions */
22113 module_init(hdd_module_init);
22114 module_exit(hdd_module_exit);
22115
22116 MODULE_LICENSE("Dual BSD/GPL");
22117 MODULE_AUTHOR("Qualcomm Atheros, Inc.");
22118 MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
22119
22120 const struct kernel_param_ops con_mode_ops = {
22121 .set = con_mode_handler,
22122 .get = param_get_int,
22123 };
22124
22125 #ifdef FEATURE_WLAN_RESIDENT_DRIVER
22126 EXPORT_SYMBOL(con_mode_ops);
22127 #endif
22128
22129 const struct kernel_param_ops con_mode_ftm_ops = {
22130 .set = con_mode_handler_ftm,
22131 .get = param_get_int,
22132 };
22133
22134 #ifdef FEATURE_WLAN_RESIDENT_DRIVER
22135 EXPORT_SYMBOL(con_mode_ftm_ops);
22136 #endif
22137
22138 #ifdef WLAN_FEATURE_EPPING
22139 static const struct kernel_param_ops con_mode_epping_ops = {
22140 .set = con_mode_handler_epping,
22141 .get = param_get_int,
22142 };
22143 #endif
22144
22145 static const struct kernel_param_ops fwpath_ops = {
22146 .set = fwpath_changed_handler,
22147 .get = param_get_string,
22148 };
22149
__pcie_set_gen_speed_handler(void)22150 static int __pcie_set_gen_speed_handler(void)
22151 {
22152 int ret;
22153 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
22154
22155 ret = wlan_hdd_validate_context(hdd_ctx);
22156 if (ret)
22157 return ret;
22158
22159 hdd_info_rl("Received PCIe gen speed %d", pcie_gen_speed);
22160 if (pcie_gen_speed <= HDD_INVALID_MIN_PCIE_GEN_SPEED ||
22161 pcie_gen_speed >= HDD_INVALID_MAX_PCIE_GEN_SPEED) {
22162 hdd_err_rl("invalid pcie gen speed %d", pcie_gen_speed);
22163 return -EINVAL;
22164 }
22165
22166 hdd_ctx->current_pcie_gen_speed = pcie_gen_speed;
22167
22168 return 0;
22169 }
22170
pcie_set_gen_speed_handler(const char * kmessage,const struct kernel_param * kp)22171 static int pcie_set_gen_speed_handler(const char *kmessage,
22172 const struct kernel_param *kp)
22173 {
22174 struct osif_driver_sync *driver_sync;
22175 int ret;
22176
22177 ret = osif_driver_sync_op_start(&driver_sync);
22178 if (ret)
22179 return ret;
22180
22181 ret = param_set_int(kmessage, kp);
22182 if (ret) {
22183 hdd_err_rl("param set int failed %d", ret);
22184 goto out;
22185 }
22186
22187 ret = __pcie_set_gen_speed_handler();
22188
22189 out:
22190 osif_driver_sync_op_stop(driver_sync);
22191
22192 return ret;
22193 }
22194
22195 static const struct kernel_param_ops pcie_gen_speed_ops = {
22196 .set = pcie_set_gen_speed_handler,
22197 .get = param_get_int,
22198 };
22199
22200 module_param_cb(con_mode, &con_mode_ops, &con_mode,
22201 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
22202
22203 module_param_cb(con_mode_ftm, &con_mode_ftm_ops, &con_mode_ftm,
22204 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
22205
22206 module_param_cb(pcie_gen_speed, &pcie_gen_speed_ops, &pcie_gen_speed,
22207 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
22208
22209 #ifdef WLAN_FEATURE_EPPING
22210 module_param_cb(con_mode_epping, &con_mode_epping_ops,
22211 &con_mode_epping, 0644);
22212 #endif
22213
22214 module_param_cb(fwpath, &fwpath_ops, &fwpath,
22215 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
22216
22217 module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
22218
22219 module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
22220
22221 module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);
22222
timer_multiplier_get_handler(char * buffer,const struct kernel_param * kp)22223 static int timer_multiplier_get_handler(char *buffer,
22224 const struct kernel_param *kp)
22225 {
22226 return scnprintf(buffer, PAGE_SIZE, "%u", qdf_timer_get_multiplier());
22227 }
22228
timer_multiplier_set_handler(const char * kmessage,const struct kernel_param * kp)22229 static int timer_multiplier_set_handler(const char *kmessage,
22230 const struct kernel_param *kp)
22231 {
22232 QDF_STATUS status;
22233 uint32_t scalar;
22234
22235 status = qdf_uint32_parse(kmessage, &scalar);
22236 if (QDF_IS_STATUS_ERROR(status))
22237 return qdf_status_to_os_return(status);
22238
22239 if (!cfg_in_range(CFG_TIMER_MULTIPLIER, scalar))
22240 return -ERANGE;
22241
22242 qdf_timer_set_multiplier(scalar);
22243
22244 return 0;
22245 }
22246
22247 static const struct kernel_param_ops timer_multiplier_ops = {
22248 .get = timer_multiplier_get_handler,
22249 .set = timer_multiplier_set_handler,
22250 };
22251
22252 module_param_cb(timer_multiplier, &timer_multiplier_ops, NULL, 0644);
22253