@@ -2205,6 +2205,7 @@ struct drm_i915_gem_request *
i915_gem_find_active_request(struct intel_ring_buffer *ring);
bool i915_gem_retire_requests(struct drm_device *dev);
+void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring);
int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
bool interruptible);
static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
@@ -59,7 +59,6 @@ static unsigned long i915_gem_inactive_scan(struct shrinker *shrinker,
static unsigned long i915_gem_purge(struct drm_i915_private *dev_priv, long target);
static unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv);
static void i915_gem_object_truncate(struct drm_i915_gem_object *obj);
-static void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring);
static bool cpu_cache_is_coherent(struct drm_device *dev,
enum i915_cache_level level)
@@ -2565,7 +2564,7 @@ void i915_gem_reset(struct drm_device *dev)
/**
* This function clears the request list as sequence numbers are passed.
*/
-static void
+void
i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
{
uint32_t seqno;
@@ -40,14 +40,19 @@
*/
#define CACHELINE_BYTES 64
-static inline int ring_space(struct intel_ring_buffer *ring)
+static inline int __ring_space(int head, int tail, int size)
{
- int space = (ring->head & HEAD_ADDR) - (ring->tail + I915_RING_FREE_SPACE);
+ int space = head - (tail + I915_RING_FREE_SPACE);
if (space < 0)
- space += ring->size;
+ space += size;
return space;
}
+static inline int ring_space(struct intel_ring_buffer *ring)
+{
+ return __ring_space(ring->head & HEAD_ADDR, ring->tail, ring->size);
+}
+
static bool intel_ring_stopped(struct intel_ring_buffer *ring)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
@@ -1482,7 +1487,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
{
struct drm_i915_gem_request *request;
- u32 seqno = 0, tail;
+ u32 seqno = 0;
int ret;
if (ring->last_retired_head != -1) {
@@ -1495,26 +1500,10 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
}
list_for_each_entry(request, &ring->request_list, list) {
- int space;
-
- if (request->tail == -1)
- continue;
-
- space = request->tail - (ring->tail + I915_RING_FREE_SPACE);
- if (space < 0)
- space += ring->size;
- if (space >= n) {
+ if (__ring_space(request->tail, ring->tail, ring->size) >= n) {
seqno = request->seqno;
- tail = request->tail;
break;
}
-
- /* Consume this request in case we need more space than
- * is available and so need to prevent a race between
- * updating last_retired_head and direct reads of
- * I915_RING_HEAD. It also provides a nice sanity check.
- */
- request->tail = -1;
}
if (seqno == 0)
@@ -1524,11 +1513,11 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
if (ret)
return ret;
- ring->head = tail;
- ring->space = ring_space(ring);
- if (WARN_ON(ring->space < n))
- return -ENOSPC;
+ i915_gem_retire_requests_ring(ring);
+ ring->head = ring->last_retired_head;
+ ring->last_retired_head = -1;
+ ring->space = ring_space(ring);
return 0;
}