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

Commit 595ba75f authored by Neil Leeder's avatar Neil Leeder Committed by Imran Khan
Browse files

perf: stop deadlock if attempt to bring cpu up fails



When an attempt is made to free an event on a CPU which is
no longer online, perf tries to bring the CPU online. This
can fail, resulting in an UP_CANCELLED notifier, which
eventually tries to acquire the ctx->mutex which is already
being held by the code, which brings up the CPU.

Removing the attempt to bring the cpu up will remove this
deadlock, but also requires temporarily removing support of
counting events across hotplug. This will be restored in a
later patch.

Conflicts:
	kernel/events/core.c
	kernel/events/hw_breakpoint.c

Change-Id: Iaafa3c6688d26508857472fd5bb32139a137880e
Signed-off-by: default avatarNeil Leeder <nleeder@codeaurora.org>
parent edf4d230
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -581,7 +581,6 @@ static void __init armpmu_init(struct arm_pmu *armpmu)
		.start		= armpmu_start,
		.stop		= armpmu_stop,
		.read		= armpmu_read,
		.events_across_hotplug = 1,
	};
}

+1 −34
Original line number Diff line number Diff line
@@ -1540,32 +1540,6 @@ static int __perf_remove_from_context(void *info)
	return 0;
}


#ifdef CONFIG_SMP
static void perf_retry_remove(struct perf_event *event,
			      struct remove_event *rep)
{
	int up_ret;
	/*
	 * CPU was offline. Bring it online so we can
	 * gracefully exit a perf context.
	 */
	up_ret = cpu_up(event->cpu);
	if (!up_ret)
		/* Try the remove call once again. */
		cpu_function_call(event->cpu, __perf_remove_from_context,
				  rep);
	else
		pr_err("Failed to bring up CPU: %d, ret: %d\n",
		       event->cpu, up_ret);
}
#else
static void perf_retry_remove(struct perf_event *event,
			      struct remove_event *rep)
{
}
#endif

/*
 * Remove the event from a task's (or a CPU's) list of events.
 *
@@ -1601,9 +1575,6 @@ static void __ref perf_remove_from_context(struct perf_event *event,
		 */
		ret = cpu_function_call(event->cpu, __perf_remove_from_context,
					&re);
		if (ret == -ENXIO)
			perf_retry_remove(event, &re);

		return;
	}

@@ -6185,7 +6156,6 @@ static struct pmu perf_swevent = {
	.start		= perf_swevent_start,
	.stop		= perf_swevent_stop,
	.read		= perf_swevent_read,
	.events_across_hotplug = 1,
};

#ifdef CONFIG_EVENT_TRACING
@@ -6303,7 +6273,6 @@ static struct pmu perf_tracepoint = {
	.start		= perf_swevent_start,
	.stop		= perf_swevent_stop,
	.read		= perf_swevent_read,
	.events_across_hotplug = 1,
};

static inline void perf_tp_register(void)
@@ -6529,7 +6498,6 @@ static struct pmu perf_cpu_clock = {
	.start		= cpu_clock_event_start,
	.stop		= cpu_clock_event_stop,
	.read		= cpu_clock_event_read,
	.events_across_hotplug = 1,
};

/*
@@ -6608,7 +6576,6 @@ static struct pmu perf_task_clock = {
	.start		= task_clock_event_start,
	.stop		= task_clock_event_stop,
	.read		= task_clock_event_read,
	.events_across_hotplug = 1,
};

static void perf_pmu_nop_void(struct pmu *pmu)
+0 −1
Original line number Diff line number Diff line
@@ -614,7 +614,6 @@ static struct pmu perf_breakpoint = {
	.start		= hw_breakpoint_start,
	.stop		= hw_breakpoint_stop,
	.read		= hw_breakpoint_pmu_read,
	.events_across_hotplug = 1,
};

int __init init_hw_breakpoint(void)