[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