Skip to content

Commit

Permalink
imc/catalog: Decompress catalog asynchronously
Browse files Browse the repository at this point in the history
In-Memory Collection(IMC) counters catalog is compressed blob which is
loaded from the flash; decompression starts once the data is loaded from
nvram by the main thread. This can be optimized by using the libxz API
function which creates a job to do the decompression by not blocking the
main thread.

Refactor decompress() to use the libxz asynchronous wrapper
functions. This also cleans up the error handling path in imc_init().

CC: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
  • Loading branch information
santoshs authored and stewartsmith committed Feb 26, 2019
1 parent 3ac2db0 commit c86fb12
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 84 deletions.
3 changes: 3 additions & 0 deletions core/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,9 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
preload_capp_ucode();
start_preload_kernel();

/* Catalog decompression routine */
imc_decompress_catalog();

/* Virtual Accelerator Switchboard */
vas_init();

Expand Down
141 changes: 57 additions & 84 deletions hw/imc.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,58 +180,6 @@ static int pause_microcode_at_boot(void)
return 0;
}

/*
* Decompresses the blob obtained from the IMC pnor sub-partition
* in "src" of size "src_size", assigns the uncompressed device tree
* binary to "dst" and returns.
*
* Returns 0 on success and -1 on error.
*
* TODO: Ideally this should be part of generic subpartition load
* infrastructure. And decompression can be queued as another CPU job
*/
static int decompress(void *dst, size_t dst_size, void *src, size_t src_size)
{
struct xz_dec *s;
struct xz_buf b;
int ret = 0;

/* Initialize the xz library first */
xz_crc32_init();
s = xz_dec_init(XZ_SINGLE, 0);
if (s == NULL) {
prerror("initialization error for xz\n");
return -1;
}

/*
* Source address : src
* Source size : src_size
* Destination address : dst
* Destination size : dst_src
*/
b.in = src;
b.in_pos = 0;
b.in_size = src_size;
b.out = dst;
b.out_pos = 0;
b.out_size = dst_size;

/* Start decompressing */
ret = xz_dec_run(s, &b);
if (ret != XZ_STREAM_END) {
prerror("failed to decompress subpartition\n");
ret = -1;
goto err;
}

return 0;
err:
/* Clean up memory */
xz_dec_end(s);
return ret;
}

/*
* Function return list of properties names for the fixup
*/
Expand Down Expand Up @@ -504,6 +452,50 @@ static void imc_dt_update_nest_node(struct dt_node *dev)
}
}

static struct xz_decompress *imc_xz;

void imc_decompress_catalog(void)
{
void *decompress_buf = NULL;
uint32_t pvr = (mfspr(SPR_PVR) & ~(0xf0ff));
int ret;

/* Check we succeeded in starting the preload */
if (compress_buf == NULL)
return;

ret = wait_for_resource_loaded(RESOURCE_ID_IMA_CATALOG, pvr);
if (ret != OPAL_SUCCESS) {
prerror("IMC Catalog load failed\n");
return;
}

/*
* Memory for decompression.
*/
decompress_buf = malloc(MAX_DECOMPRESSED_IMC_DTB_SIZE);
if (!decompress_buf) {
prerror("No memory for decompress_buf \n");
return;
}

/*
* Decompress the compressed buffer
*/
imc_xz = malloc(sizeof(struct xz_decompress));
if (!imc_xz) {
prerror("No memory to decompress IMC catalog\n");
free(decompress_buf);
return;
}

imc_xz->dst = decompress_buf;
imc_xz->src = compress_buf;
imc_xz->dst_size = MAX_DECOMPRESSED_IMC_DTB_SIZE;
imc_xz->src_size = compress_buf_size;
xz_start_decompress(imc_xz);
}

/*
* Load the IMC pnor partition and find the appropriate sub-partition
* based on the platform's PVR.
Expand All @@ -512,10 +504,8 @@ static void imc_dt_update_nest_node(struct dt_node *dev)
*/
void imc_init(void)
{
void *decompress_buf = NULL;
uint32_t pvr = (mfspr(SPR_PVR) & ~(0xf0ff));
struct dt_node *dev;
int ret;
int err_flag = -1;

if (proc_chip_quirks & QUIRK_MAMBO_CALLOUTS) {
dev = dt_find_compatible_node(dt_root, NULL,
Expand All @@ -530,15 +520,12 @@ void imc_init(void)
if (proc_gen != proc_gen_p9)
return;

/* Check we succeeded in starting the preload */
if (compress_buf == NULL)
if (!imc_xz)
return;

ret = wait_for_resource_loaded(RESOURCE_ID_IMA_CATALOG, pvr);
if (ret != OPAL_SUCCESS) {
prerror("IMC Catalog load failed\n");
return;
}
wait_xz_decompress(imc_xz);
if (imc_xz->status != OPAL_SUCCESS)
goto err;

/*
* Flow of the data from PNOR to main device tree:
Expand All @@ -549,22 +536,6 @@ void imc_init(void)
* free compressed local buffer
*/

/*
* Memory for decompression.
*/
decompress_buf = malloc(MAX_DECOMPRESSED_IMC_DTB_SIZE);
if (!decompress_buf) {
prerror("No memory for decompress_buf \n");
goto err;
}

/*
* Decompress the compressed buffer
*/
ret = decompress(decompress_buf, MAX_DECOMPRESSED_IMC_DTB_SIZE,
compress_buf, compress_buf_size);
if (ret < 0)
goto err;

/* Create a device tree entry for imc counters */
dev = dt_new_root("imc-counters");
Expand All @@ -575,8 +546,7 @@ void imc_init(void)
* Attach the new decompress_buf to the imc-counters node.
* dt_expand_node() does sanity checks for fdt_header, piggyback
*/
ret = dt_expand_node(dev, decompress_buf, 0);
if (ret < 0) {
if (dt_expand_node(dev, imc_xz->dst, 0) < 0) {
dt_free(dev);
goto err;
}
Expand Down Expand Up @@ -623,12 +593,15 @@ void imc_init(void)
goto err;
}

free(compress_buf);
return;
err_flag = OPAL_SUCCESS;

err:
prerror("IMC Devices not added\n");
free(decompress_buf);
if (err_flag != OPAL_SUCCESS)
prerror("IMC Devices not added\n");

free(compress_buf);
free(imc_xz->dst);
free(imc_xz);
}

/*
Expand Down
1 change: 1 addition & 0 deletions include/imc.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ struct imc_chip_cb

void imc_init(void);
void imc_catalog_preload(void);
void imc_decompress_catalog(void);

#define MAX_NEST_COMBINED_UNITS 4
struct combined_units_node {
Expand Down

0 comments on commit c86fb12

Please sign in to comment.