From 4db0c1e4f67474e1af7e9a391598d2a776485edd Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Thu, 19 Feb 2015 15:38:17 +0530 Subject: OCC/hostservices: Queue pre-preload HBRT lid load requests 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 Signed-off-by: Stewart Smith --- 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); -- cgit v1.1