[Intel-gfx] [PATCH 2/9] drm/i915/gt: Move the batch buffer pool from the engine to the gt

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Thu Apr 30 17:04:59 UTC 2020


On 30/04/2020 12:18, Chris Wilson wrote:
> Since the introduction of 'soft-rc6', we aim to park the device quickly
> and that results in frequent idling of the whole device. Currently upon
> idling we free the batch buffer pool, and so this renders the cache
> ineffective for many workloads. If we want to have an effective cache of
> recently allocated buffers available for reuse, we need to decouple that
> cache from the engine powermanagement and make it timer based. As there
> is no reason then to keep it within the engine (where it once made
> retirement order easier to track), we can move it up the hierarchy to the
> owner of the memory allocations.
> 
> v2: Hook up to debugfs/drop_caches to clear the cache on demand.
> 
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> ---
>   drivers/gpu/drm/i915/Makefile                 |   2 +-
>   .../gpu/drm/i915/gem/i915_gem_client_blt.c    |   1 -
>   .../gpu/drm/i915/gem/i915_gem_execbuffer.c    |  20 +--
>   .../gpu/drm/i915/gem/i915_gem_object_blt.c    |  18 +--
>   .../gpu/drm/i915/gem/i915_gem_object_blt.h    |   1 -
>   drivers/gpu/drm/i915/gt/intel_engine_cs.c     |   4 -
>   drivers/gpu/drm/i915/gt/intel_engine_pm.c     |   2 -
>   drivers/gpu/drm/i915/gt/intel_engine_pool.h   |  34 ------
>   drivers/gpu/drm/i915/gt/intel_engine_types.h  |   8 --
>   drivers/gpu/drm/i915/gt/intel_gt.c            |   3 +
>   ...l_engine_pool.c => intel_gt_buffer_pool.c} | 114 ++++++++++++------
>   .../gpu/drm/i915/gt/intel_gt_buffer_pool.h    |  37 ++++++
>   ...l_types.h => intel_gt_buffer_pool_types.h} |  15 ++-
>   drivers/gpu/drm/i915/gt/intel_gt_types.h      |  11 ++
>   drivers/gpu/drm/i915/gt/mock_engine.c         |   2 -
>   drivers/gpu/drm/i915/i915_debugfs.c           |   4 +
>   16 files changed, 160 insertions(+), 116 deletions(-)
>   delete mode 100644 drivers/gpu/drm/i915/gt/intel_engine_pool.h
>   rename drivers/gpu/drm/i915/gt/{intel_engine_pool.c => intel_gt_buffer_pool.c} (53%)
>   create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.h
>   rename drivers/gpu/drm/i915/gt/{intel_engine_pool_types.h => intel_gt_buffer_pool_types.h} (54%)
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index caf00d92ea9d..5359c736c789 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -87,11 +87,11 @@ gt-y += \
>   	gt/intel_engine_cs.o \
>   	gt/intel_engine_heartbeat.o \
>   	gt/intel_engine_pm.o \
> -	gt/intel_engine_pool.o \
>   	gt/intel_engine_user.o \
>   	gt/intel_ggtt.o \
>   	gt/intel_ggtt_fencing.o \
>   	gt/intel_gt.o \
> +	gt/intel_gt_buffer_pool.o \
>   	gt/intel_gt_clock_utils.o \
>   	gt/intel_gt_irq.o \
>   	gt/intel_gt_pm.o \
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c
> index 0598e5382a1d..3a146aa2593b 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c
> @@ -6,7 +6,6 @@
>   #include "i915_drv.h"
>   #include "gt/intel_context.h"
>   #include "gt/intel_engine_pm.h"
> -#include "gt/intel_engine_pool.h"
>   #include "i915_gem_client_blt.h"
>   #include "i915_gem_object_blt.h"
>   
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> index 964f73f062c1..414859fa2673 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> @@ -15,8 +15,8 @@
>   
>   #include "gem/i915_gem_ioctls.h"
>   #include "gt/intel_context.h"
> -#include "gt/intel_engine_pool.h"
>   #include "gt/intel_gt.h"
> +#include "gt/intel_gt_buffer_pool.h"
>   #include "gt/intel_gt_pm.h"
>   #include "gt/intel_ring.h"
>   
> @@ -1194,13 +1194,13 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb,
>   			     unsigned int len)
>   {
>   	struct reloc_cache *cache = &eb->reloc_cache;
> -	struct intel_engine_pool_node *pool;
> +	struct intel_gt_buffer_pool_node *pool;
>   	struct i915_request *rq;
>   	struct i915_vma *batch;
>   	u32 *cmd;
>   	int err;
>   
> -	pool = intel_engine_get_pool(eb->engine, PAGE_SIZE);
> +	pool = intel_gt_get_buffer_pool(eb->engine->gt, PAGE_SIZE);
>   	if (IS_ERR(pool))
>   		return PTR_ERR(pool);
>   
> @@ -1229,7 +1229,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb,
>   		goto err_unpin;
>   	}
>   
> -	err = intel_engine_pool_mark_active(pool, rq);
> +	err = intel_gt_buffer_pool_mark_active(pool, rq);
>   	if (err)
>   		goto err_request;
>   
> @@ -1270,7 +1270,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb,
>   err_unmap:
>   	i915_gem_object_unpin_map(pool->obj);
>   out_pool:
> -	intel_engine_pool_put(pool);
> +	intel_gt_buffer_pool_put(pool);
>   	return err;
>   }
>   
> @@ -1887,7 +1887,7 @@ static int eb_parse_pipeline(struct i915_execbuffer *eb,
>   static int eb_parse(struct i915_execbuffer *eb)
>   {
>   	struct drm_i915_private *i915 = eb->i915;
> -	struct intel_engine_pool_node *pool;
> +	struct intel_gt_buffer_pool_node *pool;
>   	struct i915_vma *shadow, *trampoline;
>   	unsigned int len;
>   	int err;
> @@ -1910,7 +1910,7 @@ static int eb_parse(struct i915_execbuffer *eb)
>   		len += I915_CMD_PARSER_TRAMPOLINE_SIZE;
>   	}
>   
> -	pool = intel_engine_get_pool(eb->engine, len);
> +	pool = intel_gt_get_buffer_pool(eb->engine->gt, len);
>   	if (IS_ERR(pool))
>   		return PTR_ERR(pool);
>   
> @@ -1958,7 +1958,7 @@ static int eb_parse(struct i915_execbuffer *eb)
>   err_shadow:
>   	i915_vma_unpin(shadow);
>   err:
> -	intel_engine_pool_put(pool);
> +	intel_gt_buffer_pool_put(pool);
>   	return err;
>   }
>   
> @@ -2643,7 +2643,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
>   	 */
>   	eb.request->batch = batch;
>   	if (batch->private)
> -		intel_engine_pool_mark_active(batch->private, eb.request);
> +		intel_gt_buffer_pool_mark_active(batch->private, eb.request);
>   
>   	trace_i915_request_queue(eb.request, eb.batch_flags);
>   	err = eb_submit(&eb, batch);
> @@ -2672,7 +2672,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
>   		i915_vma_unpin(batch);
>   err_parse:
>   	if (batch->private)
> -		intel_engine_pool_put(batch->private);
> +		intel_gt_buffer_pool_put(batch->private);
>   err_vma:
>   	if (eb.trampoline)
>   		i915_vma_unpin(eb.trampoline);
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c
> index e00792158f13..2fc7737ef5f4 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c
> @@ -6,8 +6,8 @@
>   #include "i915_drv.h"
>   #include "gt/intel_context.h"
>   #include "gt/intel_engine_pm.h"
> -#include "gt/intel_engine_pool.h"
>   #include "gt/intel_gt.h"
> +#include "gt/intel_gt_buffer_pool.h"
>   #include "gt/intel_ring.h"
>   #include "i915_gem_clflush.h"
>   #include "i915_gem_object_blt.h"
> @@ -18,7 +18,7 @@ struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce,
>   {
>   	struct drm_i915_private *i915 = ce->vm->i915;
>   	const u32 block_size = SZ_8M; /* ~1ms at 8GiB/s preemption delay */
> -	struct intel_engine_pool_node *pool;
> +	struct intel_gt_buffer_pool_node *pool;
>   	struct i915_vma *batch;
>   	u64 offset;
>   	u64 count;
> @@ -33,7 +33,7 @@ struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce,
>   	count = div_u64(round_up(vma->size, block_size), block_size);
>   	size = (1 + 8 * count) * sizeof(u32);
>   	size = round_up(size, PAGE_SIZE);
> -	pool = intel_engine_get_pool(ce->engine, size);
> +	pool = intel_gt_get_buffer_pool(ce->engine->gt, size);
>   	if (IS_ERR(pool)) {
>   		err = PTR_ERR(pool);
>   		goto out_pm;
> @@ -96,7 +96,7 @@ struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce,
>   	return batch;
>   
>   out_put:
> -	intel_engine_pool_put(pool);
> +	intel_gt_buffer_pool_put(pool);
>   out_pm:
>   	intel_engine_pm_put(ce->engine);
>   	return ERR_PTR(err);
> @@ -114,13 +114,13 @@ int intel_emit_vma_mark_active(struct i915_vma *vma, struct i915_request *rq)
>   	if (unlikely(err))
>   		return err;
>   
> -	return intel_engine_pool_mark_active(vma->private, rq);
> +	return intel_gt_buffer_pool_mark_active(vma->private, rq);
>   }
>   
>   void intel_emit_vma_release(struct intel_context *ce, struct i915_vma *vma)
>   {
>   	i915_vma_unpin(vma);
> -	intel_engine_pool_put(vma->private);
> +	intel_gt_buffer_pool_put(vma->private);
>   	intel_engine_pm_put(ce->engine);
>   }
>   
> @@ -213,7 +213,7 @@ struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce,
>   {
>   	struct drm_i915_private *i915 = ce->vm->i915;
>   	const u32 block_size = SZ_8M; /* ~1ms at 8GiB/s preemption delay */
> -	struct intel_engine_pool_node *pool;
> +	struct intel_gt_buffer_pool_node *pool;
>   	struct i915_vma *batch;
>   	u64 src_offset, dst_offset;
>   	u64 count, rem;
> @@ -228,7 +228,7 @@ struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce,
>   	count = div_u64(round_up(dst->size, block_size), block_size);
>   	size = (1 + 11 * count) * sizeof(u32);
>   	size = round_up(size, PAGE_SIZE);
> -	pool = intel_engine_get_pool(ce->engine, size);
> +	pool = intel_gt_get_buffer_pool(ce->engine->gt, size);
>   	if (IS_ERR(pool)) {
>   		err = PTR_ERR(pool);
>   		goto out_pm;
> @@ -307,7 +307,7 @@ struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce,
>   	return batch;
>   
>   out_put:
> -	intel_engine_pool_put(pool);
> +	intel_gt_buffer_pool_put(pool);
>   out_pm:
>   	intel_engine_pm_put(ce->engine);
>   	return ERR_PTR(err);
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h
> index 243a43a87824..8bcd336a90dc 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h
> @@ -10,7 +10,6 @@
>   
>   #include "gt/intel_context.h"
>   #include "gt/intel_engine_pm.h"
> -#include "gt/intel_engine_pool.h"
>   #include "i915_vma.h"
>   
>   struct drm_i915_gem_object;
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> index c9e46c5ced43..98b326a1568d 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> @@ -31,7 +31,6 @@
>   #include "intel_context.h"
>   #include "intel_engine.h"
>   #include "intel_engine_pm.h"
> -#include "intel_engine_pool.h"
>   #include "intel_engine_user.h"
>   #include "intel_gt.h"
>   #include "intel_gt_requests.h"
> @@ -631,8 +630,6 @@ static int engine_setup_common(struct intel_engine_cs *engine)
>   	intel_engine_init__pm(engine);
>   	intel_engine_init_retire(engine);
>   
> -	intel_engine_pool_init(&engine->pool);
> -
>   	/* Use the whole device by default */
>   	engine->sseu =
>   		intel_sseu_from_device_info(&RUNTIME_INFO(engine->i915)->sseu);
> @@ -829,7 +826,6 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
>   	cleanup_status_page(engine);
>   
>   	intel_engine_fini_retire(engine);
> -	intel_engine_pool_fini(&engine->pool);
>   	intel_engine_fini_breadcrumbs(engine);
>   	intel_engine_cleanup_cmd_parser(engine);
>   
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
> index cf46076c59b2..d0a1078ef632 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c
> +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
> @@ -10,7 +10,6 @@
>   #include "intel_engine.h"
>   #include "intel_engine_heartbeat.h"
>   #include "intel_engine_pm.h"
> -#include "intel_engine_pool.h"
>   #include "intel_gt.h"
>   #include "intel_gt_pm.h"
>   #include "intel_rc6.h"
> @@ -248,7 +247,6 @@ static int __engine_park(struct intel_wakeref *wf)
>   
>   	intel_engine_park_heartbeat(engine);
>   	intel_engine_disarm_breadcrumbs(engine);
> -	intel_engine_pool_park(&engine->pool);
>   
>   	/* Must be reset upon idling, or we may miss the busy wakeup. */
>   	GEM_BUG_ON(engine->execlists.queue_priority_hint != INT_MIN);
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pool.h b/drivers/gpu/drm/i915/gt/intel_engine_pool.h
> deleted file mode 100644
> index 1bd89cadc3b7..000000000000
> --- a/drivers/gpu/drm/i915/gt/intel_engine_pool.h
> +++ /dev/null
> @@ -1,34 +0,0 @@
> -/*
> - * SPDX-License-Identifier: MIT
> - *
> - * Copyright © 2014-2018 Intel Corporation
> - */
> -
> -#ifndef INTEL_ENGINE_POOL_H
> -#define INTEL_ENGINE_POOL_H
> -
> -#include "intel_engine_pool_types.h"
> -#include "i915_active.h"
> -#include "i915_request.h"
> -
> -struct intel_engine_pool_node *
> -intel_engine_get_pool(struct intel_engine_cs *engine, size_t size);
> -
> -static inline int
> -intel_engine_pool_mark_active(struct intel_engine_pool_node *node,
> -			      struct i915_request *rq)
> -{
> -	return i915_active_add_request(&node->active, rq);
> -}
> -
> -static inline void
> -intel_engine_pool_put(struct intel_engine_pool_node *node)
> -{
> -	i915_active_release(&node->active);
> -}
> -
> -void intel_engine_pool_init(struct intel_engine_pool *pool);
> -void intel_engine_pool_park(struct intel_engine_pool *pool);
> -void intel_engine_pool_fini(struct intel_engine_pool *pool);
> -
> -#endif /* INTEL_ENGINE_POOL_H */
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
> index 68a382229b4a..489deb3b8358 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
> +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
> @@ -22,7 +22,6 @@
>   #include "i915_pmu.h"
>   #include "i915_priolist_types.h"
>   #include "i915_selftest.h"
> -#include "intel_engine_pool_types.h"
>   #include "intel_sseu.h"
>   #include "intel_timeline_types.h"
>   #include "intel_wakeref.h"
> @@ -404,13 +403,6 @@ struct intel_engine_cs {
>   		struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_COUNT];
>   	} pmu;
>   
> -	/*
> -	 * 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 intel_engine_pool pool;
> -
>   	struct intel_hw_status_page status_page;
>   	struct i915_ctx_workarounds wa_ctx;
>   	struct i915_wa_list ctx_wa_list;
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
> index 52593edf8aa0..f069551e412f 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> @@ -7,6 +7,7 @@
>   #include "i915_drv.h"
>   #include "intel_context.h"
>   #include "intel_gt.h"
> +#include "intel_gt_buffer_pool.h"
>   #include "intel_gt_clock_utils.h"
>   #include "intel_gt_pm.h"
>   #include "intel_gt_requests.h"
> @@ -28,6 +29,7 @@ void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
>   	INIT_LIST_HEAD(&gt->closed_vma);
>   	spin_lock_init(&gt->closed_lock);
>   
> +	intel_gt_init_buffer_pool(gt);
>   	intel_gt_init_reset(gt);
>   	intel_gt_init_requests(gt);
>   	intel_gt_init_timelines(gt);
> @@ -621,6 +623,7 @@ void intel_gt_driver_release(struct intel_gt *gt)
>   
>   	intel_gt_pm_fini(gt);
>   	intel_gt_fini_scratch(gt);
> +	intel_gt_fini_buffer_pool(gt);
>   }
>   
>   void intel_gt_driver_late_release(struct intel_gt *gt)
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pool.c b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c
> similarity index 53%
> rename from drivers/gpu/drm/i915/gt/intel_engine_pool.c
> rename to drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c
> index 397186818305..1495054a4305 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_pool.c
> +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c
> @@ -1,6 +1,5 @@
> +// SPDX-License-Identifier: MIT
>   /*
> - * SPDX-License-Identifier: MIT
> - *
>    * Copyright © 2014-2018 Intel Corporation
>    */
>   
> @@ -8,15 +7,15 @@
>   
>   #include "i915_drv.h"
>   #include "intel_engine_pm.h"
> -#include "intel_engine_pool.h"
> +#include "intel_gt_buffer_pool.h"
>   
> -static struct intel_engine_cs *to_engine(struct intel_engine_pool *pool)
> +static struct intel_gt *to_gt(struct intel_gt_buffer_pool *pool)
>   {
> -	return container_of(pool, struct intel_engine_cs, pool);
> +	return container_of(pool, struct intel_gt, buffer_pool);
>   }
>   
>   static struct list_head *
> -bucket_for_size(struct intel_engine_pool *pool, size_t sz)
> +bucket_for_size(struct intel_gt_buffer_pool *pool, size_t sz)
>   {
>   	int n;
>   
> @@ -32,16 +31,50 @@ bucket_for_size(struct intel_engine_pool *pool, size_t sz)
>   	return &pool->cache_list[n];
>   }
>   
> -static void node_free(struct intel_engine_pool_node *node)
> +static void node_free(struct intel_gt_buffer_pool_node *node)
>   {
>   	i915_gem_object_put(node->obj);
>   	i915_active_fini(&node->active);
>   	kfree(node);
>   }
>   
> +static void pool_free_work(struct work_struct *wrk)
> +{
> +	struct intel_gt_buffer_pool *pool =
> +		container_of(wrk, typeof(*pool), work.work);
> +	struct intel_gt_buffer_pool_node *node, *next;
> +	unsigned long old = jiffies - HZ;
> +	bool active = false;
> +	LIST_HEAD(stale);
> +	int n;
> +
> +	/* Free buffers that have not been used in the past second */
> +	spin_lock_irq(&pool->lock);
> +	for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) {
> +		struct list_head *list = &pool->cache_list[n];
> +
> +		/* Most recent at head; oldest at tail */
> +		list_for_each_entry_safe_reverse(node, next, list, link) {
> +			if (time_before(node->age, old))
> +				break;
> +
> +			list_move(&node->link, &stale);
> +		}
> +		active |= !list_empty(list);
> +	}
> +	spin_unlock_irq(&pool->lock);
> +
> +	list_for_each_entry_safe(node, next, &stale, link)
> +		node_free(node);
> +
> +	if (active)
> +		schedule_delayed_work(&pool->work,
> +				      round_jiffies_up_relative(HZ));
> +}
> +
>   static int pool_active(struct i915_active *ref)
>   {
> -	struct intel_engine_pool_node *node =
> +	struct intel_gt_buffer_pool_node *node =
>   		container_of(ref, typeof(*node), active);
>   	struct dma_resv *resv = node->obj->base.resv;
>   	int err;
> @@ -64,29 +97,31 @@ static int pool_active(struct i915_active *ref)
>   __i915_active_call
>   static void pool_retire(struct i915_active *ref)
>   {
> -	struct intel_engine_pool_node *node =
> +	struct intel_gt_buffer_pool_node *node =
>   		container_of(ref, typeof(*node), active);
> -	struct intel_engine_pool *pool = node->pool;
> +	struct intel_gt_buffer_pool *pool = node->pool;
>   	struct list_head *list = bucket_for_size(pool, node->obj->base.size);
>   	unsigned long flags;
>   
> -	GEM_BUG_ON(!intel_engine_pm_is_awake(to_engine(pool)));
> -
>   	i915_gem_object_unpin_pages(node->obj);
>   
>   	/* Return this object to the shrinker pool */
>   	i915_gem_object_make_purgeable(node->obj);
>   
>   	spin_lock_irqsave(&pool->lock, flags);
> +	node->age = jiffies;
>   	list_add(&node->link, list);
>   	spin_unlock_irqrestore(&pool->lock, flags);
> +
> +	schedule_delayed_work(&pool->work,
> +			      round_jiffies_up_relative(HZ));
>   }
>   
> -static struct intel_engine_pool_node *
> -node_create(struct intel_engine_pool *pool, size_t sz)
> +static struct intel_gt_buffer_pool_node *
> +node_create(struct intel_gt_buffer_pool *pool, size_t sz)
>   {
> -	struct intel_engine_cs *engine = to_engine(pool);
> -	struct intel_engine_pool_node *node;
> +	struct intel_gt *gt = to_gt(pool);
> +	struct intel_gt_buffer_pool_node *node;
>   	struct drm_i915_gem_object *obj;
>   
>   	node = kmalloc(sizeof(*node),
> @@ -97,7 +132,7 @@ node_create(struct intel_engine_pool *pool, size_t sz)
>   	node->pool = pool;
>   	i915_active_init(&node->active, pool_active, pool_retire);
>   
> -	obj = i915_gem_object_create_internal(engine->i915, sz);
> +	obj = i915_gem_object_create_internal(gt->i915, sz);
>   	if (IS_ERR(obj)) {
>   		i915_active_fini(&node->active);
>   		kfree(node);
> @@ -110,26 +145,15 @@ node_create(struct intel_engine_pool *pool, size_t sz)
>   	return node;
>   }
>   
> -static struct intel_engine_pool *lookup_pool(struct intel_engine_cs *engine)
> +struct intel_gt_buffer_pool_node *
> +intel_gt_get_buffer_pool(struct intel_gt *gt, size_t size)
>   {
> -	if (intel_engine_is_virtual(engine))
> -		engine = intel_virtual_engine_get_sibling(engine, 0);
> -
> -	GEM_BUG_ON(!engine);
> -	return &engine->pool;
> -}
> -
> -struct intel_engine_pool_node *
> -intel_engine_get_pool(struct intel_engine_cs *engine, size_t size)
> -{
> -	struct intel_engine_pool *pool = lookup_pool(engine);
> -	struct intel_engine_pool_node *node;
> +	struct intel_gt_buffer_pool *pool = &gt->buffer_pool;
> +	struct intel_gt_buffer_pool_node *node;
>   	struct list_head *list;
>   	unsigned long flags;
>   	int ret;
>   
> -	GEM_BUG_ON(!intel_engine_pm_is_awake(to_engine(pool)));
> -
>   	size = PAGE_ALIGN(size);
>   	list = bucket_for_size(pool, size);
>   
> @@ -157,34 +181,48 @@ intel_engine_get_pool(struct intel_engine_cs *engine, size_t size)
>   	return node;
>   }
>   
> -void intel_engine_pool_init(struct intel_engine_pool *pool)
> +void intel_gt_init_buffer_pool(struct intel_gt *gt)
>   {
> +	struct intel_gt_buffer_pool *pool = &gt->buffer_pool;
>   	int n;
>   
>   	spin_lock_init(&pool->lock);
>   	for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++)
>   		INIT_LIST_HEAD(&pool->cache_list[n]);
> +	INIT_DELAYED_WORK(&pool->work, pool_free_work);
>   }
>   
> -void intel_engine_pool_park(struct intel_engine_pool *pool)
> +static void pool_free_imm(struct intel_gt_buffer_pool *pool)
>   {
>   	int n;
>   
> +	spin_lock_irq(&pool->lock);
>   	for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) {
> +		struct intel_gt_buffer_pool_node *node, *next;
>   		struct list_head *list = &pool->cache_list[n];
> -		struct intel_engine_pool_node *node, *nn;
>   
> -		list_for_each_entry_safe(node, nn, list, link)
> +		list_for_each_entry_safe(node, next, list, link)
>   			node_free(node);
> -
>   		INIT_LIST_HEAD(list);
>   	}
> +	spin_unlock_irq(&pool->lock);
> +}
> +
> +void intel_gt_flush_buffer_pool(struct intel_gt *gt)
> +{
> +	struct intel_gt_buffer_pool *pool = &gt->buffer_pool;
> +
> +	if (cancel_delayed_work_sync(&pool->work))
> +		pool_free_imm(pool);
>   }
>   
> -void intel_engine_pool_fini(struct intel_engine_pool *pool)
> +void intel_gt_fini_buffer_pool(struct intel_gt *gt)
>   {
> +	struct intel_gt_buffer_pool *pool = &gt->buffer_pool;
>   	int n;
>   
> +	intel_gt_flush_buffer_pool(gt);
> +
>   	for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++)
>   		GEM_BUG_ON(!list_empty(&pool->cache_list[n]));
>   }
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.h b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.h
> new file mode 100644
> index 000000000000..42cbac003e8a
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.h
> @@ -0,0 +1,37 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2014-2018 Intel Corporation
> + */
> +
> +#ifndef INTEL_GT_BUFFER_POOL_H
> +#define INTEL_GT_BUFFER_POOL_H
> +
> +#include <linux/types.h>
> +
> +#include "i915_active.h"
> +#include "intel_gt_buffer_pool_types.h"
> +
> +struct intel_gt;
> +struct i915_request;
> +
> +struct intel_gt_buffer_pool_node *
> +intel_gt_get_buffer_pool(struct intel_gt *gt, size_t size);
> +
> +static inline int
> +intel_gt_buffer_pool_mark_active(struct intel_gt_buffer_pool_node *node,
> +				 struct i915_request *rq)
> +{
> +	return i915_active_add_request(&node->active, rq);
> +}
> +
> +static inline void
> +intel_gt_buffer_pool_put(struct intel_gt_buffer_pool_node *node)
> +{
> +	i915_active_release(&node->active);
> +}
> +
> +void intel_gt_init_buffer_pool(struct intel_gt *gt);
> +void intel_gt_flush_buffer_pool(struct intel_gt *gt);
> +void intel_gt_fini_buffer_pool(struct intel_gt *gt);
> +
> +#endif /* INTEL_GT_BUFFER_POOL_H */
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pool_types.h b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h
> similarity index 54%
> rename from drivers/gpu/drm/i915/gt/intel_engine_pool_types.h
> rename to drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h
> index e31ee361b76f..e28bdda771ed 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_pool_types.h
> +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h
> @@ -4,26 +4,29 @@
>    * Copyright © 2014-2018 Intel Corporation
>    */
>   
> -#ifndef INTEL_ENGINE_POOL_TYPES_H
> -#define INTEL_ENGINE_POOL_TYPES_H
> +#ifndef INTEL_GT_BUFFER_POOL_TYPES_H
> +#define INTEL_GT_BUFFER_POOL_TYPES_H
>   
>   #include <linux/list.h>
>   #include <linux/spinlock.h>
> +#include <linux/workqueue.h>
>   
>   #include "i915_active_types.h"
>   
>   struct drm_i915_gem_object;
>   
> -struct intel_engine_pool {
> +struct intel_gt_buffer_pool {
>   	spinlock_t lock;
>   	struct list_head cache_list[4];
> +	struct delayed_work work;
>   };
>   
> -struct intel_engine_pool_node {
> +struct intel_gt_buffer_pool_node {
>   	struct i915_active active;
>   	struct drm_i915_gem_object *obj;
>   	struct list_head link;
> -	struct intel_engine_pool *pool;
> +	struct intel_gt_buffer_pool *pool;
> +	unsigned long age;
>   };
>   
> -#endif /* INTEL_ENGINE_POOL_TYPES_H */
> +#endif /* INTEL_GT_BUFFER_POOL_TYPES_H */
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h
> index d02ccb735e24..0cc1d6b185dc 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gt_types.h
> +++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h
> @@ -17,6 +17,7 @@
>   
>   #include "i915_vma.h"
>   #include "intel_engine_types.h"
> +#include "intel_gt_buffer_pool_types.h"
>   #include "intel_llc_types.h"
>   #include "intel_reset_types.h"
>   #include "intel_rc6_types.h"
> @@ -97,6 +98,16 @@ struct intel_gt {
>   	 */
>   	struct i915_address_space *vm;
>   
> +	/*
> +	 * 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.
> +	 *
> +	 * Buffers older than 1s are periodically reaped from the pool,
> +	 * or may be reclaimed by the shrinker before then.
> +	 */
> +	struct intel_gt_buffer_pool buffer_pool;
> +
>   	struct i915_vma *scratch;
>   };
>   
> diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c
> index 4a53ded7c2dd..b8dd3cbc8696 100644
> --- a/drivers/gpu/drm/i915/gt/mock_engine.c
> +++ b/drivers/gpu/drm/i915/gt/mock_engine.c
> @@ -28,7 +28,6 @@
>   #include "i915_drv.h"
>   #include "intel_context.h"
>   #include "intel_engine_pm.h"
> -#include "intel_engine_pool.h"
>   
>   #include "mock_engine.h"
>   #include "selftests/mock_request.h"
> @@ -328,7 +327,6 @@ int mock_engine_init(struct intel_engine_cs *engine)
>   	intel_engine_init_execlists(engine);
>   	intel_engine_init__pm(engine);
>   	intel_engine_init_retire(engine);
> -	intel_engine_pool_init(&engine->pool);
>   
>   	ce = create_kernel_context(engine);
>   	if (IS_ERR(ce))
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index c09e1afb5f79..8e98df6a3045 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -32,6 +32,7 @@
>   #include <drm/drm_debugfs.h>
>   
>   #include "gem/i915_gem_context.h"
> +#include "gt/intel_gt_buffer_pool.h"
>   #include "gt/intel_gt_clock_utils.h"
>   #include "gt/intel_gt_pm.h"
>   #include "gt/intel_gt_requests.h"
> @@ -1484,6 +1485,9 @@ gt_drop_caches(struct intel_gt *gt, u64 val)
>   	if (val & DROP_RESET_ACTIVE && intel_gt_terminally_wedged(gt))
>   		intel_gt_handle_error(gt, ALL_ENGINES, 0, NULL);
>   
> +	if (val & DROP_FREED)
> +		intel_gt_flush_buffer_pool(gt);
> +
>   	return 0;
>   }
>   
> 

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>

Regards,

Tvrtko


More information about the Intel-gfx mailing list