[Skiboot] [PATCH 06/12] opal: Re-sync failed chiptod with neighboring chiptod.

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


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

The current implementation fails to recover from TOD error on slave chip
where TOD on active master is also stopped due to an error.

This patch improves the TOD recovery for slave chip TODs. Below are the
steps for TOD recovery on slave chips:
a. HMI received on slave chip TOD (e.g. chipS).
b. Check if TOD is running on active master. If yes, jump to step (e).
c. TOD on active master is not running. Scan through all neighboring
   chips and identify one (e.g. chipX) that has TOD in running state.
d. Enable TTYPE-4 mode on 'chipX' so that it would respond to TTYPE-3
   request from another chip.
e. Move 'chipS' TOD into 'Not-set' mode.
f. Issue TTYPE-3 request from 'chipS' to request TOD value from another
   chipTOD.
g. TOD from 'chipS' will receive TOD value from 'chipX' OR from active master.
h. Check if TOD on 'chipS' is moved to 'running' state. if yes, then return
   success else return failure.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
 hw/chiptod.c |   84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 82 insertions(+), 2 deletions(-)

diff --git a/hw/chiptod.c b/hw/chiptod.c
index 1b73be0..018e39d 100644
--- a/hw/chiptod.c
+++ b/hw/chiptod.c
@@ -66,6 +66,8 @@
 #define TOD_PIB_MASTER			0x00040027
 #define   TOD_PIBM_ADDR_CFG_MCAST	PPC_BIT(25)
 #define   TOD_PIBM_ADDR_CFG_SLADDR	PPC_BITMASK(26,31)
+#define   TOD_PIBM_TTYPE4_SEND_MODE	PPC_BIT(32)
+#define   TOD_PIBM_TTYPE4_SEND_ENBL	PPC_BIT(33)
 
 /* -- TOD Error interrupt register -- */
 #define TOD_ERROR			0x00040030
@@ -884,6 +886,63 @@ static int chiptod_recover_tod_errors(void)
 	return 0;
 }
 
+static int32_t chiptod_get_active_master(void)
+{
+	if (current_topology < 0)
+		return -1;
+
+	if (chiptod_topology_info[current_topology].status ==
+							chiptod_active_master)
+		return chiptod_topology_info[current_topology].id;
+	return -1;
+}
+
+/* Return true if Active master TOD is running. */
+static bool chiptod_master_running(void)
+{
+	int32_t active_master_chip;
+
+	active_master_chip = chiptod_get_active_master();
+	if (active_master_chip != -1) {
+		if (chiptod_running_check(active_master_chip))
+			return true;
+	}
+	return false;
+}
+
+static bool chiptod_set_ttype4_mode(struct proc_chip *chip, bool enable)
+{
+	uint64_t tval;
+
+	/* Sanity check */
+	if (!chip)
+		return false;
+
+	if (xscom_read(chip->id, TOD_PIB_MASTER, &tval) != 0) {
+		prerror("CHIPTOD: XSCOM error reading PIB_MASTER\n");
+		return false;
+	}
+
+	if (enable) {
+		/*
+		 * Enable TTYPE4 send mode. This allows TOD to respond to
+		 * TTYPE3 request.
+		 */
+		tval |= TOD_PIBM_TTYPE4_SEND_MODE;
+		tval |= TOD_PIBM_TTYPE4_SEND_ENBL;
+	} else {
+		/* Disable TTYPE4 send mode. */
+		tval &= ~TOD_PIBM_TTYPE4_SEND_MODE;
+		tval &= ~TOD_PIBM_TTYPE4_SEND_ENBL;
+	}
+
+	if (xscom_write(chip->id, TOD_PIB_MASTER, tval) != 0) {
+		prerror("CHIPTOD: XSCOM error writing PIB_MASTER\n");
+		return false;
+	}
+	return true;
+}
+
 /*
  * Sync up TOD with other chips and get TOD in running state.
  * For non-master, we request TOD value from another chip.
@@ -891,6 +950,9 @@ static int chiptod_recover_tod_errors(void)
  */
 static int chiptod_start_tod(void)
 {
+	struct proc_chip *chip = NULL;
+	int rc = 1;
+
 	/*  Handle TOD recovery on master chip. */
 	if (this_cpu()->chip_id == chiptod_primary) {
 		/*
@@ -910,6 +972,22 @@ static int chiptod_start_tod(void)
 		chiptod_secondary = this_cpu()->chip_id;
 	}
 
+	if (!chiptod_master_running()) {
+		/*
+		 * Active Master TOD is not running, which means it won't
+		 * respond to TTYPE_3 request.
+		 *
+		 * Find a chip that has TOD in running state and configure
+		 * it to respond to TTYPE_3 request.
+		 */
+		for_each_chip(chip) {
+			if (chiptod_running_check(chip->id)) {
+				if (chiptod_set_ttype4_mode(chip, true))
+					break;
+			}
+		}
+	}
+
 	/* Switch local chiptod to "Not Set" state */
 	if (xscom_writeme(TOD_LOAD_TOD_MOD, (1UL << 63)) != 0) {
 		prerror("CHIPTOD: XSCOM error sending LOAD_TOD_MOD\n");
@@ -927,9 +1005,11 @@ static int chiptod_start_tod(void)
 
 	/* Check if chip TOD is running. */
 	if (!chiptod_poll_running())
-		return 0;
+		rc = 0;
 
-	return 1;
+	/* Restore the ttype4_mode. */
+	chiptod_set_ttype4_mode(chip, false);
+	return rc;
 }
 
 static bool tfmr_recover_tb_errors(uint64_t tfmr)



More information about the Skiboot mailing list