*/
 
 #include <linux/of.h>
+#include <linux/lmb.h>
 #include <asm/firmware.h>
 #include <asm/machdep.h>
 #include <asm/pSeries_reconfig.h>
        if (ret)
                return ret;
 
+       /*
+        * Update memory regions for memory remove
+        */
+       lmb_remove(start_pfn << PAGE_SHIFT, regs[3]);
+
        /*
         * Remove htab bolted mappings for this section of memory
         */
        return ret;
 }
 
+static int pseries_add_memory(struct device_node *np)
+{
+       const char *type;
+       const unsigned int *my_index;
+       const unsigned int *regs;
+       u64 start_pfn;
+       int ret = -EINVAL;
+
+       /*
+        * Check to see if we are actually adding memory
+        */
+       type = of_get_property(np, "device_type", NULL);
+       if (type == NULL || strcmp(type, "memory") != 0)
+               return 0;
+
+       /*
+        * Find the memory index and size of the added section
+        */
+       my_index = of_get_property(np, "ibm,my-drc-index", NULL);
+       if (!my_index)
+               return ret;
+
+       regs = of_get_property(np, "reg", NULL);
+       if (!regs)
+               return ret;
+
+       start_pfn = section_nr_to_pfn(*my_index & 0xffff);
+
+       /*
+        * Update memory region to represent the memory add
+        */
+       lmb_add(start_pfn << PAGE_SHIFT, regs[3]);
+       return 0;
+}
+
 static int pseries_memory_notifier(struct notifier_block *nb,
                                unsigned long action, void *node)
 {
 
        switch (action) {
        case PSERIES_RECONFIG_ADD:
+               if (pseries_add_memory(node))
+                       err = NOTIFY_BAD;
                break;
        case PSERIES_RECONFIG_REMOVE:
                if (pseries_remove_memory(node))
 
 #endif /* DEBUG */
 }
 
-static unsigned long __init lmb_addrs_overlap(u64 base1, u64 size1,
-               u64 base2, u64 size2)
+static unsigned long lmb_addrs_overlap(u64 base1, u64 size1, u64 base2,
+                                       u64 size2)
 {
        return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
 }
 
-static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
-               u64 base2, u64 size2)
+static long lmb_addrs_adjacent(u64 base1, u64 size1, u64 base2, u64 size2)
 {
        if (base2 == base1 + size1)
                return 1;
        return 0;
 }
 
-static long __init lmb_regions_adjacent(struct lmb_region *rgn,
+static long lmb_regions_adjacent(struct lmb_region *rgn,
                unsigned long r1, unsigned long r2)
 {
        u64 base1 = rgn->region[r1].base;
        return lmb_addrs_adjacent(base1, size1, base2, size2);
 }
 
-static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
+static void lmb_remove_region(struct lmb_region *rgn, unsigned long r)
 {
        unsigned long i;
 
 }
 
 /* Assumption: base addr of region 1 < base addr of region 2 */
-static void __init lmb_coalesce_regions(struct lmb_region *rgn,
+static void lmb_coalesce_regions(struct lmb_region *rgn,
                unsigned long r1, unsigned long r2)
 {
        rgn->region[r1].size += rgn->region[r2].size;
                lmb.memory.size += lmb.memory.region[i].size;
 }
 
-static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
+static long lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
 {
        unsigned long coalesced = 0;
        long adjacent, i;
        return 0;
 }
 
-long __init lmb_add(u64 base, u64 size)
+long lmb_add(u64 base, u64 size)
 {
        struct lmb_region *_rgn = &lmb.memory;
 
 
 }
 
+long lmb_remove(u64 base, u64 size)
+{
+       struct lmb_region *rgn = &(lmb.memory);
+       u64 rgnbegin, rgnend;
+       u64 end = base + size;
+       int i;
+
+       rgnbegin = rgnend = 0; /* supress gcc warnings */
+
+       /* Find the region where (base, size) belongs to */
+       for (i=0; i < rgn->cnt; i++) {
+               rgnbegin = rgn->region[i].base;
+               rgnend = rgnbegin + rgn->region[i].size;
+
+               if ((rgnbegin <= base) && (end <= rgnend))
+                       break;
+       }
+
+       /* Didn't find the region */
+       if (i == rgn->cnt)
+               return -1;
+
+       /* Check to see if we are removing entire region */
+       if ((rgnbegin == base) && (rgnend == end)) {
+               lmb_remove_region(rgn, i);
+               return 0;
+       }
+
+       /* Check to see if region is matching at the front */
+       if (rgnbegin == base) {
+               rgn->region[i].base = end;
+               rgn->region[i].size -= size;
+               return 0;
+       }
+
+       /* Check to see if the region is matching at the end */
+       if (rgnend == end) {
+               rgn->region[i].size -= size;
+               return 0;
+       }
+
+       /*
+        * We need to split the entry -  adjust the current one to the
+        * beginging of the hole and add the region after hole.
+        */
+       rgn->region[i].size = base - rgn->region[i].base;
+       return lmb_add_region(rgn, end, rgnend - end);
+}
+
 long __init lmb_reserve(u64 base, u64 size)
 {
        struct lmb_region *_rgn = &lmb.reserved;