Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0db9360a authored by Nathan Fontenot's avatar Nathan Fontenot Committed by Paul Mackerras
Browse files

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: default avatarNathan Fontenot <nfont@austin.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 8342681d
Loading
Loading
Loading
Loading
+83 −18
Original line number Diff line number Diff line
@@ -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 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
		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 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
	}
	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 */