summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--external/opal-prd/opal-prd.c6
-rw-r--r--hw/occ.c56
-rw-r--r--hw/prd.c4
-rw-r--r--include/opal-api.h1
-rw-r--r--include/opal-internal.h1
5 files changed, 45 insertions, 23 deletions
diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c
index 56943c40..17239248 100644
--- a/external/opal-prd/opal-prd.c
+++ b/external/opal-prd/opal-prd.c
@@ -1381,6 +1381,7 @@ static void handle_prd_control_run_cmd(struct control_msg *send_msg,
static void handle_prd_control(struct opal_prd_ctx *ctx, int fd)
{
struct control_msg msg, *recv_msg, *send_msg;
+ struct opal_prd_msg omsg;
bool enabled = false;
int rc, size;
@@ -1433,6 +1434,11 @@ static void handle_prd_control(struct opal_prd_ctx *ctx, int fd)
handle_prd_control_occ_actuation(send_msg, enabled);
break;
case CONTROL_MSG_TEMP_OCC_RESET:
+ omsg.hdr.type = OPAL_PRD_MSG_TYPE_OCC_RESET_NOTIFY;
+ omsg.hdr.size = htobe16(sizeof(omsg));
+ rc = write(ctx->fd, &omsg, sizeof(omsg));
+ if (rc != sizeof(omsg))
+ pr_log(LOG_WARNING, "FW: Failed to send OCC_RESET message: %m");
handle_prd_control_occ_reset(send_msg);
break;
case CONTROL_MSG_TEMP_OCC_ERROR:
diff --git a/hw/occ.c b/hw/occ.c
index c8457320..63e142cf 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 27b8ad81..e520e13d 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;
}
diff --git a/include/opal-api.h b/include/opal-api.h
index f607a416..05ff51dd 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -923,6 +923,7 @@ enum opal_prd_msg_type {
OPAL_PRD_MSG_TYPE_ATTN_ACK, /* HBRT --> OPAL */
OPAL_PRD_MSG_TYPE_OCC_ERROR, /* HBRT <-- OPAL */
OPAL_PRD_MSG_TYPE_OCC_RESET, /* HBRT <-- OPAL */
+ OPAL_PRD_MSG_TYPE_OCC_RESET_NOTIFY, /* HBRT --> OPAL */
};
struct opal_prd_msg_header {
diff --git a/include/opal-internal.h b/include/opal-internal.h
index 2faaa468..583e9994 100644
--- a/include/opal-internal.h
+++ b/include/opal-internal.h
@@ -81,6 +81,7 @@ extern void opal_del_host_sync_notifier(bool (*notify)(void *data));
*/
struct OpalHMIEvent;
extern int handle_hmi_exception(__be64 hmer, struct OpalHMIEvent *hmi_evt);
+extern int occ_msg_queue_occ_reset(void);
extern unsigned long top_of_ram;
OpenPOWER on IntegriCloud