1
0

icnss2: trigger wpss self recovery

Icnss driver receives early crash indication when
fatal error happens in wpss. In few cases rproc
framework didn't receive any notification regarding
wpss fatal crash due to which icnss driver wpss
notfier is not getting called. This prevents wpss ssr
recovery. To recover wpss from this scenerio icnss
driver tries to do self recovery of wpss subystem.

Change-Id: Ie22dfb6a6218aafd1fec84fb14f3efb16c60bf5e
CRs-Fixed: 3265930
Este cometimento está contido em:
Sandeep Singh
2023-02-01 16:54:45 +05:30
cometido por Madan Koyyalamudi
ascendente 54df2d964c
cometimento 172b8aee52
2 ficheiros modificados com 47 adições e 0 eliminações

Ver ficheiro

@@ -84,10 +84,12 @@ module_param(qmi_timeout, ulong, 0600);
#endif
#define ICNSS_RECOVERY_TIMEOUT 60000
#define ICNSS_WPSS_SSR_TIMEOUT 5000
#define ICNSS_CAL_TIMEOUT 40000
static struct icnss_priv *penv;
static struct work_struct wpss_loader;
static struct work_struct wpss_ssr_work;
uint64_t dynamic_feature_mask = ICNSS_DEFAULT_FEATURE_MASK;
#define ICNSS_EVENT_PENDING 2989
@@ -536,6 +538,10 @@ static irqreturn_t fw_crash_indication_handler(int irq, void *ctx)
icnss_pr_err("Received early crash indication from FW\n");
if (priv->wpss_self_recovery_enabled)
mod_timer(&priv->wpss_ssr_timer,
jiffies + msecs_to_jiffies(ICNSS_WPSS_SSR_TIMEOUT));
if (priv) {
set_bit(ICNSS_FW_DOWN, &priv->state);
icnss_ignore_fw_timeout(true);
@@ -1778,6 +1784,19 @@ static int icnss_subsys_restart_level(struct icnss_priv *priv, void *data)
return ret;
}
static void icnss_wpss_self_recovery(struct work_struct *wpss_load_work)
{
int ret;
struct icnss_priv *priv = icnss_get_plat_priv();
rproc_shutdown(priv->rproc);
ret = rproc_boot(priv->rproc);
if (ret) {
icnss_pr_err("Failed to self recover wpss rproc, ret: %d", ret);
rproc_put(priv->rproc);
}
}
static void icnss_driver_event_work(struct work_struct *work)
{
struct icnss_priv *priv =
@@ -2082,6 +2101,9 @@ static int icnss_wpss_notifier_nb(struct notifier_block *nb,
if (code != QCOM_SSR_BEFORE_SHUTDOWN)
goto out;
if (priv->wpss_self_recovery_enabled)
del_timer(&priv->wpss_ssr_timer);
priv->is_ssr = true;
icnss_pr_info("WPSS went down, state: 0x%lx, crashed: %d\n",
@@ -4330,6 +4352,10 @@ static void icnss_read_device_configs(struct icnss_priv *priv)
"wlan-ipa-disabled")) {
set_bit(ICNSS_IPA_DISABLED, &priv->device_config);
}
if (of_property_read_bool(priv->pdev->dev.of_node,
"qcom,wpss-self-recovery"))
priv->wpss_self_recovery_enabled = true;
}
static inline void icnss_runtime_pm_init(struct icnss_priv *priv)
@@ -4506,6 +4532,12 @@ static int icnss_probe(struct platform_device *pdev)
timer_setup(&priv->recovery_timer,
icnss_recovery_timeout_hdlr, 0);
if (priv->wpss_self_recovery_enabled) {
INIT_WORK(&wpss_ssr_work, icnss_wpss_self_recovery);
timer_setup(&priv->wpss_ssr_timer,
icnss_wpss_ssr_timeout_hdlr, 0);
}
INIT_LIST_HEAD(&priv->icnss_tcdev_list);
icnss_pr_info("Platform driver probed successfully\n");
@@ -4558,6 +4590,9 @@ static int icnss_remove(struct platform_device *pdev)
del_timer(&priv->recovery_timer);
if (priv->wpss_self_recovery_enabled)
del_timer(&priv->wpss_ssr_timer);
device_init_wakeup(&priv->pdev->dev, false);
icnss_debugfs_destroy(priv);
@@ -4624,6 +4659,15 @@ void icnss_recovery_timeout_hdlr(struct timer_list *t)
ICNSS_ASSERT(0);
}
void icnss_wpss_ssr_timeout_hdlr(struct timer_list *t)
{
struct icnss_priv *priv = from_timer(priv, t, wpss_ssr_timer);
icnss_pr_err("Timeout waiting for WPSS SSR notification 0x%lx\n",
priv->state);
schedule_work(&wpss_ssr_work);
}
#ifdef CONFIG_PM_SLEEP
static int icnss_pm_suspend(struct device *dev)
{

Ver ficheiro

@@ -503,6 +503,8 @@ struct icnss_priv {
u8 is_slate_rfa;
struct completion slate_boot_complete;
struct timer_list recovery_timer;
struct timer_list wpss_ssr_timer;
bool wpss_self_recovery_enabled;
};
struct icnss_reg_info {
@@ -531,5 +533,6 @@ void icnss_add_fw_prefix_name(struct icnss_priv *priv, char *prefix_name,
char *name);
int icnss_aop_mbox_init(struct icnss_priv *priv);
void icnss_recovery_timeout_hdlr(struct timer_list *t);
void icnss_wpss_ssr_timeout_hdlr(struct timer_list *t);
#endif