/* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /** * DOC: define internal APIs related to the fwol component */ #include "wlan_fw_offload_main.h" #include "wlan_fwol_public_structs.h" #include "wlan_fwol_ucfg_api.h" #include "wlan_fwol_tgt_api.h" #include "target_if_fwol.h" #include "wlan_objmgr_vdev_obj.h" QDF_STATUS ucfg_fwol_psoc_open(struct wlan_objmgr_psoc *psoc) { QDF_STATUS status; status = fwol_cfg_on_psoc_enable(psoc); if (QDF_IS_STATUS_ERROR(status)) fwol_err("Failed to initialize FWOL CFG"); return status; } void ucfg_fwol_psoc_close(struct wlan_objmgr_psoc *psoc) { /* Clear the FWOL CFG Structure */ } QDF_STATUS ucfg_fwol_psoc_enable(struct wlan_objmgr_psoc *psoc) { tgt_fwol_register_ev_handler(psoc); return QDF_STATUS_SUCCESS; } void ucfg_fwol_psoc_disable(struct wlan_objmgr_psoc *psoc) { tgt_fwol_unregister_ev_handler(psoc); } /** * fwol_psoc_object_created_notification(): fwol psoc create handler * @psoc: psoc which is going to created by objmgr * @arg: argument for vdev create handler * * Register this api with objmgr to detect psoc is created * * Return QDF_STATUS status in case of success else return error */ static QDF_STATUS fwol_psoc_object_created_notification(struct wlan_objmgr_psoc *psoc, void *arg) { QDF_STATUS status; struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = qdf_mem_malloc(sizeof(*fwol_obj)); if (!fwol_obj) return QDF_STATUS_E_NOMEM; status = wlan_objmgr_psoc_component_obj_attach(psoc, WLAN_UMAC_COMP_FWOL, fwol_obj, QDF_STATUS_SUCCESS); if (QDF_IS_STATUS_ERROR(status)) { fwol_err("Failed to attach psoc_ctx with psoc"); qdf_mem_free(fwol_obj); return status; } tgt_fwol_register_rx_ops(&fwol_obj->rx_ops); target_if_fwol_register_tx_ops(&fwol_obj->tx_ops); return status; } /** * fwol_psoc_object_destroyed_notification(): fwol psoc delete handler * @psoc: psoc which is going to delete by objmgr * @arg: argument for vdev delete handler * * Register this api with objmgr to detect psoc is deleted * * Return QDF_STATUS status in case of success else return error */ static QDF_STATUS fwol_psoc_object_destroyed_notification( struct wlan_objmgr_psoc *psoc, void *arg) { struct wlan_fwol_psoc_obj *fwol_obj; QDF_STATUS status; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) return QDF_STATUS_E_NOMEM; status = wlan_objmgr_psoc_component_obj_detach(psoc, WLAN_UMAC_COMP_FWOL, fwol_obj); if (QDF_IS_STATUS_ERROR(status)) { fwol_err("Failed to detach psoc_ctx from psoc"); return status; } qdf_mem_free(fwol_obj); return status; } QDF_STATUS ucfg_fwol_init(void) { QDF_STATUS status; status = wlan_objmgr_register_psoc_create_handler( WLAN_UMAC_COMP_FWOL, fwol_psoc_object_created_notification, NULL); if (QDF_IS_STATUS_ERROR(status)) { fwol_err("unable to register psoc create handle"); return status; } status = wlan_objmgr_register_psoc_destroy_handler( WLAN_UMAC_COMP_FWOL, fwol_psoc_object_destroyed_notification, NULL); if (QDF_IS_STATUS_ERROR(status)) { fwol_err("unable to register psoc create handle"); wlan_objmgr_unregister_psoc_create_handler( WLAN_UMAC_COMP_FWOL, fwol_psoc_object_created_notification, NULL); } return status; } void ucfg_fwol_deinit(void) { QDF_STATUS status; status = wlan_objmgr_unregister_psoc_destroy_handler( WLAN_UMAC_COMP_FWOL, fwol_psoc_object_destroyed_notification, NULL); if (QDF_IS_STATUS_ERROR(status)) fwol_err("unable to unregister psoc destroy handle"); status = wlan_objmgr_unregister_psoc_create_handler( WLAN_UMAC_COMP_FWOL, fwol_psoc_object_created_notification, NULL); if (QDF_IS_STATUS_ERROR(status)) fwol_err("unable to unregister psoc create handle"); } #ifdef FW_THERMAL_THROTTLE_SUPPORT QDF_STATUS ucfg_fwol_thermal_register_callbacks( struct wlan_objmgr_psoc *psoc, struct fwol_thermal_callbacks *cb) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } fwol_obj->thermal_cbs = *cb; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_thermal_unregister_callbacks( struct wlan_objmgr_psoc *psoc) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } qdf_mem_zero(&fwol_obj->thermal_cbs, sizeof(fwol_obj->thermal_cbs)); return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_thermal_get_target_level(struct wlan_objmgr_psoc *psoc, enum thermal_throttle_level *level) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } *level = fwol_obj->thermal_throttle.level; return QDF_STATUS_SUCCESS; } #endif QDF_STATUS ucfg_fwol_get_coex_config_params(struct wlan_objmgr_psoc *psoc, struct wlan_fwol_coex_config *coex_config) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } *coex_config = fwol_obj->cfg.coex_config; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_thermal_temp(struct wlan_objmgr_psoc *psoc, struct wlan_fwol_thermal_temp *thermal_info) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } *thermal_info = fwol_obj->cfg.thermal_temp_cfg; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_is_neighbor_report_req_supported(struct wlan_objmgr_psoc *psoc, bool *neighbor_report_req) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); *neighbor_report_req = !!(cfg_get(psoc, CFG_OFFLOAD_11K_ENABLE_BITMASK) & OFFLOAD_11K_BITMASK_NEIGHBOR_REPORT_REQUEST); return QDF_STATUS_E_FAILURE; } *neighbor_report_req = !!(fwol_obj->cfg.neighbor_report_cfg.enable_bitmask & OFFLOAD_11K_BITMASK_NEIGHBOR_REPORT_REQUEST); return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_ie_allowlist(struct wlan_objmgr_psoc *psoc, bool *ie_allowlist) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } *ie_allowlist = fwol_obj->cfg.ie_allowlist_cfg.ie_allowlist; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_set_ie_allowlist(struct wlan_objmgr_psoc *psoc, bool ie_allowlist) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } fwol_obj->cfg.ie_allowlist_cfg.ie_allowlist = ie_allowlist; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_ani_enabled(struct wlan_objmgr_psoc *psoc, bool *ani_enabled) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *ani_enabled = fwol_obj->cfg.ani_enabled; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_pcie_config(struct wlan_objmgr_psoc *psoc, uint8_t *pcie_config) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *pcie_config = fwol_obj->cfg.pcie_config; return QDF_STATUS_SUCCESS; } static QDF_STATUS ucfg_fwol_get_ilp_config(struct wlan_objmgr_psoc *psoc, uint32_t *enable_ilp) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_ilp = fwol_obj->cfg.enable_ilp; return QDF_STATUS_SUCCESS; } static QDF_STATUS ucfg_fwol_get_sap_sho(struct wlan_objmgr_psoc *psoc, uint32_t *sap_sho) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *sap_sho = fwol_obj->cfg.sap_sho; return QDF_STATUS_SUCCESS; } static QDF_STATUS ucfg_fwol_get_hw_assist_config(struct wlan_objmgr_psoc *psoc, bool *disable_hw_assist) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *disable_hw_assist = fwol_obj->cfg.disable_hw_assist; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_get_enable_rts_sifsbursting(struct wlan_objmgr_psoc *psoc, bool *enable_rts_sifsbursting) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_rts_sifsbursting = fwol_obj->cfg.enable_rts_sifsbursting; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_get_enable_sifs_burst(struct wlan_objmgr_psoc *psoc, uint8_t *enable_sifs_burst) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_sifs_burst = fwol_obj->cfg.enable_sifs_burst; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_get_max_mpdus_inampdu(struct wlan_objmgr_psoc *psoc, uint8_t *max_mpdus_inampdu) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *max_mpdus_inampdu = fwol_obj->cfg.max_mpdus_inampdu; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_get_enable_phy_reg_retention(struct wlan_objmgr_psoc *psoc, uint8_t *enable_phy_reg_retention) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_phy_reg_retention = fwol_obj->cfg.enable_phy_reg_retention; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_all_allowlist_params(struct wlan_objmgr_psoc *psoc, struct wlan_fwol_ie_allowlist *allowlist) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } *allowlist = fwol_obj->cfg.ie_allowlist_cfg; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_get_upper_brssi_thresh(struct wlan_objmgr_psoc *psoc, uint16_t *upper_brssi_thresh) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *upper_brssi_thresh = fwol_obj->cfg.upper_brssi_thresh; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_get_lower_brssi_thresh(struct wlan_objmgr_psoc *psoc, uint16_t *lower_brssi_thresh) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *lower_brssi_thresh = fwol_obj->cfg.lower_brssi_thresh; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_get_enable_dtim_1chrx(struct wlan_objmgr_psoc *psoc, bool *enable_dtim_1chrx) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_dtim_1chrx = fwol_obj->cfg.enable_dtim_1chrx; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_get_alternative_chainmask_enabled(struct wlan_objmgr_psoc *psoc, bool *alternative_chainmask_enabled) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } *alternative_chainmask_enabled = fwol_obj->cfg.alternative_chainmask_enabled; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_get_smart_chainmask_enabled(struct wlan_objmgr_psoc *psoc, bool *smart_chainmask_enabled) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *smart_chainmask_enabled = fwol_obj->cfg.smart_chainmask_enabled; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_rts_profile(struct wlan_objmgr_psoc *psoc, uint16_t *get_rts_profile) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *get_rts_profile = fwol_obj->cfg.get_rts_profile; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_enable_fw_log_level(struct wlan_objmgr_psoc *psoc, uint16_t *enable_fw_log_level) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_fw_log_level = fwol_obj->cfg.enable_fw_log_level; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_enable_fw_log_type(struct wlan_objmgr_psoc *psoc, uint16_t *enable_fw_log_type) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_fw_log_type = fwol_obj->cfg.enable_fw_log_type; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_enable_fw_module_log_level( struct wlan_objmgr_psoc *psoc, uint8_t **enable_fw_module_log_level, uint8_t *enable_fw_module_log_level_num) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_fw_module_log_level = fwol_obj->cfg.enable_fw_module_log_level; *enable_fw_module_log_level_num = fwol_obj->cfg.enable_fw_module_log_level_num; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_wow_get_enable_fw_module_log_level( struct wlan_objmgr_psoc *psoc, uint8_t **enable_fw_wow_module_log_level, uint8_t *enable_fw_wow_module_log_level_num) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_fw_wow_module_log_level = fwol_obj->cfg.enable_fw_mod_wow_log_level; *enable_fw_wow_module_log_level_num = fwol_obj->cfg.enable_fw_mod_wow_log_level_num; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_sap_xlna_bypass(struct wlan_objmgr_psoc *psoc, bool *sap_xlna_bypass) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *sap_xlna_bypass = fwol_obj->cfg.sap_xlna_bypass; return QDF_STATUS_SUCCESS; } #ifdef FEATURE_WLAN_RA_FILTERING QDF_STATUS ucfg_fwol_set_is_rate_limit_enabled(struct wlan_objmgr_psoc *psoc, bool is_rate_limit_enabled) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } fwol_obj->cfg.is_rate_limit_enabled = is_rate_limit_enabled; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_is_rate_limit_enabled(struct wlan_objmgr_psoc *psoc, bool *is_rate_limit_enabled) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *is_rate_limit_enabled = fwol_obj->cfg.is_rate_limit_enabled; return QDF_STATUS_SUCCESS; } #endif #ifdef WLAN_FEATURE_TSF QDF_STATUS ucfg_fwol_get_tsf_gpio_pin(struct wlan_objmgr_psoc *psoc, uint32_t *tsf_gpio_pin) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); *tsf_gpio_pin = cfg_default(CFG_SET_TSF_GPIO_PIN); return QDF_STATUS_E_FAILURE; } *tsf_gpio_pin = fwol_obj->cfg.tsf_gpio_pin; return QDF_STATUS_SUCCESS; } #ifdef WLAN_FEATURE_TSF_PLUS QDF_STATUS ucfg_fwol_get_tsf_ptp_options(struct wlan_objmgr_psoc *psoc, uint32_t *tsf_ptp_options) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); *tsf_ptp_options = cfg_default(CFG_SET_TSF_PTP_OPT); return QDF_STATUS_E_FAILURE; } *tsf_ptp_options = fwol_obj->cfg.tsf_ptp_options; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_tsf_sync_enable(struct wlan_objmgr_psoc *psoc, bool *tsf_sync_enable) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); *tsf_sync_enable = cfg_default(CFG_TSF_SYNC_ENABLE); return QDF_STATUS_E_FAILURE; } *tsf_sync_enable = fwol_obj->cfg.tsf_sync_enable; return QDF_STATUS_SUCCESS; } #ifdef WLAN_FEATURE_TSF_ACCURACY QDF_STATUS ucfg_fwol_get_tsf_accuracy_configs(struct wlan_objmgr_psoc *psoc, struct wlan_fwol_tsf_accuracy_configs **config) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *config = &fwol_obj->cfg.tsf_accuracy_configs; return QDF_STATUS_SUCCESS; } #endif #ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ QDF_STATUS ucfg_fwol_get_tsf_irq_host_gpio_pin(struct wlan_objmgr_psoc *psoc, uint32_t *tsf_irq_host_gpio_pin) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); *tsf_irq_host_gpio_pin = cfg_default(CFG_SET_TSF_IRQ_HOST_GPIO_PIN); return QDF_STATUS_E_FAILURE; } *tsf_irq_host_gpio_pin = fwol_obj->cfg.tsf_irq_host_gpio_pin; return QDF_STATUS_SUCCESS; } #endif #ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_SYNC QDF_STATUS ucfg_fwol_get_tsf_sync_host_gpio_pin(struct wlan_objmgr_psoc *psoc, uint32_t *tsf_sync_host_gpio_pin) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); *tsf_sync_host_gpio_pin = cfg_default(CFG_SET_TSF_SYNC_HOST_GPIO_PIN); return QDF_STATUS_E_FAILURE; } *tsf_sync_host_gpio_pin = fwol_obj->cfg.tsf_sync_host_gpio_pin; return QDF_STATUS_SUCCESS; } #endif #endif #else QDF_STATUS ucfg_fwol_get_tsf_gpio_pin(struct wlan_objmgr_psoc *psoc, uint32_t *tsf_gpio_pin) { return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_tsf_ptp_options(struct wlan_objmgr_psoc *psoc, uint32_t *tsf_ptp_options) { return QDF_STATUS_E_NOSUPPORT; } #endif #ifdef WLAN_FEATURE_SAE bool ucfg_fwol_get_sae_enable(struct wlan_objmgr_psoc *psoc) { return cfg_get(psoc, CFG_IS_SAE_ENABLED); } #else bool ucfg_fwol_get_sae_enable(struct wlan_objmgr_psoc *psoc) { return false; } #endif bool ucfg_fwol_get_gcmp_enable(struct wlan_objmgr_psoc *psoc) { return cfg_get(psoc, CFG_ENABLE_GCMP); } QDF_STATUS ucfg_fwol_get_enable_tx_sch_delay(struct wlan_objmgr_psoc *psoc, uint8_t *enable_tx_sch_delay) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); *enable_tx_sch_delay = cfg_default(CFG_TX_SCH_DELAY); return QDF_STATUS_E_FAILURE; } *enable_tx_sch_delay = fwol_obj->cfg.enable_tx_sch_delay; return QDF_STATUS_SUCCESS; } #ifdef WLAN_FEATURE_OFDM_SCRAMBLER_SEED QDF_STATUS ucfg_fwol_get_ofdm_scrambler_seed(struct wlan_objmgr_psoc *psoc, bool *enable_ofdm_scrambler_seed) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { *enable_ofdm_scrambler_seed = cfg_default(CFG_ENABLE_OFDM_SCRAMBLER_SEED); return QDF_STATUS_E_FAILURE; } *enable_ofdm_scrambler_seed = fwol_obj->cfg.enable_ofdm_scrambler_seed; return QDF_STATUS_SUCCESS; } #endif QDF_STATUS ucfg_fwol_get_enable_secondary_rate(struct wlan_objmgr_psoc *psoc, uint32_t *enable_secondary_rate) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); *enable_secondary_rate = cfg_default(CFG_ENABLE_SECONDARY_RATE); return QDF_STATUS_E_FAILURE; } *enable_secondary_rate = fwol_obj->cfg.enable_secondary_rate; return QDF_STATUS_SUCCESS; } #ifdef DHCP_SERVER_OFFLOAD QDF_STATUS ucfg_fwol_get_enable_dhcp_server_offload(struct wlan_objmgr_psoc *psoc, bool *enable_dhcp_server_offload) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *enable_dhcp_server_offload = fwol_obj->cfg.enable_dhcp_server_offload; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_dhcp_max_num_clients(struct wlan_objmgr_psoc *psoc, uint32_t *dhcp_max_num_clients) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *dhcp_max_num_clients = fwol_obj->cfg.dhcp_max_num_clients; return QDF_STATUS_SUCCESS; } #endif QDF_STATUS ucfg_fwol_get_all_adaptive_dwelltime_params( struct wlan_objmgr_psoc *psoc, struct adaptive_dwelltime_params *dwelltime_params) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } *dwelltime_params = fwol_obj->cfg.dwelltime_params; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_adaptive_dwell_mode_enabled( struct wlan_objmgr_psoc *psoc, bool *adaptive_dwell_mode_enabled) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *adaptive_dwell_mode_enabled = fwol_obj->cfg.dwelltime_params.is_enabled; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_global_adapt_dwelltime_mode(struct wlan_objmgr_psoc *psoc, uint8_t *global_adapt_dwelltime_mode) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *global_adapt_dwelltime_mode = fwol_obj->cfg.dwelltime_params.dwelltime_mode; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_adapt_dwell_lpf_weight(struct wlan_objmgr_psoc *psoc, uint8_t *adapt_dwell_lpf_weight) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *adapt_dwell_lpf_weight = fwol_obj->cfg.dwelltime_params.lpf_weight; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_adapt_dwell_passive_mon_intval( struct wlan_objmgr_psoc *psoc, uint8_t *adapt_dwell_passive_mon_intval) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *adapt_dwell_passive_mon_intval = fwol_obj->cfg.dwelltime_params.passive_mon_intval; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_get_adapt_dwell_wifi_act_threshold( struct wlan_objmgr_psoc *psoc, uint8_t *adapt_dwell_wifi_act_threshold) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL obj"); return QDF_STATUS_E_FAILURE; } *adapt_dwell_wifi_act_threshold = fwol_obj->cfg.dwelltime_params.wifi_act_threshold; return QDF_STATUS_SUCCESS; } #ifdef WLAN_FEATURE_ELNA QDF_STATUS ucfg_fwol_set_elna_bypass(struct wlan_objmgr_vdev *vdev, struct set_elna_bypass_request *req) { QDF_STATUS status; struct wlan_objmgr_psoc *psoc; struct wlan_fwol_psoc_obj *fwol_obj; struct wlan_fwol_tx_ops *tx_ops; psoc = wlan_vdev_get_psoc(vdev); if (!psoc) { fwol_err("NULL pointer for psoc"); return QDF_STATUS_E_INVAL; } fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL Obj"); return QDF_STATUS_E_INVAL; } tx_ops = &fwol_obj->tx_ops; if (tx_ops->set_elna_bypass) status = tx_ops->set_elna_bypass(psoc, req); else status = QDF_STATUS_E_IO; return status; } QDF_STATUS ucfg_fwol_get_elna_bypass(struct wlan_objmgr_vdev *vdev, struct get_elna_bypass_request *req, void (*callback)(void *context, struct get_elna_bypass_response *response), void *context) { QDF_STATUS status; struct wlan_objmgr_psoc *psoc; struct wlan_fwol_psoc_obj *fwol_obj; struct wlan_fwol_tx_ops *tx_ops; struct wlan_fwol_callbacks *cbs; psoc = wlan_vdev_get_psoc(vdev); if (!psoc) { fwol_err("NULL pointer for psoc"); return QDF_STATUS_E_INVAL; } fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL Obj"); return QDF_STATUS_E_INVAL; } cbs = &fwol_obj->cbs; cbs->get_elna_bypass_callback = callback; cbs->get_elna_bypass_context = context; tx_ops = &fwol_obj->tx_ops; if (tx_ops->get_elna_bypass) status = tx_ops->get_elna_bypass(psoc, req); else status = QDF_STATUS_E_IO; return status; } #endif /* WLAN_FEATURE_ELNA */ #ifdef WLAN_SEND_DSCP_UP_MAP_TO_FW QDF_STATUS ucfg_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev *vdev, uint32_t *dscp_to_up_map) { QDF_STATUS status; struct wlan_objmgr_psoc *psoc; struct wlan_fwol_psoc_obj *fwol_obj; struct wlan_fwol_tx_ops *tx_ops; psoc = wlan_vdev_get_psoc(vdev); if (!psoc) { fwol_err("NULL pointer for psoc"); return QDF_STATUS_E_INVAL; } fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL Obj"); return QDF_STATUS_E_INVAL; } tx_ops = &fwol_obj->tx_ops; if (tx_ops && tx_ops->send_dscp_up_map_to_fw) status = tx_ops->send_dscp_up_map_to_fw(psoc, dscp_to_up_map); else status = QDF_STATUS_E_IO; return status; } #endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */ #ifdef WLAN_FEATURE_MDNS_OFFLOAD QDF_STATUS ucfg_fwol_set_mdns_config(struct wlan_objmgr_psoc *psoc, struct mdns_config_info *mdns_info) { QDF_STATUS status; struct wlan_fwol_psoc_obj *fwol_obj; struct wlan_fwol_tx_ops *tx_ops; if (!psoc) { fwol_err("NULL pointer for psoc"); return QDF_STATUS_E_INVAL; } fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL Obj"); return QDF_STATUS_E_INVAL; } tx_ops = &fwol_obj->tx_ops; if (tx_ops->set_mdns_config) status = tx_ops->set_mdns_config(psoc, mdns_info); else status = QDF_STATUS_E_IO; return status; } #endif /* WLAN_FEATURE_MDNS_OFFLOAD */ void ucfg_fwol_update_fw_cap_info(struct wlan_objmgr_psoc *psoc, struct wlan_fwol_capability_info *caps) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return; } qdf_mem_copy(&fwol_obj->capability_info, caps, sizeof(fwol_obj->capability_info)); } #ifdef THERMAL_STATS_SUPPORT static QDF_STATUS ucfg_fwol_get_cap(struct wlan_objmgr_psoc *psoc, struct wlan_fwol_capability_info *cap_info) { struct wlan_fwol_psoc_obj *fwol_obj; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } if (!cap_info) { fwol_err("Failed to get fwol obj"); return QDF_STATUS_E_FAILURE; } *cap_info = fwol_obj->capability_info; return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_fwol_send_get_thermal_stats_cmd(struct wlan_objmgr_psoc *psoc, enum thermal_stats_request_type req_type, void (*callback)(void *context, struct thermal_throttle_info *response), void *context) { QDF_STATUS status; struct wlan_fwol_psoc_obj *fwol_obj; struct wlan_fwol_tx_ops *tx_ops; struct wlan_fwol_thermal_temp thermal_temp = {0}; struct wlan_fwol_capability_info cap_info; struct wlan_fwol_callbacks *cbs; fwol_obj = fwol_get_psoc_obj(psoc); if (!fwol_obj) { fwol_err("Failed to get FWOL Obj"); return QDF_STATUS_E_INVAL; } status = ucfg_fwol_get_thermal_temp(psoc, &thermal_temp); if (QDF_IS_STATUS_ERROR(status)) return QDF_STATUS_E_INVAL; status = ucfg_fwol_get_cap(psoc, &cap_info); if (QDF_IS_STATUS_ERROR(status)) return QDF_STATUS_E_INVAL; if (!thermal_temp.therm_stats_offset || !cap_info.fw_thermal_stats_cap) { fwol_err("Command Disabled in Ini gThermalStatsTempOffset %d or not enabled in FW %d", thermal_temp.therm_stats_offset, cap_info.fw_thermal_stats_cap); return QDF_STATUS_E_INVAL; } /* Registering Callback for the Request command */ if (callback && context) { cbs = &fwol_obj->cbs; cbs->get_thermal_stats_callback = callback; cbs->get_thermal_stats_context = context; } tx_ops = &fwol_obj->tx_ops; if (tx_ops && tx_ops->get_thermal_stats) status = tx_ops->get_thermal_stats(psoc, req_type, thermal_temp.therm_stats_offset); else status = QDF_STATUS_E_INVAL; return status; } #endif /* THERMAL_STATS_SUPPORT */ QDF_STATUS ucfg_fwol_configure_global_params(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev) { QDF_STATUS status; uint32_t enable_ilp; bool value; /* Configure ILP feature in FW */ status = ucfg_fwol_get_ilp_config(psoc, &enable_ilp); if (QDF_IS_STATUS_ERROR(status)) return status; status = fwol_set_ilp_config(pdev, enable_ilp); if (QDF_IS_STATUS_ERROR(status)) return status; /* Configure HW assist feature in FW */ status = ucfg_fwol_get_hw_assist_config(psoc, &value); if (QDF_IS_STATUS_ERROR(status)) return status; status = fwol_configure_hw_assist(pdev, value); if (QDF_IS_STATUS_ERROR(status)) return status; return status; } QDF_STATUS ucfg_fwol_set_ilp_config(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, uint32_t enable_ilp) { return fwol_set_ilp_config(pdev, enable_ilp); } QDF_STATUS ucfg_fwol_configure_vdev_params(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev) { uint32_t value; QDF_STATUS status; uint8_t vdev_id = wlan_vdev_get_id(vdev); switch (wlan_vdev_mlme_get_opmode(vdev)) { case QDF_SAP_MODE: status = ucfg_fwol_get_sap_sho(psoc, &value); if (QDF_IS_STATUS_ERROR(status)) break; status = fwol_set_sap_sho(psoc, vdev_id, value); if (QDF_IS_STATUS_ERROR(status)) break; status = fwol_set_sap_wds_config(psoc, vdev_id); break; default: status = QDF_STATUS_SUCCESS; break; } return status; }