See below.

On 05/22/2018 04:31 PM, Nathan Fontenot wrote:
> On 05/22/2018 11:37 AM, Michael Bringmann wrote:
>> This patch applies a common parse function for the ibm,drc-info
>> property that can be modified by a callback function to the
>> hot-add CPU code.  Candidate code is replaced by a call to the
>> parser including a pointer to a local context-specific functions,
>> and local data.
>>
>> In addition, a bug in the release of the previous patch set may
>> break things in some of the CPU DLPAR operations.  For instance,
>> when attempting to hot-add a new CPU or set of CPUs, the original
>> patch failed to always properly calculate the available resources,
>> and aborted the operation.
>>
>> Signed-off-by: Michael Bringmann <m...@linux.vnet.ibm.com>
>> Fixes: 3f38000eda48 ("powerpc/firmware: Add definitions for new drc-info 
>> firmwar
>> e feature" -- end of patch series applied to powerpc next)
>> ---
>> Changes in V4:
>>   -- Update code to account for latest kernel checkins.
>>   -- Rebased to 4.17-rc5 kernel
>>   -- Compress some more code
>> ---
>>  arch/powerpc/platforms/pseries/hotplug-cpu.c    |  118 
>> +++++++++++++++++------
>>  arch/powerpc/platforms/pseries/pseries_energy.c |  107 +++++++++++----------
>>  2 files changed, 141 insertions(+), 84 deletions(-)
>>
>> diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c 
>> b/arch/powerpc/platforms/pseries/hotplug-cpu.c
>> index 6ef77ca..ceacad9 100644
>> --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
>> +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
>> @@ -411,27 +411,63 @@ 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 check_cpu_drc_index(struct device_node *parent,
>> +                            int (*cb)(struct of_drc_info *drc,
>> +                                    void *data, void *not_used,
>> +                                    int *ret_code),
>> +                            void *cdata)
>>  {
>>      bool found = false;
>> -    int rc, index;
>>
>> -    index = 0;
>> -    while (!found) {
>> -            u32 drc;
>> +    if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
>> +            if (drc_info_parser(parent, cb, "CPU", cdata))
>> +                    found = true;
>> +    } else {
>> +            int index = 0;
>>
>> -            rc = of_property_read_u32_index(parent, "ibm,drc-indexes",
>> -                                            index++, &drc);
>> -            if (rc)
>> -                    break;
>> +            while (!found) {
>> +                    u32 drc;
>>
>> -            if (drc == drc_index)
>> -                    found = true;
>> +                    if (of_property_read_u32_index(parent,
>> +                                            "ibm,drc-indexes",
>> +                                            index++, &drc))
>> +                            break;
>> +                    if (cb(NULL, cdata, &drc, NULL))
>> +                            found = true;
>> +            }
>>      }
>>
>>      return found;
>>  }
>>
>> +struct valid_drc_index_struct {
>> +    u32 targ_drc_index;
>> +};
> 
> Can you help me understand the need to encapsulate the drc_index as a struct.

At this point, it is consistency of use across all of the instances
of using 'walk_drc_info'.  I believe that there were more values in
the structure earlier on.

> 
>> +
>> +static int valid_drc_index_cb(struct of_drc_info *drc, void *idata,
>> +                            void *drc_index, int *ret_code)
>> +{
>> +    struct valid_drc_index_struct *cdata = idata;
>> +
>> +    if (drc) {
>> +            if (!((drc->drc_index_start <= cdata->targ_drc_index) &&
>> +                    (cdata->targ_drc_index <= drc->last_drc_index)))
>> +                    return 0;
>> +    } else {
>> +            if (*((u32 *)drc_index) != cdata->targ_drc_index)
>> +                    return 0;
>> +    }
>> +    (*ret_code) = 1;
>> +    return 1;
>> +}
>> +
>> +static bool valid_cpu_drc_index(struct device_node *parent, u32 drc_index)
>> +{
>> +    struct valid_drc_index_struct cdata = { drc_index };
>> +
>> +    return check_cpu_drc_index(parent, valid_drc_index_cb, &cdata);
>> +}
>> +
>>  static ssize_t dlpar_cpu_add(u32 drc_index)
>>  {
>>      struct device_node *dn, *parent;
>> @@ -721,11 +757,43 @@ static int dlpar_cpu_remove_by_count(u32 
>> cpus_to_remove)
>>      return rc;
>>  }
>>
>> +struct cpus_to_add_struct {
>> +    struct device_node *parent;
>> +    u32 *cpu_drcs;
>> +    u32 cpus_to_add;
>> +    u32 cpus_found;
>> +};
>> +
>> +static int cpus_to_add_cb(struct of_drc_info *drc, void *idata,
>> +                    void *drc_index, int *ret_code)
>> +{
>> +    struct cpus_to_add_struct *cdata = idata;
>> +
>> +    if (drc) {
>> +            int k;
>> +
>> +            for (k = 0; (k < drc->num_sequential_elems) &&
>> +                    (cdata->cpus_found < cdata->cpus_to_add); k++) {
>> +                    u32 idrc = drc->drc_index_start +
>> +                            (k * drc->sequential_inc);
>> +
>> +                    if (dlpar_cpu_exists(cdata->parent, idrc))
>> +                            continue;
>> +                    cdata->cpu_drcs[cdata->cpus_found++] = idrc;
>> +            }
>> +    } else {
>> +            if (!dlpar_cpu_exists(cdata->parent, *((u32 *)drc_index)))
>> +                    cdata->cpu_drcs[cdata->cpus_found++] =
>> +                            *((u32 *)drc_index);
>> +    }
>> +    return 0;
>> +}
>> +
>>  static int find_dlpar_cpus_to_add(u32 *cpu_drcs, u32 cpus_to_add)
>>  {
>>      struct device_node *parent;
>> -    int cpus_found = 0;
>> -    int index, rc;
>> +    struct cpus_to_add_struct cdata = {
>> +            NULL, cpu_drcs, cpus_to_add, 0 };
>>
>>      parent = of_find_node_by_path("/cpus");
>>      if (!parent) {
>> @@ -734,28 +802,14 @@ 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.
>> +    /* Search the appropriate property for possible CPU drcs to
>> +     * add.
>>       */
>> -    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[cpus_found++] = drc;
>> -    }
>> +    cdata.parent = parent;
>> +    check_cpu_drc_index(parent, cpus_to_add_cb, &cdata);
>>
>>      of_node_put(parent);
>> -    return cpus_found;
>> +    return cdata.cpus_found;
>>  }
>>
>>  static int dlpar_cpu_add_by_count(u32 cpus_to_add)
>> diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c 
>> b/arch/powerpc/platforms/pseries/pseries_energy.c
>> index 5261975..d8d7750 100644
>> --- a/arch/powerpc/platforms/pseries/pseries_energy.c
>> +++ b/arch/powerpc/platforms/pseries/pseries_energy.c
>> @@ -36,6 +36,26 @@
>>
>>  /* Helper Routines to convert between drc_index to cpu numbers */
>>
>> +struct cpu_to_drc_index_struct {
>> +    u32     thread_index;
>> +    u32     ret;
>> +};
>> +
>> +static int cpu_to_drc_index_cb(struct of_drc_info *drc, void *idata,
>> +                            void *not_used, int *ret_code)
>> +{
>> +    struct cpu_to_drc_index_struct *cdata = idata;
>> +    int ret = 0;
>> +
>> +    if (cdata->thread_index < drc->last_drc_index) {
> 
> Is this correct? You're comparing a thread index to a drc index.

I believe so.  I will check when I retest this week, hopefully.

> 
>> +            cdata->ret = drc->drc_index_start +
>> +                    (cdata->thread_index * drc->sequential_inc);
>> +            ret = 1;
>> +    }
>> +    (*ret_code) = ret;
>> +    return ret;
>> +}
>> +
>>  static u32 cpu_to_drc_index(int cpu)
>>  {
>>      struct device_node *dn = NULL;
>> @@ -51,30 +71,14 @@ static u32 cpu_to_drc_index(int cpu)
>>      thread_index = cpu_core_index_of_thread(cpu);
>>
>>      if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
>> -            struct property *info = NULL;
>> -            struct of_drc_info drc;
>> -            int j;
>> -            u32 num_set_entries;
>> -            const __be32 *value;
>> -
>> -            info = of_find_property(dn, "ibm,drc-info", NULL);
>> -            if (info == NULL)
>> -                    goto err_of_node_put;
>> +            struct cpu_to_drc_index_struct cdata = {
>> +                    thread_index, 0 };
>>
>> -            value = info->value;
>> -            num_set_entries = of_read_number(value++, 1);
>> -
>> -            for (j = 0; j < num_set_entries; j++) {
>> -
>> -                    of_read_drc_info_cell(&info, &value, &drc);
>> -                    if (strncmp(drc.drc_type, "CPU", 3))
>> -                            goto err;
>> -
>> -                    if (thread_index < drc.last_drc_index)
>> -                            break;
>> -            }
>> -
>> -            ret = drc.drc_index_start + (thread_index * drc.sequential_inc);
>> +            rc = drc_info_parser(dn, &cpu_to_drc_index_cb,
>> +                                    "CPU", &cdata);
>> +            if (rc < 0)
>> +                    goto err_of_node_put;
>> +            ret = cdata.ret;
>>      } else {
>>              const __be32 *indexes;
>>
>> @@ -100,11 +104,33 @@ static u32 cpu_to_drc_index(int cpu)
>>      return ret;
>>  }
>>
>> +struct drc_index_to_cpu_struct {
>> +    u32     drc_index;
>> +    u32     thread_index;
>> +    u32     cpu;
>> +};
>> +
>> +static int drc_index_to_cpu_cb(struct of_drc_info *drc,
>> +                            void *idata, void *not_used, int *ret_code)
>> +{
>> +    struct drc_index_to_cpu_struct *cdata = idata;
>> +
>> +    if (cdata->drc_index > drc->last_drc_index) {
>> +            cdata->cpu += drc->num_sequential_elems;
>> +    } else {
>> +            cdata->cpu += ((cdata->drc_index - drc->drc_index_start) /
>> +                            drc->sequential_inc);
>> +            cdata->thread_index = cpu_first_thread_of_core(cdata->cpu);
> 
> Should this return 1 here to avoid continuing to walk the drc_info entries?

Yes.

> 
> -Nathan

Michael

> 
>> +    }
>> +    (*ret_code) = 0;
>> +    return 0;
>> +}
>> +
>>  static int drc_index_to_cpu(u32 drc_index)
>>  {
>>      struct device_node *dn = NULL;
>>      const int *indexes;
>> -    int thread_index = 0, cpu = 0;
>> +    int thread_index = 0;
>>      int rc = 1;
>>
>>      dn = of_find_node_by_path("/cpus");
>> @@ -112,36 +138,13 @@ static int drc_index_to_cpu(u32 drc_index)
>>              goto err;
>>
>>      if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
>> -            struct property *info = NULL;
>> -            struct of_drc_info drc;
>> -            int j;
>> -            u32 num_set_entries;
>> -            const __be32 *value;
>> -
>> -            info = of_find_property(dn, "ibm,drc-info", NULL);
>> -            if (info == NULL)
>> -                    goto err_of_node_put;
>> -
>> -            value = info->value;
>> -            num_set_entries = of_read_number(value++, 1);
>> -
>> -            for (j = 0; j < num_set_entries; j++) {
>> +            struct drc_index_to_cpu_struct cdata = {
>> +                    drc_index, 0, 0 };
>>
>> -                    of_read_drc_info_cell(&info, &value, &drc);
>> -                    if (strncmp(drc.drc_type, "CPU", 3))
>> -                            goto err;
>> +            rc = drc_info_parser(dn, &drc_index_to_cpu_cb,
>> +                                    "CPU", &cdata);
>> +            thread_index = cdata.thread_index;
>>
>> -                    if (drc_index > drc.last_drc_index) {
>> -                            cpu += drc.num_sequential_elems;
>> -                            continue;
>> -                    }
>> -                    cpu += ((drc_index - drc.drc_index_start) /
>> -                            drc.sequential_inc);
>> -
>> -                    thread_index = cpu_first_thread_of_core(cpu);
>> -                    rc = 0;
>> -                    break;
>> -            }
>>      } else {
>>              unsigned long int i;
>>
> 
> 

-- 
Michael W. Bringmann
Linux Technology Center
IBM Corporation
Tie-Line  363-5196
External: (512) 286-5196
Cell:       (512) 466-0650
m...@linux.vnet.ibm.com

Reply via email to