diff options
author | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-05-06 14:00:54 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-05-07 17:54:30 +1000 |
commit | 4d78c68415f5ac3081b724628aee5e34e46a65b3 (patch) | |
tree | a54701dd53b7ee03df38ef3f5f74caab4e975858 /core/vpd.c | |
parent | 18a462983f934bbb6651116ac347c7acf92b2cff (diff) | |
download | skiboot-4d78c68415f5ac3081b724628aee5e34e46a65b3.zip skiboot-4d78c68415f5ac3081b724628aee5e34e46a65b3.tar.gz skiboot-4d78c68415f5ac3081b724628aee5e34e46a65b3.tar.bz2 |
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/vpd.c')
-rw-r--r-- | core/vpd.c | 93 |
1 files changed, 63 insertions, 30 deletions
@@ -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); } |