drm/i915: Track requests inside each intel_ring
By tracking each request occupying space inside an individual intel_ring, we can greatly simplify the logic of tracking available space and not worry about other timelines. (Each ring is an ordered timeline of committed requests.) Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1470293567-10811-17-git-send-email-chris@chris-wilson.co.uk
This commit is contained in:
parent
fa545cbf97
commit
675d9ad71b
|
@ -180,6 +180,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
|
|||
* Note this requires that we are always called in request
|
||||
* completion order.
|
||||
*/
|
||||
list_del(&request->ring_link);
|
||||
request->ring->last_retired_head = request->postfix;
|
||||
|
||||
/* Walk through the active list, calling retire on each. This allows
|
||||
|
@ -487,6 +488,7 @@ void __i915_add_request(struct drm_i915_gem_request *request,
|
|||
request->previous_seqno = engine->last_submitted_seqno;
|
||||
smp_store_mb(engine->last_submitted_seqno, request->fence.seqno);
|
||||
list_add_tail(&request->link, &engine->request_list);
|
||||
list_add_tail(&request->ring_link, &ring->request_list);
|
||||
|
||||
/* Record the position of the start of the request so that
|
||||
* should we detect the updated seqno part-way through the
|
||||
|
|
|
@ -109,6 +109,9 @@ struct drm_i915_gem_request {
|
|||
/** engine->request_list entry for this request */
|
||||
struct list_head link;
|
||||
|
||||
/** ring->request_list entry for this request */
|
||||
struct list_head ring_link;
|
||||
|
||||
struct drm_i915_file_private *file_priv;
|
||||
/** file_priv list entry for this request */
|
||||
struct list_head client_list;
|
||||
|
|
|
@ -2046,6 +2046,8 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size)
|
|||
ring->engine = engine;
|
||||
list_add(&ring->link, &engine->buffers);
|
||||
|
||||
INIT_LIST_HEAD(&ring->request_list);
|
||||
|
||||
ring->size = size;
|
||||
/* Workaround an erratum on the i830 which causes a hang if
|
||||
* the TAIL pointer points to within the last 2 cachelines
|
||||
|
@ -2266,7 +2268,6 @@ int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request)
|
|||
static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
|
||||
{
|
||||
struct intel_ring *ring = req->ring;
|
||||
struct intel_engine_cs *engine = req->engine;
|
||||
struct drm_i915_gem_request *target;
|
||||
|
||||
intel_ring_update_space(ring);
|
||||
|
@ -2284,17 +2285,9 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
|
|||
*/
|
||||
GEM_BUG_ON(!req->reserved_space);
|
||||
|
||||
list_for_each_entry(target, &engine->request_list, link) {
|
||||
list_for_each_entry(target, &ring->request_list, ring_link) {
|
||||
unsigned space;
|
||||
|
||||
/*
|
||||
* The request queue is per-engine, so can contain requests
|
||||
* from multiple ringbuffers. Here, we must ignore any that
|
||||
* aren't from the ringbuffer we're considering.
|
||||
*/
|
||||
if (target->ring != ring)
|
||||
continue;
|
||||
|
||||
/* Would completion of this request free enough space? */
|
||||
space = __intel_ring_space(target->postfix, ring->tail,
|
||||
ring->size);
|
||||
|
@ -2302,7 +2295,7 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
|
|||
break;
|
||||
}
|
||||
|
||||
if (WARN_ON(&target->link == &engine->request_list))
|
||||
if (WARN_ON(&target->ring_link == &ring->request_list))
|
||||
return -ENOSPC;
|
||||
|
||||
return i915_wait_request(target);
|
||||
|
|
|
@ -90,6 +90,8 @@ struct intel_ring {
|
|||
struct intel_engine_cs *engine;
|
||||
struct list_head link;
|
||||
|
||||
struct list_head request_list;
|
||||
|
||||
u32 head;
|
||||
u32 tail;
|
||||
int space;
|
||||
|
|
Loading…
Reference in New Issue