Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / powerpc / platforms / pseries / hotplug-memory.c
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_drconf_property(struct property *prop)
73 {
74         kfree(prop->name);
75         kfree(prop->value);
76         kfree(prop);
77 }
78
79 static struct property *dlpar_clone_drconf_property(struct device_node *dn)
80 {
81         struct property *prop, *new_prop;
82         struct of_drconf_cell *lmbs;
83         u32 num_lmbs, *p;
84         int i;
85
86         prop = of_find_property(dn, "ibm,dynamic-memory", NULL);
87         if (!prop)
88                 return NULL;
89
90         new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
91         if (!new_prop)
92                 return NULL;
93
94         new_prop->name = kstrdup(prop->name, GFP_KERNEL);
95         new_prop->value = kmalloc(prop->length, GFP_KERNEL);
96         if (!new_prop->name || !new_prop->value) {
97                 dlpar_free_drconf_property(new_prop);
98                 return NULL;
99         }
100
101         memcpy(new_prop->value, prop->value, prop->length);
102         new_prop->length = prop->length;
103
104         /* Convert the property to cpu endian-ness */
105         p = new_prop->value;
106         *p = be32_to_cpu(*p);
107
108         num_lmbs = *p++;
109         lmbs = (struct of_drconf_cell *)p;
110
111         for (i = 0; i < num_lmbs; i++) {
112                 lmbs[i].base_addr = be64_to_cpu(lmbs[i].base_addr);
113                 lmbs[i].drc_index = be32_to_cpu(lmbs[i].drc_index);
114                 lmbs[i].flags = be32_to_cpu(lmbs[i].flags);
115         }
116
117         return new_prop;
118 }
119
120 static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
121 {
122         unsigned long section_nr;
123         struct mem_section *mem_sect;
124         struct memory_block *mem_block;
125
126         section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
127         mem_sect = __nr_to_section(section_nr);
128
129         mem_block = find_memory_block(mem_sect);
130         return mem_block;
131 }
132
133 #ifdef CONFIG_MEMORY_HOTREMOVE
134 static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
135 {
136         unsigned long block_sz, start_pfn;
137         int sections_per_block;
138         int i, nid;
139
140         start_pfn = base >> PAGE_SHIFT;
141
142         lock_device_hotplug();
143
144         if (!pfn_valid(start_pfn))
145                 goto out;
146
147         block_sz = pseries_memory_block_size();
148         sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
149         nid = memory_add_physaddr_to_nid(base);
150
151         for (i = 0; i < sections_per_block; i++) {
152                 remove_memory(nid, base, MIN_MEMORY_BLOCK_SIZE);
153                 base += MIN_MEMORY_BLOCK_SIZE;
154         }
155
156 out:
157         /* Update memory regions for memory remove */
158         memblock_remove(base, memblock_size);
159         unlock_device_hotplug();
160         return 0;
161 }
162
163 static int pseries_remove_mem_node(struct device_node *np)
164 {
165         const char *type;
166         const __be32 *regs;
167         unsigned long base;
168         unsigned int lmb_size;
169         int ret = -EINVAL;
170
171         /*
172          * Check to see if we are actually removing memory
173          */
174         type = of_get_property(np, "device_type", NULL);
175         if (type == NULL || strcmp(type, "memory") != 0)
176                 return 0;
177
178         /*
179          * Find the base address and size of the memblock
180          */
181         regs = of_get_property(np, "reg", NULL);
182         if (!regs)
183                 return ret;
184
185         base = be64_to_cpu(*(unsigned long *)regs);
186         lmb_size = be32_to_cpu(regs[3]);
187
188         pseries_remove_memblock(base, lmb_size);
189         return 0;
190 }
191
192 static bool lmb_is_removable(struct of_drconf_cell *lmb)
193 {
194         int i, scns_per_block;
195         int rc = 1;
196         unsigned long pfn, block_sz;
197         u64 phys_addr;
198
199         if (!(lmb->flags & DRCONF_MEM_ASSIGNED))
200                 return false;
201
202         block_sz = memory_block_size_bytes();
203         scns_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
204         phys_addr = lmb->base_addr;
205
206         for (i = 0; i < scns_per_block; i++) {
207                 pfn = PFN_DOWN(phys_addr);
208                 if (!pfn_present(pfn))
209                         continue;
210
211                 rc &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
212                 phys_addr += MIN_MEMORY_BLOCK_SIZE;
213         }
214
215         return rc ? true : false;
216 }
217
218 static int dlpar_add_lmb(struct of_drconf_cell *);
219
220 static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
221 {
222         struct memory_block *mem_block;
223         unsigned long block_sz;
224         int nid, rc;
225
226         if (!lmb_is_removable(lmb))
227                 return -EINVAL;
228
229         mem_block = lmb_to_memblock(lmb);
230         if (!mem_block)
231                 return -EINVAL;
232
233         rc = device_offline(&mem_block->dev);
234         put_device(&mem_block->dev);
235         if (rc)
236                 return rc;
237
238         block_sz = pseries_memory_block_size();
239         nid = memory_add_physaddr_to_nid(lmb->base_addr);
240
241         remove_memory(nid, lmb->base_addr, block_sz);
242
243         /* Update memory regions for memory remove */
244         memblock_remove(lmb->base_addr, block_sz);
245
246         dlpar_release_drc(lmb->drc_index);
247
248         lmb->flags &= ~DRCONF_MEM_ASSIGNED;
249         return 0;
250 }
251
252 static int dlpar_memory_remove_by_count(u32 lmbs_to_remove,
253                                         struct property *prop)
254 {
255         struct of_drconf_cell *lmbs;
256         int lmbs_removed = 0;
257         int lmbs_available = 0;
258         u32 num_lmbs, *p;
259         int i, rc;
260
261         pr_info("Attempting to hot-remove %d LMB(s)\n", lmbs_to_remove);
262
263         if (lmbs_to_remove == 0)
264                 return -EINVAL;
265
266         p = prop->value;
267         num_lmbs = *p++;
268         lmbs = (struct of_drconf_cell *)p;
269
270         /* Validate that there are enough LMBs to satisfy the request */
271         for (i = 0; i < num_lmbs; i++) {
272                 if (lmbs[i].flags & DRCONF_MEM_ASSIGNED)
273                         lmbs_available++;
274         }
275
276         if (lmbs_available < lmbs_to_remove)
277                 return -EINVAL;
278
279         for (i = 0; i < num_lmbs && lmbs_removed < lmbs_to_remove; i++) {
280                 rc = dlpar_remove_lmb(&lmbs[i]);
281                 if (rc)
282                         continue;
283
284                 lmbs_removed++;
285
286                 /* Mark this lmb so we can add it later if all of the
287                  * requested LMBs cannot be removed.
288                  */
289                 lmbs[i].reserved = 1;
290         }
291
292         if (lmbs_removed != lmbs_to_remove) {
293                 pr_err("Memory hot-remove failed, adding LMB's back\n");
294
295                 for (i = 0; i < num_lmbs; i++) {
296                         if (!lmbs[i].reserved)
297                                 continue;
298
299                         rc = dlpar_add_lmb(&lmbs[i]);
300                         if (rc)
301                                 pr_err("Failed to add LMB back, drc index %x\n",
302                                        lmbs[i].drc_index);
303
304                         lmbs[i].reserved = 0;
305                 }
306
307                 rc = -EINVAL;
308         } else {
309                 for (i = 0; i < num_lmbs; i++) {
310                         if (!lmbs[i].reserved)
311                                 continue;
312
313                         pr_info("Memory at %llx was hot-removed\n",
314                                 lmbs[i].base_addr);
315
316                         lmbs[i].reserved = 0;
317                 }
318                 rc = 0;
319         }
320
321         return rc;
322 }
323
324 static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
325 {
326         struct of_drconf_cell *lmbs;
327         u32 num_lmbs, *p;
328         int lmb_found;
329         int i, rc;
330
331         pr_info("Attempting to hot-remove LMB, drc index %x\n", drc_index);
332
333         p = prop->value;
334         num_lmbs = *p++;
335         lmbs = (struct of_drconf_cell *)p;
336
337         lmb_found = 0;
338         for (i = 0; i < num_lmbs; i++) {
339                 if (lmbs[i].drc_index == drc_index) {
340                         lmb_found = 1;
341                         rc = dlpar_remove_lmb(&lmbs[i]);
342                         break;
343                 }
344         }
345
346         if (!lmb_found)
347                 rc = -EINVAL;
348
349         if (rc)
350                 pr_info("Failed to hot-remove memory at %llx\n",
351                         lmbs[i].base_addr);
352         else
353                 pr_info("Memory at %llx was hot-removed\n", lmbs[i].base_addr);
354
355         return rc;
356 }
357
358 #else
359 static inline int pseries_remove_memblock(unsigned long base,
360                                           unsigned int memblock_size)
361 {
362         return -EOPNOTSUPP;
363 }
364 static inline int pseries_remove_mem_node(struct device_node *np)
365 {
366         return 0;
367 }
368 static inline int dlpar_memory_remove(struct pseries_hp_errorlog *hp_elog)
369 {
370         return -EOPNOTSUPP;
371 }
372 static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
373 {
374         return -EOPNOTSUPP;
375 }
376 static int dlpar_memory_remove_by_count(u32 lmbs_to_remove,
377                                         struct property *prop)
378 {
379         return -EOPNOTSUPP;
380 }
381 static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
382 {
383         return -EOPNOTSUPP;
384 }
385
386 #endif /* CONFIG_MEMORY_HOTREMOVE */
387
388 static int dlpar_add_lmb(struct of_drconf_cell *lmb)
389 {
390         struct memory_block *mem_block;
391         unsigned long block_sz;
392         int nid, rc;
393
394         if (lmb->flags & DRCONF_MEM_ASSIGNED)
395                 return -EINVAL;
396
397         block_sz = memory_block_size_bytes();
398
399         rc = dlpar_acquire_drc(lmb->drc_index);
400         if (rc)
401                 return rc;
402
403         /* Find the node id for this address */
404         nid = memory_add_physaddr_to_nid(lmb->base_addr);
405
406         /* Add the memory */
407         rc = add_memory(nid, lmb->base_addr, block_sz);
408         if (rc) {
409                 dlpar_release_drc(lmb->drc_index);
410                 return rc;
411         }
412
413         /* Register this block of memory */
414         rc = memblock_add(lmb->base_addr, block_sz);
415         if (rc) {
416                 remove_memory(nid, lmb->base_addr, block_sz);
417                 dlpar_release_drc(lmb->drc_index);
418                 return rc;
419         }
420
421         mem_block = lmb_to_memblock(lmb);
422         if (!mem_block) {
423                 remove_memory(nid, lmb->base_addr, block_sz);
424                 dlpar_release_drc(lmb->drc_index);
425                 return -EINVAL;
426         }
427
428         rc = device_online(&mem_block->dev);
429         put_device(&mem_block->dev);
430         if (rc) {
431                 remove_memory(nid, lmb->base_addr, block_sz);
432                 dlpar_release_drc(lmb->drc_index);
433                 return rc;
434         }
435
436         lmb->flags |= DRCONF_MEM_ASSIGNED;
437         return 0;
438 }
439
440 static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop)
441 {
442         struct of_drconf_cell *lmbs;
443         u32 num_lmbs, *p;
444         int lmbs_available = 0;
445         int lmbs_added = 0;
446         int i, rc;
447
448         pr_info("Attempting to hot-add %d LMB(s)\n", lmbs_to_add);
449
450         if (lmbs_to_add == 0)
451                 return -EINVAL;
452
453         p = prop->value;
454         num_lmbs = *p++;
455         lmbs = (struct of_drconf_cell *)p;
456
457         /* Validate that there are enough LMBs to satisfy the request */
458         for (i = 0; i < num_lmbs; i++) {
459                 if (!(lmbs[i].flags & DRCONF_MEM_ASSIGNED))
460                         lmbs_available++;
461         }
462
463         if (lmbs_available < lmbs_to_add)
464                 return -EINVAL;
465
466         for (i = 0; i < num_lmbs && lmbs_to_add != lmbs_added; i++) {
467                 rc = dlpar_add_lmb(&lmbs[i]);
468                 if (rc)
469                         continue;
470
471                 lmbs_added++;
472
473                 /* Mark this lmb so we can remove it later if all of the
474                  * requested LMBs cannot be added.
475                  */
476                 lmbs[i].reserved = 1;
477         }
478
479         if (lmbs_added != lmbs_to_add) {
480                 pr_err("Memory hot-add failed, removing any added LMBs\n");
481
482                 for (i = 0; i < num_lmbs; i++) {
483                         if (!lmbs[i].reserved)
484                                 continue;
485
486                         rc = dlpar_remove_lmb(&lmbs[i]);
487                         if (rc)
488                                 pr_err("Failed to remove LMB, drc index %x\n",
489                                        be32_to_cpu(lmbs[i].drc_index));
490                 }
491                 rc = -EINVAL;
492         } else {
493                 for (i = 0; i < num_lmbs; i++) {
494                         if (!lmbs[i].reserved)
495                                 continue;
496
497                         pr_info("Memory at %llx (drc index %x) was hot-added\n",
498                                 lmbs[i].base_addr, lmbs[i].drc_index);
499                         lmbs[i].reserved = 0;
500                 }
501         }
502
503         return rc;
504 }
505
506 static int dlpar_memory_add_by_index(u32 drc_index, struct property *prop)
507 {
508         struct of_drconf_cell *lmbs;
509         u32 num_lmbs, *p;
510         int i, lmb_found;
511         int rc;
512
513         pr_info("Attempting to hot-add LMB, drc index %x\n", drc_index);
514
515         p = prop->value;
516         num_lmbs = *p++;
517         lmbs = (struct of_drconf_cell *)p;
518
519         lmb_found = 0;
520         for (i = 0; i < num_lmbs; i++) {
521                 if (lmbs[i].drc_index == drc_index) {
522                         lmb_found = 1;
523                         rc = dlpar_add_lmb(&lmbs[i]);
524                         break;
525                 }
526         }
527
528         if (!lmb_found)
529                 rc = -EINVAL;
530
531         if (rc)
532                 pr_info("Failed to hot-add memory, drc index %x\n", drc_index);
533         else
534                 pr_info("Memory at %llx (drc index %x) was hot-added\n",
535                         lmbs[i].base_addr, drc_index);
536
537         return rc;
538 }
539
540 static void dlpar_update_drconf_property(struct device_node *dn,
541                                          struct property *prop)
542 {
543         struct of_drconf_cell *lmbs;
544         u32 num_lmbs, *p;
545         int i;
546
547         /* Convert the property back to BE */
548         p = prop->value;
549         num_lmbs = *p;
550         *p = cpu_to_be32(*p);
551         p++;
552
553         lmbs = (struct of_drconf_cell *)p;
554         for (i = 0; i < num_lmbs; i++) {
555                 lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr);
556                 lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index);
557                 lmbs[i].flags = cpu_to_be32(lmbs[i].flags);
558         }
559
560         rtas_hp_event = true;
561         of_update_property(dn, prop);
562         rtas_hp_event = false;
563 }
564
565 int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
566 {
567         struct device_node *dn;
568         struct property *prop;
569         u32 count, drc_index;
570         int rc;
571
572         count = hp_elog->_drc_u.drc_count;
573         drc_index = hp_elog->_drc_u.drc_index;
574
575         lock_device_hotplug();
576
577         dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
578         if (!dn) {
579                 rc = -EINVAL;
580                 goto dlpar_memory_out;
581         }
582
583         prop = dlpar_clone_drconf_property(dn);
584         if (!prop) {
585                 rc = -EINVAL;
586                 goto dlpar_memory_out;
587         }
588
589         switch (hp_elog->action) {
590         case PSERIES_HP_ELOG_ACTION_ADD:
591                 if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT)
592                         rc = dlpar_memory_add_by_count(count, prop);
593                 else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
594                         rc = dlpar_memory_add_by_index(drc_index, prop);
595                 else
596                         rc = -EINVAL;
597                 break;
598         case PSERIES_HP_ELOG_ACTION_REMOVE:
599                 if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT)
600                         rc = dlpar_memory_remove_by_count(count, prop);
601                 else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
602                         rc = dlpar_memory_remove_by_index(drc_index, prop);
603                 else
604                         rc = -EINVAL;
605                 break;
606         default:
607                 pr_err("Invalid action (%d) specified\n", hp_elog->action);
608                 rc = -EINVAL;
609                 break;
610         }
611
612         if (rc)
613                 dlpar_free_drconf_property(prop);
614         else
615                 dlpar_update_drconf_property(dn, prop);
616
617 dlpar_memory_out:
618         of_node_put(dn);
619         unlock_device_hotplug();
620         return rc;
621 }
622
623 static int pseries_add_mem_node(struct device_node *np)
624 {
625         const char *type;
626         const __be32 *regs;
627         unsigned long base;
628         unsigned int lmb_size;
629         int ret = -EINVAL;
630
631         /*
632          * Check to see if we are actually adding memory
633          */
634         type = of_get_property(np, "device_type", NULL);
635         if (type == NULL || strcmp(type, "memory") != 0)
636                 return 0;
637
638         /*
639          * Find the base and size of the memblock
640          */
641         regs = of_get_property(np, "reg", NULL);
642         if (!regs)
643                 return ret;
644
645         base = be64_to_cpu(*(unsigned long *)regs);
646         lmb_size = be32_to_cpu(regs[3]);
647
648         /*
649          * Update memory region to represent the memory add
650          */
651         ret = memblock_add(base, lmb_size);
652         return (ret < 0) ? -EINVAL : 0;
653 }
654
655 static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
656 {
657         struct of_drconf_cell *new_drmem, *old_drmem;
658         unsigned long memblock_size;
659         u32 entries;
660         __be32 *p;
661         int i, rc = -EINVAL;
662
663         if (rtas_hp_event)
664                 return 0;
665
666         memblock_size = pseries_memory_block_size();
667         if (!memblock_size)
668                 return -EINVAL;
669
670         p = (__be32 *) pr->old_prop->value;
671         if (!p)
672                 return -EINVAL;
673
674         /* The first int of the property is the number of lmb's described
675          * by the property. This is followed by an array of of_drconf_cell
676          * entries. Get the number of entries and skip to the array of
677          * of_drconf_cell's.
678          */
679         entries = be32_to_cpu(*p++);
680         old_drmem = (struct of_drconf_cell *)p;
681
682         p = (__be32 *)pr->prop->value;
683         p++;
684         new_drmem = (struct of_drconf_cell *)p;
685
686         for (i = 0; i < entries; i++) {
687                 if ((be32_to_cpu(old_drmem[i].flags) & DRCONF_MEM_ASSIGNED) &&
688                     (!(be32_to_cpu(new_drmem[i].flags) & DRCONF_MEM_ASSIGNED))) {
689                         rc = pseries_remove_memblock(
690                                 be64_to_cpu(old_drmem[i].base_addr),
691                                                      memblock_size);
692                         break;
693                 } else if ((!(be32_to_cpu(old_drmem[i].flags) &
694                             DRCONF_MEM_ASSIGNED)) &&
695                             (be32_to_cpu(new_drmem[i].flags) &
696                             DRCONF_MEM_ASSIGNED)) {
697                         rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
698                                           memblock_size);
699                         rc = (rc < 0) ? -EINVAL : 0;
700                         break;
701                 }
702         }
703         return rc;
704 }
705
706 static int pseries_memory_notifier(struct notifier_block *nb,
707                                    unsigned long action, void *data)
708 {
709         struct of_reconfig_data *rd = data;
710         int err = 0;
711
712         switch (action) {
713         case OF_RECONFIG_ATTACH_NODE:
714                 err = pseries_add_mem_node(rd->dn);
715                 break;
716         case OF_RECONFIG_DETACH_NODE:
717                 err = pseries_remove_mem_node(rd->dn);
718                 break;
719         case OF_RECONFIG_UPDATE_PROPERTY:
720                 if (!strcmp(rd->prop->name, "ibm,dynamic-memory"))
721                         err = pseries_update_drconf_memory(rd);
722                 break;
723         }
724         return notifier_from_errno(err);
725 }
726
727 static struct notifier_block pseries_mem_nb = {
728         .notifier_call = pseries_memory_notifier,
729 };
730
731 static int __init pseries_memory_hotplug_init(void)
732 {
733         if (firmware_has_feature(FW_FEATURE_LPAR))
734                 of_reconfig_notifier_register(&pseries_mem_nb);
735
736         return 0;
737 }
738 machine_device_initcall(pseries, pseries_memory_hotplug_init);