Add the ability to hotplug add cpus via rtas hotplug events by either specifying the drc index of the CPU to add, or providing a count of the number of CPUs to add.
Signed-off-by: Nathan Fontenot <nf...@linux.vnet.ibm.com> --- arch/powerpc/platforms/pseries/hotplug-cpu.c | 94 ++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 635f0ba..8ec52c0 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -679,6 +679,92 @@ static int dlpar_cpu_remove_by_count(u32 cpus_to_remove) return rc; } +static u32 *dlpar_cpus_to_add(u32 cpus_to_add) +{ + struct device_node *parent; + u32 *cpu_drcs; + int cpus_found = 0; + int i, index, rc; + + cpu_drcs = kcalloc(cpus_to_add, sizeof(*cpu_drcs), GFP_KERNEL); + if (!cpu_drcs) + return NULL; + + parent = of_find_node_by_path("/cpus"); + if (!parent) { + kfree(cpu_drcs); + return NULL; + } + + /* Search the ibm,drc-indexes array for possible CPU drcs to + * add. Note that the format of the ibm,drc-indexes array is + * the number of entries in the array followed by the array + * of drc values so we start looking at index = 1. + */ + i = 0; + index = 1; + while (cpus_found < cpus_to_add) { + u32 drc; + + rc = of_property_read_u32_index(parent, "ibm,drc-indexes", + index++, &drc); + if (rc) + break; + + if (dlpar_cpu_exists(parent, drc)) + continue; + + cpu_drcs[i++] = drc; + cpus_found++; + } + + of_node_put(parent); + + if (cpus_found < cpus_to_add) { + pr_warn("Failed to find enough CPUs (%d of %d) to add\n", + cpus_found, cpus_to_add); + kfree(cpu_drcs); + cpu_drcs = NULL; + } + + return cpu_drcs; +} + +static int dlpar_cpu_add_by_count(u32 cpus_to_add) +{ + u32 *cpu_drcs; + int cpus_added = 0; + int i, rc; + + pr_debug("Attempting to hot-add %d CPUs\n", cpus_to_add); + + cpu_drcs = dlpar_cpus_to_add(cpus_to_add); + if (!cpu_drcs) + return -EINVAL; + + for (i = 0; i < cpus_to_add; i++) { + rc = dlpar_cpu_add(cpu_drcs[i]); + if (rc) + break; + + cpus_added++; + } + + if (cpus_added < cpus_to_add) { + pr_warn("CPU hot-add failed, removing any added CPUs\n"); + + for (i = 0; i < cpus_added; i++) + dlpar_cpu_remove_by_index(cpu_drcs[i]); + + rc = -EINVAL; + } else { + rc = 0; + } + + kfree(cpu_drcs); + return rc; +} + int dlpar_cpu(struct pseries_hp_errorlog *hp_elog) { u32 count, drc_index; @@ -698,6 +784,14 @@ int dlpar_cpu(struct pseries_hp_errorlog *hp_elog) else rc = -EINVAL; break; + case PSERIES_HP_ELOG_ACTION_ADD: + if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) + rc = dlpar_cpu_add_by_count(count); + else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) + rc = dlpar_cpu_add(drc_index); + else + rc = -EINVAL; + break; default: pr_err("Invalid action (%d) specified\n", hp_elog->action); rc = -EINVAL; _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev