powerpc/pseries: Update numa association of hotplug memory add for drconf memory
Update the association of a memory section with a numa node that occurs during hotplug add of a memory section. This adds a check in the hot_add_scn_to_nid() routine for the ibm,dynamic-reconfiguration-memory node in the device tree. If present the new hot_add_drconf_scn_to_nid() routine is invoked, which can properly parse the ibm,dynamic-reconfiguration-memory node of the device tree and make the proper numa node associations. This also introduces the valid_hot_add_scn() routine as a helper function for code that is common to the hot_add_scn_to_nid() and hot_add_drconf_scn_to_nid() routines. Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Родитель
8342681d3e
Коммит
0db9360aaa
|
@ -900,6 +900,79 @@ static int __init early_numa(char *p)
|
|||
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.
|
||||
*/
|
||||
static int hot_add_drconf_scn_to_nid(struct device_node *memory,
|
||||
unsigned long scn_addr)
|
||||
{
|
||||
const u32 *dm;
|
||||
unsigned int n, rc;
|
||||
unsigned long lmb_size;
|
||||
int default_nid = any_online_node(NODE_MASK_ALL);
|
||||
int nid;
|
||||
struct assoc_arrays aa;
|
||||
|
||||
n = of_get_drconf_memory(memory, &dm);
|
||||
if (!n)
|
||||
return default_nid;;
|
||||
|
||||
lmb_size = of_get_lmb_size(memory);
|
||||
if (!lmb_size)
|
||||
return default_nid;
|
||||
|
||||
rc = of_get_assoc_arrays(memory, &aa);
|
||||
if (rc)
|
||||
return default_nid;
|
||||
|
||||
for (; n != 0; --n) {
|
||||
struct of_drconf_cell drmem;
|
||||
|
||||
read_drconf_cell(&drmem, &dm);
|
||||
|
||||
/* skip this block if it is reserved or not assigned to
|
||||
* this partition */
|
||||
if ((drmem.flags & DRCONF_MEM_RESERVED)
|
||||
|| !(drmem.flags & DRCONF_MEM_ASSIGNED))
|
||||
continue;
|
||||
|
||||
nid = of_drconf_to_nid_single(&drmem, &aa);
|
||||
|
||||
if (valid_hot_add_scn(&nid, drmem.base_addr, lmb_size,
|
||||
scn_addr))
|
||||
return nid;
|
||||
}
|
||||
|
||||
BUG(); /* section address should be found above */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the node associated with a hot added memory section. Section
|
||||
* corresponds to a SPARSEMEM section, not an LMB. It is assumed that
|
||||
|
@ -908,12 +981,17 @@ early_param("numa", early_numa);
|
|||
int hot_add_scn_to_nid(unsigned long scn_addr)
|
||||
{
|
||||
struct device_node *memory = NULL;
|
||||
nodemask_t nodes;
|
||||
int default_nid = any_online_node(NODE_MASK_ALL);
|
||||
int nid;
|
||||
|
||||
if (!numa_enabled || (min_common_depth < 0))
|
||||
return default_nid;
|
||||
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;
|
||||
}
|
||||
|
||||
while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
|
||||
unsigned long start, size;
|
||||
|
@ -932,13 +1010,9 @@ ha_new_range:
|
|||
size = read_n_cells(n_mem_size_cells, &memcell_buf);
|
||||
nid = of_node_to_nid_single(memory);
|
||||
|
||||
/* Domains not present at boot default to 0 */
|
||||
if (nid < 0 || !node_online(nid))
|
||||
nid = default_nid;
|
||||
|
||||
if ((scn_addr >= start) && (scn_addr < (start + size))) {
|
||||
if (valid_hot_add_scn(&nid, start, size, scn_addr)) {
|
||||
of_node_put(memory);
|
||||
goto got_nid;
|
||||
return nid;
|
||||
}
|
||||
|
||||
if (--ranges) /* process all ranges in cell */
|
||||
|
@ -946,14 +1020,5 @@ ha_new_range:
|
|||
}
|
||||
BUG(); /* section address should be found above */
|
||||
return 0;
|
||||
|
||||
/* Temporary code to ensure that returned node is not empty */
|
||||
got_nid:
|
||||
nodes_setall(nodes);
|
||||
while (NODE_DATA(nid)->node_spanned_pages == 0) {
|
||||
node_clear(nid, nodes);
|
||||
nid = any_online_node(nodes);
|
||||
}
|
||||
return nid;
|
||||
}
|
||||
#endif /* CONFIG_MEMORY_HOTPLUG */
|
||||
|
|
Загрузка…
Ссылка в новой задаче