summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/bus/arm-ccn.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
index 572360f1f493..fb589d4dbaf6 100644
--- a/drivers/bus/arm-ccn.c
+++ b/drivers/bus/arm-ccn.c
@@ -660,6 +660,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
int valid, bit;
struct arm_ccn_component *source;
int i;
+ struct perf_event *sibling;
if (event->attr.type != event->pmu->type)
return -ENOENT;
@@ -762,6 +763,21 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
node_xp, type, port);
}
+ /*
+ * We must NOT create groups containing mixed PMUs, although software
+ * events are acceptable (for example to create a CCN group
+ * periodically read when a hrtimer aka cpu-clock leader triggers).
+ */
+ if (event->group_leader->pmu != event->pmu &&
+ !is_software_event(event->group_leader))
+ return -EINVAL;
+
+ list_for_each_entry(sibling, &event->group_leader->sibling_list,
+ group_entry)
+ if (sibling->pmu != event->pmu &&
+ !is_software_event(sibling))
+ return -EINVAL;
+
/* Allocate the cycle counter */
if (type == CCN_TYPE_CYCLES) {
if (test_and_set_bit(CCN_IDX_PMU_CYCLE_COUNTER,