summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Leeder <nleeder@codeaurora.org>2015-09-24 12:14:20 -0400
committerImran Khan <kimran@codeaurora.org>2017-06-28 10:09:20 +0530
commit5f71e693df3a02dc436ed383276e85bdcb8cb4bf (patch)
tree80532d1944517333317517d7a427318819ee7d2a
parent6f56b2a9c8e2ce69e2a98e52d5f1342b25cae44e (diff)
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: Neil Leeder <nleeder@codeaurora.org>
-rw-r--r--drivers/perf/arm_pmu.c1
-rw-r--r--kernel/events/core.c39
-rw-r--r--kernel/events/hw_breakpoint.c2
3 files changed, 1 insertions, 41 deletions
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 39400dda27c2..63ec68e6ac2a 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -552,7 +552,6 @@ static void armpmu_init(struct arm_pmu *armpmu)
.stop = armpmu_stop,
.read = armpmu_read,
.filter_match = armpmu_filter_match,
- .events_across_hotplug = 1,
};
}
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6cd152e99891..7fee87daac56 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1693,33 +1693,7 @@ 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.
*
* CPU events are removed with a smp call. For task events we only
@@ -1754,9 +1728,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;
}
@@ -7138,8 +7109,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
@@ -7261,8 +7230,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)
@@ -7550,8 +7517,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,
};
/*
@@ -7633,8 +7598,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)
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index 7da5b674d16e..92ce5f4ccc26 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -614,8 +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)