aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMadhavan Srinivasan <maddy@linux.vnet.ibm.com>2017-11-22 00:15:39 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2017-11-22 07:04:23 -0500
commit73ce9aec65b17433e18163d07eb5cb6bf114bd6c (patch)
tree5542875410b1fb049b34625245de3bfa10f708c6
parentde34787f1096cce38e2590be0013b44418d14546 (diff)
powerpc/perf: Fix IMC_MAX_PMU macro
IMC_MAX_PMU is used for static storage (per_nest_pmu_arr) which holds nest pmu information. Current value for the macro is 32 based on the initial number of nest pmu units supported by the nest microcode. But going forward, microcode could support more nest units. Instead of static storage, patch to fix the code to dynamically allocate an array based on the number of nest imc units found in the device tree. Fixes:8f95faaac56c1 ('powerpc/powernv: Detect and create IMC device') Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/imc-pmu.h6
-rw-r--r--arch/powerpc/perf/imc-pmu.c15
-rw-r--r--arch/powerpc/platforms/powernv/opal-imc.c16
3 files changed, 29 insertions, 8 deletions
diff --git a/arch/powerpc/include/asm/imc-pmu.h b/arch/powerpc/include/asm/imc-pmu.h
index 7f74c282710f..fad0e6ff460f 100644
--- a/arch/powerpc/include/asm/imc-pmu.h
+++ b/arch/powerpc/include/asm/imc-pmu.h
@@ -21,11 +21,6 @@
21#include <asm/opal.h> 21#include <asm/opal.h>
22 22
23/* 23/*
24 * For static allocation of some of the structures.
25 */
26#define IMC_MAX_PMUS 32
27
28/*
29 * Compatibility macros for IMC devices 24 * Compatibility macros for IMC devices
30 */ 25 */
31#define IMC_DTB_COMPAT "ibm,opal-in-memory-counters" 26#define IMC_DTB_COMPAT "ibm,opal-in-memory-counters"
@@ -125,4 +120,5 @@ enum {
125extern int init_imc_pmu(struct device_node *parent, 120extern int init_imc_pmu(struct device_node *parent,
126 struct imc_pmu *pmu_ptr, int pmu_id); 121 struct imc_pmu *pmu_ptr, int pmu_id);
127extern void thread_imc_disable(void); 122extern void thread_imc_disable(void);
123extern int get_max_nest_dev(void);
128#endif /* __ASM_POWERPC_IMC_PMU_H */ 124#endif /* __ASM_POWERPC_IMC_PMU_H */
diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
index cf64e16f92c2..0ead3cd73caa 100644
--- a/arch/powerpc/perf/imc-pmu.c
+++ b/arch/powerpc/perf/imc-pmu.c
@@ -26,7 +26,7 @@
26 */ 26 */
27static DEFINE_MUTEX(nest_init_lock); 27static DEFINE_MUTEX(nest_init_lock);
28static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc); 28static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc);
29static struct imc_pmu *per_nest_pmu_arr[IMC_MAX_PMUS]; 29static struct imc_pmu **per_nest_pmu_arr;
30static cpumask_t nest_imc_cpumask; 30static cpumask_t nest_imc_cpumask;
31struct imc_pmu_ref *nest_imc_refc; 31struct imc_pmu_ref *nest_imc_refc;
32static int nest_pmus; 32static int nest_pmus;
@@ -286,13 +286,14 @@ static struct imc_pmu_ref *get_nest_pmu_ref(int cpu)
286static void nest_change_cpu_context(int old_cpu, int new_cpu) 286static void nest_change_cpu_context(int old_cpu, int new_cpu)
287{ 287{
288 struct imc_pmu **pn = per_nest_pmu_arr; 288 struct imc_pmu **pn = per_nest_pmu_arr;
289 int i;
290 289
291 if (old_cpu < 0 || new_cpu < 0) 290 if (old_cpu < 0 || new_cpu < 0)
292 return; 291 return;
293 292
294 for (i = 0; *pn && i < IMC_MAX_PMUS; i++, pn++) 293 while (*pn) {
295 perf_pmu_migrate_context(&(*pn)->pmu, old_cpu, new_cpu); 294 perf_pmu_migrate_context(&(*pn)->pmu, old_cpu, new_cpu);
295 pn++;
296 }
296} 297}
297 298
298static int ppc_nest_imc_cpu_offline(unsigned int cpu) 299static int ppc_nest_imc_cpu_offline(unsigned int cpu)
@@ -1194,6 +1195,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
1194 kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs); 1195 kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs);
1195 kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]); 1196 kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]);
1196 kfree(pmu_ptr); 1197 kfree(pmu_ptr);
1198 kfree(per_nest_pmu_arr);
1197 return; 1199 return;
1198} 1200}
1199 1201
@@ -1218,6 +1220,13 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent,
1218 return -ENOMEM; 1220 return -ENOMEM;
1219 1221
1220 /* Needed for hotplug/migration */ 1222 /* Needed for hotplug/migration */
1223 if (!per_nest_pmu_arr) {
1224 per_nest_pmu_arr = kcalloc(get_max_nest_dev() + 1,
1225 sizeof(struct imc_pmu *),
1226 GFP_KERNEL);
1227 if (!per_nest_pmu_arr)
1228 return -ENOMEM;
1229 }
1221 per_nest_pmu_arr[pmu_index] = pmu_ptr; 1230 per_nest_pmu_arr[pmu_index] = pmu_ptr;
1222 break; 1231 break;
1223 case IMC_DOMAIN_CORE: 1232 case IMC_DOMAIN_CORE:
diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c
index b150f4deaccf..465ea105b771 100644
--- a/arch/powerpc/platforms/powernv/opal-imc.c
+++ b/arch/powerpc/platforms/powernv/opal-imc.c
@@ -153,6 +153,22 @@ static void disable_core_pmu_counters(void)
153 put_online_cpus(); 153 put_online_cpus();
154} 154}
155 155
156int get_max_nest_dev(void)
157{
158 struct device_node *node;
159 u32 pmu_units = 0, type;
160
161 for_each_compatible_node(node, NULL, IMC_DTB_UNIT_COMPAT) {
162 if (of_property_read_u32(node, "type", &type))
163 continue;
164
165 if (type == IMC_TYPE_CHIP)
166 pmu_units++;
167 }
168
169 return pmu_units;
170}
171
156static int opal_imc_counters_probe(struct platform_device *pdev) 172static int opal_imc_counters_probe(struct platform_device *pdev)
157{ 173{
158 struct device_node *imc_dev = pdev->dev.of_node; 174 struct device_node *imc_dev = pdev->dev.of_node;