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

Commit ba5677fe authored by Neil Leeder's avatar Neil Leeder
Browse files

msm: perf: clean up duplicate constraint events



Events with a duplicate constraint are set to state=OFF when detected,
so that their duplicate counts are not read. However, they were not being
cleaned up because the core code only cleaned up ACTIVE events.
This resulted in counters not being freed and eventually running out
of resources.

Clean up the events with state==OFF that were marked that way because of
constraint duplication.
Ensure counts are not updated for OFF events.

Change-Id: If532801c79e6ad6809869eb0a3063774f00c92c3
Signed-off-by: default avatarNeil Leeder <nleeder@codeaurora.org>
parent 718fc96a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -131,6 +131,9 @@ u64 armpmu_event_update(struct perf_event *event)
	struct hw_perf_event *hwc = &event->hw;
	u64 delta, prev_raw_count, new_raw_count;

	if (event->state <= PERF_EVENT_STATE_OFF)
		return 0;

again:
	prev_raw_count = local64_read(&hwc->prev_count);
	new_raw_count = armpmu->read_counter(event);
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ static char *descriptions =
	" 3 Perf: bring CPU online if needed when disabling irq\n"
	" 4 Perf: Support sw events across hotplug\n"
	" 5 msm: perf: initialise krait perf L2 counter enables\n"
	" 6 msm: perf: clean up duplicate constraint events\n"
;

static ssize_t desc_read(struct file *fp, char __user *buf,
+3 −1
Original line number Diff line number Diff line
@@ -504,8 +504,10 @@ static int msm_l2_test_set_ev_constraint(struct perf_event *event)
			 * This sets the event OFF on all but one
			 * CPU.
			 */
			if (!(event->cpu < 0))
			if (!(event->cpu < 0)) {
				event->state = PERF_EVENT_STATE_OFF;
				event->attr.constraint_duplicate = 1;
			}
	}
out:
	raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
+2 −1
Original line number Diff line number Diff line
@@ -272,8 +272,9 @@ struct perf_event_attr {

				exclude_callchain_kernel : 1, /* exclude kernel callchains */
				exclude_callchain_user   : 1, /* exclude user callchains */
				constraint_duplicate : 1,

				__reserved_1   : 41;
				__reserved_1   : 40;

	union {
		__u32		wakeup_events;	  /* wakeup every n events */
+10 −0
Original line number Diff line number Diff line
@@ -3082,6 +3082,16 @@ static void put_event(struct perf_event *event)

static int perf_release(struct inode *inode, struct file *file)
{
	struct perf_event *event = file->private_data;

	/*
	 * Event can be in state OFF because of a constraint check.
	 * Change to ACTIVE so that it gets cleaned up correctly.
	 */
	if ((event->state == PERF_EVENT_STATE_OFF) &&
	    event->attr.constraint_duplicate)
		event->state = PERF_EVENT_STATE_ACTIVE;

	put_event(file->private_data);
	return 0;
}