diff options
-rw-r--r-- | core/hostservices.c | 7 | ||||
-rw-r--r-- | core/init.c | 1 | ||||
-rw-r--r-- | core/vpd.c | 93 | ||||
-rw-r--r-- | hw/fsp/fsp-codeupdate.c | 18 | ||||
-rw-r--r-- | hw/fsp/fsp.c | 16 | ||||
-rw-r--r-- | hw/p5ioc2.c | 1 | ||||
-rw-r--r-- | hw/p7ioc.c | 1 | ||||
-rw-r--r-- | hw/phb3.c | 11 | ||||
-rw-r--r-- | include/fsp.h | 3 | ||||
-rw-r--r-- | include/skiboot.h | 1 | ||||
-rw-r--r-- | include/vpd.h | 1 |
11 files changed, 114 insertions, 39 deletions
diff --git a/core/hostservices.c b/core/hostservices.c index a290094b..68f2e777 100644 --- a/core/hostservices.c +++ b/core/hostservices.c @@ -415,7 +415,8 @@ static int __hservice_lid_load(uint32_t lid, void **buf, size_t *len) */ *buf = malloc(HBRT_LOAD_LID_SIZE); *len = HBRT_LOAD_LID_SIZE; - rc = fsp_load_lid(lid, *buf, len); + rc = fsp_preload_lid(lid, *buf, len); + rc = fsp_wait_lid_loaded(lid); if (rc != 0) /* Take advantage of realloc corner case here. */ *len = 0; @@ -495,8 +496,8 @@ static int hservice_lid_load(uint32_t lid, void **buf, size_t *len) if (hlid->id == lid) { *buf = hlid->load_addr; *len = hlid->len; - prlog(PR_DEBUG, "HBRT: Serviced from cache," - " len=0x%lx\n", hlid->len); + prlog(PR_DEBUG, "HBRT: LID Serviced from cache," + " %x, len=0x%lx\n", hlid->id, hlid->len); return 0; } } diff --git a/core/init.c b/core/init.c index 14a129fc..88a4037e 100644 --- a/core/init.c +++ b/core/init.c @@ -701,6 +701,7 @@ void __noreturn main_cpu_entry(const void *fdt, u32 master_cpu) /* Read in NVRAM and set it up */ nvram_init(); + phb3_preload_vpd(); phb3_preload_capp_ucode(); start_preload_kernel(); @@ -115,9 +115,15 @@ const void *vpd_find(const void *vpd, size_t vpd_size, return p; } +static void *vpd; +static size_t vpd_size; +static uint32_t vpd_lid_no; + /* Helper to load a VPD LID. Pass a ptr to the corresponding LX keyword */ -static void *vpd_lid_load(const uint8_t *lx, uint8_t lxrn, size_t *size) +static void *vpd_lid_preload(const uint8_t *lx) { + int rc; + /* Now this is a guess game as we don't have the info from the * pHyp folks. But basically, it seems to boil down to loading * a LID whose name is 0x80e000yy where yy is the last 2 digits @@ -130,44 +136,71 @@ static void *vpd_lid_load(const uint8_t *lx, uint8_t lxrn, size_t *size) * For safety, we look for a matching LX record in an LXRn * (n = lxrn argument) or in VINI if lxrn=0xff */ - uint32_t lid_no = 0x80e00000 | ((lx[6] & 0xf) << 8) | lx[7]; + vpd_lid_no = 0x80e00000 | ((lx[6] & 0xf) << 8) | lx[7]; /* We don't quite know how to get to the LID directory so * we don't know the size. Let's allocate 16K. All the VPD LIDs * I've seen so far are much smaller. */ #define VPD_LID_MAX_SIZE 0x4000 - void *data = malloc(VPD_LID_MAX_SIZE); - char record[4] = "LXR0"; - const void *valid_lx; - uint8_t lx_size; - int rc; + vpd = malloc(VPD_LID_MAX_SIZE); - if (!data) { + if (!vpd) { prerror("VPD: Failed to allocate memory for LID\n"); return NULL; } /* Adjust LID number for flash side */ - lid_no = fsp_adjust_lid_side(lid_no); - printf("VPD: Trying to load VPD LID 0x%08x...\n", lid_no); + vpd_lid_no = fsp_adjust_lid_side(vpd_lid_no); + printf("VPD: Trying to load VPD LID 0x%08x...\n", vpd_lid_no); - *size = VPD_LID_MAX_SIZE; + vpd_size = VPD_LID_MAX_SIZE; /* Load it from the FSP */ - rc = fsp_load_lid(lid_no, data, size); + rc = fsp_preload_lid(vpd_lid_no, vpd, &vpd_size); if (rc) { prerror("VPD: Error %d loading VPD LID\n", rc); goto fail; } + return vpd; + fail: + free(vpd); + return NULL; +} + +void vpd_iohub_load(struct dt_node *hub_node) +{ + char record[4] = "LXR0"; + const void *valid_lx; + uint8_t lx_size; + int r; + const uint32_t *p; + const uint8_t *lx; + unsigned int lxrn; + + p = dt_prop_get_def(hub_node, "ibm,vpd-lx-info", NULL); + if (!p) + return; + + lxrn = p[0]; + lx = (const char *)&p[1]; + + assert(vpd); + assert(vpd_lid_no); + + r = fsp_wait_lid_loaded(vpd_lid_no); + + if (r) + goto fail; + /* Validate it */ if (lxrn < 9) record[3] = '0' + lxrn; else memcpy(record, "VINI", 4); - valid_lx = vpd_find(data, *size, record, "LX", &lx_size); + valid_lx = vpd_find(vpd, vpd_size, record, "LX", &lx_size); if (!valid_lx || lx_size != 8) { prerror("VPD: Cannot find validation LX record\n"); goto fail; @@ -177,35 +210,35 @@ static void *vpd_lid_load(const uint8_t *lx, uint8_t lxrn, size_t *size) goto fail; } - printf("VPD: Loaded %zu bytes\n", *size); + printf("VPD: Loaded %zu bytes\n", vpd_size); /* Got it ! */ - return realloc(data, *size); - fail: - free(data); - return NULL; + vpd = realloc(vpd, vpd_size); + + if (!vpd) + goto fail; + + dt_add_property(hub_node, "ibm,io-vpd", vpd, vpd_size); + free(vpd); + return; + +fail: + free(vpd); + vpd = NULL; + prerror("VPD: Failed to load VPD LID\n"); + return; } -void vpd_iohub_load(struct dt_node *hub_node) +void vpd_preload(struct dt_node *hub_node) { - void *vpd; - size_t sz; const uint32_t *p; - unsigned int lx_idx; const char *lxr; p = dt_prop_get_def(hub_node, "ibm,vpd-lx-info", NULL); if (!p) return; - lx_idx = p[0]; lxr = (const char *)&p[1]; - vpd = vpd_lid_load(lxr, lx_idx, &sz); - if (!vpd) { - prerror("VPD: Failed to load VPD LID\n"); - } else { - dt_add_property(hub_node, "ibm,io-vpd", vpd, sz); - free(vpd); - } + vpd = vpd_lid_preload(lxr); } diff --git a/hw/fsp/fsp-codeupdate.c b/hw/fsp/fsp-codeupdate.c index 5b9a9b46..5cac7ca2 100644 --- a/hw/fsp/fsp-codeupdate.c +++ b/hw/fsp/fsp-codeupdate.c @@ -454,13 +454,27 @@ static void add_opal_firmware_version(void) */ void fsp_code_update_wait_vpd(bool is_boot) { + int waited = 0; + if (!fsp_present()) return; prlog(PR_NOTICE, "CUPD: Waiting read marker LID" " and in flight parsm completion...\n"); - while (flash_state == FLASH_STATE_READING || in_flight_params) - time_wait_ms(100); + + lock(&flash_lock); + while(true) { + if (!(flash_state == FLASH_STATE_READING || in_flight_params)) + break; + unlock(&flash_lock); + time_wait_ms(5); + waited+=5; + lock(&flash_lock); + } + unlock(&flash_lock); + + if (waited) + prlog(PR_DEBUG, "CUPD: fsp_code_update_wait_vpd %d\n", waited); if (is_boot) add_opal_firmware_version(); diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c index 54968e29..12e162d4 100644 --- a/hw/fsp/fsp.c +++ b/hw/fsp/fsp.c @@ -2467,10 +2467,10 @@ static int fsp_lid_loaded(uint32_t lid_no) return rc; } -int fsp_load_lid(uint32_t lid_no, char *buf, size_t *size) +int fsp_preload_lid(uint32_t lid_no, char *buf, size_t *size) { struct fsp_fetch_lid_item *resource; - int r; + int r = OPAL_SUCCESS; resource = malloc(sizeof(struct fsp_fetch_lid_item)); assert(resource != NULL); @@ -2497,17 +2497,27 @@ int fsp_load_lid(uint32_t lid_no, char *buf, size_t *size) fsp_start_fetching_next_lid(); unlock(&fsp_fetch_lock); + return r; +} + +int fsp_wait_lid_loaded(uint32_t lid_no) +{ + int r; + int waited = 0; + r = fsp_lid_loaded(lid_no); while(r == OPAL_BUSY) { opal_run_pollers(); time_wait_nopoll(msecs_to_tb(5)); + waited+=5; cpu_relax(); r = fsp_lid_loaded(lid_no); } - return r; + prlog(PR_DEBUG, "FSP: fsp_wait_lid_loaded %x %u ms\n", lid_no, waited); + return r; } void fsp_used_by_console(void) diff --git a/hw/p5ioc2.c b/hw/p5ioc2.c index eb35e292..b0592d61 100644 --- a/hw/p5ioc2.c +++ b/hw/p5ioc2.c @@ -203,6 +203,7 @@ static void p5ioc2_create_hub(struct dt_node *np) dt_add_property_cells(np, "ibm,opal-hubid", 0, id); /* Load VPD LID */ + vpd_preload(np); vpd_iohub_load(np); ioc = zalloc(sizeof(struct p5ioc2)); @@ -603,6 +603,7 @@ static void p7ioc_create_hub(struct dt_node *np) free(path); /* Load VPD LID */ + vpd_preload(np); vpd_iohub_load(np); ioc = zalloc(sizeof(struct p7ioc)); @@ -4539,6 +4539,17 @@ end: return ret; } +void phb3_preload_vpd(void) +{ + const struct dt_property *prop; + + prop = dt_find_property(dt_root, "ibm,io-vpd"); + if (!prop) { + /* LX VPD Lid not already loaded */ + vpd_preload(dt_root); + } +} + void probe_phb3(void) { struct dt_node *np; diff --git a/include/fsp.h b/include/fsp.h index c74996d4..56897982 100644 --- a/include/fsp.h +++ b/include/fsp.h @@ -737,7 +737,8 @@ extern int fsp_fetch_data_queue(uint8_t flags, uint16_t id, uint32_t sub_id, extern int fsp_start_preload_resource(enum resource_id id, uint32_t idx, void *buf, size_t *size); extern int fsp_resource_loaded(enum resource_id id, uint32_t idx); -extern int fsp_load_lid(uint32_t lid_no, char *buf, size_t *size); +extern int fsp_preload_lid(uint32_t lid_no, char *buf, size_t *size); +extern int fsp_wait_lid_loaded(uint32_t lid_no); /* FSP console stuff */ extern void fsp_console_preinit(void); diff --git a/include/skiboot.h b/include/skiboot.h index 20fe79ab..2684c739 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -191,6 +191,7 @@ extern void probe_p5ioc2(void); extern void probe_p7ioc(void); extern void probe_phb3(void); extern int phb3_preload_capp_ucode(void); +extern void phb3_preload_vpd(void); extern void uart_init(bool enable_interrupt); extern void homer_init(void); extern void occ_pstates_init(void); diff --git a/include/vpd.h b/include/vpd.h index c49ab711..bc60d81f 100644 --- a/include/vpd.h +++ b/include/vpd.h @@ -38,6 +38,7 @@ const void *vpd_find(const void *vpd, size_t vpd_size, void add_dtb_model(void); void vpd_iohub_load(struct dt_node *hub_node); +void vpd_preload(struct dt_node *hub_node); #define VPD_LOAD_LXRN_VINI 0xff |