aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorShilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>2016-06-29 10:34:22 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-09-26 14:12:11 +1000
commitb5e54375bdc424eb2e709d41d2306d854f7e07bb (patch)
tree57372ca141273947bf9cda55ee4fd68078eb9424 /hw
parent583c8203dcb26b42cea81e4734ea926dae05dbb9 (diff)
downloadskiboot-b5e54375bdc424eb2e709d41d2306d854f7e07bb.zip
skiboot-b5e54375bdc424eb2e709d41d2306d854f7e07bb.tar.gz
skiboot-b5e54375bdc424eb2e709d41d2306d854f7e07bb.tar.bz2
occ/prd/opal-prd: Queue OCC_RESET event message to host in OpenPOWER
During an OCC reset cycle the system is forced to Psafe pstate. When OCC becomes active, the system has to be restored to its last pstate as requested by host. So host needs to be notified of OCC_RESET event or else system will continue to remian in Psafe state until host requests a new pstate after the OCC reset cycle. This patch defines 'OPAL_PRD_MSG_TYPE_OCC_RESET_NOTIFY' to notify OPAL when opal-prd issues OCC reset. OPAL will queue OCC_RESET message to host when it receives opal_prd_msg of type '*_OCC_RESET_NOTIFY'. Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/occ.c56
-rw-r--r--hw/prd.c4
2 files changed, 37 insertions, 23 deletions
diff --git a/hw/occ.c b/hw/occ.c
index c845732..63e142c 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -742,6 +742,38 @@ static void occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id)
__occ_do_load(scope, dbob_id, seq_id);
}
+int occ_msg_queue_occ_reset(void)
+{
+ struct opal_occ_msg occ_msg = { OCC_RESET, 0, 0 };
+ struct proc_chip *chip;
+ int rc;
+
+ lock(&occ_lock);
+ rc = _opal_queue_msg(OPAL_MSG_OCC, NULL, NULL, 3,
+ (uint64_t *)&occ_msg);
+ if (rc) {
+ prlog(PR_INFO, "OCC: Failed to queue OCC_RESET message\n");
+ goto out;
+ }
+ /*
+ * Set 'valid' byte of chip_occ_data to 0 since OCC
+ * may not clear this byte on a reset.
+ * OCC will set the 'valid' byte to 1 when it becomes
+ * active again.
+ */
+ for_each_chip(chip) {
+ struct occ_pstate_table *occ_data;
+
+ occ_data = chip_occ_data(chip);
+ occ_data->valid = 0;
+ chip->throttle = 0;
+ }
+ occ_reset = true;
+out:
+ unlock(&occ_lock);
+ return rc;
+}
+
static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id)
{
struct fsp_msg *rsp, *stat;
@@ -790,8 +822,6 @@ static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id)
rc = 0;
}
if (!rc) {
- struct opal_occ_msg occ_msg = { OCC_RESET, 0, 0 };
-
/* Send a single success response for all chips */
stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2, 0, seq_id);
if (stat)
@@ -802,27 +832,7 @@ static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id)
"OCC: Error %d queueing FSP OCC RESET"
" STATUS message\n", rc);
}
- lock(&occ_lock);
- rc = _opal_queue_msg(OPAL_MSG_OCC, NULL, NULL, 3,
- (uint64_t *)&occ_msg);
- if (rc)
- prlog(PR_INFO, "OCC: Failed to queue message %d\n",
- OCC_RESET);
- /*
- * Set 'valid' byte of chip_occ_data to 0 since OCC
- * may not clear this byte on a reset.
- * OCC will set the 'valid' byte to 1 when it becomes
- * active again.
- */
- for_each_chip(chip) {
- struct occ_pstate_table *occ_data;
-
- occ_data = chip_occ_data(chip);
- occ_data->valid = 0;
- chip->throttle = 0;
- }
- occ_reset = true;
- unlock(&occ_lock);
+ occ_msg_queue_occ_reset();
} else {
/*
diff --git a/hw/prd.c b/hw/prd.c
index 27b8ad8..e520e13 100644
--- a/hw/prd.c
+++ b/hw/prd.c
@@ -182,6 +182,7 @@ static void send_next_pending_event(void)
} else if (event & EVENT_OCC_RESET) {
prd_msg.hdr.type = OPAL_PRD_MSG_TYPE_OCC_RESET;
prd_msg.occ_reset.chip = proc;
+ occ_msg_queue_occ_reset();
}
queue_prd_msg(&prd_msg, prd_msg_consumed);
@@ -339,6 +340,9 @@ static int64_t opal_prd_msg(struct opal_prd_msg *msg)
case OPAL_PRD_MSG_TYPE_ATTN_ACK:
rc = prd_msg_handle_attn_ack(msg);
break;
+ case OPAL_PRD_MSG_TYPE_OCC_RESET_NOTIFY:
+ rc = occ_msg_queue_occ_reset();
+ break;
default:
rc = OPAL_UNSUPPORTED;
}