All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] media: v4l2: Adding mem2mem ftrace support
@ 2021-05-17 18:37 Emil Velikov
  2021-05-17 18:37 ` [PATCH 1/5] media: v4l2: print the fh, during qbuf/dqbuf tracing Emil Velikov
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Emil Velikov @ 2021-05-17 18:37 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Hans Verkuil, Ezequiel Garcia,
	Philipp Zabel, Alexandre Courbot, Mikhail Ulyanov, kernel
  Cc: linux-media

Hi everyone,

This RFC aims to kick off a discussion about adding ftrace events in
V4L2 and mem2mem in particular.

The goal is to aid both userspace and kernel developers alike by
allowing them to trace their individual application/library and drivers,
respectively.


# Data provided

In order to correlate the components through their lifetime we need a
few unique identifiers:

 - minor: the device minor, aka /dev/video
   Useful, when multiple devices are present.

 - fh: file handle
   Allows us to map the buffer, ioctl and mem2mem jobs.

 - fh: as a job instance... sort of
   We also use it as to distinguish between the different jobs, as long
   as we track the cancel/finish events.


Additionally, for buffers we need:
 - type: VIDEO_OUTPUT_MPLANE, VIDEO_CAPTURE_MPLANE, etc
 - index: buffer index
   Each buffer type has its own pool.


# Event list and examples

Generic:

v4l2_ioctl_s_fmt: minor = 0, fh = 5068c670, type = VIDEO_OUTPUT_MPLANE,
width=1280, height=720, ...

v4l2_qbuf: minor = 0, fh = 5068c670, index = 0, type =
VIDEO_CAPTURE_MPLANE, bytesused = 0, ...
v4l2_dqbuf: minor = 0, fh = 5068c670, index = 0, type =
VIDEO_CAPTURE_MPLANE, bytesused = 0, ...


Mem2mem specific:

v4l2_m2m_schedule: minor = 0, fh = 5068c670
v4l2_m2m_schedule_failed: minor = 0, fh = 5068c670, reason = NO_SRC
v4l2_m2m_queue_job: minor = 0, fh = 5068c670, src = 0, dst = 0
Currently src and dst only show the buffer index. Buffer type can be
deduced based on the type of job - encode or decode.

v4l2_m2m_run_job: minor = 0, fh = 5068c670
v4l2_m2m_cancel_job: minor = 0, fh = 5068c670
v4l2_m2m_finish_job: minor = 0, fh = 5068c670

v4l2_m2m_stream_on: minor = 0, fh = 5068c670, type = f9e16c2e
v4l2_m2m_stream_off: minor = 0, fh = 5068c670, type = f9e16c2e

v4l2_m2m_buf_done: minor = 0, fh = 5068c670, index = 0, type =
VIDEO_CAPTURE_MPLANE, state = DONE


# Testing and feasibility

While developing this series I've used them against the recent SAMA5D4
Hantro driver. As result I was able to measure:

 - No time differences when switching from hard to soft IRQ
 - Seemingly gstreamer issues decoding jobs, even before it has queued
   any buffers.
 - Notable 1ms queue times, when using gstreamer's new decodebin3
   element - relative to 50us when using decodebin.


# Open questions

As you may have noticed, a couple of places are not so friendly to
scripting and external tools. Here is what we can do:
 - add additional mem2mem job index identifier, so we can parse traces
   without having to track v4l2_m2m_cancel_job or v4l2_m2m_finish_job.
 - expand v4l2_m2m_queue_job() to include mode buffer details
   {src,dst}_buf { .index = foo, .type = bar, ... }


Thus looking for feedback from the overall community - is this something
we want, do the proposed trace events seem sufficient for your use-case?

Comments and reviews for the individual patches is more than welcome.

Thanks
Emil


Emil Velikov (5):
  media: v4l2: print the fh, during qbuf/dqbuf tracing
  media: v4l2: add VIDIOC_S_FMT tracing
  media: v4l2-mem2mem: add job tracing
  media: v4l2-mem2mem: add v4l2_m2m_buf_done trace point
  media: v4l2-mem2mem: add v4l2_m2m_stream_on/off tracepoints

 drivers/media/v4l2-core/v4l2-ioctl.c   |  12 +-
 drivers/media/v4l2-core/v4l2-mem2mem.c |  26 ++
 drivers/media/v4l2-core/v4l2-trace.c   |  11 +
 include/media/v4l2-mem2mem.h           |  21 +-
 include/trace/events/v4l2.h            | 357 ++++++++++++++++++++++++-
 include/uapi/linux/videodev2.h         |   1 +
 6 files changed, 411 insertions(+), 17 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/5] media: v4l2: print the fh, during qbuf/dqbuf tracing
  2021-05-17 18:37 [RFC] media: v4l2: Adding mem2mem ftrace support Emil Velikov
@ 2021-05-17 18:37 ` Emil Velikov
  2021-06-03 18:16   ` Ezequiel Garcia
  2021-05-17 18:37 ` [PATCH 2/5] media: v4l2: add VIDIOC_S_FMT tracing Emil Velikov
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Emil Velikov @ 2021-05-17 18:37 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Hans Verkuil, Ezequiel Garcia,
	Philipp Zabel, Alexandre Courbot, Mikhail Ulyanov, kernel
  Cc: linux-media

From: Emil Velikov <emil.velikov@collabora.com>

