1 /*
2  * pseries Memory Hotplug infrastructure.
3  *
4  * Copyright (C) 2008 Badari Pulavarty, IBM Corporation
5  *
6  *      This program is free software; you can redistribute it and/or
7  *      modify it under the terms of the GNU General Public License
8  *      as published by the Free Software Foundation; either version
9  *      2 of the License, or (at your option) any later version.
10  */
11 
12 #define pr_fmt(fmt)	"pseries-hotplug-mem: " fmt
13 
14 #include <linux/of.h>
15 #include <linux/of_address.h>
16 #include <linux/memblock.h>
17 #include <linux/memory.h>
18 #include <linux/memory_hotplug.h>
19 #include <linux/slab.h>
20 
21 #include <asm/firmware.h>
22 #include <asm/machdep.h>
23 #include <asm/prom.h>
24 #include <asm/sparsemem.h>
25 #include "pseries.h"
26 
27 static bool rtas_hp_event;
28 
29 unsigned long pseries_memory_block_size(void)
30 {
31 	struct device_node *np;
32 	unsigned int memblock_size = MIN_MEMORY_BLOCK_SIZE;
33 	struct resource r;
34 
35 	np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
36 	if (np) {
37 		const __be64 *size;
38 
39 		size = of_get_property(np, "ibm,lmb-size", NULL);
40 		if (size)
41 			memblock_size = be64_to_cpup(size);
42 		of_node_put(np);
43 	} else  if (machine_is(pseries)) {
44 		/* This fallback really only applies to pseries */
45 		unsigned int memzero_size = 0;
46 
47 		np = of_find_node_by_path("/memory@0");
48 		if (np) {
49 			if (!of_address_to_resource(np, 0, &r))
50 				memzero_size = resource_size(&r);
51 			of_node_put(np);
52 		}
53 
54 		if (memzero_size) {
55 			/* We now know the size of memory@0, use this to find
56 			 * the first memoryblock and get its size.
57 			 */
58 			char buf[64];
59 
60 			sprintf(buf, "/memory@%x", memzero_size);
61 			np = of_find_node_by_path(buf);
62 			if (np) {
63 				if (!of_address_to_resource(np, 0, &r))
64 					memblock_size = resource_size(&r);
65 				of_node_put(np);
66 			}
67 		}
68 	}
69 	return memblock_size;
70 }
71 
72 static void dlpar_free_property(struct property *prop)
73 {
74 	kfree(prop->name);
75 	kfree(prop->value);
76 	kfree(prop);
77 }
78 
79 static struct property *dlpar_clone_property(struct property *prop,
80 					     u32 prop_size)
81 {
82 	struct property *new_prop;
83 
84 	new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
85 	if (!new_prop)
86 		return NULL;
87 
88 	new_prop->name = kstrdup(prop->name, GFP_KERNEL);
89 	new_prop->value = kzalloc(prop_size, GFP_KERNEL);
90 	if (!new_prop->name || !new_prop->value) {
91 		dlpar_free_property(new_prop);
92 		return NULL;
93 	}
94 
95 	memcpy(new_prop->value, prop->value, prop->length);
96 	new_prop->length = prop_size;
97 
98 	of_property_set_flag(new_prop, OF_DYNAMIC);
99 	return new_prop;
100 }
101 
102 static struct property *dlpar_clone_drconf_property(struct device_node *dn)
103 {
104 	struct property *prop, *new_prop;
105 	struct of_drconf_cell *lmbs;
106 	u32 num_lmbs, *p;
107 	int i;
108 
109 	prop = of_find_property(dn, "ibm,dynamic-memory", NULL);
110 	if (!prop)
111 		return NULL;
112 
113 	new_prop = dlpar_clone_property(prop, prop->length);
114 	if (!new_prop)
115 		return NULL;
116 
117 	/* Convert the property to cpu endian-ness */
118 	p = new_prop->value;
119 	*p = be32_to_cpu(*p);
120 
121 	num_lmbs = *p++;
122 	lmbs = (struct of_drconf_cell *)p;
123 
124 	for (i = 0; i < num_lmbs; i++) {
125 		lmbs[i].base_addr = be64_to_cpu(lmbs[i].base_addr);
126 		lmbs[i].drc_index = be32_to_cpu(lmbs[i].drc_index);
127 		lmbs[i].aa_index = be32_to_cpu(lmbs[i].aa_index);
128 		lmbs[i].flags = be32_to_cpu(lmbs[i].flags);
129 	}
130 
131 	return new_prop;
132 }
133 
134 static void dlpar_update_drconf_property(struct device_node *dn,
135 					 struct property *prop)
136 {
137 	struct of_drconf_cell *lmbs;
138 	u32 num_lmbs, *p;
139 	int i;
140 
141 	/* Convert the property back to BE */
142 	p = prop->value;
143 	num_lmbs = *p;
144 	*p = cpu_to_be32(*p);
145 	p++;
146 
147 	lmbs = (struct of_drconf_cell *)p;
148 	for (i = 0; i < num_lmbs; i++) {
149 		lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr);
150 		lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index);
151 		lmbs[i].aa_index = cpu_to_be32(lmbs[i].aa_index);
152 		lmbs[i].flags = cpu_to_be32(lmbs[i].flags);
153 	}
154 
155 	rtas_hp_event = true;
156 	of_update_property(dn, prop);
157 	rtas_hp_event = false;
158 }
159 
160 static int dlpar_update_device_tree_lmb(struct of_drconf_cell *lmb)
161 {
162 	struct device_node *dn;
163 	struct property *prop;
164 	struct of_drconf_cell *lmbs;
165 	u32 *p, num_lmbs;
166 	int i;
167 
168 	dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
169 	if (!dn)
170 		return -ENODEV;
171 
172 	prop = dlpar_clone_drconf_property(dn);
173 	if (!prop) {
174 		of_node_put(dn);
175 		return -ENODEV;
176 	}
177 
178 	p = prop->value;
179 	num_lmbs = *p++;
180 	lmbs = (struct of_drconf_cell *)p;
181 
182 	for (i = 0; i < num_lmbs; i++) {
183 		if (lmbs[i].drc_index == lmb->drc_index) {
184 			lmbs[i].flags = lmb->flags;
185 			lmbs[i].aa_index = lmb->aa_index;
186 
187 			dlpar_update_drconf_property(dn, prop);
188 			break;
189 		}
190 	}
191 
192 	of_node_put(dn);
193 	return 0;
194 }
195 
196 static u32 find_aa_index(struct device_node *dr_node,
197 			 struct property *ala_prop, const u32 *lmb_assoc)
198 {
199 	u32 *assoc_arrays;
200 	u32 aa_index;
201 	int aa_arrays, aa_array_entries, aa_array_sz;
202 	int i, index;
203 
204 	/*
205 	 * The ibm,associativity-lookup-arrays property is defined to be
206 	 * a 32-bit value specifying the number of associativity arrays
207 	 * followed by a 32-bitvalue specifying the number of entries per
208 	 * array, followed by the associativity arrays.
209 	 */
210 	assoc_arrays = ala_prop->value;
211 
212 	aa_arrays = be32_to_cpu(assoc_arrays[0]);
213 	aa_array_entries = be32_to_cpu(assoc_arrays[1]);
214 	aa_array_sz = aa_array_entries * sizeof(u32);
215 
216 	aa_index = -1;
217 	for (i = 0; i < aa_arrays; i++) {
218 		index = (i * aa_array_entries) + 2;
219 
220 		if (memcmp(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz))
221 			continue;
222 
223 		aa_index = i;
224 		break;
225 	}
226 
227 	if (aa_index == -1) {
228 		struct property *new_prop;
229 		u32 new_prop_size;
230 
231 		new_prop_size = ala_prop->length + aa_array_sz;
232 		new_prop = dlpar_clone_property(ala_prop, new_prop_size);
233 		if (!new_prop)
234 			return -1;
235 
236 		assoc_arrays = new_prop->value;
237 
238 		/* increment the number of entries in the lookup array */
239 		assoc_arrays[0] = cpu_to_be32(aa_arrays + 1);
240 
241 		/* copy the new associativity into the lookup array */
242 		index = aa_arrays * aa_array_entries + 2;
243 		memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz);
244 
245 		of_update_property(dr_node, new_prop);
246 
247 		/*
248 		 * The associativity lookup array index for this lmb is
249 		 * number of entries - 1 since we added its associativity
250 		 * to the end of the lookup array.
251 		 */
252 		aa_index = be32_to_cpu(assoc_arrays[0]) - 1;
253 	}
254 
255 	return aa_index;
256 }
257 
258 static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb)
259 {
260 	struct device_node *parent, *lmb_node, *dr_node;
261 	struct property *ala_prop;
262 	const u32 *lmb_assoc;
263 	u32 aa_index;
264 
265 	parent = of_find_node_by_path("/");
266 	if (!parent)
267 		return -ENODEV;
268 
269 	lmb_node = dlpar_configure_connector(cpu_to_be32(lmb->drc_index),
270 					     parent);
271 	of_node_put(parent);
272 	if (!lmb_node)
273 		return -EINVAL;
274 
275 	lmb_assoc = of_get_property(lmb_node, "ibm,associativity", NULL);
276 	if (!lmb_assoc) {
277 		dlpar_free_cc_nodes(lmb_node);
278 		return -ENODEV;
279 	}
280 
281 	dr_node = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
282 	if (!dr_node) {
283 		dlpar_free_cc_nodes(lmb_node);
284 		return -ENODEV;
285 	}
286 
287 	ala_prop = of_find_property(dr_node, "ibm,associativity-lookup-arrays",
288 				    NULL);
289 	if (!ala_prop) {
290 		of_node_put(dr_node);
291 		dlpar_free_cc_nodes(lmb_node);
292 		return -ENODEV;
293 	}
294 
295 	aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc);
296 
297 	dlpar_free_cc_nodes(lmb_node);
298 	return aa_index;
299 }
300 
301 static int dlpar_add_device_tree_lmb(struct of_drconf_cell *lmb)
302 {
303 	int aa_index;
304 
305 	lmb->flags |= DRCONF_MEM_ASSIGNED;
306 
307 	aa_index = lookup_lmb_associativity_index(lmb);
308 	if (aa_index < 0) {
309 		pr_err("Couldn't find associativity index for drc index %x\n",
310 		       lmb->drc_index);
311 		return aa_index;
312 	}
313 
314 	lmb->aa_index = aa_index;
315 	return dlpar_update_device_tree_lmb(lmb);
316 }
317 
318 static int dlpar_remove_device_tree_lmb(struct of_drconf_cell *lmb)
319 {
320 	lmb->flags &= ~DRCONF_MEM_ASSIGNED;
321 	lmb->aa_index = 0xffffffff;
322 	return dlpar_update_device_tree_lmb(lmb);
323 }
324 
325 static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
326 {
327 	unsigned long section_nr;
328 	struct mem_section *mem_sect;
329 	struct memory_block *mem_block;
330 
331 	section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
332 	mem_sect = __nr_to_section(section_nr);
333 
334 	mem_block = find_memory_block(mem_sect);
335 	return mem_block;
336 }
337 
338 #ifdef CONFIG_MEMORY_HOTREMOVE
339 static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
340 {
341 	unsigned long block_sz, start_pfn;
342 	int sections_per_block;
343 	int i, nid;
344 
345 	start_pfn = base >> PAGE_SHIFT;
346 
347 	lock_device_hotplug();
348 
349 	if (!pfn_valid(start_pfn))
350 		goto out;
351 
352 	block_sz = pseries_memory_block_size();
353 	sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
354 	nid = memory_add_physaddr_to_nid(base);
355 
356 	for (i = 0; i < sections_per_block; i++) {
357 		remove_memory(nid, base, MIN_MEMORY_BLOCK_SIZE);
358 		base += MIN_MEMORY_BLOCK_SIZE;
359 	}
360 
361 out:
362 	/* Update memory regions for memory remove */
363 	memblock_remove(base, memblock_size);
364 	unlock_device_hotplug();
365 	return 0;
366 }
367 
368 static int pseries_remove_mem_node(struct device_node *np)
369 {
370 	const char *type;
371 	const __be32 *regs;
372 	unsigned long base;
373 	unsigned int lmb_size;
374 	int ret = -EINVAL;
375 
376 	/*
377 	 * Check to see if we are actually removing memory
378 	 */
379 	type = of_get_property(np, "device_type", NULL);
380 	if (type == NULL || strcmp(type, "memory") != 0)
381 		return 0;
382 
383 	/*
384 	 * Find the base address and size of the memblock
385 	 */
386 	regs = of_get_property(np, "reg", NULL);
387 	if (!regs)
388 		return ret;
389 
390 	base = be64_to_cpu(*(unsigned long *)regs);
391 	lmb_size = be32_to_cpu(regs[3]);
392 
393 	pseries_remove_memblock(base, lmb_size);
394 	return 0;
395 }
396 
397 static bool lmb_is_removable(struct of_drconf_cell *lmb)
398 {
399 	int i, scns_per_block;
400 	int rc = 1;
401 	unsigned long pfn, block_sz;
402 	u64 phys_addr;
403 
404 	if (!(lmb->flags & DRCONF_MEM_ASSIGNED))
405 		return false;
406 
407 	block_sz = memory_block_size_bytes();
408 	scns_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
409 	phys_addr = lmb->base_addr;
410 
411 	for (i = 0; i < scns_per_block; i++) {
412 		pfn = PFN_DOWN(phys_addr);
413 		if (!pfn_present(pfn))
414 			continue;
415 
416 		rc &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
417 		phys_addr += MIN_MEMORY_BLOCK_SIZE;
418 	}
419 
420 	return rc ? true : false;
421 }
422 
423 static int dlpar_add_lmb(struct of_drconf_cell *);
424 
425 static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
426 {
427 	struct memory_block *mem_block;
428 	unsigned long block_sz;
429 	int nid, rc;
430 
431 	if (!lmb_is_removable(lmb))
432 		return -EINVAL;
433 
434 	mem_block = lmb_to_memblock(lmb);
435 	if (!mem_block)
436 		return -EINVAL;
437 
438 	rc = device_offline(&mem_block->dev);
439 	put_device(&mem_block->dev);
440 	if (rc)
441 		return rc;
442 
443 	block_sz = pseries_memory_block_size();
444 	nid = memory_add_physaddr_to_nid(lmb->base_addr);
445 
446 	remove_memory(nid, lmb->base_addr, block_sz);
447 
448 	/* Update memory regions for memory remove */
449 	memblock_remove(lmb->base_addr, block_sz);
450 
451 	dlpar_remove_device_tree_lmb(lmb);
452 	return 0;
453 }
454 
455 static int dlpar_memory_remove_by_count(u32 lmbs_to_remove,
456 					struct property *prop)
457 {
458 	struct of_drconf_cell *lmbs;
459 	int lmbs_removed = 0;
460 	int lmbs_available = 0;
461 	u32 num_lmbs, *p;
462 	int i, rc;
463 
464 	pr_info("Attempting to hot-remove %d LMB(s)\n", lmbs_to_remove);
465 
466 	if (lmbs_to_remove == 0)
467 		return -EINVAL;
468 
469 	p = prop->value;
470 	num_lmbs = *p++;
471 	lmbs = (struct of_drconf_cell *)p;
472 
473 	/* Validate that there are enough LMBs to satisfy the request */
474 	for (i = 0; i < num_lmbs; i++) {
475 		if (lmb_is_removable(&lmbs[i]))
476 			lmbs_available++;
477 	}
478 
479 	if (lmbs_available < lmbs_to_remove) {
480 		pr_info("Not enough LMBs available (%d of %d) to satisfy request\n",
481 			lmbs_available, lmbs_to_remove);
482 		return -EINVAL;
483 	}
484 
485 	for (i = 0; i < num_lmbs && lmbs_removed < lmbs_to_remove; i++) {
486 		rc = dlpar_remove_lmb(&lmbs[i]);
487 		if (rc)
488 			continue;
489 
490 		lmbs_removed++;
491 
492 		/* Mark this lmb so we can add it later if all of the
493 		 * requested LMBs cannot be removed.
494 		 */
495 		lmbs[i].reserved = 1;
496 	}
497 
498 	if (lmbs_removed != lmbs_to_remove) {
499 		pr_err("Memory hot-remove failed, adding LMB's back\n");
500 
501 		for (i = 0; i < num_lmbs; i++) {
502 			if (!lmbs[i].reserved)
503 				continue;
504 
505 			rc = dlpar_add_lmb(&lmbs[i]);
506 			if (rc)
507 				pr_err("Failed to add LMB back, drc index %x\n",
508 				       lmbs[i].drc_index);
509 
510 			lmbs[i].reserved = 0;
511 		}
512 
513 		rc = -EINVAL;
514 	} else {
515 		for (i = 0; i < num_lmbs; i++) {
516 			if (!lmbs[i].reserved)
517 				continue;
518 
519 			dlpar_release_drc(lmbs[i].drc_index);
520 			pr_info("Memory at %llx was hot-removed\n",
521 				lmbs[i].base_addr);
522 
523 			lmbs[i].reserved = 0;
524 		}
525 		rc = 0;
526 	}
527 
528 	return rc;
529 }
530 
531 static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
532 {
533 	struct of_drconf_cell *lmbs;
534 	u32 num_lmbs, *p;
535 	int lmb_found;
536 	int i, rc;
537 
538 	pr_info("Attempting to hot-remove LMB, drc index %x\n", drc_index);
539 
540 	p = prop->value;
541 	num_lmbs = *p++;
542 	lmbs = (struct of_drconf_cell *)p;
543 
544 	lmb_found = 0;
545 	for (i = 0; i < num_lmbs; i++) {
546 		if (lmbs[i].drc_index == drc_index) {
547 			lmb_found = 1;
548 			rc = dlpar_remove_lmb(&lmbs[i]);
549 			if (!rc)
550 				dlpar_release_drc(lmbs[i].drc_index);
551 
552 			break;
553 		}
554 	}
555 
556 	if (!lmb_found)
557 		rc = -EINVAL;
558 
559 	if (rc)
560 		pr_info("Failed to hot-remove memory at %llx\n",
561 			lmbs[i].base_addr);
562 	else
563 		pr_info("Memory at %llx was hot-removed\n", lmbs[i].base_addr);
564 
565 	return rc;
566 }
567 
568 static int dlpar_memory_readd_by_index(u32 drc_index, struct property *prop)
569 {
570 	struct of_drconf_cell *lmbs;
571 	u32 num_lmbs, *p;
572 	int lmb_found;
573 	int i, rc;
574 
575 	pr_info("Attempting to update LMB, drc index %x\n", drc_index);
576 
577 	p = prop->value;
578 	num_lmbs = *p++;
579 	lmbs = (struct of_drconf_cell *)p;
580 
581 	lmb_found = 0;
582 	for (i = 0; i < num_lmbs; i++) {
583 		if (lmbs[i].drc_index == drc_index) {
584 			lmb_found = 1;
585 			rc = dlpar_remove_lmb(&lmbs[i]);
586 			if (!rc) {
587 				rc = dlpar_add_lmb(&lmbs[i]);
588 				if (rc)
589 					dlpar_release_drc(lmbs[i].drc_index);
590 			}
591 			break;
592 		}
593 	}
594 
595 	if (!lmb_found)
596 		rc = -EINVAL;
597 
598 	if (rc)
599 		pr_info("Failed to update memory at %llx\n",
600 			lmbs[i].base_addr);
601 	else
602 		pr_info("Memory at %llx was updated\n", lmbs[i].base_addr);
603 
604 	return rc;
605 }
606 
607 static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index,
608 				     struct property *prop)
609 {
610 	struct of_drconf_cell *lmbs;
611 	u32 num_lmbs, *p;
612 	int i, rc, start_lmb_found;
613 	int lmbs_available = 0, start_index = 0, end_index;
614 
615 	pr_info("Attempting to hot-remove %u LMB(s) at %x\n",
616 		lmbs_to_remove, drc_index);
617 
618 	if (lmbs_to_remove == 0)
619 		return -EINVAL;
620 
621 	p = prop->value;
622 	num_lmbs = *p++;
623 	lmbs = (struct of_drconf_cell *)p;
624 	start_lmb_found = 0;
625 
626 	/* Navigate to drc_index */
627 	while (start_index < num_lmbs) {
628 		if (lmbs[start_index].drc_index == drc_index) {
629 			start_lmb_found = 1;
630 			break;
631 		}
632 
633 		start_index++;
634 	}
635 
636 	if (!start_lmb_found)
637 		return -EINVAL;
638 
639 	end_index = start_index + lmbs_to_remove;
640 
641 	/* Validate that there are enough LMBs to satisfy the request */
642 	for (i = start_index; i < end_index; i++) {
643 		if (lmbs[i].flags & DRCONF_MEM_RESERVED)
644 			break;
645 
646 		lmbs_available++;
647 	}
648 
649 	if (lmbs_available < lmbs_to_remove)
650 		return -EINVAL;
651 
652 	for (i = start_index; i < end_index; i++) {
653 		if (!(lmbs[i].flags & DRCONF_MEM_ASSIGNED))
654 			continue;
655 
656 		rc = dlpar_remove_lmb(&lmbs[i]);
657 		if (rc)
658 			break;
659 
660 		lmbs[i].reserved = 1;
661 	}
662 
663 	if (rc) {
664 		pr_err("Memory indexed-count-remove failed, adding any removed LMBs\n");
665 
666 		for (i = start_index; i < end_index; i++) {
667 			if (!lmbs[i].reserved)
668 				continue;
669 
670 			rc = dlpar_add_lmb(&lmbs[i]);
671 			if (rc)
672 				pr_err("Failed to add LMB, drc index %x\n",
673 				       be32_to_cpu(lmbs[i].drc_index));
674 
675 			lmbs[i].reserved = 0;
676 		}
677 		rc = -EINVAL;
678 	} else {
679 		for (i = start_index; i < end_index; i++) {
680 			if (!lmbs[i].reserved)
681 				continue;
682 
683 			dlpar_release_drc(lmbs[i].drc_index);
684 			pr_info("Memory at %llx (drc index %x) was hot-removed\n",
685 				lmbs[i].base_addr, lmbs[i].drc_index);
686 
687 			lmbs[i].reserved = 0;
688 		}
689 	}
690 
691 	return rc;
692 }
693 
694 #else
695 static inline int pseries_remove_memblock(unsigned long base,
696 					  unsigned int memblock_size)
697 {
698 	return -EOPNOTSUPP;
699 }
700 static inline int pseries_remove_mem_node(struct device_node *np)
701 {
702 	return 0;
703 }
704 static inline int dlpar_memory_remove(struct pseries_hp_errorlog *hp_elog)
705 {
706 	return -EOPNOTSUPP;
707 }
708 static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
709 {
710 	return -EOPNOTSUPP;
711 }
712 static int dlpar_memory_remove_by_count(u32 lmbs_to_remove,
713 					struct property *prop)
714 {
715 	return -EOPNOTSUPP;
716 }
717 static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
718 {
719 	return -EOPNOTSUPP;
720 }
721 static int dlpar_memory_readd_by_index(u32 drc_index, struct property *prop)
722 {
723 	return -EOPNOTSUPP;
724 }
725 
726 static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index,
727 				     struct property *prop)
728 {
729 	return -EOPNOTSUPP;
730 }
731 #endif /* CONFIG_MEMORY_HOTREMOVE */
732 
733 static int dlpar_online_lmb(struct of_drconf_cell *lmb)
734 {
735 	struct memory_block *mem_block;
736 	int rc;
737 
738 	mem_block = lmb_to_memblock(lmb);
739 	if (!mem_block)
740 		return -EINVAL;
741 
742 	rc = device_online(&mem_block->dev);
743 	put_device(&mem_block->dev);
744 	return rc;
745 }
746 
747 static int dlpar_add_lmb(struct of_drconf_cell *lmb)
748 {
749 	unsigned long block_sz;
750 	int nid, rc;
751 
752 	if (lmb->flags & DRCONF_MEM_ASSIGNED)
753 		return -EINVAL;
754 
755 	rc = dlpar_add_device_tree_lmb(lmb);
756 	if (rc) {
757 		pr_err("Couldn't update device tree for drc index %x\n",
758 		       lmb->drc_index);
759 		dlpar_release_drc(lmb->drc_index);
760 		return rc;
761 	}
762 
763 	block_sz = memory_block_size_bytes();
764 
765 	/* Find the node id for this address */
766 	nid = memory_add_physaddr_to_nid(lmb->base_addr);
767 
768 	/* Add the memory */
769 	rc = add_memory(nid, lmb->base_addr, block_sz);
770 	if (rc) {
771 		dlpar_remove_device_tree_lmb(lmb);
772 		return rc;
773 	}
774 
775 	rc = dlpar_online_lmb(lmb);
776 	if (rc) {
777 		remove_memory(nid, lmb->base_addr, block_sz);
778 		dlpar_remove_device_tree_lmb(lmb);
779 	} else {
780 		lmb->flags |= DRCONF_MEM_ASSIGNED;
781 	}
782 
783 	return rc;
784 }
785 
786 static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop)
787 {
788 	struct of_drconf_cell *lmbs;
789 	u32 num_lmbs, *p;
790 	int lmbs_available = 0;
791 	int lmbs_added = 0;
792 	int i, rc;
793 
794 	pr_info("Attempting to hot-add %d LMB(s)\n", lmbs_to_add);
795 
796 	if (lmbs_to_add == 0)
797 		return -EINVAL;
798 
799 	p = prop->value;
800 	num_lmbs = *p++;
801 	lmbs = (struct of_drconf_cell *)p;
802 
803 	/* Validate that there are enough LMBs to satisfy the request */
804 	for (i = 0; i < num_lmbs; i++) {
805 		if (!(lmbs[i].flags & DRCONF_MEM_ASSIGNED))
806 			lmbs_available++;
807 	}
808 
809 	if (lmbs_available < lmbs_to_add)
810 		return -EINVAL;
811 
812 	for (i = 0; i < num_lmbs && lmbs_to_add != lmbs_added; i++) {
813 		rc = dlpar_acquire_drc(lmbs[i].drc_index);
814 		if (rc)
815 			continue;
816 
817 		rc = dlpar_add_lmb(&lmbs[i]);
818 		if (rc) {
819 			dlpar_release_drc(lmbs[i].drc_index);
820 			continue;
821 		}
822 
823 		lmbs_added++;
824 
825 		/* Mark this lmb so we can remove it later if all of the
826 		 * requested LMBs cannot be added.
827 		 */
828 		lmbs[i].reserved = 1;
829 	}
830 
831 	if (lmbs_added != lmbs_to_add) {
832 		pr_err("Memory hot-add failed, removing any added LMBs\n");
833 
834 		for (i = 0; i < num_lmbs; i++) {
835 			if (!lmbs[i].reserved)
836 				continue;
837 
838 			rc = dlpar_remove_lmb(&lmbs[i]);
839 			if (rc)
840 				pr_err("Failed to remove LMB, drc index %x\n",
841 				       be32_to_cpu(lmbs[i].drc_index));
842 			else
843 				dlpar_release_drc(lmbs[i].drc_index);
844 		}
845 		rc = -EINVAL;
846 	} else {
847 		for (i = 0; i < num_lmbs; i++) {
848 			if (!lmbs[i].reserved)
849 				continue;
850 
851 			pr_info("Memory at %llx (drc index %x) was hot-added\n",
852 				lmbs[i].base_addr, lmbs[i].drc_index);
853 			lmbs[i].reserved = 0;
854 		}
855 	}
856 
857 	return rc;
858 }
859 
860 static int dlpar_memory_add_by_index(u32 drc_index, struct property *prop)
861 {
862 	struct of_drconf_cell *lmbs;
863 	u32 num_lmbs, *p;
864 	int i, lmb_found;
865 	int rc;
866 
867 	pr_info("Attempting to hot-add LMB, drc index %x\n", drc_index);
868 
869 	p = prop->value;
870 	num_lmbs = *p++;
871 	lmbs = (struct of_drconf_cell *)p;
872 
873 	lmb_found = 0;
874 	for (i = 0; i < num_lmbs; i++) {
875 		if (lmbs[i].drc_index == drc_index) {
876 			lmb_found = 1;
877 			rc = dlpar_acquire_drc(lmbs[i].drc_index);
878 			if (!rc) {
879 				rc = dlpar_add_lmb(&lmbs[i]);
880 				if (rc)
881 					dlpar_release_drc(lmbs[i].drc_index);
882 			}
883 
884 			break;
885 		}
886 	}
887 
888 	if (!lmb_found)
889 		rc = -EINVAL;
890 
891 	if (rc)
892 		pr_info("Failed to hot-add memory, drc index %x\n", drc_index);
893 	else
894 		pr_info("Memory at %llx (drc index %x) was hot-added\n",
895 			lmbs[i].base_addr, drc_index);
896 
897 	return rc;
898 }
899 
900 static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index,
901 				  struct property *prop)
902 {
903 	struct of_drconf_cell *lmbs;
904 	u32 num_lmbs, *p;
905 	int i, rc, start_lmb_found;
906 	int lmbs_available = 0, start_index = 0, end_index;
907 
908 	pr_info("Attempting to hot-add %u LMB(s) at index %x\n",
909 		lmbs_to_add, drc_index);
910 
911 	if (lmbs_to_add == 0)
912 		return -EINVAL;
913 
914 	p = prop->value;
915 	num_lmbs = *p++;
916 	lmbs = (struct of_drconf_cell *)p;
917 	start_lmb_found = 0;
918 
919 	/* Navigate to drc_index */
920 	while (start_index < num_lmbs) {
921 		if (lmbs[start_index].drc_index == drc_index) {
922 			start_lmb_found = 1;
923 			break;
924 		}
925 
926 		start_index++;
927 	}
928 
929 	if (!start_lmb_found)
930 		return -EINVAL;
931 
932 	end_index = start_index + lmbs_to_add;
933 
934 	/* Validate that the LMBs in this range are not reserved */
935 	for (i = start_index; i < end_index; i++) {
936 		if (lmbs[i].flags & DRCONF_MEM_RESERVED)
937 			break;
938 
939 		lmbs_available++;
940 	}
941 
942 	if (lmbs_available < lmbs_to_add)
943 		return -EINVAL;
944 
945 	for (i = start_index; i < end_index; i++) {
946 		if (lmbs[i].flags & DRCONF_MEM_ASSIGNED)
947 			continue;
948 
949 		rc = dlpar_acquire_drc(lmbs[i].drc_index);
950 		if (rc)
951 			break;
952 
953 		rc = dlpar_add_lmb(&lmbs[i]);
954 		if (rc) {
955 			dlpar_release_drc(lmbs[i].drc_index);
956 			break;
957 		}
958 
959 		lmbs[i].reserved = 1;
960 	}
961 
962 	if (rc) {
963 		pr_err("Memory indexed-count-add failed, removing any added LMBs\n");
964 
965 		for (i = start_index; i < end_index; i++) {
966 			if (!lmbs[i].reserved)
967 				continue;
968 
969 			rc = dlpar_remove_lmb(&lmbs[i]);
970 			if (rc)
971 				pr_err("Failed to remove LMB, drc index %x\n",
972 				       be32_to_cpu(lmbs[i].drc_index));
973 			else
974 				dlpar_release_drc(lmbs[i].drc_index);
975 		}
976 		rc = -EINVAL;
977 	} else {
978 		for (i = start_index; i < end_index; i++) {
979 			if (!lmbs[i].reserved)
980 				continue;
981 
982 			pr_info("Memory at %llx (drc index %x) was hot-added\n",
983 				lmbs[i].base_addr, lmbs[i].drc_index);
984 			lmbs[i].reserved = 0;
985 		}
986 	}
987 
988 	return rc;
989 }
990 
991 int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
992 {
993 	struct device_node *dn;
994 	struct property *prop;
995 	u32 count, drc_index;
996 	int rc;
997 
998 	lock_device_hotplug();
999 
1000 	dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
1001 	if (!dn) {
1002 		rc = -EINVAL;
1003 		goto dlpar_memory_out;
1004 	}
1005 
1006 	prop = dlpar_clone_drconf_property(dn);
1007 	if (!prop) {
1008 		rc = -EINVAL;
1009 		goto dlpar_memory_out;
1010 	}
1011 
1012 	switch (hp_elog->action) {
1013 	case PSERIES_HP_ELOG_ACTION_ADD:
1014 		if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
1015 			count = hp_elog->_drc_u.drc_count;
1016 			rc = dlpar_memory_add_by_count(count, prop);
1017 		} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
1018 			drc_index = hp_elog->_drc_u.drc_index;
1019 			rc = dlpar_memory_add_by_index(drc_index, prop);
1020 		} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
1021 			count = hp_elog->_drc_u.ic.count;
1022 			drc_index = hp_elog->_drc_u.ic.index;
1023 			rc = dlpar_memory_add_by_ic(count, drc_index, prop);
1024 		} else {
1025 			rc = -EINVAL;
1026 		}
1027 
1028 		break;
1029 	case PSERIES_HP_ELOG_ACTION_REMOVE:
1030 		if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
1031 			count = hp_elog->_drc_u.drc_count;
1032 			rc = dlpar_memory_remove_by_count(count, prop);
1033 		} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
1034 			drc_index = hp_elog->_drc_u.drc_index;
1035 			rc = dlpar_memory_remove_by_index(drc_index, prop);
1036 		} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
1037 			count = hp_elog->_drc_u.ic.count;
1038 			drc_index = hp_elog->_drc_u.ic.index;
1039 			rc = dlpar_memory_remove_by_ic(count, drc_index, prop);
1040 		} else {
1041 			rc = -EINVAL;
1042 		}
1043 
1044 		break;
1045 	case PSERIES_HP_ELOG_ACTION_READD:
1046 		drc_index = hp_elog->_drc_u.drc_index;
1047 		rc = dlpar_memory_readd_by_index(drc_index, prop);
1048 		break;
1049 	default:
1050 		pr_err("Invalid action (%d) specified\n", hp_elog->action);
1051 		rc = -EINVAL;
1052 		break;
1053 	}
1054 
1055 	dlpar_free_property(prop);
1056 
1057 dlpar_memory_out:
1058 	of_node_put(dn);
1059 	unlock_device_hotplug();
1060 	return rc;
1061 }
1062 
1063 static int pseries_add_mem_node(struct device_node *np)
1064 {
1065 	const char *type;
1066 	const __be32 *regs;
1067 	unsigned long base;
1068 	unsigned int lmb_size;
1069 	int ret = -EINVAL;
1070 
1071 	/*
1072 	 * Check to see if we are actually adding memory
1073 	 */
1074 	type = of_get_property(np, "device_type", NULL);
1075 	if (type == NULL || strcmp(type, "memory") != 0)
1076 		return 0;
1077 
1078 	/*
1079 	 * Find the base and size of the memblock
1080 	 */
1081 	regs = of_get_property(np, "reg", NULL);
1082 	if (!regs)
1083 		return ret;
1084 
1085 	base = be64_to_cpu(*(unsigned long *)regs);
1086 	lmb_size = be32_to_cpu(regs[3]);
1087 
1088 	/*
1089 	 * Update memory region to represent the memory add
1090 	 */
1091 	ret = memblock_add(base, lmb_size);
1092 	return (ret < 0) ? -EINVAL : 0;
1093 }
1094 
1095 static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
1096 {
1097 	struct of_drconf_cell *new_drmem, *old_drmem;
1098 	unsigned long memblock_size;
1099 	u32 entries;
1100 	__be32 *p;
1101 	int i, rc = -EINVAL;
1102 
1103 	if (rtas_hp_event)
1104 		return 0;
1105 
1106 	memblock_size = pseries_memory_block_size();
1107 	if (!memblock_size)
1108 		return -EINVAL;
1109 
1110 	p = (__be32 *) pr->old_prop->value;
1111 	if (!p)
1112 		return -EINVAL;
1113 
1114 	/* The first int of the property is the number of lmb's described
1115 	 * by the property. This is followed by an array of of_drconf_cell
1116 	 * entries. Get the number of entries and skip to the array of
1117 	 * of_drconf_cell's.
1118 	 */
1119 	entries = be32_to_cpu(*p++);
1120 	old_drmem = (struct of_drconf_cell *)p;
1121 
1122 	p = (__be32 *)pr->prop->value;
1123 	p++;
1124 	new_drmem = (struct of_drconf_cell *)p;
1125 
1126 	for (i = 0; i < entries; i++) {
1127 		if ((be32_to_cpu(old_drmem[i].flags) & DRCONF_MEM_ASSIGNED) &&
1128 		    (!(be32_to_cpu(new_drmem[i].flags) & DRCONF_MEM_ASSIGNED))) {
1129 			rc = pseries_remove_memblock(
1130 				be64_to_cpu(old_drmem[i].base_addr),
1131 						     memblock_size);
1132 			break;
1133 		} else if ((!(be32_to_cpu(old_drmem[i].flags) &
1134 			    DRCONF_MEM_ASSIGNED)) &&
1135 			    (be32_to_cpu(new_drmem[i].flags) &
1136 			    DRCONF_MEM_ASSIGNED)) {
1137 			rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
1138 					  memblock_size);
1139 			rc = (rc < 0) ? -EINVAL : 0;
1140 			break;
1141 		}
1142 	}
1143 	return rc;
1144 }
1145 
1146 static int pseries_memory_notifier(struct notifier_block *nb,
1147 				   unsigned long action, void *data)
1148 {
1149 	struct of_reconfig_data *rd = data;
1150 	int err = 0;
1151 
1152 	switch (action) {
1153 	case OF_RECONFIG_ATTACH_NODE:
1154 		err = pseries_add_mem_node(rd->dn);
1155 		break;
1156 	case OF_RECONFIG_DETACH_NODE:
1157 		err = pseries_remove_mem_node(rd->dn);
1158 		break;
1159 	case OF_RECONFIG_UPDATE_PROPERTY:
1160 		if (!strcmp(rd->prop->name, "ibm,dynamic-memory"))
1161 			err = pseries_update_drconf_memory(rd);
1162 		break;
1163 	}
1164 	return notifier_from_errno(err);
1165 }
1166 
1167 static struct notifier_block pseries_mem_nb = {
1168 	.notifier_call = pseries_memory_notifier,
1169 };
1170 
1171 static int __init pseries_memory_hotplug_init(void)
1172 {
1173 	if (firmware_has_feature(FW_FEATURE_LPAR))
1174 		of_reconfig_notifier_register(&pseries_mem_nb);
1175 
1176 	return 0;
1177 }
1178 machine_device_initcall(pseries, pseries_memory_hotplug_init);
1179