Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33059f23 authored by Raghavendra Rao Ananta's avatar Raghavendra Rao Ananta Committed by Gerrit - the friendly Code Review server
Browse files

perf: Add exclude_idle support for armv7 PMU



By adding the exclude_idle support, the driver would update
the PMU counter values into event->count right before it goes
into an idle state. This way, even if the client, from another
core, tries to read the value during this idle period, it would
return the last updated value before moving into idle without
waking the idle core up.

Change-Id: Iccc9a9d73e7079b27d0e2978bd286c4c464ce28f
Signed-off-by: default avatarRaghavendra Rao Ananta <rananta@codeaurora.org>
parent 2a98f234
Loading
Loading
Loading
Loading
+68 −13
Original line number Diff line number Diff line
@@ -1072,8 +1072,6 @@ static int armv7pmu_set_event_filter(struct hw_perf_event *event,
{
	unsigned long config_base = 0;

	if (attr->exclude_idle)
		return -EPERM;
	if (attr->exclude_user)
		config_base |= ARMV7_EXCLUDE_USER;
	if (attr->exclude_kernel)
@@ -1190,11 +1188,68 @@ static void armv7_read_num_pmnc_events(void *info)
	*nb_cnt += 1;
}

static int armv7_probe_num_events(struct arm_pmu *arm_pmu)
static void armv7_pmu_idle_update(struct arm_pmu *cpu_pmu)
{
	return smp_call_function_any(&arm_pmu->supported_cpus,
	struct pmu_hw_events *hw_events;
	struct perf_event *event;
	int idx;

	if (!cpu_pmu)
		return;

	hw_events = this_cpu_ptr(cpu_pmu->hw_events);
	if (!hw_events)
		return;

	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
		event = hw_events->events[idx];

		if (!event || !event->attr.exclude_idle ||
			event->state != PERF_EVENT_STATE_ACTIVE)
			continue;

		cpu_pmu->pmu.read(event);
	}
}

struct armv7_pmu_idle_nb {
	struct arm_pmu *cpu_pmu;
	struct notifier_block perf_cpu_idle_nb;
};

static int armv7_pmu_idle_notifier(struct notifier_block *nb,
				unsigned long action, void *data)
{
	struct armv7_pmu_idle_nb *pmu_idle_nb = container_of(nb,
				struct armv7_pmu_idle_nb, perf_cpu_idle_nb);

	if (action == IDLE_START)
		armv7_pmu_idle_update(pmu_idle_nb->cpu_pmu);

	return NOTIFY_OK;
}

static int armv7_probe_pmu(struct arm_pmu *arm_pmu)
{
	int ret;
	struct armv7_pmu_idle_nb *pmu_idle_nb;

	pmu_idle_nb = devm_kzalloc(&arm_pmu->plat_device->dev,
				sizeof(*pmu_idle_nb), GFP_KERNEL);
	if (!pmu_idle_nb)
		return -ENOMEM;

	ret = smp_call_function_any(&arm_pmu->supported_cpus,
				     armv7_read_num_pmnc_events,
				     &arm_pmu->num_events, 1);
	if (ret)
		return ret;

	pmu_idle_nb->cpu_pmu = arm_pmu;
	pmu_idle_nb->perf_cpu_idle_nb.notifier_call = armv7_pmu_idle_notifier;
	idle_notifier_register(&pmu_idle_nb->perf_cpu_idle_nb);

	return 0;
}

static int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
@@ -1206,7 +1261,7 @@ static int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
		&armv7_pmuv1_events_attr_group;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
		&armv7_pmu_format_attr_group;
	return armv7_probe_num_events(cpu_pmu);
	return armv7_probe_pmu(cpu_pmu);
}

static int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
@@ -1218,7 +1273,7 @@ static int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
		&armv7_pmuv1_events_attr_group;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
		&armv7_pmu_format_attr_group;
	return armv7_probe_num_events(cpu_pmu);
	return armv7_probe_pmu(cpu_pmu);
}

static int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
@@ -1230,7 +1285,7 @@ static int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
		&armv7_pmuv1_events_attr_group;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
		&armv7_pmu_format_attr_group;
	return armv7_probe_num_events(cpu_pmu);
	return armv7_probe_pmu(cpu_pmu);
}

static int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
@@ -1243,7 +1298,7 @@ static int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
		&armv7_pmuv2_events_attr_group;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
		&armv7_pmu_format_attr_group;
	return armv7_probe_num_events(cpu_pmu);
	return armv7_probe_pmu(cpu_pmu);
}

static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
@@ -1256,7 +1311,7 @@ static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
		&armv7_pmuv2_events_attr_group;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
		&armv7_pmu_format_attr_group;
	return armv7_probe_num_events(cpu_pmu);
	return armv7_probe_pmu(cpu_pmu);
}

static int armv7_a12_pmu_init(struct arm_pmu *cpu_pmu)
@@ -1269,7 +1324,7 @@ static int armv7_a12_pmu_init(struct arm_pmu *cpu_pmu)
		&armv7_pmuv2_events_attr_group;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
		&armv7_pmu_format_attr_group;
	return armv7_probe_num_events(cpu_pmu);
	return armv7_probe_pmu(cpu_pmu);
}

static int armv7_a17_pmu_init(struct arm_pmu *cpu_pmu)
@@ -1667,7 +1722,7 @@ static int krait_pmu_init(struct arm_pmu *cpu_pmu)
	cpu_pmu->disable	= krait_pmu_disable_event;
	cpu_pmu->get_event_idx	= krait_pmu_get_event_idx;
	cpu_pmu->clear_event_idx = krait_pmu_clear_event_idx;
	return armv7_probe_num_events(cpu_pmu);
	return armv7_probe_pmu(cpu_pmu);
}

/*
@@ -1991,7 +2046,7 @@ static int scorpion_pmu_init(struct arm_pmu *cpu_pmu)
	cpu_pmu->disable	= scorpion_pmu_disable_event;
	cpu_pmu->get_event_idx	= scorpion_pmu_get_event_idx;
	cpu_pmu->clear_event_idx = scorpion_pmu_clear_event_idx;
	return armv7_probe_num_events(cpu_pmu);
	return armv7_probe_pmu(cpu_pmu);
}

static int scorpion_mp_pmu_init(struct arm_pmu *cpu_pmu)
@@ -2004,7 +2059,7 @@ static int scorpion_mp_pmu_init(struct arm_pmu *cpu_pmu)
	cpu_pmu->disable	= scorpion_pmu_disable_event;
	cpu_pmu->get_event_idx	= scorpion_pmu_get_event_idx;
	cpu_pmu->clear_event_idx = scorpion_pmu_clear_event_idx;
	return armv7_probe_num_events(cpu_pmu);
	return armv7_probe_pmu(cpu_pmu);
}

static const struct of_device_id armv7_pmu_of_device_ids[] = {