Merge tag 'powerpc-5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux-2.6-microblaze.git] / arch / powerpc / platforms / pseries / hotplug-memory.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * pseries Memory Hotplug infrastructure.
4  *
5  * Copyright (C) 2008 Badari Pulavarty, IBM Corporation
6  */
7
8 #define pr_fmt(fmt)     "pseries-hotplug-mem: " fmt
9
10 #include <linux/of.h>
11 #include <linux/of_address.h>
12 #include <linux/memblock.h>
13 #include <linux/memory.h>
14 #include <linux/memory_hotplug.h>
15 #include <linux/slab.h>
16
17 #include <asm/firmware.h>
18 #include <asm/machdep.h>
19 #include <asm/prom.h>
20 #include <asm/sparsemem.h>
21 #include <asm/fadump.h>
22 #include <asm/drmem.h>
23 #include "pseries.h"
24
25 unsigned long pseries_memory_block_size(void)
26 {
27         struct device_node *np;
28         u64 memblock_size = MIN_MEMORY_BLOCK_SIZE;
29         struct resource r;
30
31         np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
32         if (np) {
33                 int len;
34                 int size_cells;
35                 const __be32 *prop;
36
37                 size_cells = of_n_size_cells(np);
38
39                 prop = of_get_property(np, "ibm,lmb-size", &len);
40                 if (prop && len >= size_cells * sizeof(__be32))
41                         memblock_size = of_read_number(prop, size_cells);
42                 of_node_put(np);
43
44         } else  if (machine_is(pseries)) {
45                 /* This fallback really only applies to pseries */
46                 unsigned int memzero_size = 0;
47
48                 np = of_find_node_by_path("/memory@0");
49                 if (np) {
50                         if (!of_address_to_resource(np, 0, &r))
51                                 memzero_size = resource_size(&r);
52                         of_node_put(np);
53                 }
54
55                 if (memzero_size) {
56                         /* We now know the size of memory@0, use this to find
57                          * the first memoryblock and get its size.
58                          */
59                         char buf[64];
60
61                         sprintf(buf, "/memory@%x", memzero_size);
62                         np = of_find_node_by_path(buf);
63                         if (np) {
64                                 if (!of_address_to_resource(np, 0, &r))
65                                         memblock_size = resource_size(&r);
66                                 of_node_put(np);
67                         }
68                 }
69         }
70         return memblock_size;
71 }
72
73 static void dlpar_free_property(struct property *prop)
74 {
75         kfree(prop->name);
76         kfree(prop->value);
77         kfree(prop);
78 }
79
80 static struct property *dlpar_clone_property(struct property *prop,
81                                              u32 prop_size)
82 {
83         struct property *new_prop;
84
85         new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
86         if (!new_prop)
87                 return NULL;
88
89         new_prop->name = kstrdup(prop->name, GFP_KERNEL);
90         new_prop->value = kzalloc(prop_size, GFP_KERNEL);
91         if (!new_prop->name || !new_prop->value) {
92                 dlpar_free_property(new_prop);
93                 return NULL;
94         }
95
96         memcpy(new_prop->value, prop->value, prop->length);
97         new_prop->length = prop_size;
98
99         of_property_set_flag(new_prop, OF_DYNAMIC);
100         return new_prop;
101 }
102
103 static bool find_aa_index(struct device_node *dr_node,
104                          struct property *ala_prop,
105                          const u32 *lmb_assoc, u32 *aa_index)
106 {
107         u32 *assoc_arrays, new_prop_size;
108         struct property *new_prop;
109         int aa_arrays, aa_array_entries, aa_array_sz;
110         int i, index;
111
112         /*
113          * The ibm,associativity-lookup-arrays property is defined to be
114          * a 32-bit value specifying the number of associativity arrays
115          * followed by a 32-bitvalue specifying the number of entries per
116          * array, followed by the associativity arrays.
117          */
118         assoc_arrays = ala_prop->value;
119
120         aa_arrays = be32_to_cpu(assoc_arrays[0]);
121         aa_array_entries = be32_to_cpu(assoc_arrays[1]);
122         aa_array_sz = aa_array_entries * sizeof(u32);
123
124         for (i = 0; i < aa_arrays; i++) {
125                 index = (i * aa_array_entries) + 2;
126
127                 if (memcmp(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz))
128                         continue;
129
130                 *aa_index = i;
131                 return true;
132         }
133
134         new_prop_size = ala_prop->length + aa_array_sz;
135         new_prop = dlpar_clone_property(ala_prop, new_prop_size);
136         if (!new_prop)
137                 return false;
138
139         assoc_arrays = new_prop->value;
140
141         /* increment the number of entries in the lookup array */
142         assoc_arrays[0] = cpu_to_be32(aa_arrays + 1);
143
144         /* copy the new associativity into the lookup array */
145         index = aa_arrays * aa_array_entries + 2;
146         memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz);
147
148         of_update_property(dr_node, new_prop);
149
150         /*
151          * The associativity lookup array index for this lmb is
152          * number of entries - 1 since we added its associativity
153          * to the end of the lookup array.
154          */
155         *aa_index = be32_to_cpu(assoc_arrays[0]) - 1;
156         return true;
157 }
158
159 static int update_lmb_associativity_index(struct drmem_lmb *lmb)
160 {
161         struct device_node *parent, *lmb_node, *dr_node;
162         struct property *ala_prop;
163         const u32 *lmb_assoc;
164         u32 aa_index;
165         bool found;
166
167         parent = of_find_node_by_path("/");
168         if (!parent)
169                 return -ENODEV;
170
171         lmb_node = dlpar_configure_connector(cpu_to_be32(lmb->drc_index),
172                                              parent);
173         of_node_put(parent);
174         if (!lmb_node)
175                 return -EINVAL;
176
177         lmb_assoc = of_get_property(lmb_node, "ibm,associativity", NULL);
178         if (!lmb_assoc) {
179                 dlpar_free_cc_nodes(lmb_node);
180                 return -ENODEV;
181         }
182
183         update_numa_distance(lmb_node);
184
185         dr_node = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
186         if (!dr_node) {
187                 dlpar_free_cc_nodes(lmb_node);
188                 return -ENODEV;
189         }
190
191         ala_prop = of_find_property(dr_node, "ibm,associativity-lookup-arrays",
192                                     NULL);
193         if (!ala_prop) {
194                 of_node_put(dr_node);
195                 dlpar_free_cc_nodes(lmb_node);
196                 return -ENODEV;
197         }
198
199         found = find_aa_index(dr_node, ala_prop, lmb_assoc, &aa_index);
200
201         of_node_put(dr_node);
202         dlpar_free_cc_nodes(lmb_node);
203
204         if (!found) {
205                 pr_err("Could not find LMB associativity\n");
206                 return -1;
207         }
208
209         lmb->aa_index = aa_index;
210         return 0;
211 }
212
213 static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb)
214 {
215         unsigned long section_nr;
216         struct memory_block *mem_block;
217
218         section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
219
220         mem_block = find_memory_block(section_nr);
221         return mem_block;
222 }
223
224 static int get_lmb_range(u32 drc_index, int n_lmbs,
225                          struct drmem_lmb **start_lmb,
226                          struct drmem_lmb **end_lmb)
227 {
228         struct drmem_lmb *lmb, *start, *end;
229         struct drmem_lmb *limit;
230
231         start = NULL;
232         for_each_drmem_lmb(lmb) {
233                 if (lmb->drc_index == drc_index) {
234                         start = lmb;
235                         break;
236                 }
237         }
238
239         if (!start)
240                 return -EINVAL;
241
242         end = &start[n_lmbs];
243
244         limit = &drmem_info->lmbs[drmem_info->n_lmbs];
245         if (end > limit)
246                 return -EINVAL;
247
248         *start_lmb = start;
249         *end_lmb = end;
250         return 0;
251 }
252
253 static int dlpar_change_lmb_state(struct drmem_lmb *lmb, bool online)
254 {
255         struct memory_block *mem_block;
256         int rc;
257
258         mem_block = lmb_to_memblock(lmb);
259         if (!mem_block)
260                 return -EINVAL;
261
262         if (online && mem_block->dev.offline)
263                 rc = device_online(&mem_block->dev);
264         else if (!online && !mem_block->dev.offline)
265                 rc = device_offline(&mem_block->dev);
266         else
267                 rc = 0;
268
269         put_device(&mem_block->dev);
270
271         return rc;
272 }
273
274 static int dlpar_online_lmb(struct drmem_lmb *lmb)
275 {
276         return dlpar_change_lmb_state(lmb, true);
277 }
278
279 #ifdef CONFIG_MEMORY_HOTREMOVE
280 static int dlpar_offline_lmb(struct drmem_lmb *lmb)
281 {
282         return dlpar_change_lmb_state(lmb, false);
283 }
284
285 static int pseries_remove_memblock(unsigned long base, unsigned long memblock_size)
286 {
287         unsigned long block_sz, start_pfn;
288         int sections_per_block;
289         int i, nid;
290
291         start_pfn = base >> PAGE_SHIFT;
292
293         lock_device_hotplug();
294
295         if (!pfn_valid(start_pfn))
296                 goto out;
297
298         block_sz = pseries_memory_block_size();
299         sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
300         nid = memory_add_physaddr_to_nid(base);
301
302         for (i = 0; i < sections_per_block; i++) {
303                 __remove_memory(nid, base, MIN_MEMORY_BLOCK_SIZE);
304                 base += MIN_MEMORY_BLOCK_SIZE;
305         }
306
307 out:
308         /* Update memory regions for memory remove */
309         memblock_remove(base, memblock_size);
310         unlock_device_hotplug();
311         return 0;
312 }
313
314 static int pseries_remove_mem_node(struct device_node *np)
315 {
316         const __be32 *prop;
317         unsigned long base;
318         unsigned long lmb_size;
319         int ret = -EINVAL;
320         int addr_cells, size_cells;
321
322         /*
323          * Check to see if we are actually removing memory
324          */
325         if (!of_node_is_type(np, "memory"))
326                 return 0;
327
328         /*
329          * Find the base address and size of the memblock
330          */
331         prop = of_get_property(np, "reg", NULL);
332         if (!prop)
333                 return ret;
334
335         addr_cells = of_n_addr_cells(np);
336         size_cells = of_n_size_cells(np);
337
338         /*
339          * "reg" property represents (addr,size) tuple.
340          */
341         base = of_read_number(prop, addr_cells);
342         prop += addr_cells;
343         lmb_size = of_read_number(prop, size_cells);
344
345         pseries_remove_memblock(base, lmb_size);
346         return 0;
347 }
348
349 static bool lmb_is_removable(struct drmem_lmb *lmb)
350 {
351         if ((lmb->flags & DRCONF_MEM_RESERVED) ||
352                 !(lmb->flags & DRCONF_MEM_ASSIGNED))
353                 return false;
354
355 #ifdef CONFIG_FA_DUMP
356         /*
357          * Don't hot-remove memory that falls in fadump boot memory area
358          * and memory that is reserved for capturing old kernel memory.
359          */
360         if (is_fadump_memory_area(lmb->base_addr, memory_block_size_bytes()))
361                 return false;
362 #endif
363         /* device_offline() will determine if we can actually remove this lmb */
364         return true;
365 }
366
367 static int dlpar_add_lmb(struct drmem_lmb *);
368
369 static int dlpar_remove_lmb(struct drmem_lmb *lmb)
370 {
371         struct memory_block *mem_block;
372         unsigned long block_sz;
373         int rc;
374
375         if (!lmb_is_removable(lmb))
376                 return -EINVAL;
377
378         mem_block = lmb_to_memblock(lmb);
379         if (mem_block == NULL)
380                 return -EINVAL;
381
382         rc = dlpar_offline_lmb(lmb);
383         if (rc) {
384                 put_device(&mem_block->dev);
385                 return rc;
386         }
387
388         block_sz = pseries_memory_block_size();
389
390         __remove_memory(mem_block->nid, lmb->base_addr, block_sz);
391         put_device(&mem_block->dev);
392
393         /* Update memory regions for memory remove */
394         memblock_remove(lmb->base_addr, block_sz);
395
396         invalidate_lmb_associativity_index(lmb);
397         lmb->flags &= ~DRCONF_MEM_ASSIGNED;
398
399         return 0;
400 }
401
402 static int dlpar_memory_remove_by_count(u32 lmbs_to_remove)
403 {
404         struct drmem_lmb *lmb;
405         int lmbs_reserved = 0;
406         int lmbs_available = 0;
407         int rc;
408
409         pr_info("Attempting to hot-remove %d LMB(s)\n", lmbs_to_remove);
410
411         if (lmbs_to_remove == 0)
412                 return -EINVAL;
413
414         /* Validate that there are enough LMBs to satisfy the request */
415         for_each_drmem_lmb(lmb) {
416                 if (lmb_is_removable(lmb))
417                         lmbs_available++;
418
419                 if (lmbs_available == lmbs_to_remove)
420                         break;
421         }
422
423         if (lmbs_available < lmbs_to_remove) {
424                 pr_info("Not enough LMBs available (%d of %d) to satisfy request\n",
425                         lmbs_available, lmbs_to_remove);
426                 return -EINVAL;
427         }
428
429         for_each_drmem_lmb(lmb) {
430                 rc = dlpar_remove_lmb(lmb);
431                 if (rc)
432                         continue;
433
434                 /* Mark this lmb so we can add it later if all of the
435                  * requested LMBs cannot be removed.
436                  */
437                 drmem_mark_lmb_reserved(lmb);
438
439                 lmbs_reserved++;
440                 if (lmbs_reserved == lmbs_to_remove)
441                         break;
442         }
443
444         if (lmbs_reserved != lmbs_to_remove) {
445                 pr_err("Memory hot-remove failed, adding LMB's back\n");
446
447                 for_each_drmem_lmb(lmb) {
448                         if (!drmem_lmb_reserved(lmb))
449                                 continue;
450
451                         rc = dlpar_add_lmb(lmb);
452                         if (rc)
453                                 pr_err("Failed to add LMB back, drc index %x\n",
454                                        lmb->drc_index);
455
456                         drmem_remove_lmb_reservation(lmb);
457
458                         lmbs_reserved--;
459                         if (lmbs_reserved == 0)
460                                 break;
461                 }
462
463                 rc = -EINVAL;
464         } else {
465                 for_each_drmem_lmb(lmb) {
466                         if (!drmem_lmb_reserved(lmb))
467                                 continue;
468
469                         dlpar_release_drc(lmb->drc_index);
470                         pr_info("Memory at %llx was hot-removed\n",
471                                 lmb->base_addr);
472
473                         drmem_remove_lmb_reservation(lmb);
474
475                         lmbs_reserved--;
476                         if (lmbs_reserved == 0)
477                                 break;
478                 }
479                 rc = 0;
480         }
481
482         return rc;
483 }
484
485 static int dlpar_memory_remove_by_index(u32 drc_index)
486 {
487         struct drmem_lmb *lmb;
488         int lmb_found;
489         int rc;
490
491         pr_debug("Attempting to hot-remove LMB, drc index %x\n", drc_index);
492
493         lmb_found = 0;
494         for_each_drmem_lmb(lmb) {
495                 if (lmb->drc_index == drc_index) {
496                         lmb_found = 1;
497                         rc = dlpar_remove_lmb(lmb);
498                         if (!rc)
499                                 dlpar_release_drc(lmb->drc_index);
500
501                         break;
502                 }
503         }
504
505         if (!lmb_found)
506                 rc = -EINVAL;
507
508         if (rc)
509                 pr_debug("Failed to hot-remove memory at %llx\n",
510                          lmb->base_addr);
511         else
512                 pr_debug("Memory at %llx was hot-removed\n", lmb->base_addr);
513
514         return rc;
515 }
516
517 static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index)
518 {
519         struct drmem_lmb *lmb, *start_lmb, *end_lmb;
520         int rc;
521
522         pr_info("Attempting to hot-remove %u LMB(s) at %x\n",
523                 lmbs_to_remove, drc_index);
524
525         if (lmbs_to_remove == 0)
526                 return -EINVAL;
527
528         rc = get_lmb_range(drc_index, lmbs_to_remove, &start_lmb, &end_lmb);
529         if (rc)
530                 return -EINVAL;
531
532         /*
533          * Validate that all LMBs in range are not reserved. Note that it
534          * is ok if they are !ASSIGNED since our goal here is to remove the
535          * LMB range, regardless of whether some LMBs were already removed
536          * by any other reason.
537          *
538          * This is a contrast to what is done in remove_by_count() where we
539          * check for both RESERVED and !ASSIGNED (via lmb_is_removable()),
540          * because we want to remove a fixed amount of LMBs in that function.
541          */
542         for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
543                 if (lmb->flags & DRCONF_MEM_RESERVED) {
544                         pr_err("Memory at %llx (drc index %x) is reserved\n",
545                                 lmb->base_addr, lmb->drc_index);
546                         return -EINVAL;
547                 }
548         }
549
550         for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
551                 /*
552                  * dlpar_remove_lmb() will error out if the LMB is already
553                  * !ASSIGNED, but this case is a no-op for us.
554                  */
555                 if (!(lmb->flags & DRCONF_MEM_ASSIGNED))
556                         continue;
557
558                 rc = dlpar_remove_lmb(lmb);
559                 if (rc)
560                         break;
561
562                 drmem_mark_lmb_reserved(lmb);
563         }
564
565         if (rc) {
566                 pr_err("Memory indexed-count-remove failed, adding any removed LMBs\n");
567
568
569                 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
570                         if (!drmem_lmb_reserved(lmb))
571                                 continue;
572
573                         /*
574                          * Setting the isolation state of an UNISOLATED/CONFIGURED
575                          * device to UNISOLATE is a no-op, but the hypervisor can
576                          * use it as a hint that the LMB removal failed.
577                          */
578                         dlpar_unisolate_drc(lmb->drc_index);
579
580                         rc = dlpar_add_lmb(lmb);
581                         if (rc)
582                                 pr_err("Failed to add LMB, drc index %x\n",
583                                        lmb->drc_index);
584
585                         drmem_remove_lmb_reservation(lmb);
586                 }
587                 rc = -EINVAL;
588         } else {
589                 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
590                         if (!drmem_lmb_reserved(lmb))
591                                 continue;
592
593                         dlpar_release_drc(lmb->drc_index);
594                         pr_info("Memory at %llx (drc index %x) was hot-removed\n",
595                                 lmb->base_addr, lmb->drc_index);
596
597                         drmem_remove_lmb_reservation(lmb);
598                 }
599         }
600
601         return rc;
602 }
603
604 #else
605 static inline int pseries_remove_memblock(unsigned long base,
606                                           unsigned long memblock_size)
607 {
608         return -EOPNOTSUPP;
609 }
610 static inline int pseries_remove_mem_node(struct device_node *np)
611 {
612         return 0;
613 }
614 static int dlpar_remove_lmb(struct drmem_lmb *lmb)
615 {
616         return -EOPNOTSUPP;
617 }
618 static int dlpar_memory_remove_by_count(u32 lmbs_to_remove)
619 {
620         return -EOPNOTSUPP;
621 }
622 static int dlpar_memory_remove_by_index(u32 drc_index)
623 {
624         return -EOPNOTSUPP;
625 }
626
627 static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index)
628 {
629         return -EOPNOTSUPP;
630 }
631 #endif /* CONFIG_MEMORY_HOTREMOVE */
632
633 static int dlpar_add_lmb(struct drmem_lmb *lmb)
634 {
635         unsigned long block_sz;
636         int nid, rc;
637
638         if (lmb->flags & DRCONF_MEM_ASSIGNED)
639                 return -EINVAL;
640
641         rc = update_lmb_associativity_index(lmb);
642         if (rc) {
643                 dlpar_release_drc(lmb->drc_index);
644                 return rc;
645         }
646
647         block_sz = memory_block_size_bytes();
648
649         /* Find the node id for this LMB.  Fake one if necessary. */
650         nid = of_drconf_to_nid_single(lmb);
651         if (nid < 0 || !node_possible(nid))
652                 nid = first_online_node;
653
654         /* Add the memory */
655         rc = __add_memory(nid, lmb->base_addr, block_sz, MHP_NONE);
656         if (rc) {
657                 invalidate_lmb_associativity_index(lmb);
658                 return rc;
659         }
660
661         rc = dlpar_online_lmb(lmb);
662         if (rc) {
663                 __remove_memory(nid, lmb->base_addr, block_sz);
664                 invalidate_lmb_associativity_index(lmb);
665         } else {
666                 lmb->flags |= DRCONF_MEM_ASSIGNED;
667         }
668
669         return rc;
670 }
671
672 static int dlpar_memory_add_by_count(u32 lmbs_to_add)
673 {
674         struct drmem_lmb *lmb;
675         int lmbs_available = 0;
676         int lmbs_reserved = 0;
677         int rc;
678
679         pr_info("Attempting to hot-add %d LMB(s)\n", lmbs_to_add);
680
681         if (lmbs_to_add == 0)
682                 return -EINVAL;
683
684         /* Validate that there are enough LMBs to satisfy the request */
685         for_each_drmem_lmb(lmb) {
686                 if (lmb->flags & DRCONF_MEM_RESERVED)
687                         continue;
688
689                 if (!(lmb->flags & DRCONF_MEM_ASSIGNED))
690                         lmbs_available++;
691
692                 if (lmbs_available == lmbs_to_add)
693                         break;
694         }
695
696         if (lmbs_available < lmbs_to_add)
697                 return -EINVAL;
698
699         for_each_drmem_lmb(lmb) {
700                 if (lmb->flags & DRCONF_MEM_ASSIGNED)
701                         continue;
702
703                 rc = dlpar_acquire_drc(lmb->drc_index);
704                 if (rc)
705                         continue;
706
707                 rc = dlpar_add_lmb(lmb);
708                 if (rc) {
709                         dlpar_release_drc(lmb->drc_index);
710                         continue;
711                 }
712
713                 /* Mark this lmb so we can remove it later if all of the
714                  * requested LMBs cannot be added.
715                  */
716                 drmem_mark_lmb_reserved(lmb);
717                 lmbs_reserved++;
718                 if (lmbs_reserved == lmbs_to_add)
719                         break;
720         }
721
722         if (lmbs_reserved != lmbs_to_add) {
723                 pr_err("Memory hot-add failed, removing any added LMBs\n");
724
725                 for_each_drmem_lmb(lmb) {
726                         if (!drmem_lmb_reserved(lmb))
727                                 continue;
728
729                         rc = dlpar_remove_lmb(lmb);
730                         if (rc)
731                                 pr_err("Failed to remove LMB, drc index %x\n",
732                                        lmb->drc_index);
733                         else
734                                 dlpar_release_drc(lmb->drc_index);
735
736                         drmem_remove_lmb_reservation(lmb);
737                         lmbs_reserved--;
738
739                         if (lmbs_reserved == 0)
740                                 break;
741                 }
742                 rc = -EINVAL;
743         } else {
744                 for_each_drmem_lmb(lmb) {
745                         if (!drmem_lmb_reserved(lmb))
746                                 continue;
747
748                         pr_debug("Memory at %llx (drc index %x) was hot-added\n",
749                                  lmb->base_addr, lmb->drc_index);
750                         drmem_remove_lmb_reservation(lmb);
751                         lmbs_reserved--;
752
753                         if (lmbs_reserved == 0)
754                                 break;
755                 }
756                 rc = 0;
757         }
758
759         return rc;
760 }
761
762 static int dlpar_memory_add_by_index(u32 drc_index)
763 {
764         struct drmem_lmb *lmb;
765         int rc, lmb_found;
766
767         pr_info("Attempting to hot-add LMB, drc index %x\n", drc_index);
768
769         lmb_found = 0;
770         for_each_drmem_lmb(lmb) {
771                 if (lmb->drc_index == drc_index) {
772                         lmb_found = 1;
773                         rc = dlpar_acquire_drc(lmb->drc_index);
774                         if (!rc) {
775                                 rc = dlpar_add_lmb(lmb);
776                                 if (rc)
777                                         dlpar_release_drc(lmb->drc_index);
778                         }
779
780                         break;
781                 }
782         }
783
784         if (!lmb_found)
785                 rc = -EINVAL;
786
787         if (rc)
788                 pr_info("Failed to hot-add memory, drc index %x\n", drc_index);
789         else
790                 pr_info("Memory at %llx (drc index %x) was hot-added\n",
791                         lmb->base_addr, drc_index);
792
793         return rc;
794 }
795
796 static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index)
797 {
798         struct drmem_lmb *lmb, *start_lmb, *end_lmb;
799         int rc;
800
801         pr_info("Attempting to hot-add %u LMB(s) at index %x\n",
802                 lmbs_to_add, drc_index);
803
804         if (lmbs_to_add == 0)
805                 return -EINVAL;
806
807         rc = get_lmb_range(drc_index, lmbs_to_add, &start_lmb, &end_lmb);
808         if (rc)
809                 return -EINVAL;
810
811         /* Validate that the LMBs in this range are not reserved */
812         for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
813                 /* Fail immediately if the whole range can't be hot-added */
814                 if (lmb->flags & DRCONF_MEM_RESERVED) {
815                         pr_err("Memory at %llx (drc index %x) is reserved\n",
816                                         lmb->base_addr, lmb->drc_index);
817                         return -EINVAL;
818                 }
819         }
820
821         for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
822                 if (lmb->flags & DRCONF_MEM_ASSIGNED)
823                         continue;
824
825                 rc = dlpar_acquire_drc(lmb->drc_index);
826                 if (rc)
827                         break;
828
829                 rc = dlpar_add_lmb(lmb);
830                 if (rc) {
831                         dlpar_release_drc(lmb->drc_index);
832                         break;
833                 }
834
835                 drmem_mark_lmb_reserved(lmb);
836         }
837
838         if (rc) {
839                 pr_err("Memory indexed-count-add failed, removing any added LMBs\n");
840
841                 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
842                         if (!drmem_lmb_reserved(lmb))
843                                 continue;
844
845                         rc = dlpar_remove_lmb(lmb);
846                         if (rc)
847                                 pr_err("Failed to remove LMB, drc index %x\n",
848                                        lmb->drc_index);
849                         else
850                                 dlpar_release_drc(lmb->drc_index);
851
852                         drmem_remove_lmb_reservation(lmb);
853                 }
854                 rc = -EINVAL;
855         } else {
856                 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
857                         if (!drmem_lmb_reserved(lmb))
858                                 continue;
859
860                         pr_info("Memory at %llx (drc index %x) was hot-added\n",
861                                 lmb->base_addr, lmb->drc_index);
862                         drmem_remove_lmb_reservation(lmb);
863                 }
864         }
865
866         return rc;
867 }
868
869 int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
870 {
871         u32 count, drc_index;
872         int rc;
873
874         lock_device_hotplug();
875
876         switch (hp_elog->action) {
877         case PSERIES_HP_ELOG_ACTION_ADD:
878                 switch (hp_elog->id_type) {
879                 case PSERIES_HP_ELOG_ID_DRC_COUNT:
880                         count = hp_elog->_drc_u.drc_count;
881                         rc = dlpar_memory_add_by_count(count);
882                         break;
883                 case PSERIES_HP_ELOG_ID_DRC_INDEX:
884                         drc_index = hp_elog->_drc_u.drc_index;
885                         rc = dlpar_memory_add_by_index(drc_index);
886                         break;
887                 case PSERIES_HP_ELOG_ID_DRC_IC:
888                         count = hp_elog->_drc_u.ic.count;
889                         drc_index = hp_elog->_drc_u.ic.index;
890                         rc = dlpar_memory_add_by_ic(count, drc_index);
891                         break;
892                 default:
893                         rc = -EINVAL;
894                         break;
895                 }
896
897                 break;
898         case PSERIES_HP_ELOG_ACTION_REMOVE:
899                 switch (hp_elog->id_type) {
900                 case PSERIES_HP_ELOG_ID_DRC_COUNT:
901                         count = hp_elog->_drc_u.drc_count;
902                         rc = dlpar_memory_remove_by_count(count);
903                         break;
904                 case PSERIES_HP_ELOG_ID_DRC_INDEX:
905                         drc_index = hp_elog->_drc_u.drc_index;
906                         rc = dlpar_memory_remove_by_index(drc_index);
907                         break;
908                 case PSERIES_HP_ELOG_ID_DRC_IC:
909                         count = hp_elog->_drc_u.ic.count;
910                         drc_index = hp_elog->_drc_u.ic.index;
911                         rc = dlpar_memory_remove_by_ic(count, drc_index);
912                         break;
913                 default:
914                         rc = -EINVAL;
915                         break;
916                 }
917
918                 break;
919         default:
920                 pr_err("Invalid action (%d) specified\n", hp_elog->action);
921                 rc = -EINVAL;
922                 break;
923         }
924
925         if (!rc)
926                 rc = drmem_update_dt();
927
928         unlock_device_hotplug();
929         return rc;
930 }
931
932 static int pseries_add_mem_node(struct device_node *np)
933 {
934         const __be32 *prop;
935         unsigned long base;
936         unsigned long lmb_size;
937         int ret = -EINVAL;
938         int addr_cells, size_cells;
939
940         /*
941          * Check to see if we are actually adding memory
942          */
943         if (!of_node_is_type(np, "memory"))
944                 return 0;
945
946         /*
947          * Find the base and size of the memblock
948          */
949         prop = of_get_property(np, "reg", NULL);
950         if (!prop)
951                 return ret;
952
953         addr_cells = of_n_addr_cells(np);
954         size_cells = of_n_size_cells(np);
955         /*
956          * "reg" property represents (addr,size) tuple.
957          */
958         base = of_read_number(prop, addr_cells);
959         prop += addr_cells;
960         lmb_size = of_read_number(prop, size_cells);
961
962         /*
963          * Update memory region to represent the memory add
964          */
965         ret = memblock_add(base, lmb_size);
966         return (ret < 0) ? -EINVAL : 0;
967 }
968
969 static int pseries_memory_notifier(struct notifier_block *nb,
970                                    unsigned long action, void *data)
971 {
972         struct of_reconfig_data *rd = data;
973         int err = 0;
974
975         switch (action) {
976         case OF_RECONFIG_ATTACH_NODE:
977                 err = pseries_add_mem_node(rd->dn);
978                 break;
979         case OF_RECONFIG_DETACH_NODE:
980                 err = pseries_remove_mem_node(rd->dn);
981                 break;
982         case OF_RECONFIG_UPDATE_PROPERTY:
983                 if (!strcmp(rd->dn->name,
984                             "ibm,dynamic-reconfiguration-memory"))
985                         drmem_update_lmbs(rd->prop);
986         }
987         return notifier_from_errno(err);
988 }
989
990 static struct notifier_block pseries_mem_nb = {
991         .notifier_call = pseries_memory_notifier,
992 };
993
994 static int __init pseries_memory_hotplug_init(void)
995 {
996         if (firmware_has_feature(FW_FEATURE_LPAR))
997                 of_reconfig_notifier_register(&pseries_mem_nb);
998
999         return 0;
1000 }
1001 machine_device_initcall(pseries, pseries_memory_hotplug_init);