msm: mdm: Add shutdown ioctl and send poweroff request to the mdm

When the whole phone is being powered off, a poweroff request needs
to be sent to the external modem so that it can shutdown gracefully.
This request needs to be triggered from userspace before kernel drivers
start unloading so that other drivers needed to send the request are
still available. The shutdown ioctl is provided for this purpose.
The request is sent over system monitor.

Crs-Fixed: 401598
Signed-off-by: Joel King <joelking@codeaurora.org>
diff --git a/arch/arm/mach-msm/sysmon.c b/arch/arm/mach-msm/sysmon.c
index 78290a2..0d62e6a 100644
--- a/arch/arm/mach-msm/sysmon.c
+++ b/arch/arm/mach-msm/sysmon.c
@@ -159,6 +159,33 @@
 }
 
 /**
+ * sysmon_send_shutdown() - send shutdown command to a
+ * subsystem.
+ * @dest_ss:	ID of subsystem to send to.
+ *
+ * Returns 0 for success, -EINVAL for an invalid destination, -ENODEV if
+ * the SMD transport channel is not open, -ETIMEDOUT if the destination
+ * subsystem does not respond, and -ENOSYS if the destination subsystem
+ * responds with something unexpected.
+ *
+ * If CONFIG_MSM_SYSMON_COMM is not defined, always return success (0).
+ */
+int sysmon_send_shutdown(enum subsys_id dest_ss)
+{
+	struct sysmon_subsys *ss = &subsys[dest_ss];
+	const char tx_buf[] = "ssr:poweroff";
+	int ret;
+
+	if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS)
+		return -EINVAL;
+
+	mutex_lock(&ss->lock);
+	ret = sysmon_send_msg(ss, tx_buf, ARRAY_SIZE(tx_buf));
+	mutex_unlock(&ss->lock);
+	return ret;
+}
+
+/**
  * sysmon_get_reason() - Retrieve failure reason from a subsystem.
  * @dest_ss:	ID of subsystem to query
  * @buf:	Caller-allocated buffer for the returned NUL-terminated reason