forked from Minki/linux
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>
This commit is contained in:
parent
f52862f407
commit
0f16ef7fd3
@ -1012,57 +1012,32 @@ early_param("numa", early_numa);
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
/*
|
||||
* Validate the node associated with the memory section we are
|
||||
* trying to add.
|
||||
*/
|
||||
int valid_hot_add_scn(int *nid, unsigned long start, u32 lmb_size,
|
||||
unsigned long scn_addr)
|
||||
{
|
||||
nodemask_t nodes;
|
||||
|
||||
if (*nid < 0 || !node_online(*nid))
|
||||
*nid = any_online_node(NODE_MASK_ALL);
|
||||
|
||||
if ((scn_addr >= start) && (scn_addr < (start + lmb_size))) {
|
||||
nodes_setall(nodes);
|
||||
while (NODE_DATA(*nid)->node_spanned_pages == 0) {
|
||||
node_clear(*nid, nodes);
|
||||
*nid = any_online_node(nodes);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the node associated with a hot added memory section represented
|
||||
* by the ibm,dynamic-reconfiguration-memory node.
|
||||
* Find the node associated with a hot added memory section for
|
||||
* memory represented in the device tree by the property
|
||||
* ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory.
|
||||
*/
|
||||
static int hot_add_drconf_scn_to_nid(struct device_node *memory,
|
||||
unsigned long scn_addr)
|
||||
{
|
||||
const u32 *dm;
|
||||
unsigned int n, rc;
|
||||
unsigned int drconf_cell_cnt, rc;
|
||||
unsigned long lmb_size;
|
||||
int default_nid = any_online_node(NODE_MASK_ALL);
|
||||
int nid;
|
||||
struct assoc_arrays aa;
|
||||
int nid = -1;
|
||||
|
||||
n = of_get_drconf_memory(memory, &dm);
|
||||
if (!n)
|
||||
return default_nid;;
|
||||
drconf_cell_cnt = of_get_drconf_memory(memory, &dm);
|
||||
if (!drconf_cell_cnt)
|
||||
return -1;
|
||||
|
||||
lmb_size = of_get_lmb_size(memory);
|
||||
if (!lmb_size)
|
||||
return default_nid;
|
||||
return -1;
|
||||
|
||||
rc = of_get_assoc_arrays(memory, &aa);
|
||||
if (rc)
|
||||
return default_nid;
|
||||
return -1;
|
||||
|
||||
for (; n != 0; --n) {
|
||||
for (; drconf_cell_cnt != 0; --drconf_cell_cnt) {
|
||||
struct of_drconf_cell drmem;
|
||||
|
||||
read_drconf_cell(&drmem, &dm);
|
||||
@ -1073,36 +1048,26 @@ static int hot_add_drconf_scn_to_nid(struct device_node *memory,
|
||||
|| !(drmem.flags & DRCONF_MEM_ASSIGNED))
|
||||
continue;
|
||||
|
||||
nid = of_drconf_to_nid_single(&drmem, &aa);
|
||||
if ((scn_addr < drmem.base_addr)
|
||||
|| (scn_addr >= (drmem.base_addr + lmb_size)))
|
||||
continue;
|
||||
|
||||
if (valid_hot_add_scn(&nid, drmem.base_addr, lmb_size,
|
||||
scn_addr))
|
||||
return nid;
|
||||
nid = of_drconf_to_nid_single(&drmem, &aa);
|
||||
break;
|
||||
}
|
||||
|
||||
BUG(); /* section address should be found above */
|
||||
return 0;
|
||||
return nid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the node associated with a hot added memory section. Section
|
||||
* corresponds to a SPARSEMEM section, not an LMB. It is assumed that
|
||||
* sections are fully contained within a single LMB.
|
||||
* Find the node associated with a hot added memory section for memory
|
||||
* represented in the device tree as a node (i.e. memory@XXXX) for
|
||||
* each lmb.
|
||||
*/
|
||||
int hot_add_scn_to_nid(unsigned long scn_addr)
|
||||
int hot_add_node_scn_to_nid(unsigned long scn_addr)
|
||||
{
|
||||
struct device_node *memory = NULL;
|
||||
int nid;
|
||||
|
||||
if (!numa_enabled || (min_common_depth < 0))
|
||||
return any_online_node(NODE_MASK_ALL);
|
||||
|
||||
memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
|
||||
if (memory) {
|
||||
nid = hot_add_drconf_scn_to_nid(memory, scn_addr);
|
||||
of_node_put(memory);
|
||||
return nid;
|
||||
}
|
||||
int nid = -1;
|
||||
|
||||
while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
|
||||
unsigned long start, size;
|
||||
@ -1116,20 +1081,62 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
|
||||
|
||||
/* ranges in cell */
|
||||
ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells);
|
||||
ha_new_range:
|
||||
start = read_n_cells(n_mem_addr_cells, &memcell_buf);
|
||||
size = read_n_cells(n_mem_size_cells, &memcell_buf);
|
||||
nid = of_node_to_nid_single(memory);
|
||||
|
||||
if (valid_hot_add_scn(&nid, start, size, scn_addr)) {
|
||||
of_node_put(memory);
|
||||
return nid;
|
||||
while (ranges--) {
|
||||
start = read_n_cells(n_mem_addr_cells, &memcell_buf);
|
||||
size = read_n_cells(n_mem_size_cells, &memcell_buf);
|
||||
|
||||
if ((scn_addr < start) || (scn_addr >= (start + size)))
|
||||
continue;
|
||||
|
||||
nid = of_node_to_nid_single(memory);
|
||||
break;
|
||||
}
|
||||
|
||||
if (--ranges) /* process all ranges in cell */
|
||||
goto ha_new_range;
|
||||
of_node_put(memory);
|
||||
if (nid >= 0)
|
||||
break;
|
||||
}
|
||||
BUG(); /* section address should be found above */
|
||||
return 0;
|
||||
|
||||
return nid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the node associated with a hot added memory section. Section
|
||||
* corresponds to a SPARSEMEM section, not an LMB. It is assumed that
|
||||
* sections are fully contained within a single LMB.
|
||||
*/
|
||||
int hot_add_scn_to_nid(unsigned long scn_addr)
|
||||
{
|
||||
struct device_node *memory = NULL;
|
||||
int nid, found = 0;
|
||||
|
||||
if (!numa_enabled || (min_common_depth < 0))
|
||||
return any_online_node(NODE_MASK_ALL);
|
||||
|
||||
memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
|
||||
if (memory) {
|
||||
nid = hot_add_drconf_scn_to_nid(memory, scn_addr);
|
||||
of_node_put(memory);
|
||||
} else {
|
||||
nid = hot_add_node_scn_to_nid(scn_addr);
|
||||
}
|
||||
|
||||
if (nid < 0 || !node_online(nid))
|
||||
nid = any_online_node(NODE_MASK_ALL);
|
||||
|
||||
if (NODE_DATA(nid)->node_spanned_pages)
|
||||
return nid;
|
||||
|
||||
for_each_online_node(nid) {
|
||||
if (NODE_DATA(nid)->node_spanned_pages) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BUG_ON(!found);
|
||||
return nid;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MEMORY_HOTPLUG */
|
||||
|
Loading…
Reference in New Issue
Block a user