Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pseries/drc-info: Search DRC properties for CPU indexes

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 <mwb@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Michael Bringmann and committed by
Michael Ellerman
e83636ac 3f38000e

+173 -28
+15
arch/powerpc/include/asm/prom.h
··· 80 80 81 81 extern int of_get_ibm_chip_id(struct device_node *np); 82 82 83 + struct of_drc_info { 84 + char *drc_type; 85 + char *drc_name_prefix; 86 + u32 drc_index_start; 87 + u32 drc_name_suffix_start; 88 + u32 num_sequential_elems; 89 + u32 sequential_inc; 90 + u32 drc_power_domain; 91 + u32 last_drc_index; 92 + }; 93 + 94 + extern int of_read_drc_info_cell(struct property **prop, 95 + const __be32 **curval, struct of_drc_info *data); 96 + 97 + 83 98 /* 84 99 * There are two methods for telling firmware what our capabilities are. 85 100 * Newer machines have an "ibm,client-architecture-support" method on the
+60
arch/powerpc/platforms/pseries/of_helpers.c
··· 3 3 #include <linux/err.h> 4 4 #include <linux/slab.h> 5 5 #include <linux/of.h> 6 + #include <asm/prom.h> 6 7 7 8 #include "of_helpers.h" 8 9 ··· 38 37 kfree(parent_path); 39 38 return parent ? parent : ERR_PTR(-EINVAL); 40 39 } 40 + 41 + 42 + /* Helper Routines to convert between drc_index to cpu numbers */ 43 + 44 + int of_read_drc_info_cell(struct property **prop, const __be32 **curval, 45 + struct of_drc_info *data) 46 + { 47 + const char *p; 48 + const __be32 *p2; 49 + 50 + if (!data) 51 + return -EINVAL; 52 + 53 + /* Get drc-type:encode-string */ 54 + p = data->drc_type = (char*) (*curval); 55 + p = of_prop_next_string(*prop, p); 56 + if (!p) 57 + return -EINVAL; 58 + 59 + /* Get drc-name-prefix:encode-string */ 60 + data->drc_name_prefix = (char *)p; 61 + p = of_prop_next_string(*prop, p); 62 + if (!p) 63 + return -EINVAL; 64 + 65 + /* Get drc-index-start:encode-int */ 66 + p2 = (const __be32 *)p; 67 + p2 = of_prop_next_u32(*prop, p2, &data->drc_index_start); 68 + if (!p2) 69 + return -EINVAL; 70 + 71 + /* Get drc-name-suffix-start:encode-int */ 72 + p2 = of_prop_next_u32(*prop, p2, &data->drc_name_suffix_start); 73 + if (!p2) 74 + return -EINVAL; 75 + 76 + /* Get number-sequential-elements:encode-int */ 77 + p2 = of_prop_next_u32(*prop, p2, &data->num_sequential_elems); 78 + if (!p2) 79 + return -EINVAL; 80 + 81 + /* Get sequential-increment:encode-int */ 82 + p2 = of_prop_next_u32(*prop, p2, &data->sequential_inc); 83 + if (!p2) 84 + return -EINVAL; 85 + 86 + /* Get drc-power-domain:encode-int */ 87 + p2 = of_prop_next_u32(*prop, p2, &data->drc_power_domain); 88 + if (!p2) 89 + return -EINVAL; 90 + 91 + /* Should now know end of current entry */ 92 + (*curval) = (void *)p2; 93 + data->last_drc_index = data->drc_index_start + 94 + ((data->num_sequential_elems - 1) * data->sequential_inc); 95 + 96 + return 0; 97 + } 98 + EXPORT_SYMBOL(of_read_drc_info_cell);
+98 -28
arch/powerpc/platforms/pseries/pseries_energy.c
··· 22 22 #include <asm/page.h> 23 23 #include <asm/hvcall.h> 24 24 #include <asm/firmware.h> 25 + #include <asm/prom.h> 25 26 26 27 27 28 #define MODULE_VERS "1.0" ··· 39 38 static u32 cpu_to_drc_index(int cpu) 40 39 { 41 40 struct device_node *dn = NULL; 42 - const int *indexes; 43 - int i; 41 + int thread_index; 44 42 int rc = 1; 45 43 u32 ret = 0; 46 44 47 45 dn = of_find_node_by_path("/cpus"); 48 46 if (dn == NULL) 49 47 goto err; 50 - indexes = of_get_property(dn, "ibm,drc-indexes", NULL); 51 - if (indexes == NULL) 52 - goto err_of_node_put; 48 + 53 49 /* Convert logical cpu number to core number */ 54 - i = cpu_core_index_of_thread(cpu); 55 - /* 56 - * The first element indexes[0] is the number of drc_indexes 57 - * returned in the list. Hence i+1 will get the drc_index 58 - * corresponding to core number i. 59 - */ 60 - WARN_ON(i > indexes[0]); 61 - ret = indexes[i + 1]; 50 + thread_index = cpu_core_index_of_thread(cpu); 51 + 52 + if (firmware_has_feature(FW_FEATURE_DRC_INFO)) { 53 + struct property *info = NULL; 54 + struct of_drc_info drc; 55 + int j; 56 + u32 num_set_entries; 57 + const __be32 *value; 58 + 59 + info = of_find_property(dn, "ibm,drc-info", NULL); 60 + if (info == NULL) 61 + goto err_of_node_put; 62 + 63 + value = of_prop_next_u32(info, NULL, &num_set_entries); 64 + if (!value) 65 + goto err_of_node_put; 66 + 67 + for (j = 0; j < num_set_entries; j++) { 68 + 69 + of_read_drc_info_cell(&info, &value, &drc); 70 + if (strncmp(drc.drc_type, "CPU", 3)) 71 + goto err; 72 + 73 + if (thread_index < drc.last_drc_index) 74 + break; 75 + } 76 + 77 + ret = drc.drc_index_start + (thread_index * drc.sequential_inc); 78 + } else { 79 + const __be32 *indexes; 80 + 81 + indexes = of_get_property(dn, "ibm,drc-indexes", NULL); 82 + if (indexes == NULL) 83 + goto err_of_node_put; 84 + 85 + /* 86 + * The first element indexes[0] is the number of drc_indexes 87 + * returned in the list. Hence thread_index+1 will get the 88 + * drc_index corresponding to core number thread_index. 89 + */ 90 + ret = indexes[thread_index + 1]; 91 + } 92 + 62 93 rc = 0; 63 94 64 95 err_of_node_put: ··· 105 72 { 106 73 struct device_node *dn = NULL; 107 74 const int *indexes; 108 - int i, cpu = 0; 75 + int thread_index = 0, cpu = 0; 109 76 int rc = 1; 110 77 111 78 dn = of_find_node_by_path("/cpus"); 112 79 if (dn == NULL) 113 80 goto err; 114 - indexes = of_get_property(dn, "ibm,drc-indexes", NULL); 115 - if (indexes == NULL) 116 - goto err_of_node_put; 117 - /* 118 - * First element in the array is the number of drc_indexes 119 - * returned. Search through the list to find the matching 120 - * drc_index and get the core number 121 - */ 122 - for (i = 0; i < indexes[0]; i++) { 123 - if (indexes[i + 1] == drc_index) 81 + 82 + if (firmware_has_feature(FW_FEATURE_DRC_INFO)) { 83 + struct property *info = NULL; 84 + struct of_drc_info drc; 85 + int j; 86 + u32 num_set_entries; 87 + const __be32 *value; 88 + 89 + info = of_find_property(dn, "ibm,drc-info", NULL); 90 + if (info == NULL) 91 + goto err_of_node_put; 92 + 93 + value = of_prop_next_u32(info, NULL, &num_set_entries); 94 + if (!value) 95 + goto err_of_node_put; 96 + 97 + for (j = 0; j < num_set_entries; j++) { 98 + 99 + of_read_drc_info_cell(&info, &value, &drc); 100 + if (strncmp(drc.drc_type, "CPU", 3)) 101 + goto err; 102 + 103 + if (drc_index > drc.last_drc_index) { 104 + cpu += drc.num_sequential_elems; 105 + continue; 106 + } 107 + cpu += ((drc_index - drc.drc_index_start) / 108 + drc.sequential_inc); 109 + 110 + thread_index = cpu_first_thread_of_core(cpu); 111 + rc = 0; 124 112 break; 113 + } 114 + } else { 115 + unsigned long int i; 116 + 117 + indexes = of_get_property(dn, "ibm,drc-indexes", NULL); 118 + if (indexes == NULL) 119 + goto err_of_node_put; 120 + /* 121 + * First element in the array is the number of drc_indexes 122 + * returned. Search through the list to find the matching 123 + * drc_index and get the core number 124 + */ 125 + for (i = 0; i < indexes[0]; i++) { 126 + if (indexes[i + 1] == drc_index) 127 + break; 128 + } 129 + /* Convert core number to logical cpu number */ 130 + thread_index = cpu_first_thread_of_core(i); 131 + rc = 0; 125 132 } 126 - /* Convert core number to logical cpu number */ 127 - cpu = cpu_first_thread_of_core(i); 128 - rc = 0; 129 133 130 134 err_of_node_put: 131 135 of_node_put(dn); 132 136 err: 133 137 if (rc) 134 138 printk(KERN_WARNING "drc_index_to_cpu(%d) failed", drc_index); 135 - return cpu; 139 + return thread_index; 136 140 } 137 141 138 142 /*