Recent updates to the PAPR for memory hotplug has now made the reserved field of the ibm,dynamic-memory property a capabilities field. To support this update we can no longer use the reserved field to track which LMBs have been updated during a DLPAR operation.
This patch adds a bitfield to track any LMBs that are updated during a DLPAR operation so that we can roll back to the state proior to the DLPAR operation if an error occurs. Signed-off-by: Nathan Fontenot <nf...@linux.vnet.ibm.com> --- arch/powerpc/platforms/pseries/hotplug-memory.c | 25 ++++++++++------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index a0371d1..4be1b61 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -27,6 +27,7 @@ static struct drconf_mem { u32 num_lmbs; struct of_drconf_cell *lmbs; + unsigned long *lmb_update_map; } drmem; #define for_each_lmb_range(lmb, start, end) \ @@ -46,15 +47,15 @@ static void lmb_set_aa_index(u32 lmb, u32 aa_index) { } static bool lmb_updated(u32 lmb) { - return drmem.lmbs[lmb].reserved; + return test_bit(lmb, drmem.lmb_update_map); } static void mark_lmb_updated(u32 lmb) { - drmem.lmbs[lmb].reserved = 1; + set_bit(lmb, drmem.lmb_update_map); } -static void rm_lmb_update(u32 lmb) { - drmem.lmbs[lmb].reserved = 0; +static void clear_lmb_updates(void) { + bitmap_zero(drmem.lmb_update_map, drmem.num_lmbs); } static bool lmb_reserved(u32 lmb) { @@ -99,6 +100,11 @@ static void __init update_drconf_memory(void) p = prop->value; drmem.num_lmbs = be32_to_cpu(*p++); drmem.lmbs = (struct of_drconf_cell *)p; + + if (!drmem.lmb_update_map) { + drmem.lmb_update_map = kmalloc(BITS_TO_LONGS(drmem.num_lmbs), + GFP_KERNEL); + } } unsigned long pseries_memory_block_size(void) @@ -484,8 +490,6 @@ static int dlpar_memory_remove_by_count(u32 lmbs_to_remove) if (rc) pr_err("Failed to add LMB back, drc index %x\n", lmb_drc_index(lmb)); - - rm_lmb_update(lmb); } rc = -EINVAL; @@ -496,8 +500,6 @@ static int dlpar_memory_remove_by_count(u32 lmbs_to_remove) pr_info("Memory at %llx was hot-removed\n", lmb_base_address(lmb)); - - rm_lmb_update(lmb); } rc = 0; } @@ -588,8 +590,6 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index) if (rc) pr_err("Failed to add LMB, drc index %x\n", lmb_drc_index(lmb)); - - rm_lmb_update(lmb); } rc = -EINVAL; } else { @@ -599,8 +599,6 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index) pr_info("Memory at %llx (drc index %x) was hot-removed\n", lmb_base_address(lmb), lmb_drc_index(lmb)); - - rm_lmb_update(lmb); } } @@ -732,7 +730,6 @@ static int dlpar_memory_add_by_count(u32 lmbs_to_add) pr_info("Memory at %llx (drc index %x) was hot-added\n", lmb_base_address(lmb), lmb_drc_index(lmb)); - rm_lmb_update(lmb); } } @@ -830,7 +827,6 @@ static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index) pr_info("Memory at %llx (drc index %x) was hot-added\n", lmb_base_address(lmb), lmb_drc_index(lmb)); - rm_lmb_update(lmb); } } @@ -843,6 +839,7 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) int rc; lock_device_hotplug(); + clear_lmb_updates(); switch (hp_elog->action) { case PSERIES_HP_ELOG_ACTION_ADD: