aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/numa.c
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@austin.ibm.com>2009-02-17 03:08:30 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-02-22 23:53:04 -0500
commit0f16ef7fd3880575b59d0b0f0c9a2ef96e057522 (patch)
treef6fb686562a88813dc83d8d13bee00adf524e4c1 /arch/powerpc/mm/numa.c
parentf52862f4070fb930e407d466aa82d8efcc98c9ed (diff)
powerpc/numa: Cleanup hot_add_scn_to_nid
This patch reworks the hot_add_scn_to_nid and its supporting functions to make them easier to understand. There are no functional changes in this patch and has been tested on machine with memory represented in the device tree as memory nodes and in the ibm,dynamic-memory property. My previous patch that introduced support for hotplug memory add on systems whose memory was represented by the ibm,dynamic-memory property of the device tree only left the code more unintelligible. This will hopefully makes things easier to understand. Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/mm/numa.c')
-rw-r--r--arch/powerpc/mm/numa.c139
1 files changed, 73 insertions, 66 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 0507faa65478..9047145095aa 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1012,57 +1012,32 @@ early_param("numa", early_numa);
1012 1012
1013#ifdef CONFIG_MEMORY_HOTPLUG 1013#ifdef CONFIG_MEMORY_HOTPLUG
1014/* 1014/*
1015 * Validate the node associated with the memory section we are 1015 * Find the node associated with a hot added memory section for
1016 * trying to add. 1016 * memory represented in the device tree by the property
1017 */ 1017 * ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory.
1018int valid_hot_add_scn(int *nid, unsigned long start, u32 lmb_size,
1019 unsigned long scn_addr)
1020{
1021 nodemask_t nodes;
1022
1023 if (*nid < 0 || !node_online(*nid))
1024 *nid = any_online_node(NODE_MASK_ALL);
1025
1026 if ((scn_addr >= start) && (scn_addr < (start + lmb_size))) {
1027 nodes_setall(nodes);
1028 while (NODE_DATA(*nid)->node_spanned_pages == 0) {
1029 node_clear(*nid, nodes);
1030 *nid = any_online_node(nodes);
1031 }
1032
1033 return 1;
1034 }
1035
1036 return 0;
1037}
1038
1039/*
1040 * Find the node associated with a hot added memory section represented
1041 * by the ibm,dynamic-reconfiguration-memory node.
1042 */ 1018 */
1043static int hot_add_drconf_scn_to_nid(struct device_node *memory, 1019static int hot_add_drconf_scn_to_nid(struct device_node *memory,
1044 unsigned long scn_addr) 1020 unsigned long scn_addr)
1045{ 1021{
1046 const u32 *dm; 1022 const u32 *dm;
1047 unsigned int n, rc; 1023 unsigned int drconf_cell_cnt, rc;
1048 unsigned long lmb_size; 1024 unsigned long lmb_size;
1049 int default_nid = any_online_node(NODE_MASK_ALL);
1050 int nid;
1051 struct assoc_arrays aa; 1025 struct assoc_arrays aa;
1026 int nid = -1;
1052 1027
1053 n = of_get_drconf_memory(memory, &dm); 1028 drconf_cell_cnt = of_get_drconf_memory(memory, &dm);
1054 if (!n) 1029 if (!drconf_cell_cnt)
1055 return default_nid;; 1030 return -1;
1056 1031
1057 lmb_size = of_get_lmb_size(memory); 1032 lmb_size = of_get_lmb_size(memory);
1058 if (!lmb_size) 1033 if (!lmb_size)
1059 return default_nid; 1034 return -1;
1060 1035
1061 rc = of_get_assoc_arrays(memory, &aa); 1036 rc = of_get_assoc_arrays(memory, &aa);
1062 if (rc) 1037 if (rc)
1063 return default_nid; 1038 return -1;
1064 1039
1065 for (; n != 0; --n) { 1040 for (; drconf_cell_cnt != 0; --drconf_cell_cnt) {
1066 struct of_drconf_cell drmem; 1041 struct of_drconf_cell drmem;
1067 1042
1068 read_drconf_cell(&drmem, &dm); 1043 read_drconf_cell(&drmem, &dm);
@@ -1073,15 +1048,57 @@ static int hot_add_drconf_scn_to_nid(struct device_node *memory,
1073 || !(drmem.flags & DRCONF_MEM_ASSIGNED)) 1048 || !(drmem.flags & DRCONF_MEM_ASSIGNED))
1074 continue; 1049 continue;
1075 1050
1051 if ((scn_addr < drmem.base_addr)
1052 || (scn_addr >= (drmem.base_addr + lmb_size)))
1053 continue;
1054
1076 nid = of_drconf_to_nid_single(&drmem, &aa); 1055 nid = of_drconf_to_nid_single(&drmem, &aa);
1056 break;
1057 }
1058
1059 return nid;
1060}
1061
1062/*
1063 * Find the node associated with a hot added memory section for memory
1064 * represented in the device tree as a node (i.e. memory@XXXX) for
1065 * each lmb.
1066 */
1067int hot_add_node_scn_to_nid(unsigned long scn_addr)
1068{
1069 struct device_node *memory = NULL;
1070 int nid = -1;
1071
1072 while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
1073 unsigned long start, size;
1074 int ranges;
1075 const unsigned int *memcell_buf;
1076 unsigned int len;
1077
1078 memcell_buf = of_get_property(memory, "reg", &len);
1079 if (!memcell_buf || len <= 0)
1080 continue;
1081
1082 /* ranges in cell */
1083 ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells);
1084
1085 while (ranges--) {
1086 start = read_n_cells(n_mem_addr_cells, &memcell_buf);
1087 size = read_n_cells(n_mem_size_cells, &memcell_buf);
1088
1089 if ((scn_addr < start) || (scn_addr >= (start + size)))
1090 continue;
1091
1092 nid = of_node_to_nid_single(memory);
1093 break;
1094 }
1077 1095
1078 if (valid_hot_add_scn(&nid, drmem.base_addr, lmb_size, 1096 of_node_put(memory);
1079 scn_addr)) 1097 if (nid >= 0)
1080 return nid; 1098 break;
1081 } 1099 }
1082 1100
1083 BUG(); /* section address should be found above */ 1101 return nid;
1084 return 0;
1085} 1102}
1086 1103
1087/* 1104/*
@@ -1092,7 +1109,7 @@ static int hot_add_drconf_scn_to_nid(struct device_node *memory,
1092int hot_add_scn_to_nid(unsigned long scn_addr) 1109int hot_add_scn_to_nid(unsigned long scn_addr)
1093{ 1110{
1094 struct device_node *memory = NULL; 1111 struct device_node *memory = NULL;
1095 int nid; 1112 int nid, found = 0;
1096 1113
1097 if (!numa_enabled || (min_common_depth < 0)) 1114 if (!numa_enabled || (min_common_depth < 0))
1098 return any_online_node(NODE_MASK_ALL); 1115 return any_online_node(NODE_MASK_ALL);
@@ -1101,35 +1118,25 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
1101 if (memory) { 1118 if (memory) {
1102 nid = hot_add_drconf_scn_to_nid(memory, scn_addr); 1119 nid = hot_add_drconf_scn_to_nid(memory, scn_addr);
1103 of_node_put(memory); 1120 of_node_put(memory);
1104 return nid; 1121 } else {
1122 nid = hot_add_node_scn_to_nid(scn_addr);
1105 } 1123 }
1106 1124
1107 while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { 1125 if (nid < 0 || !node_online(nid))
1108 unsigned long start, size; 1126 nid = any_online_node(NODE_MASK_ALL);
1109 int ranges;
1110 const unsigned int *memcell_buf;
1111 unsigned int len;
1112
1113 memcell_buf = of_get_property(memory, "reg", &len);
1114 if (!memcell_buf || len <= 0)
1115 continue;
1116 1127
1117 /* ranges in cell */ 1128 if (NODE_DATA(nid)->node_spanned_pages)
1118 ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells); 1129 return nid;
1119ha_new_range:
1120 start = read_n_cells(n_mem_addr_cells, &memcell_buf);
1121 size = read_n_cells(n_mem_size_cells, &memcell_buf);
1122 nid = of_node_to_nid_single(memory);
1123 1130
1124 if (valid_hot_add_scn(&nid, start, size, scn_addr)) { 1131 for_each_online_node(nid) {
1125 of_node_put(memory); 1132 if (NODE_DATA(nid)->node_spanned_pages) {
1126 return nid; 1133 found = 1;
1134 break;
1127 } 1135 }
1128
1129 if (--ranges) /* process all ranges in cell */
1130 goto ha_new_range;
1131 } 1136 }
1132 BUG(); /* section address should be found above */ 1137
1133 return 0; 1138 BUG_ON(!found);
1139 return nid;
1134} 1140}
1141
1135#endif /* CONFIG_MEMORY_HOTPLUG */ 1142#endif /* CONFIG_MEMORY_HOTPLUG */