msm: ipa: Check GSI status during deepsleep resume

Abort could be triggered during deepsleep suspend and HW won't
be reset. Check GSI status during deepsleep resume to avoid
loading GSI FW and uC again.

Change-Id: I360680963e9e65db50a43e17d12ebf75893efaab
Signed-off-by: Pavan Kumar M <quic_rpavan@quicinc.com>
This commit is contained in:
Pavan Kumar M 2024-09-11 16:58:15 +05:30
commit 2e77a46f0d
4 changed files with 80 additions and 30 deletions

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/of.h>
@ -1136,6 +1137,8 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl)
return -GSI_STATUS_UNSUPPORTED_OP;
}
gsi_unmap_base();
switch (props->ver) {
case GSI_VER_1_0:
case GSI_VER_1_2:
@ -1481,7 +1484,6 @@ int gsi_deregister_device(unsigned long dev_hdl, bool force)
__gsi_config_gen_irq(gsi_ctx->per.ee, ~0, 0);
devm_free_irq(gsi_ctx->dev, gsi_ctx->per.irq, gsi_ctx);
gsi_unmap_base();
gsi_ctx->per_registered = false;
return GSI_STATUS_SUCCESS;
}
@ -2813,6 +2815,28 @@ int gsi_write_wdi3_channel_scratch_6_7_reg(unsigned long chan_hdl,
}
EXPORT_SYMBOL(gsi_write_wdi3_channel_scratch_6_7_reg);
/**
* gsi_status_enabled() - Query GSI Status
*
* Returns: true if ENABLED, false on DISABLED
*
*/
bool gsi_status_enabled(void)
{
uint32_t val;
bool ret = false;
if (!gsi_ctx->base)
return ret;
val = gsi_readl(gsi_ctx->base +
GSI_EE_n_GSI_STATUS_OFFS(gsi_ctx->per.ee));
if (val & GSI_EE_n_GSI_STATUS_ENABLED_BMSK)
ret = true;
return ret;
}
EXPORT_SYMBOL(gsi_status_enabled);
static void __gsi_read_channel_scratch(unsigned long chan_hdl,
union __packed gsi_channel_scratch * val)
{

View file

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef GSI_H
@ -1610,6 +1611,14 @@ int gsi_poll_channel(unsigned long chan_hdl,
*/
int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode);
/**
* gsi_status_enabled() - Query GSI Status
*
* Returns: true if ENABLED, false on DISABLED
*
*/
bool gsi_status_enabled(void);
/**
* gsi_queue_xfer - Peripheral should call this function
* to queue transfers on the given channel

View file

@ -6666,7 +6666,7 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
/* GSI 2.2 requires to allocate all EE GSI channel
* during device bootup.
*/
if (gsi_props.ver == GSI_VER_2_2) {
if (gsi_props.ver == GSI_VER_2_2 && !ipa3_ctx->gsi_status) {
result = ipa3_alloc_gsi_channel();
if (result) {
IPAERR("Failed to alloc the GSI channels\n");
@ -6900,38 +6900,54 @@ static void ipa3_load_ipa_fw(struct work_struct *work)
return;
}
if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION &&
((ipa3_ctx->platform_type != IPA_PLAT_TYPE_MDM) ||
(ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5))) {
/* some targets sharing same lunch option but
* using different signing images, adding support to
* load specific FW image to based on dt entry.
*/
if (ipa3_ctx->gsi_fw_file_name)
result = ipa3_pil_load_ipa_fws(
ipa3_ctx->gsi_fw_file_name);
else
result = ipa3_pil_load_ipa_fws(IPA_SUBSYSTEM_NAME);
ipa3_ctx->gsi_status = gsi_status_enabled();
if(!ipa3_ctx->gsi_status) {
if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION &&
((ipa3_ctx->platform_type != IPA_PLAT_TYPE_MDM) ||
(ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5))) {
/* some targets sharing same lunch option but
* using different signing images, adding support to
* load specific FW image to based on dt entry.
*/
#if IS_ENABLED(CONFIG_QCOM_MDT_LOADER)
if (ipa3_ctx->gsi_fw_file_name)
result = ipa3_mdt_load_ipa_fws(
ipa3_ctx->gsi_fw_file_name);
else
result = ipa3_mdt_load_ipa_fws(IPA_SUBSYSTEM_NAME);
#else /* IS_ENABLED(CONFIG_QCOM_MDT_LOADER) */
if (ipa3_ctx->gsi_fw_file_name)
result = ipa3_pil_load_ipa_fws(
ipa3_ctx->gsi_fw_file_name);
else
result = ipa3_pil_load_ipa_fws(IPA_SUBSYSTEM_NAME);
#endif /* IS_ENABLED(CONFIG_QCOM_MDT_LOADER) */
} else {
result = ipa3_manual_load_ipa_fws();
}
if (result) {
ipa3_ctx->ipa_pil_load++;
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
IPADBG("IPA firmware loading deffered to a work queue\n");
queue_delayed_work(ipa3_ctx->transport_power_mgmt_wq,
&ipa3_fw_load_failure_handle,
msecs_to_jiffies(DELAY_BEFORE_FW_LOAD));
return;
}
mutex_lock(&ipa3_ctx->fw_load_data.lock);
ipa3_ctx->fw_load_data.state = IPA_FW_LOAD_STATE_LOADED;
mutex_unlock(&ipa3_ctx->fw_load_data.lock);
pr_info("IPA FW loaded successfully\n");
} else {
result = ipa3_manual_load_ipa_fws();
pr_info("IPA FW is already loaded\n");
/*uC is already loaded. Marking this as after SSR boot to avoid loading uc again*/
ipa3_ctx->uc_ctx.uc_loaded = true;
}
if (result) {
ipa3_ctx->ipa_pil_load++;
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
IPADBG("IPA firmware loading deffered to a work queue\n");
queue_delayed_work(ipa3_ctx->transport_power_mgmt_wq,
&ipa3_fw_load_failure_handle,
msecs_to_jiffies(DELAY_BEFORE_FW_LOAD));
return;
}
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
mutex_lock(&ipa3_ctx->fw_load_data.lock);
ipa3_ctx->fw_load_data.state = IPA_FW_LOAD_STATE_LOADED;
mutex_unlock(&ipa3_ctx->fw_load_data.lock);
pr_info("IPA FW loaded successfully\n");
result = ipa3_post_init(&ipa3_res, ipa3_ctx->cdev.dev);
if (result) {
@ -9684,7 +9700,7 @@ static void ipa3_deepsleep_suspend(void)
ipa3_ctx->deepsleep = true;
/*Disabling the LAN NAPI*/
ipa3_disable_napi_lan_rx();
/*NOt allow uC related operations until uC load again*/
/*Not allow uC related operations until uC load again*/
ipa3_ctx->uc_ctx.uc_loaded = false;
/*Disconnecting LAN PROD/LAN CONS/CMD PROD apps pipes*/
ipa3_teardown_apps_pipes();

View file

@ -2163,6 +2163,7 @@ struct ipa3_context {
struct ipa3_mhip_ctx mhip_ctx;
struct ipa3_aqc_ctx aqc_ctx;
atomic_t ipa_clk_vote;
bool gsi_status;
int (*client_lock_unlock[IPA_MAX_CLNT])(bool is_lock);