forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/arch/powerpc/platforms/pseries/hotplug-memory.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * pseries Memory Hotplug infrastructure.
34 *
45 * 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.
106 */
117
128 #define pr_fmt(fmt) "pseries-hotplug-mem: " fmt
....@@ -26,8 +22,6 @@
2622 #include <asm/drmem.h>
2723 #include "pseries.h"
2824
29
-static bool rtas_hp_event;
30
-
3125 unsigned long pseries_memory_block_size(void)
3226 {
3327 struct device_node *np;
....@@ -36,12 +30,17 @@
3630
3731 np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
3832 if (np) {
39
- const __be64 *size;
33
+ int len;
34
+ int size_cells;
35
+ const __be32 *prop;
4036
41
- size = of_get_property(np, "ibm,lmb-size", NULL);
42
- if (size)
43
- memblock_size = be64_to_cpup(size);
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);
4442 of_node_put(np);
43
+
4544 } else if (machine_is(pseries)) {
4645 /* This fallback really only applies to pseries */
4746 unsigned int memzero_size = 0;
....@@ -181,6 +180,8 @@
181180 return -ENODEV;
182181 }
183182
183
+ update_numa_distance(lmb_node);
184
+
184185 dr_node = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
185186 if (!dr_node) {
186187 dlpar_free_cc_nodes(lmb_node);
....@@ -283,7 +284,7 @@
283284 return dlpar_change_lmb_state(lmb, false);
284285 }
285286
286
-static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
287
+static int pseries_remove_memblock(unsigned long base, unsigned long memblock_size)
287288 {
288289 unsigned long block_sz, start_pfn;
289290 int sections_per_block;
....@@ -314,28 +315,34 @@
314315
315316 static int pseries_remove_mem_node(struct device_node *np)
316317 {
317
- const char *type;
318
- const __be32 *regs;
318
+ const __be32 *prop;
319319 unsigned long base;
320
- unsigned int lmb_size;
320
+ unsigned long lmb_size;
321321 int ret = -EINVAL;
322
+ int addr_cells, size_cells;
322323
323324 /*
324325 * Check to see if we are actually removing memory
325326 */
326
- type = of_get_property(np, "device_type", NULL);
327
- if (type == NULL || strcmp(type, "memory") != 0)
327
+ if (!of_node_is_type(np, "memory"))
328328 return 0;
329329
330330 /*
331331 * Find the base address and size of the memblock
332332 */
333
- regs = of_get_property(np, "reg", NULL);
334
- if (!regs)
333
+ prop = of_get_property(np, "reg", NULL);
334
+ if (!prop)
335335 return ret;
336336
337
- base = be64_to_cpu(*(unsigned long *)regs);
338
- lmb_size = be32_to_cpu(regs[3]);
337
+ addr_cells = of_n_addr_cells(np);
338
+ size_cells = of_n_size_cells(np);
339
+
340
+ /*
341
+ * "reg" property represents (addr,size) tuple.
342
+ */
343
+ base = of_read_number(prop, addr_cells);
344
+ prop += addr_cells;
345
+ lmb_size = of_read_number(prop, size_cells);
339346
340347 pseries_remove_memblock(base, lmb_size);
341348 return 0;
....@@ -343,59 +350,46 @@
343350
344351 static bool lmb_is_removable(struct drmem_lmb *lmb)
345352 {
346
- int i, scns_per_block;
347
- int rc = 1;
348
- unsigned long pfn, block_sz;
349
- u64 phys_addr;
350
-
351353 if (!(lmb->flags & DRCONF_MEM_ASSIGNED))
352354 return false;
353
-
354
- block_sz = memory_block_size_bytes();
355
- scns_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
356
- phys_addr = lmb->base_addr;
357355
358356 #ifdef CONFIG_FA_DUMP
359357 /*
360358 * Don't hot-remove memory that falls in fadump boot memory area
361359 * and memory that is reserved for capturing old kernel memory.
362360 */
363
- if (is_fadump_memory_area(phys_addr, block_sz))
361
+ if (is_fadump_memory_area(lmb->base_addr, memory_block_size_bytes()))
364362 return false;
365363 #endif
366
-
367
- for (i = 0; i < scns_per_block; i++) {
368
- pfn = PFN_DOWN(phys_addr);
369
- if (!pfn_present(pfn)) {
370
- phys_addr += MIN_MEMORY_BLOCK_SIZE;
371
- continue;
372
- }
373
-
374
- rc &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
375
- phys_addr += MIN_MEMORY_BLOCK_SIZE;
376
- }
377
-
378
- return rc ? true : false;
364
+ /* device_offline() will determine if we can actually remove this lmb */
365
+ return true;
379366 }
380367
381368 static int dlpar_add_lmb(struct drmem_lmb *);
382369
383370 static int dlpar_remove_lmb(struct drmem_lmb *lmb)
384371 {
372
+ struct memory_block *mem_block;
385373 unsigned long block_sz;
386
- int nid, rc;
374
+ int rc;
387375
388376 if (!lmb_is_removable(lmb))
389377 return -EINVAL;
390378
379
+ mem_block = lmb_to_memblock(lmb);
380
+ if (mem_block == NULL)
381
+ return -EINVAL;
382
+
391383 rc = dlpar_offline_lmb(lmb);
392
- if (rc)
384
+ if (rc) {
385
+ put_device(&mem_block->dev);
393386 return rc;
387
+ }
394388
395389 block_sz = pseries_memory_block_size();
396
- nid = memory_add_physaddr_to_nid(lmb->base_addr);
397390
398
- __remove_memory(nid, lmb->base_addr, block_sz);
391
+ __remove_memory(mem_block->nid, lmb->base_addr, block_sz);
392
+ put_device(&mem_block->dev);
399393
400394 /* Update memory regions for memory remove */
401395 memblock_remove(lmb->base_addr, block_sz);
....@@ -513,40 +507,6 @@
513507 return rc;
514508 }
515509
516
-static int dlpar_memory_readd_by_index(u32 drc_index)
517
-{
518
- struct drmem_lmb *lmb;
519
- int lmb_found;
520
- int rc;
521
-
522
- pr_info("Attempting to update LMB, drc index %x\n", drc_index);
523
-
524
- lmb_found = 0;
525
- for_each_drmem_lmb(lmb) {
526
- if (lmb->drc_index == drc_index) {
527
- lmb_found = 1;
528
- rc = dlpar_remove_lmb(lmb);
529
- if (!rc) {
530
- rc = dlpar_add_lmb(lmb);
531
- if (rc)
532
- dlpar_release_drc(lmb->drc_index);
533
- }
534
- break;
535
- }
536
- }
537
-
538
- if (!lmb_found)
539
- rc = -EINVAL;
540
-
541
- if (rc)
542
- pr_info("Failed to update memory at %llx\n",
543
- lmb->base_addr);
544
- else
545
- pr_info("Memory at %llx was updated\n", lmb->base_addr);
546
-
547
- return rc;
548
-}
549
-
550510 static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index)
551511 {
552512 struct drmem_lmb *lmb, *start_lmb, *end_lmb;
....@@ -619,7 +579,7 @@
619579
620580 #else
621581 static inline int pseries_remove_memblock(unsigned long base,
622
- unsigned int memblock_size)
582
+ unsigned long memblock_size)
623583 {
624584 return -EOPNOTSUPP;
625585 }
....@@ -640,10 +600,6 @@
640600 return -EOPNOTSUPP;
641601 }
642602 static int dlpar_memory_remove_by_index(u32 drc_index)
643
-{
644
- return -EOPNOTSUPP;
645
-}
646
-static int dlpar_memory_readd_by_index(u32 drc_index)
647603 {
648604 return -EOPNOTSUPP;
649605 }
....@@ -670,11 +626,13 @@
670626
671627 block_sz = memory_block_size_bytes();
672628
673
- /* Find the node id for this address */
674
- nid = memory_add_physaddr_to_nid(lmb->base_addr);
629
+ /* Find the node id for this LMB. Fake one if necessary. */
630
+ nid = of_drconf_to_nid_single(lmb);
631
+ if (nid < 0 || !node_possible(nid))
632
+ nid = first_online_node;
675633
676634 /* Add the memory */
677
- rc = __add_memory(nid, lmb->base_addr, block_sz);
635
+ rc = __add_memory(nid, lmb->base_addr, block_sz, MHP_NONE);
678636 if (rc) {
679637 invalidate_lmb_associativity_index(lmb);
680638 return rc;
....@@ -889,40 +847,46 @@
889847
890848 switch (hp_elog->action) {
891849 case PSERIES_HP_ELOG_ACTION_ADD:
892
- if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
850
+ switch (hp_elog->id_type) {
851
+ case PSERIES_HP_ELOG_ID_DRC_COUNT:
893852 count = hp_elog->_drc_u.drc_count;
894853 rc = dlpar_memory_add_by_count(count);
895
- } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
854
+ break;
855
+ case PSERIES_HP_ELOG_ID_DRC_INDEX:
896856 drc_index = hp_elog->_drc_u.drc_index;
897857 rc = dlpar_memory_add_by_index(drc_index);
898
- } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
858
+ break;
859
+ case PSERIES_HP_ELOG_ID_DRC_IC:
899860 count = hp_elog->_drc_u.ic.count;
900861 drc_index = hp_elog->_drc_u.ic.index;
901862 rc = dlpar_memory_add_by_ic(count, drc_index);
902
- } else {
863
+ break;
864
+ default:
903865 rc = -EINVAL;
866
+ break;
904867 }
905868
906869 break;
907870 case PSERIES_HP_ELOG_ACTION_REMOVE:
908
- if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
871
+ switch (hp_elog->id_type) {
872
+ case PSERIES_HP_ELOG_ID_DRC_COUNT:
909873 count = hp_elog->_drc_u.drc_count;
910874 rc = dlpar_memory_remove_by_count(count);
911
- } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
875
+ break;
876
+ case PSERIES_HP_ELOG_ID_DRC_INDEX:
912877 drc_index = hp_elog->_drc_u.drc_index;
913878 rc = dlpar_memory_remove_by_index(drc_index);
914
- } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
879
+ break;
880
+ case PSERIES_HP_ELOG_ID_DRC_IC:
915881 count = hp_elog->_drc_u.ic.count;
916882 drc_index = hp_elog->_drc_u.ic.index;
917883 rc = dlpar_memory_remove_by_ic(count, drc_index);
918
- } else {
884
+ break;
885
+ default:
919886 rc = -EINVAL;
887
+ break;
920888 }
921889
922
- break;
923
- case PSERIES_HP_ELOG_ACTION_READD:
924
- drc_index = hp_elog->_drc_u.drc_index;
925
- rc = dlpar_memory_readd_by_index(drc_index);
926890 break;
927891 default:
928892 pr_err("Invalid action (%d) specified\n", hp_elog->action);
....@@ -930,11 +894,8 @@
930894 break;
931895 }
932896
933
- if (!rc) {
934
- rtas_hp_event = true;
897
+ if (!rc)
935898 rc = drmem_update_dt();
936
- rtas_hp_event = false;
937
- }
938899
939900 unlock_device_hotplug();
940901 return rc;
....@@ -942,88 +903,39 @@
942903
943904 static int pseries_add_mem_node(struct device_node *np)
944905 {
945
- const char *type;
946
- const __be32 *regs;
906
+ const __be32 *prop;
947907 unsigned long base;
948
- unsigned int lmb_size;
908
+ unsigned long lmb_size;
949909 int ret = -EINVAL;
910
+ int addr_cells, size_cells;
950911
951912 /*
952913 * Check to see if we are actually adding memory
953914 */
954
- type = of_get_property(np, "device_type", NULL);
955
- if (type == NULL || strcmp(type, "memory") != 0)
915
+ if (!of_node_is_type(np, "memory"))
956916 return 0;
957917
958918 /*
959919 * Find the base and size of the memblock
960920 */
961
- regs = of_get_property(np, "reg", NULL);
962
- if (!regs)
921
+ prop = of_get_property(np, "reg", NULL);
922
+ if (!prop)
963923 return ret;
964924
965
- base = be64_to_cpu(*(unsigned long *)regs);
966
- lmb_size = be32_to_cpu(regs[3]);
925
+ addr_cells = of_n_addr_cells(np);
926
+ size_cells = of_n_size_cells(np);
927
+ /*
928
+ * "reg" property represents (addr,size) tuple.
929
+ */
930
+ base = of_read_number(prop, addr_cells);
931
+ prop += addr_cells;
932
+ lmb_size = of_read_number(prop, size_cells);
967933
968934 /*
969935 * Update memory region to represent the memory add
970936 */
971937 ret = memblock_add(base, lmb_size);
972938 return (ret < 0) ? -EINVAL : 0;
973
-}
974
-
975
-static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
976
-{
977
- struct of_drconf_cell_v1 *new_drmem, *old_drmem;
978
- unsigned long memblock_size;
979
- u32 entries;
980
- __be32 *p;
981
- int i, rc = -EINVAL;
982
-
983
- if (rtas_hp_event)
984
- return 0;
985
-
986
- memblock_size = pseries_memory_block_size();
987
- if (!memblock_size)
988
- return -EINVAL;
989
-
990
- if (!pr->old_prop)
991
- return 0;
992
-
993
- p = (__be32 *) pr->old_prop->value;
994
- if (!p)
995
- return -EINVAL;
996
-
997
- /* The first int of the property is the number of lmb's described
998
- * by the property. This is followed by an array of of_drconf_cell
999
- * entries. Get the number of entries and skip to the array of
1000
- * of_drconf_cell's.
1001
- */
1002
- entries = be32_to_cpu(*p++);
1003
- old_drmem = (struct of_drconf_cell_v1 *)p;
1004
-
1005
- p = (__be32 *)pr->prop->value;
1006
- p++;
1007
- new_drmem = (struct of_drconf_cell_v1 *)p;
1008
-
1009
- for (i = 0; i < entries; i++) {
1010
- if ((be32_to_cpu(old_drmem[i].flags) & DRCONF_MEM_ASSIGNED) &&
1011
- (!(be32_to_cpu(new_drmem[i].flags) & DRCONF_MEM_ASSIGNED))) {
1012
- rc = pseries_remove_memblock(
1013
- be64_to_cpu(old_drmem[i].base_addr),
1014
- memblock_size);
1015
- break;
1016
- } else if ((!(be32_to_cpu(old_drmem[i].flags) &
1017
- DRCONF_MEM_ASSIGNED)) &&
1018
- (be32_to_cpu(new_drmem[i].flags) &
1019
- DRCONF_MEM_ASSIGNED)) {
1020
- rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
1021
- memblock_size);
1022
- rc = (rc < 0) ? -EINVAL : 0;
1023
- break;
1024
- }
1025
- }
1026
- return rc;
1027939 }
1028940
1029941 static int pseries_memory_notifier(struct notifier_block *nb,
....@@ -1038,10 +950,6 @@
1038950 break;
1039951 case OF_RECONFIG_DETACH_NODE:
1040952 err = pseries_remove_mem_node(rd->dn);
1041
- break;
1042
- case OF_RECONFIG_UPDATE_PROPERTY:
1043
- if (!strcmp(rd->prop->name, "ibm,dynamic-memory"))
1044
- err = pseries_update_drconf_memory(rd);
1045953 break;
1046954 }
1047955 return notifier_from_errno(err);