[Intel-gfx] [PATCH] First stab at doing wait accounting

Ben Gamari bgamari.foss at gmail.com
Fri May 22 22:06:56 CEST 2009


---
 drivers/gpu/drm/Kconfig                 |    8 ++++++++
 drivers/gpu/drm/i915/i915_drv.h         |   26 ++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem.c         |   15 ++++++++++++++-
 drivers/gpu/drm/i915/i915_gem_debugfs.c |   21 +++++++++++++++++++++
 4 files changed, 69 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 4cd35d8..1bb7724 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -97,6 +97,14 @@ config DRM_I915_KMS
 	  the driver to bind to PCI devices, which precludes loading things
 	  like intelfb.
 
+config DRM_I915_WAIT_ACCOUNTING
+	bool "Enable i915 wait accounting"
+	depends on DRM_I915
+	help
+	  Choose this option if you want to enable wait accounting in the i915
+	  driver. This is used to identify performance problems within the
+	  driver. If unsure, say N.
+
 endchoice
 
 config DRM_MGA
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9b149fe..263ab5e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -33,6 +33,7 @@
 #include "i915_reg.h"
 #include "intel_bios.h"
 #include <linux/io-mapping.h>
+#include <linux/time.h>
 
 /* General customization:
  */
@@ -126,6 +127,27 @@ struct drm_i915_fence_reg {
 	struct drm_gem_object *obj;
 };
 
+enum drm_i915_wait_srcs {
+	I915_WAITSRC_WAIT_FOR_ACTIVE_OBJ,
+	I915_WAITSRC_WAIT_ON_RENDER_FOR_OBJ,
+	I915_WAITSRC_FLUSH_FOR_OBJ,
+	I915_WAITSRC_FLUSH_FOR_FENCE,
+	I915_WAITSRC_LAST
+};
+
+#ifdef CONFIG_DRM_I915_WAIT_ACCOUNTING
+#define I915_MIGHT_WAIT() struct timeval _wait_ts_begin, _wait_ts_end;
+#define I915_BEGIN_WAIT() do_gettimeofday(&_wait_ts_begin);
+#define I915_END_WAIT(src) { \
+	do_gettimeofday(&_wait_ts_end); \
+	dev_priv->mm.wait_time[src] += _wait_ts_end.tv_usec - _wait_ts_begin.tv_usec; \
+	dev_priv->mm.wait_count[src]++; }
+#else
+#define I915_MIGHT_WAIT() {}
+#define I915_BEGIN_WAIT() {}
+#define I915_END_WAIT(src) {}
+#endif
+
 typedef struct drm_i915_private {
 	struct drm_device *dev;
 
@@ -380,6 +402,10 @@ typedef struct drm_i915_private {
 
 		/* storage for physical objects */
 		struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
+
+		/* wait source accumulators */
+		long int wait_time[I915_WAITSRC_LAST];
+		long int wait_count[I915_WAITSRC_LAST];
 	} mm;
 } drm_i915_private_t;
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index b189b49..0121008 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1912,6 +1912,8 @@ i915_gem_evict_something(struct drm_device *dev)
 	struct drm_gem_object *obj;
 	struct drm_i915_gem_object *obj_priv;
 	int ret = 0;
+	int wait_reason = I915_WAITSRC_WAIT_FOR_ACTIVE_OBJ;
+	I915_MIGHT_WAIT();
 
 	for (;;) {
 		/* If there's an inactive buffer available now, grab it
@@ -1929,7 +1931,10 @@ i915_gem_evict_something(struct drm_device *dev)
 			BUG_ON(obj_priv->active);
 
 			/* Wait on the rendering and unbind the buffer. */
+			I915_BEGIN_WAIT();
 			ret = i915_gem_object_unbind(obj);
+			if (ret)
+				I915_END_WAIT(I915_WAITSRC_WAIT_ON_RENDER_FOR_OBJ);
 			break;
 		}
 
@@ -1944,9 +1949,11 @@ i915_gem_evict_something(struct drm_device *dev)
 						   struct drm_i915_gem_request,
 						   list);
 
+			I915_BEGIN_WAIT();
 			ret = i915_wait_request(dev, request->seqno);
 			if (ret)
 				break;
+			I915_END_WAIT(wait_reason);
 
 			/* if waiting caused an object to become inactive,
 			 * then loop around and wait for it. Otherwise, we
@@ -1968,7 +1975,8 @@ i915_gem_evict_something(struct drm_device *dev)
 						    struct drm_i915_gem_object,
 						    list);
 			obj = obj_priv->obj;
-
+			
+			wait_reason = I915_WAITSRC_FLUSH_FOR_OBJ;
 			i915_gem_flush(dev,
 				       obj->write_domain,
 				       obj->write_domain);
@@ -2238,7 +2246,10 @@ try_again:
 		 * objects to finish before trying again.
 		 */
 		if (i == dev_priv->num_fence_regs) {
+			I915_MIGHT_WAIT();
+
 			if (seqno == dev_priv->mm.next_gem_seqno) {
+
 				i915_gem_flush(dev,
 					       I915_GEM_GPU_DOMAINS,
 					       I915_GEM_GPU_DOMAINS);
@@ -2248,9 +2259,11 @@ try_again:
 					return -ENOMEM;
 			}
 
+			I915_BEGIN_WAIT();
 			ret = i915_wait_request(dev, seqno);
 			if (ret)
 				return ret;
+			I915_END_WAIT(I915_WAITSRC_FLUSH_FOR_FENCE);
 			goto try_again;
 		}
 
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c
index 986f108..4e95180 100644
--- a/drivers/gpu/drm/i915/i915_gem_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c
@@ -323,6 +323,24 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
 	return 0;
 }
 
+#ifdef CONFIG_DRM_I915_WAIT_ACCOUNTING
+static int i915_wait_source_info(struct seq_file *m, void *data) {
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+#define WAITSRC(SRC) seq_printf(m, "%s\t%ld\t%ld\n", #SRC, \
+		dev_priv->mm.wait_time[I915_WAITSRC_##SRC], \
+		dev_priv->mm.wait_count[I915_WAITSRC_##SRC])
+	WAITSRC(WAIT_FOR_ACTIVE_OBJ);
+	WAITSRC(WAIT_ON_RENDER_FOR_OBJ);
+	WAITSRC(FLUSH_FOR_OBJ);
+	WAITSRC(FLUSH_FOR_FENCE);
+#undef WAITSRC
+
+	return 0;
+}
+#endif
 
 static struct drm_info_list i915_gem_debugfs_list[] = {
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
@@ -336,6 +354,9 @@ static struct drm_info_list i915_gem_debugfs_list[] = {
 	{"i915_ringbuffer_data", i915_ringbuffer_data, 0},
 	{"i915_ringbuffer_info", i915_ringbuffer_info, 0},
 	{"i915_batchbuffers", i915_batchbuffer_info, 0},
+#ifdef CONFIG_DRM_I915_WAIT_ACCOUNTING
+	{"i915_wait_sources", i915_wait_source_info, 0},
+#endif
 };
 #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
 
-- 
1.6.2.2




More information about the Intel-gfx mailing list