summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.vnet.ibm.com>2015-05-06 14:00:54 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-05-07 17:54:30 +1000
commit4d78c68415f5ac3081b724628aee5e34e46a65b3 (patch)
treea54701dd53b7ee03df38ef3f5f74caab4e975858 /core
parent18a462983f934bbb6651116ac347c7acf92b2cff (diff)
downloadtalos-skiboot-4d78c68415f5ac3081b724628aee5e34e46a65b3.tar.gz
talos-skiboot-4d78c68415f5ac3081b724628aee5e34e46a65b3.zip
Preload VPD LID and set up fsp_lid_load() for async queued loading
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@linux.vnet.ibm.com>
Diffstat (limited to 'core')
-rw-r--r--core/hostservices.c7
-rw-r--r--core/init.c1
-rw-r--r--core/vpd.c93
3 files changed, 68 insertions, 33 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);
}
OpenPOWER on IntegriCloud