static void etm_event_stop()

in coresight/coresight-etm-perf.c [502:596]


static void etm_event_stop(struct perf_event *event, int mode)
{
	int cpu = smp_processor_id();
	unsigned long size;
	struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
	struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt);
	struct perf_output_handle *handle = &ctxt->handle;
	struct etm_event_data *event_data;
	struct list_head *path;

	/*
	 * If we still have access to the event_data via handle,
	 * confirm that we haven't messed up the tracking.
	 */
	if (handle->event &&
	    WARN_ON(perf_get_aux(handle) != ctxt->event_data))
		return;

	event_data = ctxt->event_data;
	/* Clear the event_data as this ETM is stopping the trace. */
	ctxt->event_data = NULL;

	if (event->hw.state == PERF_HES_STOPPED)
		return;

	/* We must have a valid event_data for a running event */
	if (WARN_ON(!event_data))
		return;

	/*
	 * Check if this ETM was allowed to trace, as decided at
	 * etm_setup_aux(). If it wasn't allowed to trace, then
	 * nothing needs to be torn down other than outputting a
	 * zero sized record.
	 */
	if (handle->event && (mode & PERF_EF_UPDATE) &&
	    !cpumask_test_cpu(cpu, &event_data->mask)) {
		event->hw.state = PERF_HES_STOPPED;
		perf_aux_output_end(handle, 0);
		return;
	}

	if (!csdev)
		return;

	path = etm_event_cpu_path(event_data, cpu);
	if (!path)
		return;

	sink = coresight_get_sink(path);
	if (!sink)
		return;

	/* stop tracer */
	source_ops(csdev)->disable(csdev, event);

	/* tell the core */
	event->hw.state = PERF_HES_STOPPED;

	/*
	 * If the handle is not bound to an event anymore
	 * (e.g, the sink driver was unable to restart the
	 * handle due to lack of buffer space), we don't
	 * have to do anything here.
	 */
	if (handle->event && (mode & PERF_EF_UPDATE)) {
		if (WARN_ON_ONCE(handle->event != event))
			return;

		/* update trace information */
		if (!sink_ops(sink)->update_buffer)
			return;

		size = sink_ops(sink)->update_buffer(sink, handle,
					      event_data->snk_config);
		/*
		 * Make sure the handle is still valid as the
		 * sink could have closed it from an IRQ.
		 * The sink driver must handle the race with
		 * update_buffer() and IRQ. Thus either we
		 * should get a valid handle and valid size
		 * (which may be 0).
		 *
		 * But we should never get a non-zero size with
		 * an invalid handle.
		 */
		if (READ_ONCE(handle->event))
			perf_aux_output_end(handle, size);
		else
			WARN_ON(size);
	}

	/* Disabling the path make its elements available to other sessions */
	coresight_disable_path(path);
}