[Skiboot] [PATCH 2/3] OCC/hostservices: Queue pre-preload HBRT lid load requests

Ananth N Mavinakayanahalli ananth at in.ibm.com
Thu Feb 19 21:08:17 AEDT 2015


There is no guarantee that a hostservices lid load request will arrive
after we have cached the required lids. For such cases, queue the
request and service them after caching.

Signed-off-by: Ananth N Mavinakayanahalli <ananth at in.ibm.com>
---
 core/hostservices.c    |   10 +++++
 hw/occ.c               |  100 ++++++++++++++++++++++++++++++++++++------------
 include/hostservices.h |    1 
 include/skiboot.h      |    3 +
 4 files changed, 90 insertions(+), 24 deletions(-)

diff --git a/core/hostservices.c b/core/hostservices.c
index 1c41a95..769d6f0 100644
--- a/core/hostservices.c
+++ b/core/hostservices.c
@@ -394,6 +394,13 @@ struct hbrt_lid {
 };
 static LIST_HEAD(hbrt_lid_list);
 
+static bool hbrt_lid_preload_complete = false;
+
+bool hservices_lid_preload_complete(void)
+{
+	return hbrt_lid_preload_complete;
+}
+
 /* TODO: Few of the following routines can be generalized */
 static int __hservice_lid_load(uint32_t lid, void **buf, size_t *len)
 {
@@ -468,6 +475,9 @@ void hservices_lid_preload(void)
 	/* Currently HBRT needs only one (OCC) lid */
 	for (i = 0; i < num_lids; i++)
 		__hservice_lid_preload(lid_list[i]);
+
+	hbrt_lid_preload_complete = true;
+	occ_poke_load_queue();
 }
 
 static int hservice_lid_load(uint32_t lid, void **buf, size_t *len)
diff --git a/hw/occ.c b/hw/occ.c
index 6dbbe6b..7ca1218 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -347,34 +347,36 @@ void occ_pstates_init(void)
 	}
 }
 
-static void occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id)
-{
-	struct fsp_msg *rsp, *stat;
-	int rc = -ENOMEM;
-	int status_word = 0;
-	struct proc_chip *chip = next_chip(NULL);
-	u8 err = 0;
+struct occ_load_req {
+	u8 scope;
+	u32 dbob_id;
+	u32 seq_id;
+	struct list_node link;
+};
+static LIST_HEAD(occ_load_req_list);
 
-	/* Check arguments */
-	if (scope != 0x01 && scope != 0x02) {
-		prerror("OCC: Load message with invalid scope 0x%x\n",
-			scope);
-		err = 0x22;
-	}
+static void occ_queue_load(u8 scope, u32 dbob_id, u32 seq_id)
+{
+	struct occ_load_req *occ_req;
 
-	/* First queue up an OK response to the load message itself */
-	rsp = fsp_mkmsg(FSP_RSP_LOAD_OCC | err, 0);
-	if (rsp)
-		rc = fsp_queue_msg(rsp, fsp_freemsg);
-	if (rc) {
-		log_simple_error(&e_info(OPAL_RC_OCC_LOAD),
-			"OCC: Error %d queueing FSP OCC LOAD reply\n", rc);
+	occ_req = zalloc(sizeof(struct occ_load_req));
+	if (!occ_req) {
+		prerror("OCC: Could not allocate occ_load_req\n");
 		return;
 	}
 
-	/* If we had an error, return */
-	if (err)
-		return;
+	occ_req->scope = scope;
+	occ_req->dbob_id = dbob_id;
+	occ_req->seq_id = seq_id;
+	list_add_tail(&occ_load_req_list, &occ_req->link);
+}
+
+static void __occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id)
+{
+	struct fsp_msg *stat;
+	int rc = -ENOMEM;
+	int status_word = 0;
+	struct proc_chip *chip = next_chip(NULL);
 
 	/* Call HBRT... */
 	rc = host_services_occ_load();
@@ -397,7 +399,7 @@ static void occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id)
 			break;
 		}
 		log_simple_error(&e_info(OPAL_RC_OCC_LOAD),
-			"OCC: Error %d in load/start OCC\n", err);
+			"OCC: Error %d in load/start OCC\n", rc);
 	}
 
 	/* Send a single response for all chips */
@@ -410,6 +412,56 @@ static void occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id)
 	}
 }
 
+void occ_poke_load_queue(void)
+{
+	struct occ_load_req *occ_req;
+
+	if (list_empty(&occ_load_req_list))
+		return;
+
+	list_for_each(&occ_load_req_list, occ_req, link) {
+		__occ_do_load(occ_req->scope, occ_req->dbob_id,
+				occ_req->seq_id);
+		list_del(&occ_req->link);
+		free(occ_req);
+	}
+}
+
+static void occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id)
+{
+	struct fsp_msg *rsp;
+	int rc = -ENOMEM;
+	u8 err = 0;
+
+	if (scope != 0x01 && scope != 0x02) {
+		prerror("OCC: Load message with invalid scope 0x%x\n",
+				scope);
+		err = 0x22;
+	}
+
+	/* First queue up an OK response to the load message itself */
+	rsp = fsp_mkmsg(FSP_RSP_LOAD_OCC | err, 0);
+	if (rsp)
+		rc = fsp_queue_msg(rsp, fsp_freemsg);
+	if (rc) {
+		log_simple_error(&e_info(OPAL_RC_OCC_LOAD),
+			"OCC: Error %d queueing FSP OCC LOAD reply\n", rc);
+		return;
+	}
+
+	if (err)
+		return;
+
+	/*
+	 * Check if hostservices lid caching is complete. If not, queue
+	 * the load request.
+	 */
+	if (!hservices_lid_preload_complete())
+		occ_queue_load(scope, dbob_id, seq_id);
+
+	__occ_do_load(scope, dbob_id, seq_id);
+}
+
 static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id)
 {
 	struct fsp_msg *rsp, *stat;
diff --git a/include/hostservices.h b/include/hostservices.h
index c8958a3..e85abc3 100644
--- a/include/hostservices.h
+++ b/include/hostservices.h
@@ -19,6 +19,7 @@
 
 bool hservices_init(void);
 void hservices_lid_preload(void);
+bool hservices_lid_preload_complete(void);
 
 int host_services_occ_load(void);
 int host_services_occ_start(void);
diff --git a/include/skiboot.h b/include/skiboot.h
index a13b438..d20a9a2 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -215,6 +215,9 @@ extern void uart_setup_opal_console(void);
 extern void occ_interrupt(uint32_t chip_id);
 extern void occ_send_dummy_interrupt(void);
 
+/* OCC load support */
+extern void occ_poke_load_queue(void);
+
 /* Flatten device-tree */
 extern void *create_dtb(const struct dt_node *root);
 



More information about the Skiboot mailing list