diff options
author | Ananth N Mavinakayanahalli <ananth@in.ibm.com> | 2015-02-16 22:12:58 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-02-18 11:57:50 +1100 |
commit | 2233891f71e5a282b2d4f66dcdc866a6697ffd8f (patch) | |
tree | 3e343968f12c02475400846927f2094c8b2fb699 | |
parent | c48f1a3d7df2dec1c157f1b12b4925bfd666b710 (diff) | |
download | skiboot-2233891f71e5a282b2d4f66dcdc866a6697ffd8f.zip skiboot-2233891f71e5a282b2d4f66dcdc866a6697ffd8f.tar.gz skiboot-2233891f71e5a282b2d4f66dcdc866a6697ffd8f.tar.bz2 |
hostservices: Cache lids prior to first load request
... to prevent any potential poller recursions during lid load.
With this change:
...
[10810950484,5] CUPD: P side ML Keyword = FW830.00
[10832756491,6] HBRT: 1 lids to load
[10832762732,7] FSP: Fetch data id: 05 sid: 81e00430 to 0x306cf500(0x100000
bytes)
[10832766825,7] FSP: 0x00100000 bytes balign=306cf000 boff=500 bsize=101000
[10857829395,5] CUPD: Marker LID id : size : status = 0x80a08001 : 0x5d0 : 0x0
[10966464432,7] FSP: -> rc=0x00 off: 00000000 twritten: 0007fb80
[10966468418,7] HBRT: LID 0x81e00430 successfully loaded, len=0x31b83db8
...
[19485180658,7] HBRT: stopOCCs() rc = 0
[19582727570,6] OCC: Got OCC Load message, scope=0x2 dbob=0x0 seq=0x10
[19582732660,7] HBRT: OCC Load requested
[19582734678,7] HBRT: Calling loadOCC() homer 0000000401400000, occ_common_area
0000000400800000, chip 0000
[19582803643,6] HBRT: Lid load request for 0x81e00430
[19582806532,7] HBRT: Serviced from cache, len=0x7fb80
[19582996931,7] HBRT: -> rc = 0
[19582999113,7] HBRT: Calling loadOCC() homer 0000000401c00000, occ_common_area
0000000400800000, chip 0001
[19583097594,6] HBRT: Lid load request for 0x81e00430
[19583100343,7] HBRT: Serviced from cache, len=0x7fb80
[19583274638,7] HBRT: -> rc = 0
[19583277114,6] HBRT: OCC Start requested
V2:
Address Vasant's comments (bz reference and OPAL_NO_MEM)
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | core/hostservices.c | 117 | ||||
-rw-r--r-- | core/init.c | 3 | ||||
-rw-r--r-- | include/hostservices.h | 1 |
3 files changed, 89 insertions, 32 deletions
diff --git a/core/hostservices.c b/core/hostservices.c index 952f6b8..ad19e15 100644 --- a/core/hostservices.c +++ b/core/hostservices.c @@ -386,36 +386,26 @@ static int hservice_scom_write(uint64_t chip_id, uint64_t addr, return xscom_write(chip_id, addr, val); } -static int hservice_lid_load(uint32_t lid, void **buf, size_t *len) +struct hbrt_lid { + void *load_addr; + size_t len; + uint32_t id; + struct list_node link; +}; +static LIST_HEAD(hbrt_lid_list); + +/* TODO: Few of the following routines can be generalized */ +static int __hservice_lid_load(uint32_t lid, void **buf, size_t *len) { int rc; - static void *lid_cache; - static size_t lid_cache_len; - static uint32_t lid_cache_id; - - prlog(PR_INFO, "HBRT: LID load request for 0x%08x\n", lid); /* Adjust LID side first or we get a cache mismatch */ lid = fsp_adjust_lid_side(lid); - /* Check for cache */ - if (lid_cache && lid_cache_id == lid) { - *buf = lid_cache; - *len = lid_cache_len; - prlog(PR_DEBUG, "HBRT: Serviced from cache, len=0x%lx\n", - lid_cache_len); - return 0; - } - - /* Cache mismatch, discard old one */ - if (lid_cache) { - prlog(PR_DEBUG, "HBRT: Cache mismatch, discarding old" - " 0x%08x\n", lid_cache_id); - free(lid_cache); - lid_cache = NULL; - } - - /* Allocate a new buffer and load the LID into it */ + /* + * Allocate a new buffer and load the LID into it + * XXX: We currently use the same size for each HBRT lid. + */ *buf = malloc(HBRT_LOAD_LID_SIZE); *len = HBRT_LOAD_LID_SIZE; rc = fsp_fetch_data(0, FSP_DATASET_NONSP_LID, lid, 0, *buf, len); @@ -424,17 +414,80 @@ static int hservice_lid_load(uint32_t lid, void **buf, size_t *len) *len = 0; *buf = realloc(*buf, *len); - /* We managed, let's cache it */ - if (rc == 0 && *len) { - lid_cache = *buf; - lid_cache_len = *len; - lid_cache_id = lid; + prlog(PR_DEBUG, "HBRT: LID 0x%08x successfully loaded, len=0x%lx\n", + lid, (unsigned long)len); - prlog(PR_DEBUG, "HBRT: LID 0x%08x successfully loaded and" - " cached, len=0x%lx\n", lid, lid_cache_len); + return rc; +} + +static int __hservice_lid_preload(const uint32_t lid) +{ + struct hbrt_lid *hlid; + void *buf; + size_t len; + int rc; + + hlid = zalloc(sizeof(struct hbrt_lid)); + if (!hlid) { + prerror("HBRT: Could not allocate struct hbrt_lid\n"); + return OPAL_NO_MEM; } - return rc; + rc = __hservice_lid_load(lid, &buf, &len); + if (rc) { + free(hlid); + return rc; + } + + hlid->load_addr = buf; + hlid->len = len; + hlid->id = lid; + list_add_tail(&hbrt_lid_list, &hlid->link); + + return 0; +} + +/* Find and preload all lids needed by hostservices */ +void hservices_lid_preload(void) +{ + const uint32_t *lid_list = NULL; + size_t num_lids; + + if (!hservice_runtime) + return; + + lid_list = (const uint32_t *)hservice_runtime->get_lid_list(&num_lids); + if (!lid_list) { + prerror("HBRT: get_lid_list() returned NULL\n"); + return; + } + + prlog(PR_INFO, "HBRT: %d lids to load\n", (int)num_lids); + + /* Currently HBRT needs only one (OCC) lid */ + while (num_lids--) + __hservice_lid_preload(lid_list[num_lids]); +} + +static int hservice_lid_load(uint32_t lid, void **buf, size_t *len) +{ + struct hbrt_lid *hlid; + + prlog(PR_INFO, "HBRT: Lid load request for 0x%08x\n", lid); + + if (list_empty(&hbrt_lid_list)) /* Should not happen */ + hservices_lid_preload(); + + list_for_each(&hbrt_lid_list, hlid, link) { + if (hlid->id == lid) { + *buf = hlid->load_addr; + *len = hlid->len; + prlog(PR_DEBUG, "HBRT: Serviced from cache," + " len=0x%lx\n", hlid->len); + return 0; + } + } + return -ENOENT; } static int hservice_lid_unload(void *buf __unused) diff --git a/core/init.c b/core/init.c index f76d6c3..42b56c1 100644 --- a/core/init.c +++ b/core/init.c @@ -641,6 +641,9 @@ void __noreturn main_cpu_entry(const void *fdt, u32 master_cpu) if (platform.init) platform.init(); + /* Preload hostservices lids */ + hservices_lid_preload(); + /* Setup dummy console nodes if it's enabled */ if (dummy_console_enabled()) dummy_console_add_nodes(); diff --git a/include/hostservices.h b/include/hostservices.h index 7279c8e..c8958a3 100644 --- a/include/hostservices.h +++ b/include/hostservices.h @@ -18,6 +18,7 @@ #define __HOSTSERVICES_H bool hservices_init(void); +void hservices_lid_preload(void); int host_services_occ_load(void); int host_services_occ_start(void); |