summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnshuman Khandual <khandual@linux.vnet.ibm.com>2014-08-13 14:27:45 +0530
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-08-13 19:01:36 +1000
commit087e04598ed74146c2f2eab5666cd4d4b53b6974 (patch)
treed0d4c15c2f4fae090f05cda1a2df20d51baf7d46
parent0a22f85f524f366a3e2ef2af4a3faa0e9cef26ca (diff)
downloadtalos-skiboot-087e04598ed74146c2f2eab5666cd4d4b53b6974.tar.gz
talos-skiboot-087e04598ed74146c2f2eab5666cd4d4b53b6974.zip
dpo: Add OPAL interface to access the DPO timeout
This patch adds a OPAL interface to fetch the DPO timeout. This functionality is required to synchronously query Sapphire about how much seconds are remaining for a forced system shutdown which is useful in cases where the host has missed the OPAL_MSG_DPO for some reason like system boot, reboot or kexec operations. This ensures host can still query about the DPO timeout status and act. This patch also adds helper routine to convert time base into seconds. Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--hw/fsp/fsp-dpo.c25
-rw-r--r--include/opal.h3
-rw-r--r--include/timebase.h5
3 files changed, 32 insertions, 1 deletions
diff --git a/hw/fsp/fsp-dpo.c b/hw/fsp/fsp-dpo.c
index 23ab1ba7..94a705e0 100644
--- a/hw/fsp/fsp-dpo.c
+++ b/hw/fsp/fsp-dpo.c
@@ -21,12 +21,33 @@
#include <fsp.h>
#include <device.h>
#include <stdio.h>
+#include <timebase.h>
#include <opal.h>
#include <opal-msg.h>
#define PREFIX "FSPDPO: "
+#define DPO_TIMEOUT 2700 /* 45 minutes in seconds */
static bool fsp_dpo_pending = false;
+unsigned long fsp_dpo_init_tb = 0;
+
+/*
+ * OPAL DPO interface
+ *
+ * Returns zero if DPO is not active, positive value indicating number
+ * of seconds remaining for a forced system shutdown. This will enable
+ * the host to schedule for shutdown voluntarily before timeout occurs.
+ */
+static int64_t fsp_opal_get_dpo_status(int64_t *dpo_timeout)
+{
+ int64_t timeout = 0;
+
+ if (fsp_dpo_init_tb && fsp_dpo_pending)
+ timeout = DPO_TIMEOUT - tb_to_secs(mftb() - fsp_dpo_init_tb);
+
+ *dpo_timeout = timeout;
+ return OPAL_SUCCESS;
+}
/* Process FSP DPO init message */
static void fsp_process_dpo(struct fsp_msg *msg)
@@ -50,6 +71,9 @@ static void fsp_process_dpo(struct fsp_msg *msg)
return;
}
+ /* Record the DPO init time */
+ fsp_dpo_init_tb = mftb();
+
/* Inform the host about DPO */
rc = opal_queue_msg(OPAL_MSG_DPO, NULL, NULL);
if (rc) {
@@ -90,5 +114,6 @@ static struct fsp_client fsp_dpo_client = {
void fsp_dpo_init(void)
{
fsp_register_client(&fsp_dpo_client, FSP_MCLASS_SERVICE);
+ opal_register(OPAL_GET_DPO_STATUS, fsp_opal_get_dpo_status, 1);
printf(PREFIX "FSP DPO support initialized\n");
}
diff --git a/include/opal.h b/include/opal.h
index eac7eb69..99a33350 100644
--- a/include/opal.h
+++ b/include/opal.h
@@ -140,7 +140,8 @@
#define OPAL_UNREGISTER_DUMP_REGION 102
#define OPAL_WRITE_TPO 103
#define OPAL_READ_TPO 104
-#define OPAL_LAST 104
+#define OPAL_GET_DPO_STATUS 105
+#define OPAL_LAST 105
#ifndef __ASSEMBLY__
diff --git a/include/timebase.h b/include/timebase.h
index a1b787f3..45372569 100644
--- a/include/timebase.h
+++ b/include/timebase.h
@@ -57,6 +57,11 @@ static inline unsigned long secs_to_tb(unsigned long secs)
return secs * tb_hz;
}
+static inline unsigned long tb_to_secs(unsigned long tb)
+{
+ return tb / tb_hz;
+}
+
static inline unsigned long msecs_to_tb(unsigned long msecs)
{
return msecs * (tb_hz / 1000);
OpenPOWER on IntegriCloud