msm: DSPS: Remove work queue from watchdog ISR

Remove the workqueue from the watchdog ISR,
to prevent raceconditions when resetting the DSPS.
Also addresses additional code review comments.

Change-Id: I453f65e0efaddaf9dbe265defc0ad881bc6a980a
CRs-fixed: 367954
Acked-by: John Larkin <jlarkin@qualcomm.com>
Signed-off-by: Karthik Karuppasamy <kkaruppa@codeaurora.org>
diff --git a/arch/arm/mach-msm/msm_dsps.c b/arch/arm/mach-msm/msm_dsps.c
index 3b52a9f..f7c651e 100644
--- a/arch/arm/mach-msm/msm_dsps.c
+++ b/arch/arm/mach-msm/msm_dsps.c
@@ -45,7 +45,7 @@
 #include "timer.h"
 
 #define DRV_NAME	"msm_dsps"
-#define DRV_VERSION	"4.00"
+#define DRV_VERSION	"4.01"
 
 #define PPSS_PAUSE_REG	0x1804
 
@@ -68,7 +68,6 @@
  *  @is_on - DSPS is on.
  *  @ref_count - open/close reference count.
  *  @wdog_irq - DSPS Watchdog IRQ
- *  @wd_crash - Watchdog ISR fired
  *  @crash_in_progress - 1 if crash recovery is in progress
  *  @ppss_base - ppss registers virtual base address.
  */
@@ -93,7 +92,6 @@
 	int ref_count;
 	int wdog_irq;
 
-	atomic_t wd_crash;
 	atomic_t crash_in_progress;
 	void __iomem *ppss_base;
 };
@@ -108,7 +106,7 @@
  */
 static int dsps_crash_shutdown_g;
 
-static void dsps_restart_handler(struct work_struct *work);
+static void dsps_restart_handler(void);
 
 /**
  *  Load DSPS Firmware.
@@ -378,7 +376,28 @@
 	return 0;
 }
 
-static DECLARE_WORK(dsps_fatal_work, dsps_restart_handler);
+/**
+ *
+ * Log subsystem restart failure reason
+ */
+static void dsps_log_sfr(void)
+{
+	const char dflt_reason[] = "Died too early due to unknown reason";
+	char *smem_reset_reason;
+	unsigned smem_reset_size;
+
+	smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_DSPS0,
+		&smem_reset_size);
+	if (smem_reset_reason != NULL && smem_reset_reason[0] != 0) {
+		smem_reset_reason[smem_reset_size-1] = 0;
+		pr_err("%s: DSPS failure: %s\nResetting DSPS\n",
+			__func__, smem_reset_reason);
+		memset(smem_reset_reason, 0, smem_reset_size);
+		wmb();
+	} else
+		pr_err("%s: DSPS failure: %s\nResetting DSPS\n",
+			__func__, dflt_reason);
+}
 
 /**
  *  Watchdog interrupt handler
@@ -386,10 +405,9 @@
  */
 static irqreturn_t dsps_wdog_bite_irq(int irq, void *dev_id)
 {
-	pr_debug("%s\n", __func__);
-	atomic_set(&drv->wd_crash, 1);
-	(void)schedule_work(&dsps_fatal_work);
-	disable_irq_nosync(irq);
+	pr_err("%s\n", __func__);
+	dsps_log_sfr();
+	dsps_restart_handler();
 	return IRQ_HANDLED;
 }
 
@@ -425,7 +443,9 @@
 		ret = put_user(val, (u32 __user *) arg);
 		break;
 	case DSPS_IOCTL_RESET:
-		dsps_restart_handler(NULL);
+		pr_err("%s: User-initiated DSPS reset.\nResetting DSPS\n",
+		       __func__);
+		dsps_restart_handler();
 		ret = 0;
 		break;
 	default:
@@ -698,36 +718,10 @@
  *  Fatal error handler
  *  Resets DSPS.
  */
-static void dsps_restart_handler(struct work_struct *work)
+static void dsps_restart_handler(void)
 {
-	uint32_t dsps_state;
-	int restart_level;
-	char *smem_reset_reason;
-	unsigned smem_reset_size;
-	const char dflt_reason[] = "Died too early due to unknown reason";
-
-	dsps_state = smsm_get_state(SMSM_DSPS_STATE);
-	restart_level = get_restart_level();
-
-	pr_debug("%s: DSPS state 0x%x. Restart lvl %d\n",
-		__func__, dsps_state, restart_level);
-
-	if ((dsps_state & SMSM_RESET) ||
-	    (atomic_read(&drv->wd_crash) == 1)) {
-		smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_DSPS0,
-			&smem_reset_size);
-		if (smem_reset_reason != NULL && smem_reset_reason[0] != 0) {
-			smem_reset_reason[smem_reset_size-1] = 0;
-			pr_err("%s: DSPS failure: %s\nResetting DSPS\n",
-				__func__, smem_reset_reason);
-			memset(smem_reset_reason, 0, smem_reset_size);
-			wmb();
-		} else
-			pr_err("%s: DSPS failure: %s\nResetting DSPS\n",
-				__func__, dflt_reason);
-	} else
-		pr_err("%s: User-initiated DSPS reset.\nResetting DSPS\n",
-		       __func__);
+	pr_debug("%s: Restart lvl %d\n",
+		__func__, get_restart_level());
 
 	if (atomic_add_return(1, &drv->crash_in_progress) > 1) {
 		pr_err("%s: DSPS already resetting. Count %d\n", __func__,
@@ -752,8 +746,10 @@
 		dsps_crash_shutdown_g = 0;
 		return;
 	}
-	if (new_state & SMSM_RESET)
-		dsps_restart_handler(NULL);
+	if (new_state & SMSM_RESET) {
+		dsps_log_sfr();
+		dsps_restart_handler();
+	}
 }
 
 /**
@@ -764,6 +760,7 @@
 static int dsps_shutdown(const struct subsys_data *subsys)
 {
 	pr_debug("%s\n", __func__);
+	disable_irq_nosync(drv->wdog_irq);
 	dsps_suspend();
 	pil_force_shutdown(drv->pdata->pil_name);
 	dsps_power_off_handler();
@@ -781,10 +778,7 @@
 	dsps_power_on_handler();
 	pil_force_boot(drv->pdata->pil_name);
 	atomic_set(&drv->crash_in_progress, 0);
-	if (atomic_read(&drv->wd_crash) > 0) {
-		atomic_set(&drv->wd_crash, 0);
-		enable_irq(drv->wdog_irq);
-	}
+	enable_irq(drv->wdog_irq);
 	dsps_resume();
 	return 0;
 }
@@ -866,7 +860,6 @@
 		pr_err("%s: kzalloc fail.\n", __func__);
 		goto alloc_err;
 	}
-	atomic_set(&drv->wd_crash, 0);
 	atomic_set(&drv->crash_in_progress, 0);
 
 	drv->pdata = pdev->dev.platform_data;