summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/hostservices.c7
-rw-r--r--core/init.c1
-rw-r--r--core/vpd.c93
-rw-r--r--hw/fsp/fsp-codeupdate.c18
-rw-r--r--hw/fsp/fsp.c16
-rw-r--r--hw/p5ioc2.c1
-rw-r--r--hw/p7ioc.c1
-rw-r--r--hw/phb3.c11
-rw-r--r--include/fsp.h3
-rw-r--r--include/skiboot.h1
-rw-r--r--include/vpd.h1
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();
diff --git a/core/vpd.c b/core/vpd.c
index 0e6f83ba..85a99373 100644
--- a/core/vpd.c
+++ b/core/vpd.c
@@ -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));
diff --git a/hw/p7ioc.c b/hw/p7ioc.c
index 48a9dc9a..c1a45141 100644
--- a/hw/p7ioc.c
+++ b/hw/p7ioc.c
@@ -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));
diff --git a/hw/phb3.c b/hw/phb3.c
index 45ed6c0b..d9cb57dd 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -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
OpenPOWER on IntegriCloud