diff --git a/components/ipa/core/inc/wlan_ipa_core.h b/components/ipa/core/inc/wlan_ipa_core.h index 5e0701b842e9..6182898b38b8 100644 --- a/components/ipa/core/inc/wlan_ipa_core.h +++ b/components/ipa/core/inc/wlan_ipa_core.h @@ -66,6 +66,20 @@ static inline bool wlan_ipa_is_rm_enabled(struct wlan_ipa_config *ipa_cfg) return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_RM_ENABLE_MASK); } +/** + * wlan_ipa_is_clk_scaling_enabled() - Is IPA clock scaling enabled? + * @ipa_cfg: IPA config + * + * Return: true if IPA RM is enabled, false otherwise + */ +static inline +bool wlan_ipa_is_clk_scaling_enabled(struct wlan_ipa_config *ipa_cfg) +{ + return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, + WLAN_IPA_CLK_SCALING_ENABLE_MASK | + WLAN_IPA_RM_ENABLE_MASK); +} + /** * wlan_ipa_setup - IPA initialize and setup * @ipa_ctx: IPA priv obj @@ -107,6 +121,17 @@ QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx); */ QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx); +/** + * wlan_ipa_set_perf_level() - Set IPA performance level + * @ipa_ctx: IPA context + * @tx_packets: Number of packets transmitted in the last sample period + * @rx_packets: Number of packets received in the last sample period + * + * Return: QDF STATUS + */ +QDF_STATUS wlan_ipa_set_perf_level(struct wlan_ipa_priv *ipa_ctx, + uint64_t tx_packets, uint64_t rx_packets); + #ifndef CONFIG_IPA_WDI_UNIFIED_API /** * wlan_ipa_wdi_rm_request_resource() - IPA WDI request resource diff --git a/components/ipa/core/inc/wlan_ipa_main.h b/components/ipa/core/inc/wlan_ipa_main.h index e82682b7c62b..fa5330da12e0 100644 --- a/components/ipa/core/inc/wlan_ipa_main.h +++ b/components/ipa/core/inc/wlan_ipa_main.h @@ -156,5 +156,16 @@ void ipa_set_dp_handle(struct wlan_objmgr_psoc *psoc, void *dp_soc); * Return: None */ void ipa_set_txrx_handle(struct wlan_objmgr_psoc *psoc, void *txrx_handle); + +/** + * ipa_rm_set_perf_level() - set ipa rm perf level + * @pdev: pdev handle + * @tx_packets: packets transmitted in the last sample period + * @rx_packets: packets received in the last sample period + * + * Return: QDF_STATUS + */ +QDF_STATUS ipa_rm_set_perf_level(struct wlan_objmgr_pdev *pdev, + uint64_t tx_packets, uint64_t rx_packets); #endif /* IPA_OFFLOAD */ #endif /* end of _WLAN_IPA_MAIN_H_ */ diff --git a/components/ipa/core/src/wlan_ipa_main.c b/components/ipa/core/src/wlan_ipa_main.c index d0a8ec19eec0..64d6149e36e3 100644 --- a/components/ipa/core/src/wlan_ipa_main.c +++ b/components/ipa/core/src/wlan_ipa_main.c @@ -157,3 +157,22 @@ void ipa_set_txrx_handle(struct wlan_objmgr_psoc *psoc, void *txrx_handle) ipa_obj->dp_pdev = txrx_handle; wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID); } + +QDF_STATUS ipa_rm_set_perf_level(struct wlan_objmgr_pdev *pdev, + uint64_t tx_packets, uint64_t rx_packets) +{ + struct wlan_ipa_priv *ipa_obj; + + if (!g_ipa_hw_support) { + ipa_info("ipa hw not present"); + return QDF_STATUS_SUCCESS; + } + + ipa_obj = ipa_pdev_get_priv_obj(pdev); + if (!ipa_obj) { + ipa_err("IPA object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + return wlan_ipa_set_perf_level(ipa_obj, tx_packets, rx_packets); +} diff --git a/components/ipa/core/src/wlan_ipa_rm.c b/components/ipa/core/src/wlan_ipa_rm.c index bbd1d1dc441a..49f807dabadc 100644 --- a/components/ipa/core/src/wlan_ipa_rm.c +++ b/components/ipa/core/src/wlan_ipa_rm.c @@ -28,8 +28,74 @@ /* Include Files */ #include "wlan_ipa_core.h" #include "wlan_ipa_main.h" +#include "cdp_txrx_ipa.h" #include "host_diag_core_event.h" +QDF_STATUS wlan_ipa_set_perf_level(struct wlan_ipa_priv *ipa_ctx, + uint64_t tx_packets, + uint64_t rx_packets) +{ + uint32_t next_cons_bw, next_prod_bw; + qdf_ipa_rm_perf_profile_t profile; + int ret; + + if ((!wlan_ipa_is_enabled(ipa_ctx->config)) || + (!wlan_ipa_is_clk_scaling_enabled(ipa_ctx->config))) + return 0; + + qdf_mem_set(&profile, 0, sizeof(profile)); + + if (tx_packets > (ipa_ctx->config->bus_bw_high / 2)) + next_cons_bw = ipa_ctx->config->ipa_bw_high; + else if (tx_packets > (ipa_ctx->config->bus_bw_medium / 2)) + next_cons_bw = ipa_ctx->config->ipa_bw_medium; + else + next_cons_bw = ipa_ctx->config->ipa_bw_low; + + if (rx_packets > (ipa_ctx->config->bus_bw_high / 2)) + next_prod_bw = ipa_ctx->config->ipa_bw_high; + else if (rx_packets > (ipa_ctx->config->bus_bw_medium / 2)) + next_prod_bw = ipa_ctx->config->ipa_bw_medium; + else + next_prod_bw = ipa_ctx->config->ipa_bw_low; + + ipa_debug("CONS perf curr: %d, next: %d", ipa_ctx->curr_cons_bw, + next_cons_bw); + ipa_debug("PROD perf curr: %d, next: %d", ipa_ctx->curr_prod_bw, + next_prod_bw); + + if (ipa_ctx->curr_cons_bw != next_cons_bw) { + ipa_debug("Requesting CONS perf curr: %d, next: %d", + ipa_ctx->curr_cons_bw, next_cons_bw); + ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc, + QDF_IPA_RM_RESOURCE_WLAN_CONS, + next_cons_bw); + if (ret) { + ipa_err("RM CONS set perf profile failed: %d", ret); + + return QDF_STATUS_E_FAILURE; + } + ipa_ctx->curr_cons_bw = next_cons_bw; + ipa_ctx->stats.num_cons_perf_req++; + } + + if (ipa_ctx->curr_prod_bw != next_prod_bw) { + ipa_debug("Requesting PROD perf curr: %d, next: %d", + ipa_ctx->curr_prod_bw, next_prod_bw); + ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc, + QDF_IPA_RM_RESOURCE_WLAN_PROD, + next_prod_bw); + if (ret) { + ipa_err("RM PROD set perf profile failed: %d", ret); + return QDF_STATUS_E_FAILURE; + } + ipa_ctx->curr_prod_bw = next_prod_bw; + ipa_ctx->stats.num_prod_perf_req++; + } + + return QDF_STATUS_SUCCESS; +} + /** * wlan_ipa_rm_notify() - IPA resource manager notifier callback * @user_data: user data registered with IPA diff --git a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h index 31f7ab3bde55..f33f7a3159d9 100644 --- a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h +++ b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h @@ -67,6 +67,17 @@ void ucfg_ipa_set_dp_handle(struct wlan_objmgr_psoc *psoc, void ucfg_ipa_set_txrx_handle(struct wlan_objmgr_psoc *psoc, void *txrx_handle); +/** + * ucfg_ipa_set_perf_level() - Set IPA perf level + * @pdev: Pdev obj handle + * @tx_packets: Number of packets transmitted in the last sample period + * @rx_packets: Number of packets received in the last sample period + * + * Return: QDF_STATUS_SUCCESS on success + */ +QDF_STATUS ucfg_ipa_set_perf_level(struct wlan_objmgr_pdev *pdev, + uint64_t tx_packets, uint64_t rx_packets); + #else static inline bool ucfg_ipa_is_present(void) @@ -91,5 +102,12 @@ QDF_STATUS ucfg_ipa_set_txrx_handle(struct wlan_objmgr_psoc *psoc, { return QDF_STATUS_SUCCESS; } + +static inline +QDF_STATUS ucfg_ipa_set_perf_level(struct wlan_objmgr_pdev *pdev, + uint64_t tx_packets, uint64_t rx_packets) +{ + return QDF_STATUS_SUCCESS; +} #endif /* IPA_OFFLOAD */ #endif /* _WLAN_IPA_UCFG_API_H_ */ diff --git a/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c b/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c index 3f602d72b0ff..45ab2c47c64a 100644 --- a/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c +++ b/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c @@ -43,3 +43,9 @@ void ucfg_ipa_update_config(struct wlan_ipa_config *config) { ipa_config_update(config); } + +QDF_STATUS ucfg_ipa_set_perf_level(struct wlan_objmgr_pdev *pdev, + uint64_t tx_packets, uint64_t rx_packets) +{ + return ipa_rm_set_perf_level(pdev, tx_packets, rx_packets); +} diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 3b40e8df0e5a..f01fedb768e3 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -7238,7 +7238,7 @@ static void hdd_bus_bw_work_handler(struct work_struct *work) hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets); - hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets); + ucfg_ipa_set_perf_level(hdd_ctx->hdd_pdev, tx_packets, rx_packets); hdd_ipa_uc_stat_request(adapter, 2); restart_timer: @@ -11387,7 +11387,7 @@ void hdd_bus_bw_compute_timer_try_start(struct hdd_context *hdd_ctx) static void __hdd_bus_bw_compute_timer_stop(struct hdd_context *hdd_ctx) { - hdd_ipa_set_perf_level(hdd_ctx, 0, 0); + ucfg_ipa_set_perf_level(hdd_ctx->hdd_pdev, 0, 0); qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock); qdf_timer_stop(&hdd_ctx->bus_bw_timer);