forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
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;
....@@ -283,7 +282,7 @@
283282 return dlpar_change_lmb_state(lmb, false);
284283 }
285284
286
-static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
285
+static int pseries_remove_memblock(unsigned long base, unsigned long memblock_size)
287286 {
288287 unsigned long block_sz, start_pfn;
289288 int sections_per_block;
....@@ -314,28 +313,34 @@
314313
315314 static int pseries_remove_mem_node(struct device_node *np)
316315 {
317
- const char *type;
318
- const __be32 *regs;
316
+ const __be32 *prop;
319317 unsigned long base;
320
- unsigned int lmb_size;
318
+ unsigned long lmb_size;
321319 int ret = -EINVAL;
320
+ int addr_cells, size_cells;
322321
323322 /*
324323 * Check to see if we are actually removing memory
325324 */
326
- type = of_get_property(np, "device_type", NULL);
327
- if (type == NULL || strcmp(type, "memory") != 0)
325
+ if (!of_node_is_type(np, "memory"))
328326 return 0;
329327
330328 /*
331329 * Find the base address and size of the memblock
332330 */
333
- regs = of_get_property(np, "reg", NULL);
334
- if (!regs)
331
+ prop = of_get_property(np, "reg", NULL);
332
+ if (!prop)
335333 return ret;
336334
337
- base = be64_to_cpu(*(unsigned long *)regs);
338
- lmb_size = be32_to_cpu(regs[3]);
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);
339344
340345 pseries_remove_memblock(base, lmb_size);
341346 return 0;
....@@ -343,59 +348,46 @@
343348
344349 static bool lmb_is_removable(struct drmem_lmb *lmb)
345350 {
346
- int i, scns_per_block;
347
- int rc = 1;
348
- unsigned long pfn, block_sz;
349
- u64 phys_addr;
350
-
351351 if (!(lmb->flags & DRCONF_MEM_ASSIGNED))
352352 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;
357353
358354 #ifdef CONFIG_FA_DUMP
359355 /*
360356 * Don't hot-remove memory that falls in fadump boot memory area
361357 * and memory that is reserved for capturing old kernel memory.
362358 */
363
- if (is_fadump_memory_area(phys_addr, block_sz))
359
+ if (is_fadump_memory_area(lmb->base_addr, memory_block_size_bytes()))
364360 return false;
365361 #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;
362
+ /* device_offline() will determine if we can actually remove this lmb */
363
+ return true;
379364 }
380365
381366 static int dlpar_add_lmb(struct drmem_lmb *);
382367
383368 static int dlpar_remove_lmb(struct drmem_lmb *lmb)
384369 {
370
+ struct memory_block *mem_block;
385371 unsigned long block_sz;
386
- int nid, rc;
372
+ int rc;
387373
388374 if (!lmb_is_removable(lmb))
389375 return -EINVAL;
390376
377
+ mem_block = lmb_to_memblock(lmb);
378
+ if (mem_block == NULL)
379
+ return -EINVAL;
380
+
391381 rc = dlpar_offline_lmb(lmb);
392
- if (rc)
382
+ if (rc) {
383
+ put_device(&mem_block->dev);
393384 return rc;
385
+ }
394386
395387 block_sz = pseries_memory_block_size();
396
- nid = memory_add_physaddr_to_nid(lmb->base_addr);
397388
398
- __remove_memory(nid, lmb->base_addr, block_sz);
389
+ __remove_memory(mem_block->nid, lmb->base_addr, block_sz);
390
+ put_device(&mem_block->dev);
399391
400392 /* Update memory regions for memory remove */
401393 memblock_remove(lmb->base_addr, block_sz);
....@@ -513,40 +505,6 @@
513505 return rc;
514506 }
515507
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
-
550508 static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index)
551509 {
552510 struct drmem_lmb *lmb, *start_lmb, *end_lmb;
....@@ -619,7 +577,7 @@
619577
620578 #else
621579 static inline int pseries_remove_memblock(unsigned long base,
622
- unsigned int memblock_size)
580
+ unsigned long memblock_size)
623581 {
624582 return -EOPNOTSUPP;
625583 }
....@@ -640,10 +598,6 @@
640598 return -EOPNOTSUPP;
641599 }
642600 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)
647601 {
648602 return -EOPNOTSUPP;
649603 }
....@@ -670,11 +624,13 @@
670624
671625 block_sz = memory_block_size_bytes();
672626
673
- /* Find the node id for this address */
674
- nid = memory_add_physaddr_to_nid(lmb->base_addr);
627
+ /* Find the node id for this LMB. Fake one if necessary. */
628
+ nid = of_drconf_to_nid_single(lmb);
629
+ if (nid < 0 || !node_possible(nid))
630
+ nid = first_online_node;
675631
676632 /* Add the memory */
677
- rc = __add_memory(nid, lmb->base_addr, block_sz);
633
+ rc = __add_memory(nid, lmb->base_addr, block_sz, MHP_NONE);
678634 if (rc) {
679635 invalidate_lmb_associativity_index(lmb);
680636 return rc;
....@@ -889,40 +845,46 @@
889845
890846 switch (hp_elog->action) {
891847 case PSERIES_HP_ELOG_ACTION_ADD:
892
- if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
848
+ switch (hp_elog->id_type) {
849
+ case PSERIES_HP_ELOG_ID_DRC_COUNT:
893850 count = hp_elog->_drc_u.drc_count;
894851 rc = dlpar_memory_add_by_count(count);
895
- } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
852
+ break;
853
+ case PSERIES_HP_ELOG_ID_DRC_INDEX:
896854 drc_index = hp_elog->_drc_u.drc_index;
897855 rc = dlpar_memory_add_by_index(drc_index);
898
- } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
856
+ break;
857
+ case PSERIES_HP_ELOG_ID_DRC_IC:
899858 count = hp_elog->_drc_u.ic.count;
900859 drc_index = hp_elog->_drc_u.ic.index;
901860 rc = dlpar_memory_add_by_ic(count, drc_index);
902
- } else {
861
+ break;
862
+ default:
903863 rc = -EINVAL;
864
+ break;
904865 }
905866
906867 break;
907868 case PSERIES_HP_ELOG_ACTION_REMOVE:
908
- if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
869
+ switch (hp_elog->id_type) {
870
+ case PSERIES_HP_ELOG_ID_DRC_COUNT:
909871 count = hp_elog->_drc_u.drc_count;
910872 rc = dlpar_memory_remove_by_count(count);
911
- } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
873
+ break;
874
+ case PSERIES_HP_ELOG_ID_DRC_INDEX:
912875 drc_index = hp_elog->_drc_u.drc_index;
913876 rc = dlpar_memory_remove_by_index(drc_index);
914
- } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
877
+ break;
878
+ case PSERIES_HP_ELOG_ID_DRC_IC:
915879 count = hp_elog->_drc_u.ic.count;
916880 drc_index = hp_elog->_drc_u.ic.index;
917881 rc = dlpar_memory_remove_by_ic(count, drc_index);
918
- } else {
882
+ break;
883
+ default:
919884 rc = -EINVAL;
885
+ break;
920886 }
921887
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);
926888 break;
927889 default:
928890 pr_err("Invalid action (%d) specified\n", hp_elog->action);
....@@ -930,11 +892,8 @@
930892 break;
931893 }
932894
933
- if (!rc) {
934
- rtas_hp_event = true;
895
+ if (!rc)
935896 rc = drmem_update_dt();
936
- rtas_hp_event = false;
937
- }
938897
939898 unlock_device_hotplug();
940899 return rc;
....@@ -942,88 +901,39 @@
942901
943902 static int pseries_add_mem_node(struct device_node *np)
944903 {
945
- const char *type;
946
- const __be32 *regs;
904
+ const __be32 *prop;
947905 unsigned long base;
948
- unsigned int lmb_size;
906
+ unsigned long lmb_size;
949907 int ret = -EINVAL;
908
+ int addr_cells, size_cells;
950909
951910 /*
952911 * Check to see if we are actually adding memory
953912 */
954
- type = of_get_property(np, "device_type", NULL);
955
- if (type == NULL || strcmp(type, "memory") != 0)
913
+ if (!of_node_is_type(np, "memory"))
956914 return 0;
957915
958916 /*
959917 * Find the base and size of the memblock
960918 */
961
- regs = of_get_property(np, "reg", NULL);
962
- if (!regs)
919
+ prop = of_get_property(np, "reg", NULL);
920
+ if (!prop)
963921 return ret;
964922
965
- base = be64_to_cpu(*(unsigned long *)regs);
966
- lmb_size = be32_to_cpu(regs[3]);
923
+ addr_cells = of_n_addr_cells(np);
924
+ size_cells = of_n_size_cells(np);
925
+ /*
926
+ * "reg" property represents (addr,size) tuple.
927
+ */
928
+ base = of_read_number(prop, addr_cells);
929
+ prop += addr_cells;
930
+ lmb_size = of_read_number(prop, size_cells);
967931
968932 /*
969933 * Update memory region to represent the memory add
970934 */
971935 ret = memblock_add(base, lmb_size);
972936 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;
1027937 }
1028938
1029939 static int pseries_memory_notifier(struct notifier_block *nb,
....@@ -1038,10 +948,6 @@
1038948 break;
1039949 case OF_RECONFIG_DETACH_NODE:
1040950 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);
1045951 break;
1046952 }
1047953 return notifier_from_errno(err);