From: Michael Bringmann <hidden> Date: 2017-11-15 18:08:58
Several properties in the DRC device tree format are replaced by
more compact representations to allow, for example, for the encoding
of vast amounts of memory, and or reduced duplication of information
in related data structures.
"ibm,drc-info": This property, when present, replaces the following
four properties: "ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains". This property is defined for all
dynamically reconfigurable platform nodes. The "ibm,drc-info" elements
are intended to provide a more compact representation, and reduce some
search overhead.
"ibm,architecture.vec": Bidirectional communication mechanism between
the host system and the front end processor indicating what features
the host system supports and what features the front end processor will
actually provide. In this case, we are indicating that the host system
can support the new device tree structure "ibm,drc-info".
Signed-off-by: Michael Bringmann <redacted>
Michael Bringmann (4):
powerpc/firmware: Add definitions for new drc-info firmware feature.
pseries/drc-info: Search new DRC properties for CPU indexes
hotplug/drc-info: Add code to search new devtree property
powerpc: Enable support for new DRC devtree property
---
Changes in V3:
-- Achieved some code compression by passing data by structure
-- Now passing more values by structure reducing use of local
declarations / initialization.
-- Improve some code spacing for better clarity.
From: Michael Bringmann <hidden> Date: 2017-11-15 18:09:29
rpadlpar_core.c: Provide parallel routines to search the older device-
tree properties ("ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains"), or the new property "ibm,drc-info".
The interface to examine the DRC information is changed from a "get"
function that returns values for local verification elsewhere, to a
"check" function that validates the 'name' and/or 'type' of a device
node. This update hides the format of the underlying device-tree
properties, and concentrates the value checks into a single function
without requiring the user to verify whether a search was successful.
Signed-off-by: Michael Bringmann <redacted>
---
Changes in V3:
-- Now passing more values by structure reducing use of local
declarations / initialization.
-- Improve some code spacing for better clarity.
---
drivers/pci/hotplug/rpadlpar_core.c | 13 ++--
drivers/pci/hotplug/rpaphp.h | 4 +
drivers/pci/hotplug/rpaphp_core.c | 110 +++++++++++++++++++++++++++--------
3 files changed, 92 insertions(+), 35 deletions(-)
@@ -30,6 +30,7 @@#include<linux/smp.h>#include<linux/init.h>#include<linux/vmalloc.h>+#include<asm/firmware.h>#include<asm/eeh.h> /* for eeh_add_device() */#include<asm/rtas.h> /* rtas_call */#include<asm/pci-bridge.h> /* for pci_controller */
@@ -196,25 +197,21 @@ static int get_children_props(struct device_node *dn, const int **drc_indexes,return0;}-/* To get the DRC props describing the current node, first obtain it's-*my-drc-indexproperty.NextobtaintheDRClistfromit'sparent.Use-*themy-drc-indexforcorrelation,andobtaintherequestedproperties.++/* Verify the existence of 'drc_name' and/or 'drc_type' within the+*currentnode.Firstobtainit'smy-drc-indexproperty.Next,+*obtaintheDRCinfofromit'sparent.Usethemy-drc-indexfor+*correlation,andobtain/validatetherequestedproperties.*/-intrpaphp_get_drc_props(structdevice_node*dn,int*drc_index,-char**drc_name,char**drc_type,int*drc_power_domain)++staticintrpaphp_check_drc_props_v1(structdevice_node*dn,char*drc_name,+char*drc_type,unsignedintmy_index){+char*name_tmp,*type_tmp;constint*indexes,*names;constint*types,*domains;-constunsignedint*my_index;-char*name_tmp,*type_tmp;inti,rc;-my_index=of_get_property(dn,"ibm,my-drc-index",NULL);-if(!my_index){-/* Node isn't DLPAR/hotplug capable */-return-EINVAL;-}-rc=get_children_props(dn->parent,&indexes,&names,&types,&domains);if(rc<0){return-EINVAL;
@@ -225,24 +222,87 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,/* Iterate through parent properties, looking for my-drc-index */for(i=0;i<be32_to_cpu(indexes[0]);i++){-if((unsignedint)indexes[i+1]==*my_index){-if(drc_name)-*drc_name=name_tmp;-if(drc_type)-*drc_type=type_tmp;-if(drc_index)-*drc_index=be32_to_cpu(*my_index);-if(drc_power_domain)-*drc_power_domain=be32_to_cpu(domains[i+1]);-return0;-}+if((unsignedint)indexes[i+1]==my_index)+break;+name_tmp+=(strlen(name_tmp)+1);type_tmp+=(strlen(type_tmp)+1);}+if(((drc_name==NULL)||(drc_name&&!strcmp(drc_name,name_tmp)))&&+((drc_type==NULL)||(drc_type&&!strcmp(drc_type,type_tmp))))+return0;++return-EINVAL;+}++staticintrpaphp_check_drc_props_v2(structdevice_node*dn,char*drc_name,+char*drc_type,unsignedintmy_index)+{+structproperty*info;+unsignedintentries;+structof_drc_infodrc;+void*value;+intj;++info=of_find_property(dn->parent,"ibm,drc-info",NULL);+if(info==NULL)+return-EINVAL;++value=info->value;+value=(void*)of_prop_next_u32(info,value,&entries);+if(!value)+return-EINVAL;++for(j=0;j<entries;j++){+of_one_drc_info(&info,&value,&drc);++/* Should now know end of current entry */++WARN_ON((my_index<drc.drc_index_start)||+(((my_index-drc.drc_index_start)%+drc.sequential_inc)!=0));++if(my_index>drc.last_drc_index)+continue;++break;+}+/* Found it */++if(((drc_name==NULL)||+(drc_name&&!strncmp(drc_name,+drc.drc_name_prefix,+strlen(drc.drc_name_prefix))))&&+((drc_type==NULL)||+(drc_type&&!strncmp(drc_type,+drc.drc_type,+strlen(drc.drc_type)))))+return0;+return-EINVAL;}-EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);++intrpaphp_check_drc_props(structdevice_node*dn,char*drc_name,+char*drc_type)+{+constunsignedint*my_index;++my_index=of_get_property(dn,"ibm,my-drc-index",NULL);+if(!my_index){+/* Node isn't DLPAR/hotplug capable */+return-EINVAL;+}++if(firmware_has_feature(FW_FEATURE_DRC_INFO))+returnrpaphp_check_drc_props_v2(dn,drc_name,drc_type,+*my_index);+else+returnrpaphp_check_drc_props_v1(dn,drc_name,drc_type,+*my_index);+}+EXPORT_SYMBOL_GPL(rpaphp_check_drc_props);+staticintis_php_type(char*drc_type){
From: Michael Bringmann <hidden> Date: 2017-11-15 18:09:30
Firmware Features: Define new bit flag representing the presence of
new device tree property "ibm,drc-info". The flag is used to tell
the front end processor whether the Linux kernel supports the new
property, and by the front end processor to tell the Linux kernel
that the new property is present in the device tree.
Signed-off-by: Michael Bringmann <redacted>
---
arch/powerpc/include/asm/firmware.h | 3 ++-
arch/powerpc/include/asm/prom.h | 1 +
arch/powerpc/platforms/pseries/firmware.c | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)
From: Michael Bringmann <hidden> Date: 2017-11-15 18:09:30
pseries/drc-info: Provide parallel routines to convert between
drc_index and CPU numbers at runtime, using the older device-tree
properties ("ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains"), or the new property "ibm,drc-info".
Signed-off-by: Michael Bringmann <redacted>
---
Changes in V3:
-- Some code compression and use of data structures for value passing.
---
arch/powerpc/include/asm/prom.h | 15 ++
arch/powerpc/platforms/pseries/of_helpers.c | 60 ++++++++++
arch/powerpc/platforms/pseries/pseries_energy.c | 139 ++++++++++++++++++-----
3 files changed, 186 insertions(+), 28 deletions(-)
@@ -36,3 +37,62 @@ struct device_node *pseries_of_derive_parent(const char *path)kfree(parent_path);returnparent?parent:ERR_PTR(-EINVAL);}+++/* Helper Routines to convert between drc_index to cpu numbers */++intof_one_drc_info(structproperty**prop,void**curval,+structof_drc_info*data)+{+constchar*p;+const__be32*p2;++if(!data)+return-EINVAL;++/* Get drc-type:encode-string */+p=data->drc_type=(*curval);+p=of_prop_next_string(*prop,p);+if(!p)+return-EINVAL;++/* Get drc-name-prefix:encode-string */+data->drc_name_prefix=(char*)p;+p=of_prop_next_string(*prop,p);+if(!p)+return-EINVAL;++/* Get drc-index-start:encode-int */+p2=(const__be32*)p;+p2=of_prop_next_u32(*prop,p2,&data->drc_index_start);+if(!p2)+return-EINVAL;++/* Get/skip drc-name-suffix-start:encode-int */+p2=of_prop_next_u32(*prop,p2,&data->drc_name_suffix_start);+if(!p2)+return-EINVAL;++/* Get number-sequential-elements:encode-int */+p2=of_prop_next_u32(*prop,p2,&data->num_sequential_elems);+if(!p2)+return-EINVAL;++/* Get sequential-increment:encode-int */+p2=of_prop_next_u32(*prop,p2,&data->sequential_inc);+if(!p2)+return-EINVAL;++/* Get/skip drc-power-domain:encode-int */+p2=of_prop_next_u32(*prop,p2,&data->drc_power_domain);+if(!p2)+return-EINVAL;++/* Should now know end of current entry */+(*curval)=(void*)p2;+data->last_drc_index=data->drc_index_start++((data->num_sequential_elems-1)*data->sequential_inc);++return0;+}+EXPORT_SYMBOL(of_one_drc_info);
@@ -38,26 +39,65 @@staticu32cpu_to_drc_index(intcpu){structdevice_node*dn=NULL;-constint*indexes;-inti;+intthread_index;intrc=1;u32ret=0;dn=of_find_node_by_path("/cpus");if(dn==NULL)gotoerr;-indexes=of_get_property(dn,"ibm,drc-indexes",NULL);-if(indexes==NULL)-gotoerr_of_node_put;+/* Convert logical cpu number to core number */-i=cpu_core_index_of_thread(cpu);-/*-*Thefirstelementindexes[0]isthenumberofdrc_indexes-*returnedinthelist.Hencei+1willgetthedrc_index-*correspondingtocorenumberi.-*/-WARN_ON(i>indexes[0]);-ret=indexes[i+1];+thread_index=cpu_core_index_of_thread(cpu);++if(firmware_has_feature(FW_FEATURE_DRC_INFO)){+structproperty*info=NULL;+structof_drc_infodrc;+intj;+u32num_set_entries;+void*value;++info=of_find_property(dn,"ibm,drc-info",NULL);+if(info==NULL)+gotoerr_of_node_put;++value=info->value;+value=(void*)of_prop_next_u32(info,value,&num_set_entries);+if(!value)+gotoerr_of_node_put;++for(j=0;j<num_set_entries;j++){++of_one_drc_info(&info,&value,&drc);+if(strncmp(drc.drc_type,"CPU",3))+gotoerr;++if(thread_index<drc.last_drc_index)+break;++WARN_ON(((thread_index-drc.drc_index_start)%+drc.sequential_inc)!=0);+}+WARN_ON((drc.num_sequential_elems==0)||+(drc.sequential_inc==0));++ret=drc.drc_index_start+(thread_index*drc.sequential_inc);+}else{+const__be32*indexes;++indexes=of_get_property(dn,"ibm,drc-indexes",NULL);+if(indexes==NULL)+gotoerr_of_node_put;++/*+*Thefirstelementindexes[0]isthenumberofdrc_indexes+*returnedinthelist.Hencethread_index+1willgetthe+*drc_indexcorrespondingtocorenumberthread_index.+*/+WARN_ON(thread_index>indexes[0]);+ret=indexes[thread_index+1];+}+rc=0;err_of_node_put:
@@ -72,34 +112,77 @@ static int drc_index_to_cpu(u32 drc_index){structdevice_node*dn=NULL;constint*indexes;-inti,cpu=0;+intthread_index=0,cpu=0;intrc=1;dn=of_find_node_by_path("/cpus");if(dn==NULL)gotoerr;-indexes=of_get_property(dn,"ibm,drc-indexes",NULL);-if(indexes==NULL)-gotoerr_of_node_put;-/*-*Firstelementinthearrayisthenumberofdrc_indexes-*returned.Searchthroughthelisttofindthematching-*drc_indexandgetthecorenumber-*/-for(i=0;i<indexes[0];i++){-if(indexes[i+1]==drc_index)++if(firmware_has_feature(FW_FEATURE_DRC_INFO)){+structproperty*info=NULL;+structof_drc_infodrc;+intj;+u32num_set_entries;+void*value;++info=of_find_property(dn,"ibm,drc-info",NULL);+if(info==NULL)+gotoerr_of_node_put;++value=info->value;+value=(void*)of_prop_next_u32(info,value,&num_set_entries);+if(!value)+gotoerr_of_node_put;++for(j=0;j<num_set_entries;j++){++of_one_drc_info(&info,&value,&drc);+if(strncmp(drc.drc_type,"CPU",3))+gotoerr;++WARN_ON(drc_index<drc.drc_index_start);+WARN_ON(((drc_index-drc.drc_index_start)%+drc.sequential_inc)!=0);++if(drc_index>drc.last_drc_index){+cpu+=drc.num_sequential_elems;+continue;+}else{+cpu+=((drc_index-drc.drc_index_start)/+drc.sequential_inc);+}++thread_index=cpu_first_thread_of_core(cpu);+rc=0;break;+}+}else{+unsignedlonginti;++indexes=of_get_property(dn,"ibm,drc-indexes",NULL);+if(indexes==NULL)+gotoerr_of_node_put;+/*+*Firstelementinthearrayisthenumberofdrc_indexes+*returned.Searchthroughthelisttofindthematching+*drc_indexandgetthecorenumber+*/+for(i=0;i<indexes[0];i++){+if(indexes[i+1]==drc_index)+break;+}+/* Convert core number to logical cpu number */+thread_index=cpu_first_thread_of_core(i);+rc=0;}-/* Convert core number to logical cpu number */-cpu=cpu_first_thread_of_core(i);-rc=0;err_of_node_put:of_node_put(dn);err:if(rc)printk(KERN_WARNING"drc_index_to_cpu(%d) failed",drc_index);-returncpu;+returnthread_index;}/*
From: Michael Bringmann <hidden> Date: 2017-11-15 18:09:34
prom_init.c: Enable support for new DRC device tree property
"ibm,drc-info" in initial handshake between the Linux kernel and
the front end processor.
Signed-off-by: Michael Bringmann <redacted>
---
arch/powerpc/kernel/prom_init.c | 1 +
1 file changed, 1 insertion(+)
Firmware Features: Define new bit flag representing the presence of
new device tree property "ibm,drc-info". The flag is used to tell
the front end processor whether the Linux kernel supports the new
property, and by the front end processor to tell the Linux kernel
that the new property is present in the device tree.
This patch seems to be adding a bit for the drc-info feature so that
we can use the firmware_has_feature() interface to determine if the
device tree has the new ibm,drc-info properties.
I'm not sure what front-end processor you're referring to? Is this
in reference to the architecture vector that is exchanged with firmware?
-Nathan
pseries/drc-info: Provide parallel routines to convert between
drc_index and CPU numbers at runtime, using the older device-tree
properties ("ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains"), or the new property "ibm,drc-info".
Signed-off-by: Michael Bringmann <redacted>
---
Changes in V3:
-- Some code compression and use of data structures for value passing.
---
arch/powerpc/include/asm/prom.h | 15 ++
arch/powerpc/platforms/pseries/of_helpers.c | 60 ++++++++++
arch/powerpc/platforms/pseries/pseries_energy.c | 139 ++++++++++++++++++-----
3 files changed, 186 insertions(+), 28 deletions(-)
I'm not sure if prom.h is where this really belongs but I also do
not see an existing header file that it really makes sense to put it in.
quoted hunk
+
+
/*
* There are two methods for telling firmware what our capabilities are.
* Newer machines have an "ibm,client-architecture-support" method on the
@@ -36,3 +37,62 @@ struct device_node *pseries_of_derive_parent(const char *path)kfree(parent_path);returnparent?parent:ERR_PTR(-EINVAL);}+++/* Helper Routines to convert between drc_index to cpu numbers */++intof_one_drc_info(structproperty**prop,void**curval,+structof_drc_info*data)
Small nit, this should probably be of_read_drc_info_cell.
+{
+ const char *p;
+ const __be32 *p2;
+
+ if (!data)
+ return -EINVAL;
+
+ /* Get drc-type:encode-string */
+ p = data->drc_type = (*curval);
+ p = of_prop_next_string(*prop, p);
+ if (!p)
+ return -EINVAL;
+
+ /* Get drc-name-prefix:encode-string */
+ data->drc_name_prefix = (char *)p;
+ p = of_prop_next_string(*prop, p);
+ if (!p)
+ return -EINVAL;
+
+ /* Get drc-index-start:encode-int */
+ p2 = (const __be32 *)p;
+ p2 = of_prop_next_u32(*prop, p2, &data->drc_index_start);
+ if (!p2)
+ return -EINVAL;
+
+ /* Get/skip drc-name-suffix-start:encode-int */
You're getting the suffix, should probably drop 'skip' in the comment.
@@ -38,26 +39,65 @@staticu32cpu_to_drc_index(intcpu){structdevice_node*dn=NULL;-constint*indexes;-inti;+intthread_index;intrc=1;u32ret=0;dn=of_find_node_by_path("/cpus");if(dn==NULL)gotoerr;-indexes=of_get_property(dn,"ibm,drc-indexes",NULL);-if(indexes==NULL)-gotoerr_of_node_put;+/* Convert logical cpu number to core number */-i=cpu_core_index_of_thread(cpu);-/*-*Thefirstelementindexes[0]isthenumberofdrc_indexes-*returnedinthelist.Hencei+1willgetthedrc_index-*correspondingtocorenumberi.-*/-WARN_ON(i>indexes[0]);-ret=indexes[i+1];+thread_index=cpu_core_index_of_thread(cpu);++if(firmware_has_feature(FW_FEATURE_DRC_INFO)){+structproperty*info=NULL;
This warning seems like it would fit better in the routine that reads the
drc-info property values.
+
+ ret = drc.drc_index_start + (thread_index*drc.sequential_inc);
Spaces... '*'
quoted hunk
+ } else {
+ const __be32 *indexes;
+
+ indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
+ if (indexes == NULL)
+ goto err_of_node_put;
+
+ /*
+ * The first element indexes[0] is the number of drc_indexes
+ * returned in the list. Hence thread_index+1 will get the
+ * drc_index corresponding to core number thread_index.
+ */
+ WARN_ON(thread_index > indexes[0]);
+ ret = indexes[thread_index + 1];
+ }
+
rc = 0;
err_of_node_put:
@@ -72,34 +112,77 @@ static int drc_index_to_cpu(u32 drc_index) { struct device_node *dn = NULL; const int *indexes;- int i, cpu = 0;+ int thread_index = 0, cpu = 0; int rc = 1; dn = of_find_node_by_path("/cpus"); if (dn == NULL) goto err;- indexes = of_get_property(dn, "ibm,drc-indexes", NULL);- if (indexes == NULL)- goto err_of_node_put;- /*- * First element in the array is the number of drc_indexes- * returned. Search through the list to find the matching- * drc_index and get the core number- */- for (i = 0; i < indexes[0]; i++) {- if (indexes[i + 1] == drc_index)++ if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {+ struct property *info = NULL;+ struct of_drc_info drc;+ int j;+ u32 num_set_entries;+ void *value;++ info = of_find_property(dn, "ibm,drc-info", NULL);+ if (info == NULL)+ goto err_of_node_put;++ value = info->value;+ value = (void *)of_prop_next_u32(info, value, &num_set_entries);+ if (!value)+ goto err_of_node_put;++ for (j = 0; j < num_set_entries; j++) {++ of_one_drc_info(&info, &value, &drc);+ if (strncmp(drc.drc_type, "CPU", 3))+ goto err;++ WARN_ON(drc_index < drc.drc_index_start);+ WARN_ON(((drc_index-drc.drc_index_start)%+ drc.sequential_inc) != 0);++ if (drc_index > drc.last_drc_index) {+ cpu += drc.num_sequential_elems;+ continue;+ } else {
Since you do a continue in the if() part above you shouldn't need to
put this in an else block.
-Nathan
+ 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;
+
+ indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
+ if (indexes == NULL)
+ goto err_of_node_put;
+ /*
+ * First element in the array is the number of drc_indexes
+ * returned. Search through the list to find the matching
+ * drc_index and get the core number
+ */
+ for (i = 0; i < indexes[0]; i++) {
+ if (indexes[i + 1] == drc_index)
+ break;
+ }
+ /* Convert core number to logical cpu number */
+ thread_index = cpu_first_thread_of_core(i);
+ rc = 0;
}
- /* Convert core number to logical cpu number */
- cpu = cpu_first_thread_of_core(i);
- rc = 0;
err_of_node_put:
of_node_put(dn);
err:
if (rc)
printk(KERN_WARNING "drc_index_to_cpu(%d) failed", drc_index);
- return cpu;
+ return thread_index;
}
/*
From: Michael Bringmann <hidden> Date: 2017-11-16 17:38:48
On 11/16/2017 11:06 AM, Nathan Fontenot wrote:
On 11/15/2017 12:09 PM, Michael Bringmann wrote:
quoted
Firmware Features: Define new bit flag representing the presence of
new device tree property "ibm,drc-info". The flag is used to tell
the front end processor whether the Linux kernel supports the new
property, and by the front end processor to tell the Linux kernel
that the new property is present in the device tree.
This patch seems to be adding a bit for the drc-info feature so that
we can use the firmware_has_feature() interface to determine if the
device tree has the new ibm,drc-info properties.
I'm not sure what front-end processor you're referring to? Is this
in reference to the architecture vector that is exchanged with firmware?
I was trying to be generic instead of writing pHyp, BMC, or other.
We can change the comment if it is misleading.
From: Michael Bringmann <hidden> Date: 2017-11-16 17:43:09
See below.
On 11/16/2017 11:34 AM, Nathan Fontenot wrote:
On 11/15/2017 12:09 PM, Michael Bringmann wrote:
quoted
pseries/drc-info: Provide parallel routines to convert between
drc_index and CPU numbers at runtime, using the older device-tree
properties ("ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains"), or the new property "ibm,drc-info".
Signed-off-by: Michael Bringmann <redacted>
---
Changes in V3:
-- Some code compression and use of data structures for value passing.
---
arch/powerpc/include/asm/prom.h | 15 ++
arch/powerpc/platforms/pseries/of_helpers.c | 60 ++++++++++
arch/powerpc/platforms/pseries/pseries_energy.c | 139 ++++++++++++++++++-----
3 files changed, 186 insertions(+), 28 deletions(-)
I'm not sure if prom.h is where this really belongs but I also do
not see an existing header file that it really makes sense to put it in.
If you think of a better place, please let me know.
quoted
+
+
/*
* There are two methods for telling firmware what our capabilities are.
* Newer machines have an "ibm,client-architecture-support" method on the
@@ -36,3 +37,62 @@ struct device_node *pseries_of_derive_parent(const char *path)kfree(parent_path);returnparent?parent:ERR_PTR(-EINVAL);}+++/* Helper Routines to convert between drc_index to cpu numbers */++intof_one_drc_info(structproperty**prop,void**curval,+structof_drc_info*data)
Small nit, this should probably be of_read_drc_info_cell.
Okay. Will change.
quoted
+{
+ const char *p;
+ const __be32 *p2;
+
+ if (!data)
+ return -EINVAL;
+
+ /* Get drc-type:encode-string */
+ p = data->drc_type = (*curval);
+ p = of_prop_next_string(*prop, p);
+ if (!p)
+ return -EINVAL;
+
+ /* Get drc-name-prefix:encode-string */
+ data->drc_name_prefix = (char *)p;
+ p = of_prop_next_string(*prop, p);
+ if (!p)
+ return -EINVAL;
+
+ /* Get drc-index-start:encode-int */
+ p2 = (const __be32 *)p;
+ p2 = of_prop_next_u32(*prop, p2, &data->drc_index_start);
+ if (!p2)
+ return -EINVAL;
+
+ /* Get/skip drc-name-suffix-start:encode-int */
You're getting the suffix, should probably drop 'skip' in the comment.
@@ -38,26 +39,65 @@staticu32cpu_to_drc_index(intcpu){structdevice_node*dn=NULL;-constint*indexes;-inti;+intthread_index;intrc=1;u32ret=0;dn=of_find_node_by_path("/cpus");if(dn==NULL)gotoerr;-indexes=of_get_property(dn,"ibm,drc-indexes",NULL);-if(indexes==NULL)-gotoerr_of_node_put;+/* Convert logical cpu number to core number */-i=cpu_core_index_of_thread(cpu);-/*-*Thefirstelementindexes[0]isthenumberofdrc_indexes-*returnedinthelist.Hencei+1willgetthedrc_index-*correspondingtocorenumberi.-*/-WARN_ON(i>indexes[0]);-ret=indexes[i+1];+thread_index=cpu_core_index_of_thread(cpu);++if(firmware_has_feature(FW_FEATURE_DRC_INFO)){+structproperty*info=NULL;
This warning seems like it would fit better in the routine that reads the
drc-info property values.
Wanted to have minimal impact on original calling code. Will remove this one.
quoted
+
+ ret = drc.drc_index_start + (thread_index*drc.sequential_inc);
Spaces... '*'
Okay.
quoted
+ } else {
+ const __be32 *indexes;
+
+ indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
+ if (indexes == NULL)
+ goto err_of_node_put;
+
+ /*
+ * The first element indexes[0] is the number of drc_indexes
+ * returned in the list. Hence thread_index+1 will get the
+ * drc_index corresponding to core number thread_index.
+ */
+ WARN_ON(thread_index > indexes[0]);
+ ret = indexes[thread_index + 1];
+ }
+
rc = 0;
err_of_node_put:
@@ -72,34 +112,77 @@ static int drc_index_to_cpu(u32 drc_index) { struct device_node *dn = NULL; const int *indexes;- int i, cpu = 0;+ int thread_index = 0, cpu = 0; int rc = 1; dn = of_find_node_by_path("/cpus"); if (dn == NULL) goto err;- indexes = of_get_property(dn, "ibm,drc-indexes", NULL);- if (indexes == NULL)- goto err_of_node_put;- /*- * First element in the array is the number of drc_indexes- * returned. Search through the list to find the matching- * drc_index and get the core number- */- for (i = 0; i < indexes[0]; i++) {- if (indexes[i + 1] == drc_index)++ if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {+ struct property *info = NULL;+ struct of_drc_info drc;+ int j;+ u32 num_set_entries;+ void *value;++ info = of_find_property(dn, "ibm,drc-info", NULL);+ if (info == NULL)+ goto err_of_node_put;++ value = info->value;+ value = (void *)of_prop_next_u32(info, value, &num_set_entries);+ if (!value)+ goto err_of_node_put;++ for (j = 0; j < num_set_entries; j++) {++ of_one_drc_info(&info, &value, &drc);+ if (strncmp(drc.drc_type, "CPU", 3))+ goto err;++ WARN_ON(drc_index < drc.drc_index_start);+ WARN_ON(((drc_index-drc.drc_index_start)%+ drc.sequential_inc) != 0);++ if (drc_index > drc.last_drc_index) {+ cpu += drc.num_sequential_elems;+ continue;+ } else {
Since you do a continue in the if() part above you shouldn't need to
put this in an else block.
Okay.
-Nathan
quoted
+ 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;
+
+ indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
+ if (indexes == NULL)
+ goto err_of_node_put;
+ /*
+ * First element in the array is the number of drc_indexes
+ * returned. Search through the list to find the matching
+ * drc_index and get the core number
+ */
+ for (i = 0; i < indexes[0]; i++) {
+ if (indexes[i + 1] == drc_index)
+ break;
+ }
+ /* Convert core number to logical cpu number */
+ thread_index = cpu_first_thread_of_core(i);
+ rc = 0;
}
- /* Convert core number to logical cpu number */
- cpu = cpu_first_thread_of_core(i);
- rc = 0;
err_of_node_put:
of_node_put(dn);
err:
if (rc)
printk(KERN_WARNING "drc_index_to_cpu(%d) failed", drc_index);
- return cpu;
+ return thread_index;
}
/*
--
Michael W. Bringmann
Linux Technology Center
IBM Corporation
Tie-Line 363-5196
External: (512) 286-5196
Cell: (512) 466-0650
mwb@linux.vnet.ibm.com
rpadlpar_core.c: Provide parallel routines to search the older device-
tree properties ("ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains"), or the new property "ibm,drc-info".
The interface to examine the DRC information is changed from a "get"
function that returns values for local verification elsewhere, to a
"check" function that validates the 'name' and/or 'type' of a device
node. This update hides the format of the underlying device-tree
properties, and concentrates the value checks into a single function
without requiring the user to verify whether a search was successful.
Signed-off-by: Michael Bringmann <redacted>
---
Changes in V3:
-- Now passing more values by structure reducing use of local
declarations / initialization.
-- Improve some code spacing for better clarity.
---
drivers/pci/hotplug/rpadlpar_core.c | 13 ++--
drivers/pci/hotplug/rpaphp.h | 4 +
drivers/pci/hotplug/rpaphp_core.c | 110 +++++++++++++++++++++++++++--------
3 files changed, 92 insertions(+), 35 deletions(-)
@@ -30,6 +30,7 @@#include<linux/smp.h>#include<linux/init.h>#include<linux/vmalloc.h>+#include<asm/firmware.h>#include<asm/eeh.h> /* for eeh_add_device() */#include<asm/rtas.h> /* rtas_call */#include<asm/pci-bridge.h> /* for pci_controller */
@@ -196,25 +197,21 @@ static int get_children_props(struct device_node *dn, const int **drc_indexes,return0;}-/* To get the DRC props describing the current node, first obtain it's-*my-drc-indexproperty.NextobtaintheDRClistfromit'sparent.Use-*themy-drc-indexforcorrelation,andobtaintherequestedproperties.++/* Verify the existence of 'drc_name' and/or 'drc_type' within the+*currentnode.Firstobtainit'smy-drc-indexproperty.Next,+*obtaintheDRCinfofromit'sparent.Usethemy-drc-indexfor+*correlation,andobtain/validatetherequestedproperties.*/-intrpaphp_get_drc_props(structdevice_node*dn,int*drc_index,-char**drc_name,char**drc_type,int*drc_power_domain)++staticintrpaphp_check_drc_props_v1(structdevice_node*dn,char*drc_name,+char*drc_type,unsignedintmy_index){+char*name_tmp,*type_tmp;constint*indexes,*names;constint*types,*domains;-constunsignedint*my_index;-char*name_tmp,*type_tmp;inti,rc;-my_index=of_get_property(dn,"ibm,my-drc-index",NULL);-if(!my_index){-/* Node isn't DLPAR/hotplug capable */-return-EINVAL;-}-rc=get_children_props(dn->parent,&indexes,&names,&types,&domains);if(rc<0){return-EINVAL;
@@ -225,24 +222,87 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,/* Iterate through parent properties, looking for my-drc-index */for(i=0;i<be32_to_cpu(indexes[0]);i++){-if((unsignedint)indexes[i+1]==*my_index){-if(drc_name)-*drc_name=name_tmp;-if(drc_type)-*drc_type=type_tmp;-if(drc_index)-*drc_index=be32_to_cpu(*my_index);-if(drc_power_domain)-*drc_power_domain=be32_to_cpu(domains[i+1]);-return0;-}+if((unsignedint)indexes[i+1]==my_index)+break;+name_tmp+=(strlen(name_tmp)+1);type_tmp+=(strlen(type_tmp)+1);}+if(((drc_name==NULL)||(drc_name&&!strcmp(drc_name,name_tmp)))&&+((drc_type==NULL)||(drc_type&&!strcmp(drc_type,type_tmp))))+return0;++return-EINVAL;+}++staticintrpaphp_check_drc_props_v2(structdevice_node*dn,char*drc_name,+char*drc_type,unsignedintmy_index)+{+structproperty*info;+unsignedintentries;+structof_drc_infodrc;+void*value;
This should be __be32 *
+ int j;
+
+ info = of_find_property(dn->parent, "ibm,drc-info", NULL);
+ if (info == NULL)
+ return -EINVAL;
+
+ value = info->value;
+ value = (void *)of_prop_next_u32(info, value, &entries);
+ if (!value)
+ return -EINVAL;
+
+ for (j = 0; j < entries; j++) {
+ of_one_drc_info(&info, &value, &drc);
+
+ /* Should now know end of current entry */
+
+ WARN_ON((my_index < drc.drc_index_start) ||
+ (((my_index-drc.drc_index_start)%
+ drc.sequential_inc) != 0));
+
+ if (my_index > drc.last_drc_index)
+ continue;
+
+ break;
+ }
+ /* Found it */
+
+ if (((drc_name == NULL) ||
+ (drc_name && !strncmp(drc_name,
+ drc.drc_name_prefix,
+ strlen(drc.drc_name_prefix)))) &&
Shouldn't we be doing a string compare on the entire name, not just the prefix?
If I remember correctly the prefix is the same for every cpu.
-Nathan
From: Michael Bringmann <hidden> Date: 2017-11-16 18:33:27
quoted
+
+static int rpaphp_check_drc_props_v2(struct device_node *dn, char *drc_name,
+ char *drc_type, unsigned int my_index)
+{
+ struct property *info;
+ unsigned int entries;
+ struct of_drc_info drc;
+ void *value;
This should be __be32 *
Okay.
quoted
+ int j;
+
+ info = of_find_property(dn->parent, "ibm,drc-info", NULL);
+ if (info == NULL)
+ return -EINVAL;
+
+ value = info->value;
+ value = (void *)of_prop_next_u32(info, value, &entries);
+ if (!value)
+ return -EINVAL;
+
+ for (j = 0; j < entries; j++) {
+ of_one_drc_info(&info, &value, &drc);
+
+ /* Should now know end of current entry */
+
+ WARN_ON((my_index < drc.drc_index_start) ||
+ (((my_index-drc.drc_index_start)%
+ drc.sequential_inc) != 0));
+
+ if (my_index > drc.last_drc_index)
+ continue;
+
+ break;
+ }
+ /* Found it */
+
+ if (((drc_name == NULL) ||
+ (drc_name && !strncmp(drc_name,
+ drc.drc_name_prefix,
+ strlen(drc.drc_name_prefix)))) &&
Shouldn't we be doing a string compare on the entire name, not just the prefix?
If I remember correctly the prefix is the same for every cpu.
The prefix may be a value like "CPU", "MEM", "PHB", or other.
I modeled the comparisons using 'drc_name_prefix' after the comparison
of the 'name_tmp' found in the array 'ibm,drc-names' and 'type_tmp'
found in the array 'ibm,drc-types'. This is modeled in the new
function 'rpaphp_check_drc_props_v1' which was lifted from the original
function rpaphp_get_drc_props().
-Nathan
--
Michael W. Bringmann
Linux Technology Center
IBM Corporation
Tie-Line 363-5196
External: (512) 286-5196
Cell: (512) 466-0650
mwb@linux.vnet.ibm.com