This patch updates the device tree manipulation routines so that memory
add/remove of lmbs represented under the
ibm,dynamic-reconfiguration-memory node of the device tree invokes the
hotplug notifier chain.

This change is needed because of the change in the way memory is
represented under the ibm,dynamic-reconfiguration-memory node.  All lmbs
are described in the ibm,dynamic-memory property instead of having a
separate node for each lmb as in previous device tree layouts.  This
requires the update_node() routine to check for updates to the
ibm,dynamic-memory property and invoke the hotplug notifier chain.

This also updates the pseries hotplug notifier to be able to gather information
for lmbs represented under the ibm,dynamic-reconfiguration-memory node and
have the lmbs added/removed.

Signed-off-by: Nathan Fontenot <[EMAIL PROTECTED]>
---
arch/powerpc/platforms/pseries/hotplug-memory.c |   95 +++++++++++++++++-------
arch/powerpc/platforms/pseries/reconfig.c       |   36 ++++++++-
include/asm-powerpc/pSeries_reconfig.h          |    6 +
3 files changed, 104 insertions(+), 33 deletions(-)

Index: linux-2.6.git/include/asm-powerpc/pSeries_reconfig.h
===================================================================
--- linux-2.6.git.orig/include/asm-powerpc/pSeries_reconfig.h   2008-07-01 
09:38:19.000000000 -0500
+++ linux-2.6.git/include/asm-powerpc/pSeries_reconfig.h        2008-07-01 
09:38:54.000000000 -0500
@@ -9,8 +9,10 @@
 * added or removed on pSeries systems.
 */

-#define PSERIES_RECONFIG_ADD    0x0001
-#define PSERIES_RECONFIG_REMOVE 0x0002
+#define PSERIES_RECONFIG_ADD           0x0001
+#define PSERIES_RECONFIG_REMOVE                0x0002
+#define PSERIES_DRCONF_MEM_ADD         0x0003
+#define PSERIES_DRCONF_MEM_REMOVE      0x0004

#ifdef CONFIG_PPC_PSERIES
extern int pSeries_reconfig_notifier_register(struct notifier_block *);
Index: linux-2.6.git/arch/powerpc/platforms/pseries/reconfig.c
===================================================================
--- linux-2.6.git.orig/arch/powerpc/platforms/pseries/reconfig.c        
2008-07-01 09:38:26.000000000 -0500
+++ linux-2.6.git/arch/powerpc/platforms/pseries/reconfig.c     2008-07-01 
09:38:54.000000000 -0500
@@ -422,8 +422,8 @@
{
        struct device_node *np;
        unsigned char *value;
-       char *name, *end;
-       int length;
+       char *name, *end, *next_prop;
+       int rc, length;
        struct property *newprop, *oldprop;
        buf = parse_node(buf, bufsize, &np);
        end = buf + bufsize;
@@ -431,7 +431,8 @@
        if (!np)
                return -ENODEV;

-       if (parse_next_property(buf, end, &name, &length, &value) == NULL)
+       next_prop = parse_next_property(buf, end, &name, &length, &value);
+       if (!next_prop)
                return -EINVAL;

        newprop = new_property(name, length, value, NULL);
@@ -442,7 +443,34 @@
        if (!oldprop)
                return -ENODEV;

-       return prom_update_property(np, newprop, oldprop);
+       rc = prom_update_property(np, newprop, oldprop);
+       if (rc)
+               return rc;
+
+       /* For memory under the ibm,dynamic-reconfiguration-memory node
+        * of the device tree, adding and removing memory is just an update
+        * to the ibm,dynamic-memory property instead of adding/removing a
+        * memory node in the device tree.  For these cases we still need to
+        * involve the notifier chain.
+        */
+       if (!strcmp(name, "ibm,dynamic-memory")) {
+               int action;
+
+               next_prop = parse_next_property(next_prop, end, &name,
+                                               &length, &value);
+               if (!next_prop)
+                       return -EINVAL;
+
+               if (!strcmp(name, "add"))
+                       action = PSERIES_DRCONF_MEM_ADD;
+               else
+                       action = PSERIES_DRCONF_MEM_REMOVE;
+
+               blocking_notifier_call_chain(&pSeries_reconfig_chain,
+                                            action, value);
+       }
+
+       return 0;
}

