[Intel-gfx] [PATCH] drm/i915: Tracing infrastructure [WIP]

Chris Wilson chris at chris-wilson.co.uk
Mon Jul 6 01:32:17 CEST 2009


Just a few tracepoints at the moment to monitor batch submits and retires,
and waits. In the future we should be able to couple tools to the tracer
and closely monitor throughput and latency. However, the immediate value
of this can be demonstrated with the new (and still rough) perf tool:

$ CAIRO_TEST_TARGET=drm perf record -e tp=i915/i915_wait -c 1 -g -f \
  ./cairo-perf-trace
[ # ]  backend                         test   min(s) median(s) stddev.  count
[  0]      drm             poppler-20090608  566.724  569.368   3.07%   3/3
$ perf report --callchain fractal,5
    97.23%   lt-cairo-perf-t  [vdso]
                |
                 --99.09%-- _i915_glyph_cache_add_glyph
                            _i915_surface_show_glyphs
                            _cairo_surface_show_text_glyphs
                            _cairo_gstate_show_text_glyphs
                            cairo_show_glyphs
                            _show_glyphs
                            0xb7efa87e
                            0xb7f06a99
                            _csi_scan_file
                            0xb7efa89f
                            cairo_script_interpreter_run
                            cairo_perf_trace
                            cairo_perf_trace_dir
                            main
                            __libc_start_main
                            0x804acd1

     2.77%   lt-cairo-perf-t  /lib/tls/i686/cmov/libc-2.9.so

which tells me:

1. Stalls are now very infrequent, just 795 i915_wait_request() during
that profile (due to no longer having to wait for fences)
2. The main culprit is having to wait for the glyph cache, and maybe I
should investigate the cache efficacy more closely.

WIP: Need to hook in bgamari's latency tracer, the only trick to work out
for that is enabling the irq along with i915trace. Hopefully that will
become possible by implementing i915 as a first class tracer as well as
providing these tracepoints.
---
 drivers/gpu/drm/Kconfig           |    9 +++
 drivers/gpu/drm/i915/Makefile     |    3 +
 drivers/gpu/drm/i915/i915_gem.c   |   16 ++++++
 drivers/gpu/drm/i915/i915_trace.c |   98 +++++++++++++++++++++++++++++++++++++
 include/trace/events/i915.h       |   90 ++++++++++++++++++++++++++++++++++
 5 files changed, 216 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/i915_trace.c
 create mode 100644 include/trace/events/i915.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 39b393d..7d467fe 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -111,6 +111,15 @@ config DRM_I915_KMS
 	  the driver to bind to PCI devices, which precludes loading things
 	  like intelfb.
 
+config DRM_I915_TRACE
+	tristate "i915 trace"
+	depends on DRM_I915
+	select EVENT_TRACING
+	help
+	  Choose this option if you want to enable event tracing in the
+	  i915 driver. This is used to identify performance problems
+	  within the driver and applications. If unsure, say N.
+
 endchoice
 
 config DRM_MGA
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 30d6b99..e727971 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -32,3 +32,6 @@ i915-$(CONFIG_ACPI)	+= i915_opregion.o
 i915-$(CONFIG_COMPAT)   += i915_ioc32.o
 
 obj-$(CONFIG_DRM_I915)  += i915.o
+
+i915-trace-y := i915_trace.o
+obj-$(CONFIG_DRM_I915_TRACE) += i915-trace.o
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 876b65c..bef5fec 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -31,6 +31,7 @@
 #include "i915_drv.h"
 #include <linux/swap.h>
 #include <linux/pci.h>
+#include <trace/events/i915.h>
 
 #define I915_GEM_GPU_DOMAINS	(~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
 
@@ -1607,6 +1608,8 @@ i915_gem_retire_request(struct drm_device *dev,
 		DRM_INFO("%s: retire %d moves to inactive list %p\n",
 			 __func__, request->seqno, obj);
 #endif
+		trace_i915_retire(request->seqno,
+				  ktime_to_ns(ktime_get()));
 
 		if (obj->write_domain != 0)
 			i915_gem_object_move_to_flushing(obj);
@@ -1712,6 +1715,8 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
 	BUG_ON(seqno == 0);
 
 	if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
+		ktime_t wait_start, wait_end;
+
 		if (IS_IGDNG(dev))
 			ier = I915_READ(DEIER) | I915_READ(GTIER);
 		else
@@ -1724,13 +1729,21 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
 		}
 
 		dev_priv->mm.waiting_gem_seqno = seqno;
+		wait_start = ktime_get();
 		i915_user_irq_get(dev);
 		ret = wait_event_interruptible(dev_priv->irq_queue,
 					       i915_seqno_passed(i915_get_gem_seqno(dev),
 								 seqno) ||
 					       dev_priv->mm.wedged);
 		i915_user_irq_put(dev);
+		wait_end = ktime_get();
 		dev_priv->mm.waiting_gem_seqno = 0;
+
+		if (ret == 0) {
+			trace_i915_wait(seqno,
+					ktime_to_ns(ktime_sub(wait_end,
+							      wait_start)));
+		}
 	}
 	if (dev_priv->mm.wedged)
 		ret = -EIO;
