aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/powernv/opal-fadump.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/arch/powerpc/platforms/powernv/opal-fadump.c b/arch/powerpc/platforms/powernv/opal-fadump.c
index b53007e82190..a4b96a7a5d6c 100644
--- a/arch/powerpc/platforms/powernv/opal-fadump.c
+++ b/arch/powerpc/platforms/powernv/opal-fadump.c
@@ -26,6 +26,8 @@ static int opal_fadump_unregister(struct fw_dump *fadump_conf);
static void opal_fadump_update_config(struct fw_dump *fadump_conf,
const struct opal_fadump_mem_struct *fdm)
{
+ pr_debug("Boot memory regions count: %d\n", fdm->region_cnt);
+
/*
* The destination address of the first boot memory region is the
* destination address of boot memory regions.
@@ -48,16 +50,34 @@ static void opal_fadump_init_metadata(struct opal_fadump_mem_struct *fdm)
static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf)
{
- u64 addr = fadump_conf->reserve_dump_area_start;
+ int max_copy_size, cur_size, size;
+ u64 src_addr, dest_addr;
opal_fdm = __va(fadump_conf->kernel_metadata);
opal_fadump_init_metadata(opal_fdm);
- opal_fdm->region_cnt = 1;
- opal_fdm->rgn[0].src = 0;
- opal_fdm->rgn[0].dest = addr;
- opal_fdm->rgn[0].size = fadump_conf->boot_memory_size;
- addr += fadump_conf->boot_memory_size;
+ /*
+ * Firmware supports 32-bit field for size. Align it to PAGE_SIZE
+ * and request firmware to copy multiple kernel boot memory regions.
+ */
+ max_copy_size = _ALIGN_DOWN(U32_MAX, PAGE_SIZE);
+
+ /* Boot memory regions */
+ src_addr = 0;
+ dest_addr = fadump_conf->reserve_dump_area_start;
+ size = fadump_conf->boot_memory_size;
+ while (size) {
+ cur_size = size > max_copy_size ? max_copy_size : size;
+
+ opal_fdm->rgn[opal_fdm->region_cnt].src = src_addr;
+ opal_fdm->rgn[opal_fdm->region_cnt].dest = dest_addr;
+ opal_fdm->rgn[opal_fdm->region_cnt].size = cur_size;
+
+ opal_fdm->region_cnt++;
+ dest_addr += cur_size;
+ src_addr += cur_size;
+ size -= cur_size;
+ }
/*
* Kernel metadata is passed to f/w and retrieved in capture kerenl.
@@ -68,7 +88,7 @@ static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf)
opal_fadump_update_config(fadump_conf, opal_fdm);
- return addr;
+ return dest_addr;
}
static u64 opal_fadump_get_metadata_size(void)