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

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
...@@ -63,21 +63,24 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ static int dlpar_online_cpu(struct device_node *dn) ...@@ -383,9 +393,8 @@ static int dlpar_online_cpu(struct device_node *dn)
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) ...@@ -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) {
......
...@@ -216,17 +216,14 @@ static int add_dt_node(u32 parent_phandle, u32 drc_index) ...@@ -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);
......
...@@ -56,7 +56,7 @@ extern void hvc_vio_init_early(void); ...@@ -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 *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment