drm/i915: Split the batch pool by engine
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 7 Apr 2015 15:20:36 +0000 (16:20 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 10 Apr 2015 06:56:04 +0000 (08:56 +0200)
I woke up one morning and found 50k objects sitting in the batch pool
and every search seemed to iterate the entire list... Painting the
screen in oils would provide a more fluid display.

One issue with the current design is that we only check for retirements
on the current ring when preparing to submit a new batch. This means
that we can have thousands of "active" batches on another ring that we
have to walk over. The simplest way to avoid that is to split the pools
per ring and then our LRU execution ordering will also ensure that the
inactive buffers remain at the front.

v2: execlists still requires duplicate code.
v3: execlists requires more duplicate code

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_batch_pool.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h

index 9c23eec3277e2af5c8886495232ef0979943bc3e..f610a2cd208810c9a595ee5bb938cd8244b31acb 100644 (file)
@@ -377,13 +377,17 @@ static void print_batch_pool_stats(struct seq_file *m,
 {
        struct drm_i915_gem_object *obj;
        struct file_stats stats;
+       struct intel_engine_cs *ring;
+       int i;
 
        memset(&stats, 0, sizeof(stats));
 
-       list_for_each_entry(obj,
-                           &dev_priv->mm.batch_pool.cache_list,
-                           batch_pool_list)
-               per_file_stats(0, obj, &stats);
+       for_each_ring(ring, dev_priv, i) {
+               list_for_each_entry(obj,
+                                   &ring->batch_pool.cache_list,
+                                   batch_pool_list)
+                       per_file_stats(0, obj, &stats);
+       }
 
        print_file_stats(m, "batch pool", stats);
 }
@@ -613,21 +617,24 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
+       struct intel_engine_cs *ring;
        int count = 0;
-       int ret;
+       int ret, i;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
 
-       seq_puts(m, "cache:\n");
-       list_for_each_entry(obj,
-                           &dev_priv->mm.batch_pool.cache_list,
-                           batch_pool_list) {
-               seq_puts(m, "   ");
-               describe_obj(m, obj);
-               seq_putc(m, '\n');
-               count++;
+       for_each_ring(ring, dev_priv, i) {
+               seq_printf(m, "%s cache:\n", ring->name);
+               list_for_each_entry(obj,
+                                   &ring->batch_pool.cache_list,
+                                   batch_pool_list) {
+                       seq_puts(m, "   ");
+                       describe_obj(m, obj);
+                       seq_putc(m, '\n');
+                       count++;
+               }
        }
 
        seq_printf(m, "total: %d\n", count);
index 68e0c85a17cfcd5779ffab7b9aa0e8dba7cf0fac..8f5428b46a2730f35905be4c05059a3f1cdf30c1 100644 (file)
@@ -1072,7 +1072,6 @@ int i915_driver_unload(struct drm_device *dev)
 
        mutex_lock(&dev->struct_mutex);
        i915_gem_cleanup_ringbuffer(dev);
-       i915_gem_batch_pool_fini(&dev_priv->mm.batch_pool);
        i915_gem_context_fini(dev);
        mutex_unlock(&dev->struct_mutex);
        i915_gem_cleanup_stolen(dev);
index 5edacad1a6e00d7cf42508965ff85455dddce744..c839b5771a837e6a0fa54a3403c8f2c4547535cd 100644 (file)
@@ -37,7 +37,6 @@
 #include "intel_bios.h"
 #include "intel_ringbuffer.h"
 #include "intel_lrc.h"
-#include "i915_gem_batch_pool.h"
 #include "i915_gem_gtt.h"
 #include "i915_gem_render_state.h"
 #include <linux/io-mapping.h>
@@ -1156,13 +1155,6 @@ struct i915_gem_mm {
         */
        struct list_head unbound_list;
 
-       /*
-        * A pool of objects to use as shadow copies of client batch buffers
-        * when the command parser is enabled. Prevents the client from
-        * modifying the batch contents after software parsing.
-        */
-       struct i915_gem_batch_pool batch_pool;
-
        /** Usable portion of the GTT for GEM */
        unsigned long stolen_base; /* limited to low memory (32-bit) */
 
index 35edc8f9309d1ff0a5e3e7994d62c188c1d7d105..d1ca192afaccb61a653f9fe9c60625fae389711d 100644 (file)
@@ -5021,8 +5021,6 @@ i915_gem_load(struct drm_device *dev)
 
        i915_gem_shrinker_init(dev_priv);
 
-       i915_gem_batch_pool_init(dev, &dev_priv->mm.batch_pool);
-
        mutex_init(&dev_priv->fb_tracking.lock);
 }
 
index 21f3356cc0aba7f151fbdb82131573d5bba2b7c3..1287abf55b8447c641eb95c53b5a7f3faccc6289 100644 (file)
@@ -96,8 +96,9 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool,
 
        list_for_each_entry_safe(tmp, next,
                                 &pool->cache_list, batch_pool_list) {
+               /* The batches are strictly LRU ordered */
                if (tmp->active)
-                       continue;
+                       break;
 
                /* While we're looping, do some clean up */
                if (tmp->madv == __I915_MADV_PURGED) {
index 166d53330ee467dd00b35f35756c1eb7112a402a..48ac5608481e4b64237ba3811a719717afffef0f 100644 (file)
@@ -1136,12 +1136,11 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
                          u32 batch_len,
                          bool is_master)
 {
-       struct drm_i915_private *dev_priv = to_i915(batch_obj->base.dev);
        struct drm_i915_gem_object *shadow_batch_obj;
        struct i915_vma *vma;
        int ret;
 
-       shadow_batch_obj = i915_gem_batch_pool_get(&dev_priv->mm.batch_pool,
+       shadow_batch_obj = i915_gem_batch_pool_get(&ring->batch_pool,
                                                   PAGE_ALIGN(batch_len));
        if (IS_ERR(shadow_batch_obj))
                return shadow_batch_obj;
index cfc73ea59804e670bc18742fd9e73243b32d1509..580248d927105f2ade057aca55043ff66ff0409a 100644 (file)
@@ -1384,6 +1384,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring)
                ring->cleanup(ring);
 
        i915_cmd_parser_fini_ring(ring);
+       i915_gem_batch_pool_fini(&ring->batch_pool);
 
        if (ring->status_page.obj) {
                kunmap(sg_page(ring->status_page.obj->pages->sgl));
@@ -1401,6 +1402,7 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin
        ring->dev = dev;
        INIT_LIST_HEAD(&ring->active_list);
        INIT_LIST_HEAD(&ring->request_list);
+       i915_gem_batch_pool_init(dev, &ring->batch_pool);
        init_waitqueue_head(&ring->irq_queue);
 
        INIT_LIST_HEAD(&ring->execlist_queue);
index b5af9b121ce1f9fe491814c5660b10ae547f8aa4..1f9463a295a561c6964635f441b0a7c369efabbc 100644 (file)
@@ -1975,6 +1975,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
        INIT_LIST_HEAD(&ring->active_list);
        INIT_LIST_HEAD(&ring->request_list);
        INIT_LIST_HEAD(&ring->execlist_queue);
+       i915_gem_batch_pool_init(dev, &ring->batch_pool);
        ringbuf->size = 32 * PAGE_SIZE;
        ringbuf->ring = ring;
        memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno));
@@ -2053,6 +2054,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
        cleanup_status_page(ring);
 
        i915_cmd_parser_fini_ring(ring);
+       i915_gem_batch_pool_fini(&ring->batch_pool);
 
        kfree(ringbuf);
        ring->buffer = NULL;
index 6566dd4474985eb7ddc781681bc88effe00fc636..39f6dfc0ee54917d1cc7eb151cd30a143d94c947 100644 (file)
@@ -2,6 +2,7 @@
 #define _INTEL_RINGBUFFER_H_
 
 #include <linux/hashtable.h>
+#include "i915_gem_batch_pool.h"
 
 #define I915_CMD_HASH_ORDER 9
 
@@ -133,6 +134,13 @@ struct  intel_engine_cs {
        struct          drm_device *dev;
        struct intel_ringbuffer *buffer;
 
+       /*
+        * A pool of objects to use as shadow copies of client batch buffers
+        * when the command parser is enabled. Prevents the client from
+        * modifying the batch contents after software parsing.
+        */
+       struct i915_gem_batch_pool batch_pool;
+
        struct intel_hw_status_page status_page;
 
        unsigned irq_refcount; /* protected by dev_priv->irq_lock */