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:

Reply via email to