Commit 2efd7f6e authored by Nathan Lynch's avatar Nathan Lynch Committed by Michael Ellerman
Browse files

powerpc/pseries/mobility: refactor node lookup during DT update



In pseries_devicetree_update(), with each call to ibm,update-nodes the
partition firmware communicates the node to be deleted or updated by
placing its phandle in the work buffer. Each of delete_dt_node(),
update_dt_node(), and add_dt_node() have duplicate lookups using the
phandle value and corresponding refcount management.

Move the lookup and of_node_put() into pseries_devicetree_update(),
and emit a warning on any failed lookups.

Signed-off-by: default avatarNathan Lynch <nathanl@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20201207215200.1785968-29-nathanl@linux.ibm.com
parent 87b57ea7
Loading
Loading
Loading
Loading
+17 −32
Original line number Original line Diff line number Diff line
@@ -61,18 +61,10 @@ static int mobility_rtas_call(int token, char *buf, s32 scope)
	return rc;
	return rc;
}
}


static int delete_dt_node(__be32 phandle)
static int delete_dt_node(struct device_node *dn)
{
{
	struct device_node *dn;

	dn = of_find_node_by_phandle(be32_to_cpu(phandle));
	if (!dn)
		return -ENOENT;

	pr_debug("removing node %pOFfp\n", dn);
	pr_debug("removing node %pOFfp\n", dn);

	dlpar_detach_node(dn);
	dlpar_detach_node(dn);
	of_node_put(dn);
	return 0;
	return 0;
}
}


@@ -137,10 +129,9 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
	return 0;
	return 0;
}
}


static int update_dt_node(__be32 phandle, s32 scope)
static int update_dt_node(struct device_node *dn, s32 scope)
{
{
	struct update_props_workarea *upwa;
	struct update_props_workarea *upwa;
	struct device_node *dn;
	struct property *prop = NULL;
	struct property *prop = NULL;
	int i, rc, rtas_rc;
	int i, rc, rtas_rc;
	char *prop_data;
	char *prop_data;
@@ -157,14 +148,8 @@ static int update_dt_node(__be32 phandle, s32 scope)
	if (!rtas_buf)
	if (!rtas_buf)
		return -ENOMEM;
		return -ENOMEM;


	dn = of_find_node_by_phandle(be32_to_cpu(phandle));
	if (!dn) {
		kfree(rtas_buf);
		return -ENOENT;
	}

	upwa = (struct update_props_workarea *)&rtas_buf[0];
	upwa = (struct update_props_workarea *)&rtas_buf[0];
	upwa->phandle = phandle;
	upwa->phandle = cpu_to_be32(dn->phandle);


	do {
	do {
		rtas_rc = mobility_rtas_call(update_properties_token, rtas_buf,
		rtas_rc = mobility_rtas_call(update_properties_token, rtas_buf,
@@ -224,26 +209,18 @@ static int update_dt_node(__be32 phandle, s32 scope)
		cond_resched();
		cond_resched();
	} while (rtas_rc == 1);
	} while (rtas_rc == 1);


	of_node_put(dn);
	kfree(rtas_buf);
	kfree(rtas_buf);
	return 0;
	return 0;
}
}


static int add_dt_node(__be32 parent_phandle, __be32 drc_index)
static int add_dt_node(struct device_node *parent_dn, __be32 drc_index)
{
{
	struct device_node *dn;
	struct device_node *dn;
	struct device_node *parent_dn;
	int rc;
	int rc;


	parent_dn = of_find_node_by_phandle(be32_to_cpu(parent_phandle));
	if (!parent_dn)
		return -ENOENT;

	dn = dlpar_configure_connector(drc_index, parent_dn);
	dn = dlpar_configure_connector(drc_index, parent_dn);
	if (!dn) {
	if (!dn)
		of_node_put(parent_dn);
		return -ENOENT;
		return -ENOENT;
	}


	rc = dlpar_attach_node(dn, parent_dn);
	rc = dlpar_attach_node(dn, parent_dn);
	if (rc)
	if (rc)
@@ -251,7 +228,6 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index)


	pr_debug("added node %pOFfp\n", dn);
	pr_debug("added node %pOFfp\n", dn);


	of_node_put(parent_dn);
	return rc;
	return rc;
}
}


@@ -284,22 +260,31 @@ int pseries_devicetree_update(s32 scope)
			data++;
			data++;


			for (i = 0; i < node_count; i++) {
			for (i = 0; i < node_count; i++) {
				struct device_node *np;
				__be32 phandle = *data++;
				__be32 phandle = *data++;
				__be32 drc_index;
				__be32 drc_index;


				np = of_find_node_by_phandle(be32_to_cpu(phandle));
				if (!np) {
					pr_warn("Failed lookup: phandle 0x%x for action 0x%x\n",
						be32_to_cpu(phandle), action);
					continue;
				}

				switch (action) {
				switch (action) {
				case DELETE_DT_NODE:
				case DELETE_DT_NODE:
					delete_dt_node(phandle);
					delete_dt_node(np);
					break;
					break;
				case UPDATE_DT_NODE:
				case UPDATE_DT_NODE:
					update_dt_node(phandle, scope);
					update_dt_node(np, scope);
					break;
					break;
				case ADD_DT_NODE:
				case ADD_DT_NODE:
					drc_index = *data++;
					drc_index = *data++;
					add_dt_node(phandle, drc_index);
					add_dt_node(np, drc_index);
					break;
					break;
				}
				}


				of_node_put(np);
				cond_resched();
				cond_resched();
			}
			}
		}
		}