msm: LPASS-8960: Retrieve LPASS failure reason
Add feature to retrieve and report LPASS subsystem reset reason.
Change-Id: I8609a0ebe42a9bcea59c8b9bba30de89b2989260
Signed-off-by: Ravishankar Sarawadi <crsaraw@codeaurora.org>
diff --git a/arch/arm/mach-msm/lpass-8960.c b/arch/arm/mach-msm/lpass-8960.c
index 7775740..c58b0e1 100644
--- a/arch/arm/mach-msm/lpass-8960.c
+++ b/arch/arm/mach-msm/lpass-8960.c
@@ -31,6 +31,7 @@
#define SCM_Q6_NMI_CMD 0x1
#define MODULE_NAME "lpass_8960"
+#define MAX_BUF_SIZE 0x51
/* Subsystem restart: QDSP6 data, functions */
static void lpass_fatal_fn(struct work_struct *);
@@ -86,10 +87,39 @@
.notifier_call = modem_notifier_cb,
};
+static void lpass_log_failure_reason(void)
+{
+ char *reason;
+ char buffer[MAX_BUF_SIZE];
+ unsigned size;
+
+ reason = smem_get_entry(SMEM_SSR_REASON_LPASS0, &size);
+
+ if (!reason) {
+ pr_err("%s: subsystem failure reason: (unknown, smem_get_entry failed).",
+ MODULE_NAME);
+ return;
+ }
+
+ if (reason[0] == '\0') {
+ pr_err("%s: subsystem failure reason: (unknown, init value found)",
+ MODULE_NAME);
+ return;
+ }
+
+ size = size < MAX_BUF_SIZE ? size : (MAX_BUF_SIZE-1);
+ memcpy(buffer, reason, size);
+ buffer[size] = '\0';
+ pr_err("%s: subsystem failure reason: %s", MODULE_NAME, buffer);
+ memset((void *)reason, 0x0, size);
+ wmb();
+}
+
static void lpass_fatal_fn(struct work_struct *work)
{
pr_err("%s %s: Watchdog bite received from Q6!\n", MODULE_NAME,
__func__);
+ lpass_log_failure_reason();
panic(MODULE_NAME ": Resetting the SoC");
}
@@ -104,6 +134,7 @@
pr_err("%s: LPASS SMSM state changed to SMSM_RESET,"
" new_state = 0x%x, old_state = 0x%x\n", __func__,
new_state, old_state);
+ lpass_log_failure_reason();
panic(MODULE_NAME ": Resetting the SoC");
}
}