@@ -3086,6 +3099,9 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
 	exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
 	exec_len = (uint32_t) exec->batch_len;
 
+	trace_i915_submit (dev_priv->mm.next_gem_seqno,
+			   ktime_to_ns(ktime_get()));
+
 	count = nbox ? nbox : 1;
 
 	for (i = 0; i < count; i++) {
diff --git a/drivers/gpu/drm/i915/i915_trace.c b/drivers/gpu/drm/i915/i915_trace.c
new file mode 100644
index 0000000..7043636
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_trace.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2009 Chris Wilson
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chris Wilson <chris at chris-wilson.co.uk>
+ *
+ */
+
+#include <linux/module.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/i915.h>
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(i915_submit);
+EXPORT_TRACEPOINT_SYMBOL_GPL(i915_retire);
+EXPORT_TRACEPOINT_SYMBOL_GPL(i915_complete);
+EXPORT_TRACEPOINT_SYMBOL_GPL(i915_wait);
+
+static void
+trace_i915_submit_hit(uint32_t seqno, s64 time)
+{
+}
+
+static void
+trace_i915_complete_hit(uint32_t seqno, s64 time)
+{
+}
+
+static void
+trace_i915_retire_hit(uint32_t seqno, s64 time)
+{
+}
+
+static void
+trace_i915_wait_hit(uint32_t seqno, s64 duration)
+{
+}
+
+static int __init
+i915_trace_init (void)
+{
+    int ret;
+
+    ret = register_trace_i915_submit(trace_i915_submit_hit);
+    if (ret)
+	return ret;
+
+    ret = register_trace_i915_complete(trace_i915_complete_hit);
+    if (ret)
+	return ret;
+
+    ret = register_trace_i915_retire(trace_i915_retire_hit);
+    if (ret)
+	return ret;
+
+    ret = register_trace_i915_wait(trace_i915_wait_hit);
+    if (ret)
+	return ret;
+
+    return 0;
+}
+
+static void __exit
+i915_trace_exit (void)
+{
+    unregister_trace_i915_wait(trace_i915_wait_hit);
+    unregister_trace_i915_retire(trace_i915_retire_hit);
+    unregister_trace_i915_complete(trace_i915_complete_hit);
+    unregister_trace_i915_submit(trace_i915_submit_hit);
+
+    tracepoint_synchronize_unregister();
+}
+
+module_init(i915_trace_init);
+module_exit(i915_trace_exit);
+
+MODULE_AUTHOR("Chris Wilson <chris at chris-wilson.co.uk>");
+MODULE_DESCRIPTION("Tracing infrastructure for i915");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/include/trace/events/i915.h b/include/trace/events/i915.h
new file mode 100644
index 0000000..aa9890a
--- /dev/null
+++ b/include/trace/events/i915.h
@@ -0,0 +1,90 @@
+#if !defined(_TRACE_I915_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_I915_H
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM i915
+
+TRACE_EVENT(i915_submit,
+
+	    TP_PROTO(uint32_t seqno, s64 time),
+
+	    TP_ARGS(seqno, time),
+
+	    TP_STRUCT__entry(
+			     __field(s64, time)
+			     __field(uint32_t, seqno)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->seqno = seqno;
+			   __entry->time = time;
+			   ),
+
+	    TP_printk("seqno=%u, time=%qd", __entry->seqno, __entry->time)
+);
+
+TRACE_EVENT(i915_complete,
+
+	    TP_PROTO(uint32_t seqno, s64 time),
+
+	    TP_ARGS(seqno, time),
+
+	    TP_STRUCT__entry(
+			     __field(s64, time)
+			     __field(uint32_t, seqno)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->seqno = seqno;
+			   __entry->time = time;
+			   ),
+
+	    TP_printk("seqno=%u, time=%qd", __entry->seqno, __entry->time)
+);
+
+TRACE_EVENT(i915_retire,
+
+	    TP_PROTO(uint32_t seqno, s64 time),
+
+	    TP_ARGS(seqno, time),
+
+	    TP_STRUCT__entry(
+			     __field(s64, time)
+			     __field(uint32_t, seqno)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->seqno = seqno;
+			   __entry->time = time;
+			   ),
+
+	    TP_printk("seqno=%u, time=%qd", __entry->seqno, __entry->time)
+);
+
+TRACE_EVENT(i915_wait,
+
+	    TP_PROTO(uint32_t seqno, s64 duration),
+
+	    TP_ARGS(seqno, duration),
+
+	    TP_STRUCT__entry(
+			     __field(s64, duration)
+			     __field(uint32_t, seqno)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->seqno = seqno;
+			   __entry->duration = duration;
+			   ),
+
+	    TP_printk("seqno=%u, duration=%qd",
+		      __entry->seqno, __entry->duration)
+);
+
+#endif /* _TRACE_I915_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
-- 
1.6.3.3




More information about the Intel-gfx mailing list