AUX cleanup is deferred to a workqueue which is never flushed on module unload. Pending work items can therefore run after coresight-config is cleaned up or the module text is unloaded.
Since commit 95ff4ca26c49 ("perf/core: Free AUX pages in unmap path"), Perf core stops AUX transactions and frees the PMU AUX data from the unmap path in non-atomic context. Release the resources directly from the free_aux() callback and remove the workqueue.
Fixes: 0bcbf2e30ff2 ("coresight: etm-perf: new PMU driver for ETM tracers") Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-etm-perf.c | 14 ++------------ drivers/hwtracing/coresight/coresight-etm-perf.h | 2 -- 2 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index 09b21a711a87..2323a68584d4 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -18,7 +18,6 @@ #include <linux/slab.h> #include <linux/stringhash.h> #include <linux/types.h> -#include <linux/workqueue.h>
#include "coresight-config.h" #include "coresight-etm-perf.h" @@ -211,13 +210,12 @@ static void free_sink_buffer(struct etm_event_data *event_data) sink_ops(sink)->free_buffer(event_data->snk_config); }
-static void free_event_data(struct work_struct *work) +static void etm_free_aux(void *data) { int cpu; cpumask_t *mask; - struct etm_event_data *event_data; + struct etm_event_data *event_data = data;
- event_data = container_of(work, struct etm_event_data, work); mask = &event_data->mask;
/* Free the sink buffers, if there are any */ @@ -288,13 +286,6 @@ static void *alloc_event_data(int cpu) return event_data; }
-static void etm_free_aux(void *data) -{ - struct etm_event_data *event_data = data; - - schedule_work(&event_data->work); -} - /* * Check if two given sinks are compatible with each other, * so that they can use the same sink buffers, when an event @@ -436,7 +427,6 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, event_data = alloc_event_data(cpu); if (!event_data) return NULL; - INIT_WORK(&event_data->work, free_event_data);
/* First get the selected sink from user space. */ sink_hash = ATTR_CFG_GET_FLD(&event->attr, sinkid); diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h index 24d929428633..5e8d985522bd 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.h +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h @@ -84,7 +84,6 @@ struct etm_filters {
/** * struct etm_event_data - Coresight specifics associated to an event - * @work: Handle to free allocated memory outside IRQ context. * @mask: Hold the CPU(s) this event was set for. * @aux_hwid_done: Whether a CPU has emitted the TraceID packet or not. * @snk_config: The sink configuration. @@ -92,7 +91,6 @@ struct etm_filters { * @path: An array of path, each slot for one CPU. */ struct etm_event_data { - struct work_struct work; cpumask_t mask; cpumask_t aux_hwid_done; void *snk_config;