summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMathieu Poirier <mathieu.poirier@linaro.org>2016-05-31 16:32:55 -0600
committerMathieu Poirier <mathieu.poirier@linaro.org>2016-06-20 11:09:45 -0600
commit1efb79086e3298b07f8734aae7614aa25ef82040 (patch)
tree4f2bf7df370b09880bc53ffadfe7aeeeba6516e5 /kernel
parent65ad7b198dccae96d776db85d1a184df214dddb4 (diff)
perf/core: adding PMU driver specific configuration
It is entirely possible that some PMUs need specific configuration that is currently not found in the perf options before a session can be setup. It is the case for the CoreSight PMU where a sink needs to be provided. That sink doesn't fall in any of the current perf options. As such this patch adds the capability to receive driver specific configuration using the existing ioctl() mechanism. Once the configuration has been pushed down the kernel PMU callbacks are used to deal with the information sent from user space. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index cda4b292135a..59552da6d6aa 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3729,6 +3729,9 @@ static void __free_event(struct perf_event *event)
if (event->destroy)
event->destroy(event);
+ if (event->pmu->free_drv_configs)
+ event->pmu->free_drv_configs(event);
+
if (event->ctx)
put_ctx(event->ctx);
@@ -4281,6 +4284,8 @@ static int perf_event_set_output(struct perf_event *event,
struct perf_event *output_event);
static int perf_event_set_filter(struct perf_event *event, void __user *arg);
static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd);
+static int perf_event_drv_configs(struct perf_event *event,
+ void __user *arg);
static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg)
{
@@ -4337,6 +4342,9 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
case PERF_EVENT_IOC_SET_BPF:
return perf_event_set_bpf_prog(event, arg);
+ case PERF_EVENT_IOC_SET_DRV_CONFIGS:
+ return perf_event_drv_configs(event, (void __user *)arg);
+
default:
return -ENOTTY;
}
@@ -4369,6 +4377,7 @@ static long perf_compat_ioctl(struct file *file, unsigned int cmd,
switch (_IOC_NR(cmd)) {
case _IOC_NR(PERF_EVENT_IOC_SET_FILTER):
case _IOC_NR(PERF_EVENT_IOC_ID):
+ case _IOC_NR(PERF_EVENT_IOC_SET_DRV_CONFIGS):
/* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */
if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
cmd &= ~IOCSIZE_MASK;
@@ -7268,6 +7277,15 @@ void perf_bp_event(struct perf_event *bp, void *data)
}
#endif
+static int perf_event_drv_configs(struct perf_event *event,
+ void __user *arg)
+{
+ if (!event->pmu->get_drv_configs)
+ return -EINVAL;
+
+ return event->pmu->get_drv_configs(event, arg);
+}
+
/*
* hrtimer based swevent callback
*/
@@ -8004,6 +8022,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
INIT_LIST_HEAD(&event->sibling_list);
INIT_LIST_HEAD(&event->rb_entry);
INIT_LIST_HEAD(&event->active_entry);
+ INIT_LIST_HEAD(&event->drv_configs);
INIT_HLIST_NODE(&event->hlist_entry);