aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/mm/numa.c101
1 files changed, 83 insertions, 18 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 39328da32edf..cf4bffba6f7c 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -901,6 +901,79 @@ early_param("numa", early_numa);
901 901
902#ifdef CONFIG_MEMORY_HOTPLUG 902#ifdef CONFIG_MEMORY_HOTPLUG
903/* 903/*
904 * Validate the node associated with the memory section we are
905 * trying to add.
906 */
907int valid_hot_add_scn(int *nid, unsigned long start, u32 lmb_size,
908 unsigned long scn_addr)
909{
910 nodemask_t nodes;
911
912 if (*nid < 0 || !node_online(*nid))
913 *nid = any_online_node(NODE_MASK_ALL);
914
915 if ((scn_addr >= start) && (scn_addr < (start + lmb_size))) {
916 nodes_setall(nodes);
917 while (NODE_DATA(*nid)->node_spanned_pages == 0) {
918 node_clear(*nid, nodes);
919 *nid = any_online_node(nodes);
920 }
921
922 return 1;
923 }
924
925 return 0;
926}
927
928/*
929 * Find the node associated with a hot added memory section represented
930 * by the ibm,dynamic-reconfiguration-memory node.
931 */
932static int hot_add_drconf_scn_to_nid(struct device_node *memory,
933 unsigned long scn_addr)
934{
935 const u32 *dm;
936 unsigned int n, rc;
937 unsigned long lmb_size;
938 int default_nid = any_online_node(NODE_MASK_ALL);
939 int nid;
940 struct assoc_arrays aa;
941
942 n = of_get_drconf_memory(memory, &dm);
943 if (!n)
944 return default_nid;;
945
946 lmb_size = of_get_lmb_size(memory);
947 if (!lmb_size)
948 return default_nid;
949
950 rc = of_get_assoc_arrays(memory, &aa);
951 if (rc)
952 return default_nid;
953
954 for (; n != 0; --n) {
955 struct of_drconf_cell drmem;
956
957 read_drconf_cell(&drmem, &dm);
958
959 /* skip this block if it is reserved or not assigned to
960 * this partition */
961 if ((drmem.flags & DRCONF_MEM_RESERVED)
962 || !(drmem.flags & DRCONF_MEM_ASSIGNED))
963 continue;
964
965 nid = of_drconf_to_nid_single(&drmem, &aa);
966
967 if (valid_hot_add_scn(&nid, drmem.base_addr, lmb_size,
968 scn_addr))
969 return nid;
970 }
971
972 BUG(); /* section address should be found above */
973 return 0;
974}
975
976/*
904 * Find the node associated with a hot added memory section. Section 977 * Find the node associated with a hot added memory section. Section
905 * corresponds to a SPARSEMEM section, not an LMB. It is assumed that 978 * corresponds to a SPARSEMEM section, not an LMB. It is assumed that
906 * sections are fully contained within a single LMB. 979 * sections are fully contained within a single LMB.
@@ -908,12 +981,17 @@ early_param("numa", early_numa);
908int hot_add_scn_to_nid(unsigned long scn_addr) 981int hot_add_scn_to_nid(unsigned long scn_addr)
909{ 982{
910 struct device_node *memory = NULL; 983 struct device_node *memory = NULL;
911 nodemask_t nodes;
912 int default_nid = any_online_node(NODE_MASK_ALL);
913 int nid; 984 int nid;
914 985
915 if (!numa_enabled || (min_common_depth < 0)) 986 if (!numa_enabled || (min_common_depth < 0))
916 return default_nid; 987 return any_online_node(NODE_MASK_ALL);
988
989 memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
990 if (memory) {
991 nid = hot_add_drconf_scn_to_nid(memory, scn_addr);
992 of_node_put(memory);
993 return nid;
994 }
917 995
918 while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { 996 while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
919 unsigned long start, size; 997 unsigned long start, size;
@@ -932,13 +1010,9 @@ ha_new_range:
932 size = read_n_cells(n_mem_size_cells, &memcell_buf); 1010 size = read_n_cells(n_mem_size_cells, &memcell_buf);
933 nid = of_node_to_nid_single(memory); 1011 nid = of_node_to_nid_single(memory);
934 1012
935 /* Domains not present at boot default to 0 */ 1013 if (valid_hot_add_scn(&nid, start, size, scn_addr)) {
936 if (nid < 0 || !node_online(nid))
937 nid = default_nid;
938
939 if ((scn_addr >= start) && (scn_addr < (start + size))) {
940 of_node_put(memory); 1014 of_node_put(memory);
941 goto got_nid; 1015 return nid;
942 } 1016 }
943 1017
944 if (--ranges) /* process all ranges in cell */ 1018 if (--ranges) /* process all ranges in cell */
@@ -946,14 +1020,5 @@ ha_new_range:
946 } 1020 }
947 BUG(); /* section address should be found above */ 1021 BUG(); /* section address should be found above */
948 return 0; 1022 return 0;
949
950 /* Temporary code to ensure that returned node is not empty */
951got_nid:
952 nodes_setall(nodes);
953 while (NODE_DATA(nid)->node_spanned_pages == 0) {
954 node_clear(nid, nodes);
955 nid = any_online_node(nodes);
956 }
957 return nid;
958} 1023}
959#endif /* CONFIG_MEMORY_HOTPLUG */ 1024#endif /* CONFIG_MEMORY_HOTPLUG */