[Skiboot] [PATCH 10/12] opal: Enable backup topology.

Mahesh J Salgaonkar mahesh at linux.vnet.ibm.com
Sat Mar 28 20:36:27 AEDT 2015


From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

Whenever FSP makes any changes to backup topology as part of either
routine hardware maintenance or fixing failed backup topology configuration,
it sends out mailbox command xE6, s/c 0x06, mod 0, to enable/disable
the backup topology. OPAL layer should keep itself up-to-date with accurate
details of current topology configurations. This will help OPAL layer to
successfully handle any TOD failover in future.

The FSP can only request that the currently inactive (backup) topology be
disabled or enabled. If the requested topology is currently the active
topology, then fail this request with a 0xB8 (TOD topology in use) status
as return code.

For disable request, set the backup topology status as disabled.
For enable request, scan all the available chips and find the new backup
master chip by looking at TOD status register of each chip.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
 hw/chiptod.c               |  106 ++++++++++++++++++++++++++++++++++++++++++++
 include/fsp.h              |    9 ++++
 platforms/ibm-fsp/common.c |    3 +
 3 files changed, 118 insertions(+)

diff --git a/hw/chiptod.c b/hw/chiptod.c
index f43d973..bb73b14 100644
--- a/hw/chiptod.c
+++ b/hw/chiptod.c
@@ -25,6 +25,7 @@
 #include <cpu.h>
 #include <timebase.h>
 #include <opal-api.h>
+#include <fsp.h>
 
 /* -- TOD primary/secondary master/slave control register -- */
 #define TOD_PSMS_CTRL			0x00040007
@@ -111,6 +112,9 @@
 /* Timebase State Machine error state */
 #define TBST_STATE_ERROR	9
 
+/* Response status for fsp command 0xE6, s/c 0x06 (Enable/Disable Topology) */
+#define FSP_STATUS_TOPO_IN_USE	0xb8		/* topology is in use */
+
 static enum chiptod_type {
 	chiptod_unknown,
 	chiptod_p7,
@@ -1425,6 +1429,102 @@ static bool chiptod_probe(void)
 	return true;
 }
 
+static void chiptod_discover_new_backup(enum chiptod_topology topo)
+{
+	struct proc_chip *chip = NULL;
+
+	/* Scan through available chips to find new backup master chip */
+	for_each_chip(chip) {
+		if (_chiptod_get_chip_status(chip->id) == chiptod_backup_master)
+			break;
+	}
+
+	/* Found new backup master chip. Update the topology info */
+	if (chip) {
+		prlog(PR_DEBUG, "CHIPTOD: New backup master: CHIP [%d]\n",
+								chip->id);
+
+		if (topo == chiptod_topo_primary)
+			chiptod_primary = chip->id;
+		else
+			chiptod_secondary = chip->id;
+		chiptod_topology_info[topo].id = chip->id;
+		chiptod_update_topology(topo);
+
+		prlog(PR_DEBUG,
+			"CHIPTOD: Backup topology configuration changed.\n");
+		print_topology_info();
+	}
+}
+
+static uint8_t chiptod_adjust_topology(enum chiptod_topology topo, bool enable)
+{
+	uint8_t rc = 0;
+	/*
+	 * The FSP can only request that the currently inactive topology
+	 * be disabled or enabled. If the requested topology is currently
+	 * the active topology, then fail this request with a 0xB8 (TOD
+	 * topology in use) status as return code.
+	 */
+	lock(&chiptod_lock);
+	if (topo == current_topology) {
+		rc = FSP_STATUS_TOPO_IN_USE;
+		goto out;
+	}
+
+	if (enable)
+		chiptod_discover_new_backup(topo);
+	else
+		chiptod_topology_info[topo].status = chiptod_backup_disabled;
+out:
+	unlock(&chiptod_lock);
+	return rc;
+}
+
+static bool fsp_chiptod_update_topology(uint32_t cmd_sub_mod,
+					       struct fsp_msg *msg __unused)
+{
+	struct fsp_msg *resp;
+	enum chiptod_topology topo;
+	bool action;
+	uint8_t rc;
+
+	switch (cmd_sub_mod) {
+	case FSP_CMD_TOPO_ENABLE_DISABLE:
+		/*
+		 * Action Values: 0x00 = Disable, 0x01 = Enable
+		 * Topology Values: 0x00 = Primary, 0x01 = Secondary
+		 */
+		action = !!msg->data.bytes[2];
+		topo = msg->data.bytes[3];
+		prlog(PR_DEBUG, "CHIPTOD: Topology update event\n");
+		prlog(PR_DEBUG, "CHIPTOD:  Action     = %s\n",
+					action ? "Enable" : "Disable");
+		prlog(PR_DEBUG, "CHIPTOD:  Topology   = %s\n",
+					topo ? "Secondary" : "Primary");
+
+		rc = chiptod_adjust_topology(topo, action);
+
+		resp = fsp_mkmsg(FSP_RSP_TOPO_ENABLE_DISABLE | rc, 0);
+		if (!resp) {
+			prerror("FSPCON: Response allocation failed\n");
+			return false;
+		}
+		if (fsp_queue_msg(resp, fsp_freemsg)) {
+			fsp_freemsg(resp);
+			prerror("FSPCON: Failed to queue response msg\n");
+		}
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static struct fsp_client fsp_chiptod_client = {
+		.message = fsp_chiptod_update_topology,
+};
+
 static void chiptod_init_topology_info(void)
 {
 	/* Find and update current topology in use. */
@@ -1508,3 +1608,9 @@ void chiptod_init(void)
 	chiptod_init_topology_info();
 	op_display(OP_LOG, OP_MOD_CHIPTOD, 4);
 }
+
+void fsp_chiptod_init(void)
+{
+	/* Register for Class E6 (HW maintanance) */
+	fsp_register_client(&fsp_chiptod_client, FSP_MCLASS_HW_MAINT);
+}
diff --git a/include/fsp.h b/include/fsp.h
index f461575..5ca89f5 100644
--- a/include/fsp.h
+++ b/include/fsp.h
@@ -508,6 +508,12 @@
 #define FSP_CMD_VSERIAL_OUT	0x0e10200 /* HV->FSP */
 
 /*
+ * Class E6
+ */
+#define FSP_CMD_TOPO_ENABLE_DISABLE	0x0e60600 /* FSP->HV */
+#define FSP_RSP_TOPO_ENABLE_DISABLE	0x0e68600 /* HV->FSP */
+
+/*
  * Class E8
  */
 #define FSP_CMD_READ_SRC	0x1e84a40 /* HV->FSP */
@@ -799,4 +805,7 @@ extern void fsp_epow_init(void);
 /* DPO */
 extern void fsp_dpo_init(void);
 
+/* Chiptod */
+extern void fsp_chiptod_init(void);
+
 #endif /* __FSP_H */
diff --git a/platforms/ibm-fsp/common.c b/platforms/ibm-fsp/common.c
index d993b95..12536bd 100644
--- a/platforms/ibm-fsp/common.c
+++ b/platforms/ibm-fsp/common.c
@@ -110,6 +110,9 @@ void ibm_fsp_init(void)
 	/* Initialize SP attention area */
 	fsp_attn_init();
 
+	/* Initialize monitoring of TOD topology change event notification */
+	fsp_chiptod_init();
+
 	/* Send MDST table notification to FSP */
 	op_display(OP_LOG, OP_MOD_INIT, 0x0000);
 	fsp_mdst_table_init();



More information about the Skiboot mailing list