[PATCH 6/8] powerpc/pseries: make dlpar_configure_connector parent node aware

Nathan Fontenot nfont at linux.vnet.ibm.com
Mon Aug 19 23:53:45 EST 2013


On 08/15/2013 12:23 AM, Tyrel Datwyler wrote:
> 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: Tyrel Datwyler <tyreld at linux.vnet.ibm.com>

Acked-by: Nathan Fontenot <nfont at linux.vnet.ibm.com>

> ---
>  arch/powerpc/platforms/pseries/dlpar.c    | 55 ++++++++++++++++---------------
>  arch/powerpc/platforms/pseries/mobility.c | 11 +++----
>  arch/powerpc/platforms/pseries/pseries.h  |  2 +-
>  3 files changed, 34 insertions(+), 34 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
> index c855233..4ea667d 100644
> --- a/arch/powerpc/platforms/pseries/dlpar.c
> +++ b/arch/powerpc/platforms/pseries/dlpar.c
> @@ -63,21 +63,24 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa)
>  	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;
>  	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);
>  	if (!dn)
>  		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;
> -	dn->full_name = kasprintf(GFP_KERNEL, "/%s", name);
> +	dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name);
>  	if (!dn->full_name) {
>  		kfree(dn);
>  		return NULL;
> @@ -123,7 +126,8 @@ void dlpar_free_cc_nodes(struct device_node *dn)
>  #define CALL_AGAIN	-2
>  #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 *first_dn = NULL;
> @@ -132,6 +136,7 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
>  	struct property *last_property = NULL;
>  	struct cc_workarea *ccwa;
>  	char *data_buf;
> +	const char *parent_path = parent->full_name;
>  	int cc_token;
>  	int rc = -1;
>  
> @@ -165,7 +170,7 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
>  			break;
>  
>  		case NEXT_SIBLING:
> -			dn = dlpar_parse_cc_node(ccwa);
> +			dn = dlpar_parse_cc_node(ccwa, parent_path);
>  			if (!dn)
>  				goto cc_error;
>  
> @@ -175,13 +180,17 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
>  			break;
>  
>  		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)
>  				goto cc_error;
>  
> -			if (!first_dn)
> +			if (!first_dn) {
> +				dn->parent = parent;
>  				first_dn = dn;
> -			else {
> +			} else {
>  				dn->parent = last_dn;
>  				if (last_dn)
>  					last_dn->child = dn;
> @@ -205,6 +214,7 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
>  
>  		case PREV_PARENT:
>  			last_dn = last_dn->parent;
> +			parent_path = last_dn->parent->full_name;
>  			break;
>  
>  		case CALL_AGAIN:
> @@ -383,9 +393,8 @@ out:
>  
>  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;
> -	char *cpu_name;
>  	int rc;
>  
>  	cpu_hotplug_driver_lock();
> @@ -395,25 +404,19 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
>  		goto out;
>  	}
>  
> -	dn = dlpar_configure_connector(drc_index);
> -	if (!dn) {
> -		rc = -EINVAL;
> +	parent = of_find_node_by_path("/cpus");
> +	if (!parent) {
> +		rc = -ENODEV;
>  		goto out;
>  	}
>  
> -	/* configure-connector reports cpus as living in the base
> -	 * directory of the device tree.  CPUs actually live in the
> -	 * cpus directory so we need to fixup the full_name.
> -	 */
> -	cpu_name = kasprintf(GFP_KERNEL, "/cpus%s", dn->full_name);
> -	if (!cpu_name) {
> -		dlpar_free_cc_nodes(dn);
> -		rc = -ENOMEM;
> +	dn = dlpar_configure_connector(drc_index, parent);
> +	if (!dn) {
> +		rc = -EINVAL;
>  		goto out;
>  	}
>  
> -	kfree(dn->full_name);
> -	dn->full_name = cpu_name;
> +	of_node_put(parent);
>  
>  	rc = dlpar_acquire_drc(drc_index);
>  	if (rc) {
> diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
> index ed5426f..ff102e2 100644
> --- a/arch/powerpc/platforms/pseries/mobility.c
> +++ b/arch/powerpc/platforms/pseries/mobility.c
> @@ -216,17 +216,14 @@ static int add_dt_node(u32 parent_phandle, u32 drc_index)
>  	struct device_node *parent_dn;
>  	int rc;
>  
> -	dn = dlpar_configure_connector(drc_index);
> -	if (!dn)
> +	parent_dn = of_find_node_by_phandle(parent_phandle);
> +	if (!parent_dn)
>  		return -ENOENT;
>  
> -	parent_dn = of_find_node_by_phandle(parent_phandle);
> -	if (!parent_dn) {
> -		dlpar_free_cc_nodes(dn);
> +	dn = dlpar_configure_connector(drc_index, parent_dn);
> +	if (!dn)
>  		return -ENOENT;
> -	}
>  
> -	dn->parent = parent_dn;
>  	rc = dlpar_attach_node(dn);
>  	if (rc)
>  		dlpar_free_cc_nodes(dn);
> diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
> index c2a3a25..defb3c9 100644
> --- a/arch/powerpc/platforms/pseries/pseries.h
> +++ b/arch/powerpc/platforms/pseries/pseries.h
> @@ -56,7 +56,7 @@ extern void hvc_vio_init_early(void);
>  /* Dynamic logical Partitioning/Mobility */
>  extern void dlpar_free_cc_nodes(struct device_node *);
>  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_detach_node(struct device_node *);
>  
> 



More information about the Linuxppc-dev mailing list