[Skiboot] [PATCH v2 9/9] Preload VPD LID and set up fsp_lid_load() for async queued loading

Stewart Smith stewart at linux.vnet.ibm.com
Wed May 6 14:00:54 AEST 2015


This means VPD LID is already loaded before we start preloading
kernel and initramfs LIDs, thus ensuring VPD doesn't have to wait
for them to finish being read from FSP.

Signed-off-by: Stewart Smith <stewart at linux.vnet.ibm.com>
---
 core/hostservices.c     |    7 ++--
 core/init.c             |    1 +
 core/vpd.c              |   93 ++++++++++++++++++++++++++++++++---------------
 hw/fsp/fsp-codeupdate.c |   18 ++++++++-
 hw/fsp/fsp.c            |   16 ++++++--
 hw/p5ioc2.c             |    1 +
 hw/p7ioc.c              |    1 +
 hw/phb3.c               |   11 ++++++
 include/fsp.h           |    3 +-
 include/skiboot.h       |    1 +
 include/vpd.h           |    1 +
 11 files changed, 114 insertions(+), 39 deletions(-)

diff --git a/core/hostservices.c b/core/hostservices.c
index a290094..68f2e77 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 14a129f..88a4037 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 0e6f83b..85a9937 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 5b9a9b4..5cac7ca 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 54968e2..12e162d 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 eb35e29..b0592d6 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 2315e81..641225d 100644
--- a/hw/p7ioc.c
+++ b/hw/p7ioc.c
@@ -600,6 +600,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 45ed6c0..d9cb57d 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 f461575..c6ccb97 100644
--- a/include/fsp.h
+++ b/include/fsp.h
@@ -725,7 +725,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 20fe79a..2684c73 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 c49ab71..bc60d81 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
 
-- 
1.7.10.4



More information about the Skiboot mailing list