diff options
Diffstat (limited to 'arch/powerpc')
-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 2d3e9a4bd6ae..3c5727dd5aa5 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/of.h> | 12 | #include <linux/of.h> |
13 | #include <linux/lmb.h> | ||
13 | #include <asm/firmware.h> | 14 | #include <asm/firmware.h> |
14 | #include <asm/machdep.h> | 15 | #include <asm/machdep.h> |
15 | #include <asm/pSeries_reconfig.h> | 16 | #include <asm/pSeries_reconfig.h> |
@@ -58,6 +59,11 @@ static int pseries_remove_memory(struct device_node *np) | |||
58 | return ret; | 59 | return ret; |
59 | 60 | ||
60 | /* | 61 | /* |
62 | * Update memory regions for memory remove | ||
63 | */ | ||
64 | lmb_remove(start_pfn << PAGE_SHIFT, regs[3]); | ||
65 | |||
66 | /* | ||
61 | * Remove htab bolted mappings for this section of memory | 67 | * Remove htab bolted mappings for this section of memory |
62 | */ | 68 | */ |
63 | start = (unsigned long)__va(start_pfn << PAGE_SHIFT); | 69 | start = (unsigned long)__va(start_pfn << PAGE_SHIFT); |
@@ -65,6 +71,41 @@ static int pseries_remove_memory(struct device_node *np) | |||
65 | return ret; | 71 | return ret; |
66 | } | 72 | } |
67 | 73 | ||
74 | static int pseries_add_memory(struct device_node *np) | ||
75 | { | ||
76 | const char *type; | ||
77 | const unsigned int *my_index; | ||
78 | const unsigned int *regs; | ||
79 | u64 start_pfn; | ||
80 | int ret = -EINVAL; | ||
81 | |||
82 | /* | ||
83 | * Check to see if we are actually adding memory | ||
84 | */ | ||
85 | type = of_get_property(np, "device_type", NULL); | ||
86 | if (type == NULL || strcmp(type, "memory") != 0) | ||
87 | return 0; | ||
88 | |||
89 | /* | ||
90 | * Find the memory index and size of the added section | ||
91 | */ | ||
92 | my_index = of_get_property(np, "ibm,my-drc-index", NULL); | ||
93 | if (!my_index) | ||
94 | return ret; | ||
95 | |||
96 | regs = of_get_property(np, "reg", NULL); | ||
97 | if (!regs) | ||
98 | return ret; | ||
99 | |||
100 | start_pfn = section_nr_to_pfn(*my_index & 0xffff); | ||
101 | |||
102 | /* | ||
103 | * Update memory region to represent the memory add | ||
104 | */ | ||
105 | lmb_add(start_pfn << PAGE_SHIFT, regs[3]); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
68 | static int pseries_memory_notifier(struct notifier_block *nb, | 109 | static int pseries_memory_notifier(struct notifier_block *nb, |
69 | unsigned long action, void *node) | 110 | unsigned long action, void *node) |
70 | { | 111 | { |
@@ -72,6 +113,8 @@ static int pseries_memory_notifier(struct notifier_block *nb, | |||
72 | 113 | ||
73 | switch (action) { | 114 | switch (action) { |
74 | case PSERIES_RECONFIG_ADD: | 115 | case PSERIES_RECONFIG_ADD: |
116 | if (pseries_add_memory(node)) | ||
117 | err = NOTIFY_BAD; | ||
75 | break; | 118 | break; |
76 | case PSERIES_RECONFIG_REMOVE: | 119 | case PSERIES_RECONFIG_REMOVE: |
77 | if (pseries_remove_memory(node)) | 120 | if (pseries_remove_memory(node)) |