diff options
author | Andi Kleen <ak@linux.intel.com> | 2013-01-24 10:10:25 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-03-26 15:50:23 -0400 |
commit | 1a6461b12872e9622c231928e1620504d741cc79 (patch) | |
tree | ebf093761ebd3a98caf71013a14601ff7b51fe1e /arch/x86/kernel/cpu/perf_event.c | |
parent | 328ccdace8855289ad114b70ee1464ba5e3f6436 (diff) |
perf/x86: Support CPU specific sysfs events
Add a way for the CPU initialization code to register additional
events, and merge them into the events attribute directory. Used
in the next patch.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: jolsa@redhat.com
Cc: namhyung.kim@lge.com
Link: http://lkml.kernel.org/r/1359040242-8269-2-git-send-email-eranian@google.com
[ small cleanups ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
[ merge_attr returns a **, not just * ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event.c')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index bf0f01aea994..c886dc8c63f8 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1330,6 +1330,32 @@ static void __init filter_events(struct attribute **attrs) | |||
1330 | } | 1330 | } |
1331 | } | 1331 | } |
1332 | 1332 | ||
1333 | /* Merge two pointer arrays */ | ||
1334 | static __init struct attribute **merge_attr(struct attribute **a, struct attribute **b) | ||
1335 | { | ||
1336 | struct attribute **new; | ||
1337 | int j, i; | ||
1338 | |||
1339 | for (j = 0; a[j]; j++) | ||
1340 | ; | ||
1341 | for (i = 0; b[i]; i++) | ||
1342 | j++; | ||
1343 | j++; | ||
1344 | |||
1345 | new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL); | ||
1346 | if (!new) | ||
1347 | return NULL; | ||
1348 | |||
1349 | j = 0; | ||
1350 | for (i = 0; a[i]; i++) | ||
1351 | new[j++] = a[i]; | ||
1352 | for (i = 0; b[i]; i++) | ||
1353 | new[j++] = b[i]; | ||
1354 | new[j] = NULL; | ||
1355 | |||
1356 | return new; | ||
1357 | } | ||
1358 | |||
1333 | static ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, | 1359 | static ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, |
1334 | char *page) | 1360 | char *page) |
1335 | { | 1361 | { |
@@ -1469,6 +1495,14 @@ static int __init init_hw_perf_events(void) | |||
1469 | else | 1495 | else |
1470 | filter_events(x86_pmu_events_group.attrs); | 1496 | filter_events(x86_pmu_events_group.attrs); |
1471 | 1497 | ||
1498 | if (x86_pmu.cpu_events) { | ||
1499 | struct attribute **tmp; | ||
1500 | |||
1501 | tmp = merge_attr(x86_pmu_events_group.attrs, x86_pmu.cpu_events); | ||
1502 | if (!WARN_ON(!tmp)) | ||
1503 | x86_pmu_events_group.attrs = tmp; | ||
1504 | } | ||
1505 | |||
1472 | pr_info("... version: %d\n", x86_pmu.version); | 1506 | pr_info("... version: %d\n", x86_pmu.version); |
1473 | pr_info("... bit width: %d\n", x86_pmu.cntval_bits); | 1507 | pr_info("... bit width: %d\n", x86_pmu.cntval_bits); |
1474 | pr_info("... generic registers: %d\n", x86_pmu.num_counters); | 1508 | pr_info("... generic registers: %d\n", x86_pmu.num_counters); |