migration/memory: This patch adds a new pseries hotplug action for CPU and memory operations, PSERIES_HP_ELOG_ACTION_READD_MULTIPLE. This is a variant of the READD operation which performs the action upon multiple instances of the resource at one time. The operation is to be triggered by device-tree analysis of updates by RTAS events analyzed by 'migation_store' during post-migration processing. It will be used for memory updates, initially.
Signed-off-by: Michael Bringmann <m...@linux.vnet.ibm.com> --- Changes in v07: -- Provide more useful return value from dlpar_memory_readd_multiple Changes in v05: -- Provide dlpar_memory_readd_helper routine to compress some common code Changes in v04: -- Move init of 'lmb->internal_flags' in init_drmem_v2_lmbs to previous patch. -- Pull in implementation of dlpar_memory_readd_multiple() to go with operation flag. --- arch/powerpc/include/asm/rtas.h | 1 arch/powerpc/platforms/pseries/hotplug-memory.c | 47 ++++++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 0183e95..cc00451 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -333,6 +333,7 @@ struct pseries_hp_errorlog { #define PSERIES_HP_ELOG_ACTION_ADD 1 #define PSERIES_HP_ELOG_ACTION_REMOVE 2 #define PSERIES_HP_ELOG_ACTION_READD 3 +#define PSERIES_HP_ELOG_ACTION_READD_MULTIPLE 4 #define PSERIES_HP_ELOG_ID_DRC_NAME 1 #define PSERIES_HP_ELOG_ID_DRC_INDEX 2 diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 2b796da..c44c6a6 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -507,6 +507,19 @@ static int dlpar_memory_remove_by_index(u32 drc_index) return rc; } +static int dlpar_memory_readd_helper(struct drmem_lmb *lmb) +{ + int rc; + + rc = dlpar_remove_lmb(lmb); + if (!rc) { + rc = dlpar_add_lmb(lmb); + if (rc) + dlpar_release_drc(lmb->drc_index); + } + return rc; +} + static int dlpar_memory_readd_by_index(u32 drc_index) { struct drmem_lmb *lmb; @@ -519,12 +532,7 @@ static int dlpar_memory_readd_by_index(u32 drc_index) for_each_drmem_lmb(lmb) { if (lmb->drc_index == drc_index) { lmb_found = 1; - rc = dlpar_remove_lmb(lmb); - if (!rc) { - rc = dlpar_add_lmb(lmb); - if (rc) - dlpar_release_drc(lmb->drc_index); - } + rc = dlpar_memory_readd_helper(lmb); break; } } @@ -541,6 +549,26 @@ static int dlpar_memory_readd_by_index(u32 drc_index) return rc; } +static int dlpar_memory_readd_multiple(void) +{ + struct drmem_lmb *lmb; + int rc = 0; + + pr_info("Attempting to update multiple LMBs\n"); + + for_each_drmem_lmb(lmb) { + if (drmem_lmb_update(lmb)) { + rc |= dlpar_memory_readd_helper(lmb); + drmem_remove_lmb_update(lmb); + } + } + + if (rc) + return -EIO; + + return rc; +} + static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index) { struct drmem_lmb *lmb, *start_lmb, *end_lmb; @@ -641,6 +669,10 @@ static int dlpar_memory_readd_by_index(u32 drc_index) { return -EOPNOTSUPP; } +static int dlpar_memory_readd_multiple(void) +{ + return -EOPNOTSUPP; +} static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index) { @@ -918,6 +950,9 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) drc_index = hp_elog->_drc_u.drc_index; rc = dlpar_memory_readd_by_index(drc_index); break; + case PSERIES_HP_ELOG_ACTION_READD_MULTIPLE: + rc = dlpar_memory_readd_multiple(); + break; default: pr_err("Invalid action (%d) specified\n", hp_elog->action); rc = -EINVAL;