return;
}
-static void etm_event_pause(struct coresight_device *csdev,
+static void etm_event_pause(struct perf_event *event,
+ struct coresight_device *csdev,
struct etm_ctxt *ctxt)
{
+ int cpu = smp_processor_id();
+ struct coresight_device *sink;
+ struct perf_output_handle *handle = &ctxt->handle;
+ struct coresight_path *path;
+ unsigned long size;
+
if (!ctxt->event_data)
return;
/* Stop tracer */
coresight_pause_source(csdev);
+
+ path = etm_event_cpu_path(ctxt->event_data, cpu);
+ sink = coresight_get_sink(path);
+ if (WARN_ON_ONCE(!sink))
+ return;
+
+ /*
+ * The per CPU sink has own interrupt handling, it might have
+ * race condition with updating buffer on AUX trace pause if
+ * it is invoked from NMI. To avoid the race condition,
+ * disallows updating buffer for the per CPU sink case.
+ */
+ if (coresight_is_percpu_sink(sink))
+ return;
+
+ if (WARN_ON_ONCE(handle->event != event))
+ return;
+
+ if (!sink_ops(sink)->update_buffer)
+ return;
+
+ size = sink_ops(sink)->update_buffer(sink, handle,
+ ctxt->event_data->snk_config);
+ if (READ_ONCE(handle->event)) {
+ if (!size)
+ return;
+
+ perf_aux_output_end(handle, size);
+ perf_aux_output_begin(handle, event);
+ } else {
+ WARN_ON_ONCE(size);
+ }
}
static void etm_event_stop(struct perf_event *event, int mode)
struct coresight_path *path;
if (mode & PERF_EF_PAUSE)
- return etm_event_pause(csdev, ctxt);
+ return etm_event_pause(event, csdev, ctxt);
/*
* If we still have access to the event_data via handle,