Skip to content

Commit

Permalink
drm/i915: Recover all available ringbuffer space following reset
Browse files Browse the repository at this point in the history
Having flushed all requests from all queues, we know that all
ringbuffers must now be empty. However, since we do not reclaim
all space when retiring the request (to prevent HEADs colliding
with rapid ringbuffer wraparound) the amount of available space
on each ringbuffer upon reset is less than when we start. Do one
more pass over all the ringbuffers to reset the available space

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Arun Siluvery <arun.siluvery@linux.intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Dave Gordon <david.s.gordon@intel.com>
  • Loading branch information
Chris Wilson authored and Tvrtko Ursulin committed Oct 28, 2015
1 parent 01403de commit 608c1a5
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 3 deletions.
14 changes: 14 additions & 0 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -2738,6 +2738,8 @@ static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
struct intel_engine_cs *ring)
{
struct intel_ringbuffer *buffer;

while (!list_empty(&ring->active_list)) {
struct drm_i915_gem_object *obj;

Expand Down Expand Up @@ -2788,6 +2790,18 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,

i915_gem_request_retire(request);
}

/* Having flushed all requests from all queues, we know that all
* ringbuffers must now be empty. However, since we do not reclaim
* all space when retiring the request (to prevent HEADs colliding
* with rapid ringbuffer wraparound) the amount of available space
* upon reset is less than when we start. Do one more pass over
* all the ringbuffers to reset last_retired_head.
*/
list_for_each_entry(buffer, &ring->buffers, link) {
buffer->last_retired_head = buffer->tail;
intel_ring_update_space(buffer);
}
}

void i915_gem_reset(struct drm_device *dev)
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/intel_lrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1897,6 +1897,7 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin
i915_gem_batch_pool_init(dev, &ring->batch_pool);
init_waitqueue_head(&ring->irq_queue);

INIT_LIST_HEAD(&ring->buffers);
INIT_LIST_HEAD(&ring->execlist_queue);
INIT_LIST_HEAD(&ring->execlist_retired_req_list);
spin_lock_init(&ring->execlist_lock);
Expand Down
13 changes: 10 additions & 3 deletions drivers/gpu/drm/i915/intel_ringbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2102,10 +2102,14 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)
int ret;

ring = kzalloc(sizeof(*ring), GFP_KERNEL);
if (ring == NULL)
if (ring == NULL) {
DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n",
engine->name);
return ERR_PTR(-ENOMEM);
}

ring->ring = engine;
list_add(&ring->link, &engine->buffers);

ring->size = size;
/* Workaround an erratum on the i830 which causes a hang if
Expand All @@ -2121,8 +2125,9 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)

ret = intel_alloc_ringbuffer_obj(engine->dev, ring);
if (ret) {
DRM_ERROR("Failed to allocate ringbuffer %s: %d\n",
engine->name, ret);
DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n",
engine->name, ret);
list_del(&ring->link);
kfree(ring);
return ERR_PTR(ret);
}
Expand All @@ -2134,6 +2139,7 @@ void
intel_ringbuffer_free(struct intel_ringbuffer *ring)
{
intel_destroy_ringbuffer_obj(ring);
list_del(&ring->link);
kfree(ring);
}

Expand All @@ -2149,6 +2155,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);
INIT_LIST_HEAD(&ring->buffers);
i915_gem_batch_pool_init(dev, &ring->batch_pool);
memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno));

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/intel_ringbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ struct intel_ringbuffer {
void __iomem *virtual_start;

struct intel_engine_cs *ring;
struct list_head link;

u32 head;
u32 tail;
Expand Down Expand Up @@ -157,6 +158,7 @@ struct intel_engine_cs {
u32 mmio_base;
struct drm_device *dev;
struct intel_ringbuffer *buffer;
struct list_head buffers;

/*
* A pool of objects to use as shadow copies of client batch buffers
Expand Down

0 comments on commit 608c1a5

Please sign in to comment.