aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Falcon <tlfalcon@linux.vnet.ibm.com>2014-08-19 16:44:57 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2014-09-08 20:37:00 -0400
commitc9ac408bc7329911237c25508f578fb2fa1c4235 (patch)
tree3f73d5caffcddbe8c39f97aae3fff983bcc203f4
parent2ce7598c9a453e0acd0e07be7be3f5eb39608ebd (diff)
powerpc/pseries: Fix endian issues in memory hotplug
Values acquired from Open Firmware are in 32-bit big endian format and need to be handled on little endian architectures. This patch ensures values are in cpu endian when hotplugging memory. Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c36
1 files changed, 19 insertions, 17 deletions
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index c904583baf4b..17ee193960a0 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -113,7 +113,7 @@ out:
113static int pseries_remove_mem_node(struct device_node *np) 113static int pseries_remove_mem_node(struct device_node *np)
114{ 114{
115 const char *type; 115 const char *type;
116 const unsigned int *regs; 116 const __be32 *regs;
117 unsigned long base; 117 unsigned long base;
118 unsigned int lmb_size; 118 unsigned int lmb_size;
119 int ret = -EINVAL; 119 int ret = -EINVAL;
@@ -132,8 +132,8 @@ static int pseries_remove_mem_node(struct device_node *np)
132 if (!regs) 132 if (!regs)
133 return ret; 133 return ret;
134 134
135 base = *(unsigned long *)regs; 135 base = be64_to_cpu(*(unsigned long *)regs);
136 lmb_size = regs[3]; 136 lmb_size = be32_to_cpu(regs[3]);
137 137
138 pseries_remove_memblock(base, lmb_size); 138 pseries_remove_memblock(base, lmb_size);
139 return 0; 139 return 0;
@@ -153,7 +153,7 @@ static inline int pseries_remove_mem_node(struct device_node *np)
153static int pseries_add_mem_node(struct device_node *np) 153static int pseries_add_mem_node(struct device_node *np)
154{ 154{
155 const char *type; 155 const char *type;
156 const unsigned int *regs; 156 const __be32 *regs;
157 unsigned long base; 157 unsigned long base;
158 unsigned int lmb_size; 158 unsigned int lmb_size;
159 int ret = -EINVAL; 159 int ret = -EINVAL;
@@ -172,8 +172,8 @@ static int pseries_add_mem_node(struct device_node *np)
172 if (!regs) 172 if (!regs)
173 return ret; 173 return ret;
174 174
175 base = *(unsigned long *)regs; 175 base = be64_to_cpu(*(unsigned long *)regs);
176 lmb_size = regs[3]; 176 lmb_size = be32_to_cpu(regs[3]);
177 177
178 /* 178 /*
179 * Update memory region to represent the memory add 179 * Update memory region to represent the memory add
@@ -187,14 +187,14 @@ static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
187 struct of_drconf_cell *new_drmem, *old_drmem; 187 struct of_drconf_cell *new_drmem, *old_drmem;
188 unsigned long memblock_size; 188 unsigned long memblock_size;
189 u32 entries; 189 u32 entries;
190 u32 *p; 190 __be32 *p;
191 int i, rc = -EINVAL; 191 int i, rc = -EINVAL;
192 192
193 memblock_size = pseries_memory_block_size(); 193 memblock_size = pseries_memory_block_size();
194 if (!memblock_size) 194 if (!memblock_size)
195 return -EINVAL; 195 return -EINVAL;
196 196
197 p = (u32 *) pr->old_prop->value; 197 p = (__be32 *) pr->old_prop->value;
198 if (!p) 198 if (!p)
199 return -EINVAL; 199 return -EINVAL;
200 200
@@ -203,28 +203,30 @@ static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
203 * entries. Get the niumber of entries and skip to the array of 203 * entries. Get the niumber of entries and skip to the array of
204 * of_drconf_cell's. 204 * of_drconf_cell's.
205 */ 205 */
206 entries = *p++; 206 entries = be32_to_cpu(*p++);
207 old_drmem = (struct of_drconf_cell *)p; 207 old_drmem = (struct of_drconf_cell *)p;
208 208
209 p = (u32 *)pr->prop->value; 209 p = (__be32 *)pr->prop->value;
210 p++; 210 p++;
211 new_drmem = (struct of_drconf_cell *)p; 211 new_drmem = (struct of_drconf_cell *)p;
212 212
213 for (i = 0; i < entries; i++) { 213 for (i = 0; i < entries; i++) {
214 if ((old_drmem[i].flags & DRCONF_MEM_ASSIGNED) && 214 if ((be32_to_cpu(old_drmem[i].flags) & DRCONF_MEM_ASSIGNED) &&
215 (!(new_drmem[i].flags & DRCONF_MEM_ASSIGNED))) { 215 (!(be32_to_cpu(new_drmem[i].flags) & DRCONF_MEM_ASSIGNED))) {
216 rc = pseries_remove_memblock(old_drmem[i].base_addr, 216 rc = pseries_remove_memblock(
217 be64_to_cpu(old_drmem[i].base_addr),
217 memblock_size); 218 memblock_size);
218 break; 219 break;
219 } else if ((!(old_drmem[i].flags & DRCONF_MEM_ASSIGNED)) && 220 } else if ((!(be32_to_cpu(old_drmem[i].flags) &
220 (new_drmem[i].flags & DRCONF_MEM_ASSIGNED)) { 221 DRCONF_MEM_ASSIGNED)) &&
221 rc = memblock_add(old_drmem[i].base_addr, 222 (be32_to_cpu(new_drmem[i].flags) &
223 DRCONF_MEM_ASSIGNED)) {
224 rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
222 memblock_size); 225 memblock_size);
223 rc = (rc < 0) ? -EINVAL : 0; 226 rc = (rc < 0) ? -EINVAL : 0;
224 break; 227 break;
225 } 228 }
226 } 229 }
227
228 return rc; 230 return rc;
229} 231}
230 232