msm: modem-8660: Ignore unnecessary SMSM_RESET notifications
Before the modem is shutdown, the SMSM_RESET bit is set to
notify the modem to allow it to flush caches and complete
its error handler operations. One of these operations is
to set its own SMSM_RESET bit and notify the apps. This
notification is forwarded by modem_notifier to the
modem_8660 driver. Since the modem is already being
shutdown, this notification needs to be ignored.
Previously modem-8660 would unregister for the notification
and re-register for it once the modem was shutdown. This
may result in a race where the notification is sent after
the re-registration, a condition more exposed on 3.0 kernels.
Change the mechanism to use a flag to ignore the SMSM_RESET
notification inside the notification handler.
Change-Id: Ia49e76950afd04d8dfde1ca66e44d4231a366b31
Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org>
diff --git a/arch/arm/mach-msm/modem-8660.c b/arch/arm/mach-msm/modem-8660.c
index 19711a2..0b7b768 100644
--- a/arch/arm/mach-msm/modem-8660.c
+++ b/arch/arm/mach-msm/modem-8660.c
@@ -40,6 +40,7 @@
#if defined(SUBSYS_FATAL_DEBUG)
static void debug_crash_modem_fn(struct work_struct *);
static int reset_modem;
+static int ignore_smsm_ack;
static DECLARE_DELAYED_WORK(debug_crash_modem_work,
debug_crash_modem_fn);
@@ -129,26 +130,30 @@
void *_cmd)
{
if (code == MODEM_NOTIFIER_START_RESET) {
-
+ if (ignore_smsm_ack) {
+ ignore_smsm_ack = 0;
+ goto out;
+ }
pr_err("%s: Modem error fatal'ed.", MODULE_NAME);
subsystem_restart("modem");
}
+out:
return NOTIFY_DONE;
}
static int modem_shutdown(const struct subsys_data *crashed_subsys)
{
void __iomem *modem_wdog_addr;
- int smsm_notif_unregistered = 0;
/* If the modem didn't already crash, setting SMSM_RESET
- * here will help flush caches etc. Unregister for SMSM
- * notifications to prevent unnecessary secondary calls to
- * subsystem_restart.
+ * here will help flush caches etc. The ignore_smsm_ack
+ * flag is set to ignore the SMSM_RESET notification
+ * that is generated due to the modem settings its own
+ * SMSM_RESET bit in response to the apps setting the
+ * apps SMSM_RESET bit.
*/
if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
- modem_unregister_notifier(&modem_notif_nb);
- smsm_notif_unregistered = 1;
+ ignore_smsm_ack = 1;
smsm_reset_modem(SMSM_RESET);
}
@@ -168,9 +173,6 @@
pil_force_shutdown("modem");
disable_irq_nosync(MARM_WDOG_EXPIRED);
- /* Re-register for SMSM notifications if necessary */
- if (smsm_notif_unregistered)
- modem_register_notifier(&modem_notif_nb);
return 0;