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;