/**
Index: linux-2.6.git/arch/powerpc/platforms/pseries/hotplug-memory.c
===================================================================
--- linux-2.6.git.orig/arch/powerpc/platforms/pseries/hotplug-memory.c  
2008-07-01 09:38:49.000000000 -0500
+++ linux-2.6.git/arch/powerpc/platforms/pseries/hotplug-memory.c       
2008-07-01 18:43:33.000000000 -0500
@@ -15,32 +15,11 @@
#include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>

-static int pseries_remove_memory(struct device_node *np)
+static int pseries_remove_lmb(unsigned long base, unsigned int lmb_size)
{
-       const char *type;
-       const unsigned int *regs;
-       unsigned long base;
-       unsigned int lmb_size;
-       u64 start_pfn, start;
+       unsigned long start, start_pfn;
        struct zone *zone;
-       int ret = -EINVAL;
-
-       /*
-        * Check to see if we are actually removing memory
-        */
-       type = of_get_property(np, "device_type", NULL);
-       if (type == NULL || strcmp(type, "memory") != 0)
-               return 0;
-
-       /*
-        * Find the bae address and size of the lmb
-        */
-       regs = of_get_property(np, "reg", NULL);
-       if (!regs)
-               return ret;
-
-       base = *(unsigned long *)regs;
-       lmb_size = regs[3];
+       int ret;

        start_pfn = base >> PFN_SECTION_SHIFT;
        zone = page_zone(pfn_to_page(start_pfn));
@@ -71,13 +50,41 @@
        return ret;
}

+static int pseries_remove_memory(struct device_node *np)
+{
+       const char *type;
+       const unsigned int *regs;
+       unsigned long base;
+       unsigned int lmb_size;
+       int ret = -EINVAL;
+
+       /*
+        * Check to see if we are actually removing memory
+        */
+       type = of_get_property(np, "device_type", NULL);
+       if (type == NULL || strcmp(type, "memory") != 0)
+               return 0;
+
+       /*
+        * Find the bae address and size of the lmb
+        */
+       regs = of_get_property(np, "reg", NULL);
+       if (!regs)
+               return ret;
+
+       base = *(unsigned long *)regs;
+       lmb_size = regs[3];
+
+       ret = pseries_remove_lmb(base, lmb_size);
+       return ret;
+}
+
static int pseries_add_memory(struct device_node *np)
{
        const char *type;
        const unsigned int *regs;
        unsigned long base;
        unsigned int lmb_size;
-       u64 start_pfn;
        int ret = -EINVAL;

        /*
@@ -100,8 +107,37 @@
        /*
         * Update memory region to represent the memory add
         */
-       lmb_add(base, lmb_size);
-       return 0;
+       ret = lmb_add(base, lmb_size);
+       return (ret < 0) ? -EINVAL : 0;
+}
+
+static int pseries_drconf_memory(unsigned long *base, unsigned int action)
+{
+       struct device_node *np;
+       const unsigned long *lmb_size;
+       int rc;
+
+       np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+       if (!np)
+               return -EINVAL;
+
+       lmb_size = of_get_property(np, "ibm,lmb-size", NULL);
+       if (!lmb_size) {
+               of_node_put(np);
+               return -EINVAL;
+       }
+
+       if (action == PSERIES_DRCONF_MEM_ADD) {
+               rc = lmb_add(*base, *lmb_size);
+               rc = (rc < 0) ? -EINVAL : 0;
+       } else if (action == PSERIES_DRCONF_MEM_REMOVE) {
+               rc = pseries_remove_lmb(*base, *lmb_size);
+       } else {
+               rc = -EINVAL;
+       }
+
+       of_node_put(np);
+       return rc;
}

static int pseries_memory_notifier(struct notifier_block *nb,
@@ -118,6 +154,11 @@
                if (pseries_remove_memory(node))
                        err = NOTIFY_BAD;
                break;
+       case PSERIES_DRCONF_MEM_ADD:
+       case PSERIES_DRCONF_MEM_REMOVE:
+               if (pseries_drconf_memory(node, action))
+                       err = NOTIFY_BAD;
+               break;
        default:
                err = NOTIFY_DONE;
                break;
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to