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
This commit is contained in:

committed by
Madan Koyyalamudi

parent
54df2d964c
commit
172b8aee52
@@ -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)
|
||||
{
|
||||
|
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user