diff options
author | Badari Pulavarty <pbadari@us.ibm.com> | 2008-04-18 13:33:52 -0700 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-04-29 15:57:53 +1000 |
commit | 98d5c21c812e4e3b795f5bd912f407ed7c5e4e38 (patch) | |
tree | 40c5680e5b8b337fdddd3becf59484a19e2037d5 /arch | |
parent | 57b539269e9eef4dedc533d83c94877bc6b4d44d (diff) |
[POWERPC] Update lmb data structures for hotplug memory add/remove
The powerpc kernel maintains information about logical memory blocks
in the lmb.memory structure, which is initialized and updated at boot
time, but not when memory is added or removed while the kernel is
running.
This adds a hotplug memory notifier which updates lmb.memory when
memory is added or removed. This information is useful for eHEA
driver to find out the memory layout and holes.
NOTE: No special locking is needed for lmb_add() and lmb_remove().
Calls to these are serialized by caller. (pSeries_reconfig_chain).
Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Cc: Yasunori Goto <y-goto@jp.fujitsu.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/pseries/hotplug-memory.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 2d3e9a4bd6a..3c5727dd5aa 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -10,6 +10,7 @@ */ #include <linux/of.h> +#include <linux/lmb.h> #include <asm/firmware.h> #include <asm/machdep.h> #include <asm/pSeries_reconfig.h> @@ -58,6 +59,11 @@ static int pseries_remove_memory(struct device_node *np) 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 */ start = (unsigned long)__va(start_pfn << PAGE_SHIFT); @@ -65,6 +71,41 @@ static int pseries_remove_memory(struct device_node *np) 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) { @@ -72,6 +113,8 @@ static int pseries_memory_notifier(struct notifier_block *nb, switch (action) { case PSERIES_RECONFIG_ADD: + if (pseries_add_memory(node)) + err = NOTIFY_BAD; break; case PSERIES_RECONFIG_REMOVE: if (pseries_remove_memory(node)) |