diff options
author | Ananth N Mavinakayanahalli <ananth@in.ibm.com> | 2015-02-19 15:38:17 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-02-23 13:32:00 +1100 |
commit | 4db0c1e4f67474e1af7e9a391598d2a776485edd (patch) | |
tree | 07ac0cc5599d90b8adf66b0de6ee4f7f9ce8115a /hw/occ.c | |
parent | 7b75c5832f55921294d1083d3083feb8ecbeb0e4 (diff) | |
download | skiboot-4db0c1e4f67474e1af7e9a391598d2a776485edd.zip skiboot-4db0c1e4f67474e1af7e9a391598d2a776485edd.tar.gz skiboot-4db0c1e4f67474e1af7e9a391598d2a776485edd.tar.bz2 |
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 <ananth@in.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/occ.c')
-rw-r--r-- | hw/occ.c | 100 |
1 files changed, 76 insertions, 24 deletions
@@ -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; |