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
此提交包含在:
Sandeep Singh
2023-02-01 16:54:45 +05:30
提交者 Madan Koyyalamudi
父節點 54df2d964c
當前提交 172b8aee52
共有 2 個檔案被更改,包括 47 行新增0 行删除

查看文件

@@ -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)
{