summaryrefslogtreecommitdiffstats
path: root/hw/chiptod.c
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2015-06-05 23:38:02 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-07-09 16:14:22 +1000
commit451bd968b8225c82d9cb5aff8ac2c7b24113440c (patch)
treed5628c3424de76a0d27791690f47d684bca4a47a /hw/chiptod.c
parentec65526b3238c32c10a98de624bf705ef110d5ef (diff)
downloadblackbird-skiboot-451bd968b8225c82d9cb5aff8ac2c7b24113440c.tar.gz
blackbird-skiboot-451bd968b8225c82d9cb5aff8ac2c7b24113440c.zip
opal: Re-sync failed chiptod with neighboring chiptod.
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@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/chiptod.c')
-rw-r--r--hw/chiptod.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/hw/chiptod.c b/hw/chiptod.c
index fc159ef3..24ab9aa8 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
@@ -882,6 +884,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.
@@ -889,6 +948,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) {
/*
@@ -908,6 +970,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");
@@ -925,9 +1003,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)
OpenPOWER on IntegriCloud