On 01/06/2017 01:27 PM, John Allen wrote: > Currently, memory must be hot removed and subsequently re-added in order > to dynamically update the affinity of LMBs specified by a PRRN event. > Earlier implementations of the PRRN event handler ran into issues in which > the hot remove would occur successfully, but a hotplug event would be > initiated from another source and grab the hotplug lock preventing the hot > add from occurring. To prevent this situation, this patch introduces the > notion of a hot "readd" action for memory which atomizes a hot remove and > a hot add into a single, serialized operation on the hotplug queue. > > Signed-off-by: John Allen <jal...@linux.vnet.ibm.com>
Reviewed-by: Nathan Fontenot <nf...@linux.vnet.ibm.com> > --- > diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h > index 9c23baa..076b892 100644 > --- a/arch/powerpc/include/asm/rtas.h > +++ b/arch/powerpc/include/asm/rtas.h > @@ -318,6 +318,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_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 0eb4b1d..06f10a8 100644 > --- a/arch/powerpc/platforms/pseries/hotplug-memory.c > +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c > @@ -560,6 +560,44 @@ static int dlpar_memory_remove_by_index(u32 drc_index, > struct property *prop) > return rc; > } > > +static int dlpar_memory_readd_by_index(u32 drc_index, struct property *prop) > +{ > + struct of_drconf_cell *lmbs; > + u32 num_lmbs, *p; > + int lmb_found; > + int i, rc; > + > + pr_info("Attempting to update LMB, drc index %x\n", drc_index); > + > + p = prop->value; > + num_lmbs = *p++; > + lmbs = (struct of_drconf_cell *)p; > + > + lmb_found = 0; > + for (i = 0; i < num_lmbs; i++) { > + if (lmbs[i].drc_index == drc_index) { > + lmb_found = 1; > + rc = dlpar_remove_lmb(&lmbs[i]); > + if (!rc) { > + rc = dlpar_add_lmb(&lmbs[i]); > + if (rc) > + dlpar_release_drc(lmbs[i].drc_index); > + } > + break; > + } > + } > + > + if (!lmb_found) > + rc = -EINVAL; > + > + if (rc) > + pr_info("Failed to update memory at %llx\n", > + lmbs[i].base_addr); > + else > + pr_info("Memory at %llx was updated\n", lmbs[i].base_addr); > + > + return rc; > +} > #else > static inline int pseries_remove_memblock(unsigned long base, > unsigned int memblock_size) > @@ -776,6 +814,9 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) > else > rc = -EINVAL; > break; > + case PSERIES_HP_ELOG_ACTION_READD: > + rc = dlpar_memory_readd_by_index(drc_index, prop); > + break; > default: > pr_err("Invalid action (%d) specified\n", hp_elog->action); > rc = -EINVAL; >