From: Tyrel Datwyler <tyreld@xxxxxxxxxxxxxxxxxx> Older firmwares provided information about Dynamic Reconfig Connectors (DRC) through several device tree properties, namely ibm,drc-types, ibm,drc-indexes, ibm,drc-names, and ibm,drc-power-domains. New firmwares have the ability to present this same information in a much condensed format through a device tree property called ibm,drc-info. The existing cpu DLPAR hotplug code only understands the older DRC property format when validating the drc-index of a cpu during a hotplug add. This updates those code paths to use the ibm,drc-info property, when present, instead for validation. Signed-off-by: Tyrel Datwyler <tyreld@xxxxxxxxxxxxx> --- arch/powerpc/platforms/pseries/hotplug-cpu.c | 117 ++++++++++++++++++++------- 1 file changed, 89 insertions(+), 28 deletions(-) diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index bbda646..a2b6cd1 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -407,25 +407,61 @@ static bool dlpar_cpu_exists(struct device_node *parent, u32 drc_index) return found; } -static bool valid_cpu_drc_index(struct device_node *parent, u32 drc_index) +static bool drc_info_valid_index(struct device_node *parent, u32 drc_index) { - bool found = false; - int rc, index; + struct property *info; + struct of_drc_info drc; + const __be32 *value; + int count, i, j; - index = 0; - while (!found) { - u32 drc; + info = of_find_property(parent, "ibm,drc-info", NULL); + if (!info) + return false; - rc = of_property_read_u32_index(parent, "ibm,drc-indexes", - index++, &drc); - if (rc) + value = of_prop_next_u32(info, NULL, &count); + + /* First value of ibm,drc-info is number of drc-info records */ + if (value) + value++; + else + return false; + + for (i = 0; i < count; i++) { + if (of_read_drc_info_cell(&info, &value, &drc)) + return false; + + if (strncmp(drc.drc_type, "CPU", 3)) break; - if (drc == drc_index) - found = true; + if (drc_index > drc.last_drc_index) + continue; + + for (j = 0; j < drc.num_sequential_elems; j++) + if (drc_index == (drc.drc_index_start + (drc.sequential_inc * j))) + return true; } - return found; + return false; +} + +static bool valid_cpu_drc_index(struct device_node *parent, u32 drc_index) +{ + const __be32 *indexes; + int i; + + if (of_find_property(parent, "ibm,drc-info", NULL)) + return drc_info_valid_index(parent, drc_index); + + indexes = of_get_property(parent, "ibm,drc-indexes", NULL); + if (!indexes) + return false; + + for (i = 0; i < indexes[0]; i++) { + if (be32_to_cpu(indexes[i + 1]) == drc_index) + return true; + } + + return false; } static ssize_t dlpar_cpu_add(u32 drc_index) @@ -720,8 +756,11 @@ static int dlpar_cpu_remove_by_count(u32 cpus_to_remove) static int find_dlpar_cpus_to_add(u32 *cpu_drcs, u32 cpus_to_add) { struct device_node *parent; + struct property *info; + const __be32 *indexes; int cpus_found = 0; - int index, rc; + int i, j; + u32 drc_index; parent = of_find_node_by_path("/cpus"); if (!parent) { @@ -730,24 +769,46 @@ static int find_dlpar_cpus_to_add(u32 *cpu_drcs, u32 cpus_to_add) return -1; } - /* 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. - */ - index = 1; - while (cpus_found < cpus_to_add) { - u32 drc; + info = of_find_property(parent, "ibm,drc-info", NULL); + if (info) { + struct of_drc_info drc; + const __be32 *value; + int count; - rc = of_property_read_u32_index(parent, "ibm,drc-indexes", - index++, &drc); - if (rc) - break; + value = of_prop_next_u32(info, NULL, &count); + if (value) + value++; - if (dlpar_cpu_exists(parent, drc)) - continue; + for (i = 0; i < count; i++) { + of_read_drc_info_cell(&info, &value, &drc); + if (strncmp(drc.drc_type, "CPU", 3)) + break; + + for (j = 0; j < drc.num_sequential_elems; j++) { + drc_index = drc.drc_index_start + (drc.sequential_inc * j); + + if (dlpar_cpu_exists(parent, drc_index)) + continue; - cpu_drcs[cpus_found++] = drc; + cpu_drcs[cpus_found++] = drc_index; + } + } + } else { + indexes = of_get_property(parent, "ibm,drc-indexes", 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. + */ + for (i = 1; i < indexes[0]; i++) { + drc_index = be32_to_cpu(indexes[i]); + + if (dlpar_cpu_exists(parent, drc_index)) + continue; + + cpu_drcs[cpus_found++] = drc_index; + } } of_node_put(parent); -- 2.7.4