To correlate the buffer handling with specific jobs, we need to provide
the file handle (pointer) used.

Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 10 ++++++++--
 include/trace/events/v4l2.h          | 22 ++++++++++++----------
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 31d1342e61e8..4b56493a1bae 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -3343,10 +3343,16 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg,
 	}
 
 	if (err == 0) {
+		struct video_device *vdev = video_devdata(file);
+		struct v4l2_fh *fh = NULL;
+
+		if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
+			fh = file->private_data;
+
 		if (cmd == VIDIOC_DQBUF)
-			trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
+			trace_v4l2_dqbuf(fh, parg);
 		else if (cmd == VIDIOC_QBUF)
-			trace_v4l2_qbuf(video_devdata(file)->minor, parg);
+			trace_v4l2_qbuf(fh, parg);
 	}
 
 	if (has_array_args) {
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index 248bc09bfc99..e07311cfe5ca 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -7,6 +7,7 @@
 
 #include <linux/tracepoint.h>
 #include <media/videobuf2-v4l2.h>
+#include <media/v4l2-device.h>
 
 /* Enums require being exported to userspace, for user tool parsing */
 #undef EM
@@ -98,12 +99,12 @@ SHOW_FIELD
 		{ V4L2_TC_USERBITS_8BITCHARS,	"USERBITS_8BITCHARS" })
 
 DECLARE_EVENT_CLASS(v4l2_event_class,
-	TP_PROTO(int minor, struct v4l2_buffer *buf),
-
-	TP_ARGS(minor, buf),
+	TP_PROTO(struct v4l2_fh *fh, struct v4l2_buffer *buf),
+	TP_ARGS(fh, buf),
 
 	TP_STRUCT__entry(
 		__field(int, minor)
+		__field(struct v4l2_fh *, fh)
 		__field(u32, index)
 		__field(u32, type)
 		__field(u32, bytesused)
@@ -124,7 +125,8 @@ DECLARE_EVENT_CLASS(v4l2_event_class,
 	),
 
 	TP_fast_assign(
-		__entry->minor = minor;
+		__entry->minor = fh ? fh->vdev->minor : -1;
+		__entry->fh = fh;
 		__entry->index = buf->index;
 		__entry->type = buf->type;
 		__entry->bytesused = buf->bytesused;
@@ -144,12 +146,12 @@ DECLARE_EVENT_CLASS(v4l2_event_class,
 		__entry->sequence = buf->sequence;
 	),
 
-	TP_printk("minor = %d, index = %u, type = %s, bytesused = %u, "
+	TP_printk("minor = %d, fh = %p, index = %u, type = %s, bytesused = %u, "
 		  "flags = %s, field = %s, timestamp = %llu, "
 		  "timecode = { type = %s, flags = %s, frames = %u, "
 		  "seconds = %u, minutes = %u, hours = %u, "
 		  "userbits = { %u %u %u %u } }, sequence = %u", __entry->minor,
-		  __entry->index, show_type(__entry->type),
+		  __entry->fh, __entry->index, show_type(__entry->type),
 		  __entry->bytesused,
 		  show_flags(__entry->flags),
 		  show_field(__entry->field),
@@ -169,13 +171,13 @@ DECLARE_EVENT_CLASS(v4l2_event_class,
 )
 
 DEFINE_EVENT(v4l2_event_class, v4l2_dqbuf,
-	TP_PROTO(int minor, struct v4l2_buffer *buf),
-	TP_ARGS(minor, buf)
+	TP_PROTO(struct v4l2_fh *fh, struct v4l2_buffer *buf),
+	TP_ARGS(fh, buf)
 );
 
 DEFINE_EVENT(v4l2_event_class, v4l2_qbuf,
-	TP_PROTO(int minor, struct v4l2_buffer *buf),
-	TP_ARGS(minor, buf)
+	TP_PROTO(struct v4l2_fh *fh, struct v4l2_buffer *buf),
+	TP_ARGS(fh, buf)
 );
 
 DECLARE_EVENT_CLASS(vb2_v4l2_event_class,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/5] media: v4l2: add VIDIOC_S_FMT tracing
  2021-05-17 18:37 [RFC] media: v4l2: Adding mem2mem ftrace support Emil Velikov
  2021-05-17 18:37 ` [PATCH 1/5] media: v4l2: print the fh, during qbuf/dqbuf tracing Emil Velikov
@ 2021-05-17 18:37 ` Emil Velikov
  2021-05-17 18:37 ` [PATCH 3/5] media: v4l2-mem2mem: add job tracing Emil Velikov
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Emil Velikov @ 2021-05-17 18:37 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Hans Verkuil, Ezequiel Garcia,
	Philipp Zabel, Alexandre Courbot, Mikhail Ulyanov, kernel
  Cc: linux-media

From: Emil Velikov <emil.velikov@collabora.com>

Add tracing for VIDIOC_S_FMT, which can be correlated to job and buffer
submission traces.

Since we're setting the format itself, we do not have distinct buffer
(index) here. Yet, we can still use the minor/fh/type to link the trace
to the corresponding job.

Co-authored-by: Robert Beckett <bob.beckett@collabora.com>
Signed-off-by: Robert Beckett <bob.beckett@collabora.com>
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
---
 drivers/media/v4l2-core/v4l2-ioctl.c |   2 +
 drivers/media/v4l2-core/v4l2-trace.c |   1 +
 include/trace/events/v4l2.h          | 132 +++++++++++++++++++++++++++
 include/uapi/linux/videodev2.h       |   1 +
 4 files changed, 136 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 4b56493a1bae..66a039ed8a43 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1662,6 +1662,8 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
 		return ret;
 	v4l_sanitize_format(p);
 
+	trace_v4l2_ioctl_s_fmt(file, fh, p);
+
 	switch (p->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		if (unlikely(!ops->vidioc_s_fmt_vid_cap))
diff --git a/drivers/media/v4l2-core/v4l2-trace.c b/drivers/media/v4l2-core/v4l2-trace.c
index 95f3b02e1f84..6df26fc7c39c 100644
--- a/drivers/media/v4l2-core/v4l2-trace.c
+++ b/drivers/media/v4l2-core/v4l2-trace.c
@@ -10,3 +10,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_done);
 EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_queue);
 EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_dqbuf);
 EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_qbuf);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_ioctl_s_fmt);
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index e07311cfe5ca..d11e38676e48 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -6,8 +6,10 @@
 #define _TRACE_V4L2_H
 
 #include <linux/tracepoint.h>
+#include <linux/videodev2.h>
 #include <media/videobuf2-v4l2.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
 
 /* Enums require being exported to userspace, for user tool parsing */
 #undef EM
@@ -264,6 +266,136 @@ DEFINE_EVENT(vb2_v4l2_event_class, vb2_v4l2_qbuf,
 	TP_ARGS(q, vb)
 );
 
+#ifdef CREATE_TRACE_POINTS
+#define __trace_array_name(a, arr, num) (((unsigned)(a)) < num ? arr[a] : "unknown")
+static inline void __trace_sprint_v4l2_format(char *str, size_t size, struct v4l2_format *p)
+{
+	const struct v4l2_pix_format *pix;
+	const struct v4l2_pix_format_mplane *mp;
+	const struct v4l2_vbi_format *vbi;
+	const struct v4l2_sliced_vbi_format *sliced;
+	const struct v4l2_window *win;
+	const struct v4l2_sdr_format *sdr;
+	const struct v4l2_meta_format *meta;
+
+	switch (p->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+		pix = &p->fmt.pix;
+		snprintf(str, size, "width=%u, height=%u, pixelformat=%c%c%c%c, "
+				    "field=%s, bytesperline=%u, sizeimage=%u, "
+				    "colorspace=%d, flags=0x%x, ycbcr_enc=%u, "
+				    "quantization=%u, xfer_func=%u",
+			pix->width, pix->height,
+			(pix->pixelformat & 0xff),
+			(pix->pixelformat >>  8) & 0xff,
+			(pix->pixelformat >> 16) & 0xff,
+			(pix->pixelformat >> 24) & 0xff,
+			__trace_array_name(pix->field, v4l2_field_names, V4L2_FIELD_NUM),
+			pix->bytesperline, pix->sizeimage,
+			pix->colorspace, pix->flags, pix->ycbcr_enc,
+			pix->quantization, pix->xfer_func);
+		break;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		mp = &p->fmt.pix_mp;
+		snprintf(str, size, "width=%u, height=%u, pixelformat=%c%c%c%c, "
+				    "field=%s, num_planes=%u, "
+				    "colorspace=%d, flags=0x%x, ycbcr_enc=%u, "
+				    "quantization=%u, xfer_func=%u}",
+			mp->width, mp->height,
+			(mp->pixelformat & 0xff),
+			(mp->pixelformat >>  8) & 0xff,
+			(mp->pixelformat >> 16) & 0xff,
+			(mp->pixelformat >> 24) & 0xff,
+			__trace_array_name(mp->field, v4l2_field_names, V4L2_FIELD_NUM),
+			mp->num_planes,
+			mp->colorspace, mp->flags, mp->ycbcr_enc,
+			mp->quantization, mp->xfer_func);
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+		win = &p->fmt.win;
+		/* Note: we can't print the clip list here since the clips
+		 * pointer is a userspace pointer, not a kernelspace
+		 * pointer. */
+		snprintf(str, size, "wxh=%dx%d, x,y=%d,%d, field=%s, "
+				    "chromakey=0x%08x, clipcount=%u, clips=%p, "
+				    "bitmap=%p, global_alpha=0x%02x",
+			win->w.width, win->w.height, win->w.left, win->w.top,
+			__trace_array_name(win->field, v4l2_field_names, V4L2_FIELD_NUM),
+			win->chromakey, win->clipcount, win->clips,
+			win->bitmap, win->global_alpha);
+		break;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+	case V4L2_BUF_TYPE_VBI_OUTPUT:
+		vbi = &p->fmt.vbi;
+		pr_cont("sampling_rate=%u, offset=%u, samples_per_line=%u, "
+			"sample_format=%c%c%c%c, start=%u,%u, count=%u,%u",
+			vbi->sampling_rate, vbi->offset,
+			vbi->samples_per_line,
+			(vbi->sample_format & 0xff),
+			(vbi->sample_format >>  8) & 0xff,
+			(vbi->sample_format >> 16) & 0xff,
+			(vbi->sample_format >> 24) & 0xff,
+			vbi->start[0], vbi->start[1],
+			vbi->count[0], vbi->count[1]);
+		break;
+	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+		sliced = &p->fmt.sliced;
+		snprintf(str, size, "service_set=0x%08x, io_size=%d",
+				sliced->service_set, sliced->io_size);
+		break;
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+	case V4L2_BUF_TYPE_SDR_OUTPUT:
+		sdr = &p->fmt.sdr;
+		snprintf(str, size, "pixelformat=%c%c%c%c",
+			(sdr->pixelformat >>  0) & 0xff,
+			(sdr->pixelformat >>  8) & 0xff,
+			(sdr->pixelformat >> 16) & 0xff,
+			(sdr->pixelformat >> 24) & 0xff);
+		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+	case V4L2_BUF_TYPE_META_OUTPUT:
+		meta = &p->fmt.meta;
+		snprintf(str, size, "dataformat=%c%c%c%c, buffersize=%u",
+			(meta->dataformat >>  0) & 0xff,
+			(meta->dataformat >>  8) & 0xff,
+			(meta->dataformat >> 16) & 0xff,
+			(meta->dataformat >> 24) & 0xff,
+			meta->buffersize);
+		break;
+	}
+}
+#endif
+
+#define V4L2_FMT_MAX   256
+
+/* v4l2-ioctl trace events */
+TRACE_EVENT(v4l2_ioctl_s_fmt,
+	TP_PROTO(struct file *file, struct v4l2_fh *fh, struct v4l2_format *fmt),
+	TP_ARGS(file, fh, fmt),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(struct v4l2_fh *, fh)
+		__field(u32, type)
+		__dynamic_array(char, details, V4L2_FMT_MAX)
+	),
+
+	TP_fast_assign(
+		__entry->minor = video_devdata(file)->minor;
+		__entry->fh = fh;
+		__entry->type = fmt->type;
+		__trace_sprint_v4l2_format(__get_str(details), V4L2_FMT_MAX, fmt);
+	),
+
+	TP_printk("minor = %d, fh = %p, type = %s, %s",
+		__entry->minor, __entry->fh,
+		show_type(__entry->type), __get_str(details))
+);
+
 #endif /* if !defined(_TRACE_V4L2_H) || defined(TRACE_HEADER_MULTI_READ) */
 
 /* This part must be outside protection */
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 79dbde3bcf8d..f9f4b63fb50f 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -105,6 +105,7 @@ enum v4l2_field {
 	V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field
 					 first and the bottom field is
 					 transmitted first */
+	V4L2_FIELD_NUM
 };
 #define V4L2_FIELD_HAS_TOP(field)	\
 	((field) == V4L2_FIELD_TOP	||\
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/5] media: v4l2-mem2mem: add job tracing
  2021-05-17 18:37 [RFC] media: v4l2: Adding mem2mem ftrace support Emil Velikov
  2021-05-17 18:37 ` [PATCH 1/5] media: v4l2: print the fh, during qbuf/dqbuf tracing Emil Velikov
  2021-05-17 18:37 ` [PATCH 2/5] media: v4l2: add VIDIOC_S_FMT tracing Emil Velikov
@ 2021-05-17 18:37 ` Emil Velikov
  2021-05-17 18:38 ` [PATCH 4/5] media: v4l2-mem2mem: add v4l2_m2m_buf_done trace point Emil Velikov
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Emil Velikov @ 2021-05-17 18:37 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Hans Verkuil, Ezequiel Garcia,
	Philipp Zabel, Alexandre Courbot, Mikhail Ulyanov, kernel
  Cc: linux-media

From: Emil Velikov <emil.velikov@collabora.com>

Add ftrace events to trace job submission and processing.

In particular, allow for tracking the whole job from the initial
submission/schedule stage until its completion.

Since there can be only a single job, per given file handle we use the
handle pointer as a unique identifier. This will allow us to correlate
that with the buffers used and their lifespan - coming with later
patches.

Co-authored-by: Robert Beckett <bob.beckett@collabora.com>
Signed-off-by: Robert Beckett <bob.beckett@collabora.com>
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
---

Not 100% sold on v4l2_m2m_queue_job().

Currently we denote with src/dst the buffer index, while use use index
throughout the rest of the series. Should we suffix those with _index?

Additionally, we don't print the type - which is known albeit not
machine read-able. I'm leaning towards having making each of those
an {src,dst}_buf { .index = foo, .type = bar }.

Does that sound reasonable?


 drivers/media/v4l2-core/v4l2-mem2mem.c |  15 +++
 drivers/media/v4l2-core/v4l2-trace.c   |   7 ++
 include/media/v4l2-mem2mem.h           |  11 +++
 include/trace/events/v4l2.h            | 128 +++++++++++++++++++++++++
 4 files changed, 161 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index e7f4bf5bc8dd..bf83d1fae701 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -20,6 +20,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
+#include <trace/events/v4l2.h>
 
 MODULE_DESCRIPTION("Mem to mem device framework for videobuf");
 MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
@@ -281,6 +282,7 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev)
 	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
 
 	dprintk("Running job on m2m_ctx: %p\n", m2m_dev->curr_ctx);
+	trace_v4l2_m2m_run_job(m2m_dev->curr_ctx);
 	m2m_dev->m2m_ops->device_run(m2m_dev->curr_ctx->priv);
 }
 
@@ -300,10 +302,12 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev,
 	struct vb2_v4l2_buffer *dst, *src;
 
 	dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx);
+	trace_v4l2_m2m_schedule(m2m_ctx);
 
 	if (!m2m_ctx->out_q_ctx.q.streaming
 	    || !m2m_ctx->cap_q_ctx.q.streaming) {
 		dprintk("Streaming needs to be on for both queues\n");
+		trace_v4l2_m2m_schedule_failed(m2m_ctx, V4L2_M2M_NOT_STREAMING);
 		return;
 	}
 
@@ -312,11 +316,13 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev,
 	/* If the context is aborted then don't schedule it */
 	if (m2m_ctx->job_flags & TRANS_ABORT) {
 		dprintk("Aborted context\n");
+		trace_v4l2_m2m_schedule_failed(m2m_ctx, V4L2_M2M_ABORTED);
 		goto job_unlock;
 	}
 
 	if (m2m_ctx->job_flags & TRANS_QUEUED) {
 		dprintk("On job queue already\n");
+		trace_v4l2_m2m_schedule_failed(m2m_ctx, V4L2_M2M_ALREADY_QUEUED);
 		goto job_unlock;
 	}
 
@@ -324,10 +330,12 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev,
 	dst = v4l2_m2m_next_dst_buf(m2m_ctx);
 	if (!src && !m2m_ctx->out_q_ctx.buffered) {
 		dprintk("No input buffers available\n");
+		trace_v4l2_m2m_schedule_failed(m2m_ctx, V4L2_M2M_NO_SRC);
 		goto job_unlock;
 	}
 	if (!dst && !m2m_ctx->cap_q_ctx.buffered) {
 		dprintk("No output buffers available\n");
+		trace_v4l2_m2m_schedule_failed(m2m_ctx, V4L2_M2M_NO_DST);
 		goto job_unlock;
 	}
 
@@ -343,6 +351,7 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev,
 
 		if (!dst && !m2m_ctx->cap_q_ctx.buffered) {
 			dprintk("No output buffers available after returning held buffer\n");
+			trace_v4l2_m2m_schedule_failed(m2m_ctx, V4L2_M2M_NO_DST_POST_HELD);
 			goto job_unlock;
 		}
 	}
@@ -354,17 +363,20 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev,
 
 	if (m2m_ctx->has_stopped) {
 		dprintk("Device has stopped\n");
+		trace_v4l2_m2m_schedule_failed(m2m_ctx, V4L2_M2M_DEV_STOPPED);
 		goto job_unlock;
 	}
 
 	if (m2m_dev->m2m_ops->job_ready
 		&& (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) {
 		dprintk("Driver not ready\n");
+		trace_v4l2_m2m_schedule_failed(m2m_ctx, V4L2_M2M_DRV_NOT_READY);
 		goto job_unlock;
 	}
 
 	list_add_tail(&m2m_ctx->queue, &m2m_dev->job_queue);
 	m2m_ctx->job_flags |= TRANS_QUEUED;
+	trace_v4l2_m2m_queue_job(m2m_ctx, src ? &src->vb2_buf : NULL, dst ? &dst->vb2_buf : NULL);
 
 job_unlock:
 	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
@@ -426,6 +438,7 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx *m2m_ctx)
 		if (m2m_dev->m2m_ops->job_abort)
 			m2m_dev->m2m_ops->job_abort(m2m_ctx->priv);
 		dprintk("m2m_ctx %p running, will wait to complete\n", m2m_ctx);
+		trace_v4l2_m2m_cancel_job_wait(m2m_ctx);
 		wait_event(m2m_ctx->finished,
 				!(m2m_ctx->job_flags & TRANS_RUNNING));
 	} else if (m2m_ctx->job_flags & TRANS_QUEUED) {
@@ -438,6 +451,7 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx *m2m_ctx)
 		/* Do nothing, was not on queue/running */
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
 	}
+	trace_v4l2_m2m_cancel_job(m2m_ctx);
 }
 
 /*
@@ -477,6 +491,7 @@ static bool _v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
 	m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
 	wake_up(&m2m_dev->curr_ctx->finished);
 	m2m_dev->curr_ctx = NULL;
+	trace_v4l2_m2m_finish_job(m2m_ctx);
 	return true;
 }
 
diff --git a/drivers/media/v4l2-core/v4l2-trace.c b/drivers/media/v4l2-core/v4l2-trace.c
index 6df26fc7c39c..cde408d06fdc 100644
--- a/drivers/media/v4l2-core/v4l2-trace.c
+++ b/drivers/media/v4l2-core/v4l2-trace.c
@@ -11,3 +11,10 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_queue);
 EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_dqbuf);
 EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_qbuf);
 EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_ioctl_s_fmt);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_schedule);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_schedule_failed);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_queue_job);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_run_job);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_cancel_job_wait);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_cancel_job);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_finish_job);
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 5a91b548ecc0..82bf54254bd8 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -15,6 +15,17 @@
 
 #include <media/videobuf2-v4l2.h>
 
+enum v4l2_m2m_state {
+	V4L2_M2M_NOT_STREAMING,
+	V4L2_M2M_ABORTED,
+	V4L2_M2M_ALREADY_QUEUED,
+	V4L2_M2M_NO_SRC,
+	V4L2_M2M_NO_DST,
+	V4L2_M2M_NO_DST_POST_HELD,
+	V4L2_M2M_DEV_STOPPED,
+	V4L2_M2M_DRV_NOT_READY
+};
+
 /**
  * struct v4l2_m2m_ops - mem-to-mem device driver callbacks
  * @device_run:	required. Begin the actual job (transaction) inside this
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index d11e38676e48..8e382bad5f8e 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -10,6 +10,7 @@
 #include <media/videobuf2-v4l2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
 
 /* Enums require being exported to userspace, for user tool parsing */
 #undef EM
@@ -55,6 +56,21 @@ SHOW_TYPE
 
 SHOW_FIELD
 
+#define show_reason(state)						\
+	__print_symbolic(state, SHOW_REASON)
+
+#define SHOW_REASON							\
+	EM( V4L2_M2M_NOT_STREAMING,	"NOT_STREAMING" )		\
+	EM( V4L2_M2M_ABORTED,		"ABORTED" )			\
+	EM( V4L2_M2M_ALREADY_QUEUED,	"ALREADY_QUEUED" )		\
+	EM( V4L2_M2M_NO_SRC,		"NO_SRC" )			\
+	EM( V4L2_M2M_NO_DST,		"NO_DST" )			\
+	EM( V4L2_M2M_NO_DST_POST_HELD,	"NO_DST_POST_HELD" )		\
+	EM( V4L2_M2M_DEV_STOPPED,	"DEV_STOPPED" )			\
+	EMe(V4L2_M2M_DRV_NOT_READY,	"DRV_NOT_READY" )
+
+SHOW_REASON
+
 /*
  * Now redefine the EM() and EMe() macros to map the enums to the strings
  * that will be printed in the output.
@@ -266,6 +282,118 @@ DEFINE_EVENT(vb2_v4l2_event_class, vb2_v4l2_qbuf,
 	TP_ARGS(q, vb)
 );
 
+/*
+ * v4l_m2m job tracing
+ * expected order of events:
+ * 	v4l2_m2m_schedule 		<= start of a job trace
+ * 	[v4l2_m2m_schedule_failed*]
+ *	v4l2_m2m_queue_job		<= job queued on list of ready jobs
+ *	v4l2_m2m_run_job 		<= driver told to run the job
+ *	[v4l2_m2m_cancel_job_wait]	<= job cancelled, but waiting for completion as it is already running
+ *	[v4l2_m2m_cancel_job*]		<= job cancelled
+ *	v4l2_m2m_finish_job		<= job finished, end of trace
+ *
+ *	events in [] indicate optional events, that may appear, but usually would not be expected
+ *	events with * indicate terminal events that end a trace early
+ *
+ *	A typical job timeline would be a 3 segment period:
+ *	[ scheduled | queued | running ]
+ *	^           ^        ^         ^
+ *	|-----------|--------|---------|-- v4l2_m2m_schedule
+ *	            |--------|---------|-- v4l2_m2m_queue_job
+ *	                     |---------|-- v4l2_m2m_run_job
+ *	                               |-- v4l2_m2m_finish_job
+ */
+DECLARE_EVENT_CLASS(v4l2_m2m_event_class,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx),
+	TP_ARGS(ctx),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(struct v4l2_fh *, fh)
+	),
+
+	TP_fast_assign(
+		struct v4l2_fh *owner = ctx->cap_q_ctx.q.owner;
+
+		__entry->minor = owner ? owner->vdev->minor : -1;
+		__entry->fh = owner;
+	),
+
+	TP_printk("minor = %d, fh = %p",
+		__entry->minor, __entry->fh)
+)
+
+DEFINE_EVENT(v4l2_m2m_event_class, v4l2_m2m_schedule,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx),
+	TP_ARGS(ctx)
+);
+
+TRACE_EVENT(v4l2_m2m_schedule_failed,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx, enum v4l2_m2m_state reason),
+	TP_ARGS(ctx, reason),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(struct v4l2_fh *, fh)
+		__field(enum v4l2_m2m_state, reason)
+	),
+
+	TP_fast_assign(
+		struct v4l2_fh *owner = ctx->cap_q_ctx.q.owner;
+
+		__entry->minor = owner ? owner->vdev->minor : -1;
+		__entry->fh = owner;
+		__entry->reason = reason;
+	),
+
+	TP_printk("minor = %d, fh = %p, reason = %s",
+		__entry->minor, __entry->fh, show_reason(__entry->reason))
+)
+
+TRACE_EVENT(v4l2_m2m_queue_job,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx, struct vb2_buffer *src, struct vb2_buffer *dst),
+	TP_ARGS(ctx, src, dst),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(struct v4l2_fh *, fh)
+		__field(s32, src)
+		__field(s32, dst)
+	),
+
+	TP_fast_assign(
+		struct v4l2_fh *owner = ctx->cap_q_ctx.q.owner;
+
+		__entry->minor = owner ? owner->vdev->minor : -1;
+		__entry->fh = owner;
+		__entry->src = src ? (s32)src->index : -1;
+		__entry->dst = dst ? (s32)dst->index : -1;
+	),
+	TP_printk("minor = %d, fh = %p, src = %d, dst = %d",
+		__entry->minor, __entry->fh, __entry->src, __entry->dst)
+);
+
+DEFINE_EVENT(v4l2_m2m_event_class, v4l2_m2m_run_job,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx),
+	TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(v4l2_m2m_event_class, v4l2_m2m_cancel_job_wait,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx),
+	TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(v4l2_m2m_event_class, v4l2_m2m_cancel_job,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx),
+	TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(v4l2_m2m_event_class, v4l2_m2m_finish_job,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx),
+	TP_ARGS(ctx)
+);
+
 #ifdef CREATE_TRACE_POINTS
 #define __trace_array_name(a, arr, num) (((unsigned)(a)) < num ? arr[a] : "unknown")
 static inline void __trace_sprint_v4l2_format(char *str, size_t size, struct v4l2_format *p)
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/5] media: v4l2-mem2mem: add v4l2_m2m_buf_done trace point
  2021-05-17 18:37 [RFC] media: v4l2: Adding mem2mem ftrace support Emil Velikov
                   ` (2 preceding siblings ...)
  2021-05-17 18:37 ` [PATCH 3/5] media: v4l2-mem2mem: add job tracing Emil Velikov
@ 2021-05-17 18:38 ` Emil Velikov
  2021-06-03 18:21   ` Ezequiel Garcia
  2021-05-17 18:38 ` [PATCH 5/5] media: v4l2-mem2mem: add v4l2_m2m_stream_on/off tracepoints Emil Velikov
  2021-06-03 18:25 ` [RFC] media: v4l2: Adding mem2mem ftrace support Ezequiel Garcia
  5 siblings, 1 reply; 9+ messages in thread
From: Emil Velikov @ 2021-05-17 18:38 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Hans Verkuil, Ezequiel Garcia,
	Philipp Zabel, Alexandre Courbot, Mikhail Ulyanov, kernel
  Cc: linux-media

From: Emil Velikov <emil.velikov@collabora.com>

Move the function out of the header, as required by the trace API and
add a tracepoint.

Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
---
 drivers/media/v4l2-core/v4l2-mem2mem.c |  9 ++++++
 drivers/media/v4l2-core/v4l2-trace.c   |  1 +
 include/media/v4l2-mem2mem.h           | 10 +++----
 include/trace/events/v4l2.h            | 41 ++++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index bf83d1fae701..a83d3e4e7a85 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -555,6 +555,15 @@ void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev,
 }
 EXPORT_SYMBOL(v4l2_m2m_buf_done_and_job_finish);
 
+void
+v4l2_m2m_buf_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state)
+{
+	// TODO: Emil move the trace after done?
+	trace_v4l2_m2m_buf_done(&buf->vb2_buf, state);
+	vb2_buffer_done(&buf->vb2_buf, state);
+}
+EXPORT_SYMBOL(v4l2_m2m_buf_done);
+
 void v4l2_m2m_suspend(struct v4l2_m2m_dev *m2m_dev)
 {
 	unsigned long flags;
diff --git a/drivers/media/v4l2-core/v4l2-trace.c b/drivers/media/v4l2-core/v4l2-trace.c
index cde408d06fdc..b70208101f3c 100644
--- a/drivers/media/v4l2-core/v4l2-trace.c
+++ b/drivers/media/v4l2-core/v4l2-trace.c
@@ -11,6 +11,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_queue);
 EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_dqbuf);
 EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_qbuf);
 EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_ioctl_s_fmt);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_buf_done);
 EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_schedule);
 EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_schedule_failed);
 EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_queue_job);
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 82bf54254bd8..013fd355ff82 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -229,11 +229,11 @@ void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev,
 				      struct v4l2_m2m_ctx *m2m_ctx,
 				      enum vb2_buffer_state state);
 
-static inline void
-v4l2_m2m_buf_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state)
-{
-	vb2_buffer_done(&buf->vb2_buf, state);
-}
+/**
+ * Something something
+ */
+void
+v4l2_m2m_buf_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state);
 
 /**
  * v4l2_m2m_clear_state() - clear encoding/decoding state
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index 8e382bad5f8e..a545f6a13d0a 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -56,6 +56,20 @@ SHOW_TYPE
 
 SHOW_FIELD
 
+#define show_state(state)						\
+	__print_symbolic(state, SHOW_STATE)
+
+#define SHOW_STATE							\
+	EM( VB2_BUF_STATE_DEQUEUED,	"DEQUEUED" )			\
+	EM( VB2_BUF_STATE_IN_REQUEST,	"IN_REQUEST" )			\
+	EM( VB2_BUF_STATE_PREPARING,	"PREPARING" )			\
+	EM( VB2_BUF_STATE_QUEUED,	"QUEUED" )			\
+	EM( VB2_BUF_STATE_ACTIVE,	"ACTIVE" )			\
+	EM( VB2_BUF_STATE_DONE,		"DONE" )			\
+	EMe(VB2_BUF_STATE_ERROR,	"ERROR" )
+
+SHOW_STATE
+
 #define show_reason(state)						\
 	__print_symbolic(state, SHOW_REASON)
 
@@ -282,6 +296,33 @@ DEFINE_EVENT(vb2_v4l2_event_class, vb2_v4l2_qbuf,
 	TP_ARGS(q, vb)
 );
 
+TRACE_EVENT(v4l2_m2m_buf_done,
+	TP_PROTO(struct vb2_buffer *vb, enum vb2_buffer_state state),
+	TP_ARGS(vb, state),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(struct v4l2_fh *, fh)
+		__field(s32, index)
+		__field(u32, type)
+		__field(enum vb2_buffer_state, state)
+	),
+
+	TP_fast_assign(
+		struct v4l2_fh *owner = vb->vb2_queue->owner;
+
+		__entry->minor = owner ? owner->vdev->minor : -1;
+		__entry->fh = owner;
+		__entry->index = vb->index;
+		__entry->type = vb->type;
+		__entry->state = state;
+	),
+
+	TP_printk("minor = %d, fh = %p, index = %u, type = %s, state = %s",
+		__entry->minor, __entry->fh, __entry->index,
+		show_type(__entry->type), show_state(__entry->state))
+);
+
 /*
  * v4l_m2m job tracing
  * expected order of events:
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/5] media: v4l2-mem2mem: add v4l2_m2m_stream_on/off tracepoints
  2021-05-17 18:37 [RFC] media: v4l2: Adding mem2mem ftrace support Emil Velikov
                   ` (3 preceding siblings ...)
  2021-05-17 18:38 ` [PATCH 4/5] media: v4l2-mem2mem: add v4l2_m2m_buf_done trace point Emil Velikov
@ 2021-05-17 18:38 ` Emil Velikov
  2021-06-03 18:25 ` [RFC] media: v4l2: Adding mem2mem ftrace support Ezequiel Garcia
  5 siblings, 0 replies; 9+ messages in thread
From: Emil Velikov @ 2021-05-17 18:38 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Hans Verkuil, Ezequiel Garcia,
	Philipp Zabel, Alexandre Courbot, Mikhail Ulyanov, kernel
  Cc: linux-media

From: Emil Velikov <emil.velikov@collabora.com>

v4l2_m2m_stream_on/off are essentially the start/end points in between
which jobs can be scheduled. Userspace can easily request a stream_off,
while the last job is being processed - we might want to indicate that
in the traces.

Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
---
 drivers/media/v4l2-core/v4l2-mem2mem.c |  2 ++
 drivers/media/v4l2-core/v4l2-trace.c   |  2 ++
 include/trace/events/v4l2.h            | 34 ++++++++++++++++++++++++++
 3 files changed, 38 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index a83d3e4e7a85..6aa4ecafac6b 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -852,6 +852,7 @@ int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 	int ret;
 
 	vq = v4l2_m2m_get_vq(m2m_ctx, type);
+	trace_v4l2_m2m_stream_on(m2m_ctx, vq);
 	ret = vb2_streamon(vq, type);
 	if (!ret)
 		v4l2_m2m_try_schedule(m2m_ctx);
@@ -895,6 +896,7 @@ int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		wake_up(&m2m_ctx->finished);
 	}
 	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
+	trace_v4l2_m2m_stream_off(m2m_ctx, &q_ctx->q);
 
 	return 0;
 }
diff --git a/drivers/media/v4l2-core/v4l2-trace.c b/drivers/media/v4l2-core/v4l2-trace.c
index b70208101f3c..ce9d393eb69e 100644
--- a/drivers/media/v4l2-core/v4l2-trace.c
+++ b/drivers/media/v4l2-core/v4l2-trace.c
@@ -19,3 +19,5 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_run_job);
 EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_cancel_job_wait);
 EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_cancel_job);
 EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_finish_job);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_stream_on);
+EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_stream_off);
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index a545f6a13d0a..a48a8859a4ef 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -326,6 +326,7 @@ TRACE_EVENT(v4l2_m2m_buf_done,
 /*
  * v4l_m2m job tracing
  * expected order of events:
+ *	v4l2_m2m_stream_on		<= userspace request to start stream processing
  * 	v4l2_m2m_schedule 		<= start of a job trace
  * 	[v4l2_m2m_schedule_failed*]
  *	v4l2_m2m_queue_job		<= job queued on list of ready jobs
@@ -333,6 +334,7 @@ TRACE_EVENT(v4l2_m2m_buf_done,
  *	[v4l2_m2m_cancel_job_wait]	<= job cancelled, but waiting for completion as it is already running
  *	[v4l2_m2m_cancel_job*]		<= job cancelled
  *	v4l2_m2m_finish_job		<= job finished, end of trace
+ *	v4l2_m2m_stream_off		<= userspace request to stop stream processing
  *
  *	events in [] indicate optional events, that may appear, but usually would not be expected
  *	events with * indicate terminal events that end a trace early
@@ -435,6 +437,38 @@ DEFINE_EVENT(v4l2_m2m_event_class, v4l2_m2m_finish_job,
 	TP_ARGS(ctx)
 );
 
+DECLARE_EVENT_CLASS(v4l2_m2m_streaming_class,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx, struct vb2_queue *queue),
+	TP_ARGS(ctx, queue),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(struct v4l2_fh *, fh)
+		__field(u32, type)
+	),
+
+	TP_fast_assign(
+		struct v4l2_fh *owner = ctx->cap_q_ctx.q.owner;
+
+		__entry->minor = owner ? owner->vdev->minor : -1;
+		__entry->fh = owner;
+		__entry->type = queue->type;
+
+	),
+	TP_printk("minor = %d, fh = %p, type = %p",
+		__entry->minor, __entry->fh, show_type(__entry->type))
+)
+
+DEFINE_EVENT(v4l2_m2m_streaming_class, v4l2_m2m_stream_on,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx, struct vb2_queue *queue),
+	TP_ARGS(ctx, queue)
+);
+
+DEFINE_EVENT(v4l2_m2m_streaming_class, v4l2_m2m_stream_off,
+	TP_PROTO(struct v4l2_m2m_ctx *ctx, struct vb2_queue *queue),
+	TP_ARGS(ctx, queue)
+);
+
 #ifdef CREATE_TRACE_POINTS
 #define __trace_array_name(a, arr, num) (((unsigned)(a)) < num ? arr[a] : "unknown")
 static inline void __trace_sprint_v4l2_format(char *str, size_t size, struct v4l2_format *p)
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/5] media: v4l2: print the fh, during qbuf/dqbuf tracing
  2021-05-17 18:37 ` [PATCH 1/5] media: v4l2: print the fh, during qbuf/dqbuf tracing Emil Velikov
@ 2021-06-03 18:16   ` Ezequiel Garcia
  0 siblings, 0 replies; 9+ messages in thread
From: Ezequiel Garcia @ 2021-06-03 18:16 UTC (permalink / raw)
  To: Emil Velikov, Mauro Carvalho Chehab, Hans Verkuil, Philipp Zabel,
	Alexandre Courbot, Mikhail Ulyanov, kernel
  Cc: linux-media

Hi Emil,

Thanks a lot for the series, I think it's great to start
discussing some generic tracing for the media subsytem.

First of all, looks like you should fix your submission
process, the cover letter didn't hit patchwork. See:

https://patchwork.linuxtv.org/project/linux-media/list/?series=5446

Unsure what's going on, but please take a look.

Some feedback about this patch.

On Mon, 2021-05-17 at 19:37 +0100, Emil Velikov wrote:
> From: Emil Velikov <emil.velikov@collabora.com>
> 
> To correlate the buffer handling with specific jobs, we need to provide
> the file handle (pointer) used.
> 

In general, it will be useful to have more information here.
For instance, you are changing traces, so e.g. a before/after
could be better.

Not just for this patch, but in general, I think we'd like
to have more documentation.
 
> Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
> ---
>  drivers/media/v4l2-core/v4l2-ioctl.c | 10 ++++++++--
>  include/trace/events/v4l2.h          | 22 ++++++++++++----------
>  2 files changed, 20 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index 31d1342e61e8..4b56493a1bae 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -3343,10 +3343,16 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg,
>         }
>  
>         if (err == 0) {
> +               struct video_device *vdev = video_devdata(file);
> +               struct v4l2_fh *fh = NULL;
> +
> +               if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
> +                       fh = file->private_data;
> +
>                 if (cmd == VIDIOC_DQBUF)
> -                       trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
> +                       trace_v4l2_dqbuf(fh, parg);
>                 else if (cmd == VIDIOC_QBUF)
> -                       trace_v4l2_qbuf(video_devdata(file)->minor, parg);
> +                       trace_v4l2_qbuf(fh, parg);
>         }
>  
>         if (has_array_args) {
> diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
> index 248bc09bfc99..e07311cfe5ca 100644
> --- a/include/trace/events/v4l2.h
> +++ b/include/trace/events/v4l2.h
> @@ -7,6 +7,7 @@
>  
>  #include <linux/tracepoint.h>
>  #include <media/videobuf2-v4l2.h>
> +#include <media/v4l2-device.h>
>  
>  /* Enums require being exported to userspace, for user tool parsing */
>  #undef EM
> @@ -98,12 +99,12 @@ SHOW_FIELD
>                 { V4L2_TC_USERBITS_8BITCHARS,   "USERBITS_8BITCHARS" })
>  
>  DECLARE_EVENT_CLASS(v4l2_event_class,
> -       TP_PROTO(int minor, struct v4l2_buffer *buf),
> -
> -       TP_ARGS(minor, buf),
> +       TP_PROTO(struct v4l2_fh *fh, struct v4l2_buffer *buf),
> +       TP_ARGS(fh, buf),
>  
>         TP_STRUCT__entry(
>                 __field(int, minor)
> +               __field(struct v4l2_fh *, fh)
>                 __field(u32, index)
>                 __field(u32, type)
>                 __field(u32, bytesused)
> @@ -124,7 +125,8 @@ DECLARE_EVENT_CLASS(v4l2_event_class,
>         ),
>  
>         TP_fast_assign(
> -               __entry->minor = minor;
> +               __entry->minor = fh ? fh->vdev->minor : -1;

I think this is a regression now, if the driver isn't using
V4L2_FL_USES_V4L2_FH, then minor field will be -1?

Maybe we could leave this ioctl trace, and drop this patch,
and instead do the tracing at the mem2mem level in v4l2_m2m_qbuf.

Thanks,
Ezequiel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/5] media: v4l2-mem2mem: add v4l2_m2m_buf_done trace point
  2021-05-17 18:38 ` [PATCH 4/5] media: v4l2-mem2mem: add v4l2_m2m_buf_done trace point Emil Velikov
@ 2021-06-03 18:21   ` Ezequiel Garcia
  0 siblings, 0 replies; 9+ messages in thread
From: Ezequiel Garcia @ 2021-06-03 18:21 UTC (permalink / raw)
  To: Emil Velikov, Mauro Carvalho Chehab, Hans Verkuil, Philipp Zabel,
	Alexandre Courbot, Mikhail Ulyanov, kernel
  Cc: linux-media

Hi Emil,

On Mon, 2021-05-17 at 19:38 +0100, Emil Velikov wrote:
> From: Emil Velikov <emil.velikov@collabora.com>
> 
> Move the function out of the header, as required by the trace API and
> add a tracepoint.
> 

Same thing here, about too short commit descriptions.
 
> Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
> ---
>  drivers/media/v4l2-core/v4l2-mem2mem.c |  9 ++++++
>  drivers/media/v4l2-core/v4l2-trace.c   |  1 +
>  include/media/v4l2-mem2mem.h           | 10 +++----
>  include/trace/events/v4l2.h            | 41 ++++++++++++++++++++++++++
>  4 files changed, 56 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
> index bf83d1fae701..a83d3e4e7a85 100644
> --- a/drivers/media/v4l2-core/v4l2-mem2mem.c
> +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
> @@ -555,6 +555,15 @@ void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev,
>  }
>  EXPORT_SYMBOL(v4l2_m2m_buf_done_and_job_finish);
>  
> +void
> +v4l2_m2m_buf_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state)
> +{
> +       // TODO: Emil move the trace after done?
> +       trace_v4l2_m2m_buf_done(&buf->vb2_buf, state);

There's a trace already in vb2_buffer_done, is that one not enough,
or not useful?

> +       vb2_buffer_done(&buf->vb2_buf, state);
> +}
> +EXPORT_SYMBOL(v4l2_m2m_buf_done);
> +
>  void v4l2_m2m_suspend(struct v4l2_m2m_dev *m2m_dev)
>  {
>         unsigned long flags;
> diff --git a/drivers/media/v4l2-core/v4l2-trace.c b/drivers/media/v4l2-core/v4l2-trace.c
> index cde408d06fdc..b70208101f3c 100644
> --- a/drivers/media/v4l2-core/v4l2-trace.c
> +++ b/drivers/media/v4l2-core/v4l2-trace.c
> @@ -11,6 +11,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_queue);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_dqbuf);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_qbuf);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_ioctl_s_fmt);
> +EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_buf_done);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_schedule);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_schedule_failed);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(v4l2_m2m_queue_job);
> diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
> index 82bf54254bd8..013fd355ff82 100644
> --- a/include/media/v4l2-mem2mem.h
> +++ b/include/media/v4l2-mem2mem.h
> @@ -229,11 +229,11 @@ void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev,
>                                       struct v4l2_m2m_ctx *m2m_ctx,
>                                       enum vb2_buffer_state state);
>  
> -static inline void
> -v4l2_m2m_buf_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state)
> -{
> -       vb2_buffer_done(&buf->vb2_buf, state);
> -}
> +/**
> + * Something something

Something needs documented :)

Thanks,
Ezequiel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC] media: v4l2: Adding mem2mem ftrace support
  2021-05-17 18:37 [RFC] media: v4l2: Adding mem2mem ftrace support Emil Velikov
                   ` (4 preceding siblings ...)
  2021-05-17 18:38 ` [PATCH 5/5] media: v4l2-mem2mem: add v4l2_m2m_stream_on/off tracepoints Emil Velikov
@ 2021-06-03 18:25 ` Ezequiel Garcia
  5 siblings, 0 replies; 9+ messages in thread
From: Ezequiel Garcia @ 2021-06-03 18:25 UTC (permalink / raw)
  To: Emil Velikov, Mauro Carvalho Chehab, Hans Verkuil, Philipp Zabel,
	Alexandre Courbot, Mikhail Ulyanov, kernel
  Cc: linux-media

Hi Emil,

On Mon, 2021-05-17 at 19:37 +0100, Emil Velikov wrote:
> Hi everyone,
> 
> This RFC aims to kick off a discussion about adding ftrace events in
> V4L2 and mem2mem in particular.
> 
> The goal is to aid both userspace and kernel developers alike by
> allowing them to trace their individual application/library and drivers,
> respectively.
> 

We'll need some developer-oriented docs, perhaps in Documentation/userspace-api/media/
or similar, with some examples and some guidelines.

Also, could you add some scripts somewhere to show us how these are used/enabled?

> 
> # Data provided
> 
> In order to correlate the components through their lifetime we need a
> few unique identifiers:
> 
>  - minor: the device minor, aka /dev/video
>    Useful, when multiple devices are present.
> 
>  - fh: file handle
>    Allows us to map the buffer, ioctl and mem2mem jobs.
> 
>  - fh: as a job instance... sort of
>    We also use it as to distinguish between the different jobs, as long
>    as we track the cancel/finish events.
> 
> 
> Additionally, for buffers we need:
>  - type: VIDEO_OUTPUT_MPLANE, VIDEO_CAPTURE_MPLANE, etc
>  - index: buffer index
>    Each buffer type has its own pool.
> 
> 
> # Event list and examples
> 
> Generic:
> 
> v4l2_ioctl_s_fmt: minor = 0, fh = 5068c670, type = VIDEO_OUTPUT_MPLANE,
> width=1280, height=720, ...
> 
> v4l2_qbuf: minor = 0, fh = 5068c670, index = 0, type =
> VIDEO_CAPTURE_MPLANE, bytesused = 0, ...
> v4l2_dqbuf: minor = 0, fh = 5068c670, index = 0, type =
> VIDEO_CAPTURE_MPLANE, bytesused = 0, ...
> 
> 
> Mem2mem specific:
> 
> v4l2_m2m_schedule: minor = 0, fh = 5068c670
> v4l2_m2m_schedule_failed: minor = 0, fh = 5068c670, reason = NO_SRC
> v4l2_m2m_queue_job: minor = 0, fh = 5068c670, src = 0, dst = 0
> Currently src and dst only show the buffer index. Buffer type can be
> deduced based on the type of job - encode or decode.
> 
> v4l2_m2m_run_job: minor = 0, fh = 5068c670
> v4l2_m2m_cancel_job: minor = 0, fh = 5068c670
> v4l2_m2m_finish_job: minor = 0, fh = 5068c670
> 
> v4l2_m2m_stream_on: minor = 0, fh = 5068c670, type = f9e16c2e
> v4l2_m2m_stream_off: minor = 0, fh = 5068c670, type = f9e16c2e
> 
> v4l2_m2m_buf_done: minor = 0, fh = 5068c670, index = 0, type =
> VIDEO_CAPTURE_MPLANE, state = DONE
> 

Do we need something to distinguish the Job ID?

Thanks,
Ezequiel


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-06-03 18:25 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-17 18:37 [RFC] media: v4l2: Adding mem2mem ftrace support Emil Velikov
2021-05-17 18:37 ` [PATCH 1/5] media: v4l2: print the fh, during qbuf/dqbuf tracing Emil Velikov
2021-06-03 18:16   ` Ezequiel Garcia
2021-05-17 18:37 ` [PATCH 2/5] media: v4l2: add VIDIOC_S_FMT tracing Emil Velikov
2021-05-17 18:37 ` [PATCH 3/5] media: v4l2-mem2mem: add job tracing Emil Velikov
2021-05-17 18:38 ` [PATCH 4/5] media: v4l2-mem2mem: add v4l2_m2m_buf_done trace point Emil Velikov
2021-06-03 18:21   ` Ezequiel Garcia
2021-05-17 18:38 ` [PATCH 5/5] media: v4l2-mem2mem: add v4l2_m2m_stream_on/off tracepoints Emil Velikov
2021-06-03 18:25 ` [RFC] media: v4l2: Adding mem2mem ftrace support Ezequiel Garcia

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.