@@ -68,6 +68,8 @@ DEFINE_LOG_ENTRY(OPAL_RC_OCC_TIMEOUT, OPAL_PLATFORM_ERR_EVT, OPAL_OCC,
OPAL_CEC_HARDWARE, OPAL_UNRECOVERABLE_ERR_GENERAL,
OPAL_NA, NULL);
+static LIST_HEAD(occ_load_req_list);
+
/* Check each chip's HOMER/Sapphire area for PState valid bit */
static bool wait_for_all_occ_init(void)
{
@@ -347,36 +349,34 @@ void occ_pstates_init(void)
}
}
-struct occ_load_req {
- u8 scope;
- u32 dbob_id;
- u32 seq_id;
- struct list_node link;
-};
-static LIST_HEAD(occ_load_req_list);
-
-static void occ_queue_load(u8 scope, u32 dbob_id, u32 seq_id)
+static void occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id)
{
- struct occ_load_req *occ_req;
+ struct fsp_msg *rsp, *stat;
+ int rc = -ENOMEM;
+ int status_word = 0;
+ struct proc_chip *chip = next_chip(NULL);
+ u8 err = 0;
- occ_req = zalloc(sizeof(struct occ_load_req));
- if (!occ_req) {
- prerror("OCC: Could not allocate occ_load_req\n");
- return;
+ /* Check arguments */
+ if (scope != 0x01 && scope != 0x02) {
+ prerror("OCC: Load message with invalid scope 0x%x\n",
+ scope);
+ err = 0x22;
}
- 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);
-}
+ /* 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);
+ fsp_freemsg(rsp);
+ return;
+ }
-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);
+ if (err)
+ return;
/* Call HBRT... */
rc = host_services_occ_load();
@@ -399,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", rc);
+ "OCC: Error %d in load/start OCC\n", err);
}
/* Send a single response for all chips */
@@ -415,55 +415,23 @@ 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;
+ struct fsp_msg *msg;
+ u32 dbob_id, seq_id;
+ u8 scope;
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);
- fsp_freemsg(rsp);
- return;
- }
-
- if (err)
- return;
+ list_for_each(&occ_load_req_list, msg, link) {
+ scope = msg->data.bytes[3];
+ dbob_id = msg->data.words[1];
+ seq_id = msg->data.words[2];
- /*
- * 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);
- return;
+ occ_do_load(scope, dbob_id, seq_id);
+ list_del(&msg->link);
+ msg->refcount--;
+ fsp_freemsg(msg);
}
-
- __occ_do_load(scope, dbob_id, seq_id);
}
static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id)
@@ -591,9 +559,22 @@ static bool fsp_occ_msg(u32 cmd_sub_mod, struct fsp_msg *msg)
seq_id = msg->data.words[2];
prlog(PR_INFO, "OCC: Got OCC Load message, scope=0x%x"
" dbob=0x%x seq=0x%x\n", scope, dbob_id, seq_id);
- occ_do_load(scope, dbob_id, seq_id);
- return true;
+ if (!hservices_lid_preload_complete()) {
+ /*
+ * We have 16 minutes to respond to the OCC load.
+ * So, no need to queue an OK response to the FSP
+ * right away.
+ */
+ prlog(PR_TRACE, "OCC: Queuing lid load for"
+ " scope=0x%x dbob=0x%x seq=0x%x\n",
+ scope, dbob_id, seq_id);
+ msg->refcount++;
+ list_add_tail(&occ_load_req_list, &msg->link);
+ } else {
+ occ_do_load(scope, dbob_id, seq_id);
+ }
+ return true;
case FSP_CMD_RESET_OCC:
/*
* We shouldn't be getting this one, but if we do, we have