[Skiboot] [PATCH] occ/prd/opal-prd: Queue OCC_RESET event message to host

Shilpasri G Bhat shilpa.bhat at linux.vnet.ibm.com
Mon Mar 21 16:19:49 AEDT 2016


Define 'OPAL_PRD_MSG_TYPE_OCC_RESET_NOTIF' 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_NOTIF'.

This fixes BZ 137249 which is caused due to clearing of PMCR in
OCC reset cycle. Host will restore the PMCR to last request when
OCC gets active after reset.

Signed-off-by: Shilpasri G Bhat <shilpa.bhat at linux.vnet.ibm.com>
---
 external/opal-prd/opal-prd.c |  6 +++++
 hw/occ.c                     | 56 ++++++++++++++++++++++++++------------------
 hw/prd.c                     |  4 ++++
 include/opal-api.h           |  1 +
 include/opal-internal.h      |  1 +
 5 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c
index 7c11c9a..dc9147e 100644
--- a/external/opal-prd/opal-prd.c
+++ b/external/opal-prd/opal-prd.c
@@ -1353,6 +1353,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;
 
@@ -1405,6 +1406,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_NOTIF;
+		omsg.hdr.size = htobe16(sizeof(omsg));
+		rc = write(ctx->fd, &msg, 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 03240b3..e53d396 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -658,6 +658,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;
@@ -701,8 +733,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)
@@ -713,27 +743,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..48aca7f 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_NOTIF:
+		rc = occ_msg_queue_occ_reset();
+		break;
 	default:
 		rc = OPAL_UNSUPPORTED;
 	}
diff --git a/include/opal-api.h b/include/opal-api.h
index 369aa93..aa4324e 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -856,6 +856,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_NOTIF, /* HBRT --> OPAL */
 };
 
 struct opal_prd_msg_header {
diff --git a/include/opal-internal.h b/include/opal-internal.h
index 5e41e10..6f866a8 100644
--- a/include/opal-internal.h
+++ b/include/opal-internal.h
@@ -81,5 +81,6 @@ 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);
 
 #endif /* __OPAL_INTERNAL_H */
-- 
1.9.3



More information about the Skiboot mailing list