[PATCH] pseries/memory-hotplug: Only update DT once per memory DLPAR request

Nathan Fontenot nfont at linux.vnet.ibm.com
Wed May 23 01:12:06 AEST 2018


Hi Michael,

I sent this patch out several weeks ago, just wanted to make sure it hasn't fallen
off your radar.

Thanks,
-Nathan

On 04/20/2018 03:29 PM, Nathan Fontenot wrote:
> The updates to powerpc numa and memory hotplug code now use the
> in-kernel LMB array instead of the device tree. This change
> allows the pseries memory DLPAR code to only update the device
> tree once after successfully handling a DLPAR request.
> 
> Prior to the in-kernel LMB array, the numa code looked up the
> affinity for memory being added in the device tree, the code
> now looks this up in the LMB array. This change means the
> memory hotplug code can just update the affinity for an LMB
> in the LMB array instead of updating the device tree.
> 
> This also provides a savings in kernel memory. When updating the
> device tree old properties are never free'ed since there is no
> usecount on properties. This behavior leads to a new copy of the
> property being allocated every time a LMB is added or removed
> (i.e. a request to add 100 LMBs creates 100 new copies of the
> property). With this update only a single new property is created
> when a DLPAR request completes successfully.
> 
> Signed-off-by: Nathan Fontenot <nfont at linux.vnet.ibm.com>
> ---
>  arch/powerpc/include/asm/drmem.h                |    5 ++
>  arch/powerpc/platforms/pseries/hotplug-memory.c |   55 +++++++----------------
>  2 files changed, 21 insertions(+), 39 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h
> index ce242b9ea8c6..7c1d8e74b25d 100644
> --- a/arch/powerpc/include/asm/drmem.h
> +++ b/arch/powerpc/include/asm/drmem.h
> @@ -99,4 +99,9 @@ void __init walk_drmem_lmbs_early(unsigned long node,
>  			void (*func)(struct drmem_lmb *, const __be32 **));
>  #endif
> 
> +static inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb)
> +{
> +	lmb->aa_index = 0xffffffff;
> +}
> +
>  #endif /* _ASM_POWERPC_LMB_H */
> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
> index c1578f54c626..9a15d39995e5 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
> @@ -163,7 +163,7 @@ static u32 find_aa_index(struct device_node *dr_node,
>  	return aa_index;
>  }
> 
> -static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb)
> +static int update_lmb_associativity_index(struct drmem_lmb *lmb)
>  {
>  	struct device_node *parent, *lmb_node, *dr_node;
>  	struct property *ala_prop;
> @@ -203,43 +203,14 @@ static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb)
>  	aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc);
> 
>  	dlpar_free_cc_nodes(lmb_node);
> -	return aa_index;
> -}
> -
> -static int dlpar_add_device_tree_lmb(struct drmem_lmb *lmb)
> -{
> -	int rc, aa_index;
> -
> -	lmb->flags |= DRCONF_MEM_ASSIGNED;
> 
> -	aa_index = lookup_lmb_associativity_index(lmb);
>  	if (aa_index < 0) {
> -		pr_err("Couldn't find associativity index for drc index %x\n",
> -		       lmb->drc_index);
> -		return aa_index;
> +		pr_err("Could not find LMB associativity\n");
> +		return -1;
>  	}
> 
>  	lmb->aa_index = aa_index;
> -
> -	rtas_hp_event = true;
> -	rc = drmem_update_dt();
> -	rtas_hp_event = false;
> -
> -	return rc;
> -}
> -
> -static int dlpar_remove_device_tree_lmb(struct drmem_lmb *lmb)
> -{
> -	int rc;
> -
> -	lmb->flags &= ~DRCONF_MEM_ASSIGNED;
> -	lmb->aa_index = 0xffffffff;
> -
> -	rtas_hp_event = true;
> -	rc = drmem_update_dt();
> -	rtas_hp_event = false;
> -
> -	return rc;
> +	return 0;
>  }
> 
>  static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb)
> @@ -428,7 +399,9 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb)
>  	/* Update memory regions for memory remove */
>  	memblock_remove(lmb->base_addr, block_sz);
> 
> -	dlpar_remove_device_tree_lmb(lmb);
> +	invalidate_lmb_associativity_index(lmb);
> +	lmb->flags &= ~DRCONF_MEM_ASSIGNED;
> +
>  	return 0;
>  }
> 
> @@ -688,10 +661,8 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb)
>  	if (lmb->flags & DRCONF_MEM_ASSIGNED)
>  		return -EINVAL;
> 
> -	rc = dlpar_add_device_tree_lmb(lmb);
> +	rc = update_lmb_associativity_index(lmb);
>  	if (rc) {
> -		pr_err("Couldn't update device tree for drc index %x\n",
> -		       lmb->drc_index);
>  		dlpar_release_drc(lmb->drc_index);
>  		return rc;
>  	}
> @@ -704,14 +675,14 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb)
>  	/* Add the memory */
>  	rc = add_memory(nid, lmb->base_addr, block_sz);
>  	if (rc) {
> -		dlpar_remove_device_tree_lmb(lmb);
> +		invalidate_lmb_associativity_index(lmb);
>  		return rc;
>  	}
> 
>  	rc = dlpar_online_lmb(lmb);
>  	if (rc) {
>  		remove_memory(nid, lmb->base_addr, block_sz);
> -		dlpar_remove_device_tree_lmb(lmb);
> +		invalidate_lmb_associativity_index(lmb);
>  	} else {
>  		lmb->flags |= DRCONF_MEM_ASSIGNED;
>  	}
> @@ -958,6 +929,12 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
>  		break;
>  	}
> 
> +	if (!rc) {
> +		rtas_hp_event = true;
> +		rc = drmem_update_dt();
> +		rtas_hp_event = false;
> +	}
> +
>  	unlock_device_hotplug();
>  	return rc;
>  }
> 



More information about the Linuxppc-dev mailing list