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
此提交包含在:
@@ -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)
|
||||
{
|
||||
|
新增問題並參考
封鎖使用者