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

Commit 8d5ff320 authored by Tyrel Datwyler's avatar Tyrel Datwyler Committed by Benjamin Herrenschmidt
Browse files

powerpc/pseries: Make dlpar_configure_connector parent node aware



Currently the device nodes created in the device subtree returned by a call to
dlpar_configure_connector are all named in the root node. This is because the
the node name in the work area returned by ibm,configure-connector rtas call
only contains the node name and not the entire node path. Passing the parent
node where the new subtree will be created to dlpar_configure_connector allows
the correct node path to be prefixed in the full_name field.

Signed-off-by: default avatarTyrel Datwyler <tyreld@linux.vnet.ibm.com>
Acked-by: default avatarNathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 1578cb76
Loading
Loading
Loading
Loading
+29 −26
Original line number Original line Diff line number Diff line
@@ -63,21 +63,24 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa)
	return prop;
	return prop;
}
}


static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa)
static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa,
					       const char *path)
{
{
	struct device_node *dn;
	struct device_node *dn;
	char *name;
	char *name;


	/* If parent node path is "/" advance path to NULL terminator to
	 * prevent double leading slashs in full_name.
	 */
	if (!path[1])
		path++;

	dn = kzalloc(sizeof(*dn), GFP_KERNEL);
	dn = kzalloc(sizeof(*dn), GFP_KERNEL);
	if (!dn)
	if (!dn)
		return NULL;
		return NULL;


	/* The configure connector reported name does not contain a
	 * preceding '/', so we allocate a buffer large enough to
	 * prepend this to the full_name.
	 */
	name = (char *)ccwa + ccwa->name_offset;
	name = (char *)ccwa + ccwa->name_offset;
	dn->full_name = kasprintf(GFP_KERNEL, "/%s", name);
	dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name);
	if (!dn->full_name) {
	if (!dn->full_name) {
		kfree(dn);
		kfree(dn);
		return NULL;
		return NULL;
@@ -123,7 +126,8 @@ void dlpar_free_cc_nodes(struct device_node *dn)
#define CALL_AGAIN	-2
#define CALL_AGAIN	-2
#define ERR_CFG_USE     -9003
#define ERR_CFG_USE     -9003


struct device_node *dlpar_configure_connector(u32 drc_index)
struct device_node *dlpar_configure_connector(u32 drc_index,
					      struct device_node *parent)
{
{
	struct device_node *dn;
	struct device_node *dn;
	struct device_node *first_dn = NULL;
	struct device_node *first_dn = NULL;
@@ -132,6 +136,7 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
	struct property *last_property = NULL;
	struct property *last_property = NULL;
	struct cc_workarea *ccwa;
	struct cc_workarea *ccwa;
	char *data_buf;
	char *data_buf;
	const char *parent_path = parent->full_name;
	int cc_token;
	int cc_token;
	int rc = -1;
	int rc = -1;


@@ -165,7 +170,7 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
			break;
			break;


		case NEXT_SIBLING:
		case NEXT_SIBLING:
			dn = dlpar_parse_cc_node(ccwa);
			dn = dlpar_parse_cc_node(ccwa, parent_path);
			if (!dn)
			if (!dn)
				goto cc_error;
				goto cc_error;


@@ -175,13 +180,17 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
			break;
			break;


		case NEXT_CHILD:
		case NEXT_CHILD:
			dn = dlpar_parse_cc_node(ccwa);
			if (first_dn)
				parent_path = last_dn->full_name;

			dn = dlpar_parse_cc_node(ccwa, parent_path);
			if (!dn)
			if (!dn)
				goto cc_error;
				goto cc_error;


			if (!first_dn)
			if (!first_dn) {
				dn->parent = parent;
				first_dn = dn;
				first_dn = dn;
			else {
			} else {
				dn->parent = last_dn;
				dn->parent = last_dn;
				if (last_dn)
				if (last_dn)
					last_dn->child = dn;
					last_dn->child = dn;
@@ -205,6 +214,7 @@ struct device_node *dlpar_configure_connector(u32 drc_index)


		case PREV_PARENT:
		case PREV_PARENT:
			last_dn = last_dn->parent;
			last_dn = last_dn->parent;
			parent_path = last_dn->parent->full_name;
			break;
			break;


		case CALL_AGAIN:
		case CALL_AGAIN:
@@ -383,9 +393,8 @@ out:


static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
{
{
	struct device_node *dn;
	struct device_node *dn, *parent;
	unsigned long drc_index;
	unsigned long drc_index;
	char *cpu_name;
	int rc;
	int rc;


	cpu_hotplug_driver_lock();
	cpu_hotplug_driver_lock();
@@ -395,25 +404,19 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
		goto out;
		goto out;
	}
	}


	dn = dlpar_configure_connector(drc_index);
	parent = of_find_node_by_path("/cpus");
	if (!dn) {
	if (!parent) {
		rc = -EINVAL;
		rc = -ENODEV;
		goto out;
		goto out;
	}
	}


	/* configure-connector reports cpus as living in the base
	dn = dlpar_configure_connector(drc_index, parent);
	 * directory of the device tree.  CPUs actually live in the
	if (!dn) {
	 * cpus directory so we need to fixup the full_name.
		rc = -EINVAL;
	 */
	cpu_name = kasprintf(GFP_KERNEL, "/cpus%s", dn->full_name);
	if (!cpu_name) {
		dlpar_free_cc_nodes(dn);
		rc = -ENOMEM;
		goto out;
		goto out;
	}
	}


	kfree(dn->full_name);
	of_node_put(parent);
	dn->full_name = cpu_name;


	rc = dlpar_acquire_drc(drc_index);
	rc = dlpar_acquire_drc(drc_index);
	if (rc) {
	if (rc) {
+4 −7
Original line number Original line Diff line number Diff line
@@ -216,17 +216,14 @@ static int add_dt_node(u32 parent_phandle, u32 drc_index)
	struct device_node *parent_dn;
	struct device_node *parent_dn;
	int rc;
	int rc;


	dn = dlpar_configure_connector(drc_index);
	parent_dn = of_find_node_by_phandle(parent_phandle);
	if (!dn)
	if (!parent_dn)
		return -ENOENT;
		return -ENOENT;


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


	dn->parent = parent_dn;
	rc = dlpar_attach_node(dn);
	rc = dlpar_attach_node(dn);
	if (rc)
	if (rc)
		dlpar_free_cc_nodes(dn);
		dlpar_free_cc_nodes(dn);
+1 −1
Original line number Original line Diff line number Diff line
@@ -56,7 +56,7 @@ extern void hvc_vio_init_early(void);
/* Dynamic logical Partitioning/Mobility */
/* Dynamic logical Partitioning/Mobility */
extern void dlpar_free_cc_nodes(struct device_node *);
extern void dlpar_free_cc_nodes(struct device_node *);
extern void dlpar_free_cc_property(struct property *);
extern void dlpar_free_cc_property(struct property *);
extern struct device_node *dlpar_configure_connector(u32);
extern struct device_node *dlpar_configure_connector(u32, struct device_node *);
extern int dlpar_attach_node(struct device_node *);
extern int dlpar_attach_node(struct device_node *);
extern int dlpar_detach_node(struct device_node *);
extern int dlpar_detach_node(struct device_node *);