diff --git a/icnss2/main.c b/icnss2/main.c index 8715e6844d..e1c33f0e8f 100644 --- a/icnss2/main.c +++ b/icnss2/main.c @@ -1910,6 +1910,24 @@ static char *icnss_qcom_ssr_notify_state_to_str(enum qcom_ssr_notify_type code) } }; +static int icnss_wpss_early_notifier_nb(struct notifier_block *nb, + unsigned long code, + void *data) +{ + struct icnss_priv *priv = container_of(nb, struct icnss_priv, + wpss_early_ssr_nb); + + icnss_pr_vdbg("WPSS-EARLY-Notify: event %s(%lu)\n", + icnss_qcom_ssr_notify_state_to_str(code), code); + + if (code == QCOM_SSR_BEFORE_SHUTDOWN) { + set_bit(ICNSS_FW_DOWN, &priv->state); + icnss_ignore_fw_timeout(true); + } + + return NOTIFY_DONE; +} + static int icnss_wpss_notifier_nb(struct notifier_block *nb, unsigned long code, void *data) @@ -2045,6 +2063,24 @@ out: return NOTIFY_OK; } +static int icnss_wpss_early_ssr_register_notifier(struct icnss_priv *priv) +{ + int ret = 0; + + priv->wpss_early_ssr_nb.notifier_call = icnss_wpss_early_notifier_nb; + + priv->wpss_early_notify_handler = + qcom_register_early_ssr_notifier("wpss", + &priv->wpss_early_ssr_nb); + + if (IS_ERR(priv->wpss_early_notify_handler)) { + ret = PTR_ERR(priv->wpss_early_notify_handler); + icnss_pr_err("WPSS register early notifier failed: %d\n", ret); + } + + return ret; +} + static int icnss_wpss_ssr_register_notifier(struct icnss_priv *priv) { int ret = 0; @@ -2093,6 +2129,16 @@ static int icnss_modem_ssr_register_notifier(struct icnss_priv *priv) return ret; } +static void icnss_wpss_early_ssr_unregister_notifier(struct icnss_priv *priv) +{ + if (IS_ERR(priv->wpss_early_notify_handler)) + return; + + qcom_unregister_early_ssr_notifier(priv->wpss_early_notify_handler, + &priv->wpss_early_ssr_nb); + priv->wpss_early_notify_handler = NULL; +} + static int icnss_wpss_ssr_unregister_notifier(struct icnss_priv *priv) { if (!test_and_clear_bit(ICNSS_SSR_REGISTERED, &priv->state)) @@ -2367,6 +2413,7 @@ static int icnss_enable_recovery(struct icnss_priv *priv) return ret; if (priv->device_id == WCN6750_DEVICE_ID) { + icnss_wpss_early_ssr_register_notifier(priv); icnss_wpss_ssr_register_notifier(priv); return 0; } @@ -4286,6 +4333,7 @@ static int icnss_remove(struct platform_device *pdev) icnss_destroy_ramdump_device(priv->msa0_dump_dev); if (priv->device_id == WCN6750_DEVICE_ID) { + icnss_wpss_early_ssr_unregister_notifier(priv); icnss_wpss_ssr_unregister_notifier(priv); rproc_put(priv->rproc); icnss_destroy_ramdump_device(priv->m3_dump_phyareg); diff --git a/icnss2/main.h b/icnss2/main.h index d8ce38ad0a..4d596a4aa3 100644 --- a/icnss2/main.h +++ b/icnss2/main.h @@ -419,8 +419,10 @@ struct icnss_priv { struct icnss_stats stats; void *modem_notify_handler; void *wpss_notify_handler; + void *wpss_early_notify_handler; struct notifier_block modem_ssr_nb; struct notifier_block wpss_ssr_nb; + struct notifier_block wpss_early_ssr_nb; uint32_t diag_reg_read_addr; uint32_t diag_reg_read_mem_type; uint32_t diag_reg_read_len;