aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c67
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c13
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h12
3 files changed, 79 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 8eedf7cac493..02adcaf6ebea 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -753,6 +753,68 @@ static int eb_select_context(struct i915_execbuffer *eb)
753 return 0; 753 return 0;
754} 754}
755 755
756static struct i915_request *__eb_wait_for_ring(struct intel_ring *ring)
757{
758 struct i915_request *rq;
759
760 /*
761 * Completely unscientific finger-in-the-air estimates for suitable
762 * maximum user request size (to avoid blocking) and then backoff.
763 */
764 if (intel_ring_update_space(ring) >= PAGE_SIZE)
765 return NULL;
766
767 /*
768 * Find a request that after waiting upon, there will be at least half
769 * the ring available. The hysteresis allows us to compete for the
770 * shared ring and should mean that we sleep less often prior to
771 * claiming our resources, but not so long that the ring completely
772 * drains before we can submit our next request.
773 */
774 list_for_each_entry(rq, &ring->request_list, ring_link) {
775 if (__intel_ring_space(rq->postfix,
776 ring->emit, ring->size) > ring->size / 2)
777 break;
778 }
779 if (&rq->ring_link == &ring->request_list)
780 return NULL; /* weird, we will check again later for real */
781
782 return i915_request_get(rq);
783}
784
785static int eb_wait_for_ring(const struct i915_execbuffer *eb)
786{
787 const struct intel_context *ce;
788 struct i915_request *rq;
789 int ret = 0;
790
791 /*
792 * Apply a light amount of backpressure to prevent excessive hogs
793 * from blocking waiting for space whilst holding struct_mutex and
794 * keeping all of their resources pinned.
795 */
796
797 ce = to_intel_context(eb->ctx, eb->engine);
798 if (!ce->ring) /* first use, assume empty! */
799 return 0;
800
801 rq = __eb_wait_for_ring(ce->ring);
802 if (rq) {
803 mutex_unlock(&eb->i915->drm.struct_mutex);
804
805 if (i915_request_wait(rq,
806 I915_WAIT_INTERRUPTIBLE,
807 MAX_SCHEDULE_TIMEOUT) < 0)
808 ret = -EINTR;
809
810 i915_request_put(rq);
811
812 mutex_lock(&eb->i915->drm.struct_mutex);
813 }
814
815 return ret;
816}
817
756static int eb_lookup_vmas(struct i915_execbuffer *eb) 818static int eb_lookup_vmas(struct i915_execbuffer *eb)
757{ 819{
758 struct radix_tree_root *handles_vma = &eb->ctx->handles_vma; 820 struct radix_tree_root *handles_vma = &eb->ctx->handles_vma;
@@ -2291,6 +2353,10 @@ i915_gem_do_execbuffer(struct drm_device *dev,
2291 if (err) 2353 if (err)
2292 goto err_rpm; 2354 goto err_rpm;
2293 2355
2356 err = eb_wait_for_ring(&eb); /* may temporarily drop struct_mutex */
2357 if (unlikely(err))
2358 goto err_unlock;
2359
2294 err = eb_relocate(&eb); 2360 err = eb_relocate(&eb);
2295 if (err) { 2361 if (err) {
2296 /* 2362 /*
@@ -2435,6 +2501,7 @@ err_batch_unpin:
2435err_vma: 2501err_vma:
2436 if (eb.exec) 2502 if (eb.exec)
2437 eb_release_vmas(&eb); 2503 eb_release_vmas(&eb);
2504err_unlock:
2438 mutex_unlock(&dev->struct_mutex); 2505 mutex_unlock(&dev->struct_mutex);
2439err_rpm: 2506err_rpm:
2440 intel_runtime_pm_put(eb.i915, wakeref); 2507 intel_runtime_pm_put(eb.i915, wakeref);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index b889b27f8aeb..7f841dba87b3 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -49,19 +49,6 @@ static inline u32 intel_hws_seqno_address(struct intel_engine_cs *engine)
49 I915_GEM_HWS_INDEX_ADDR); 49 I915_GEM_HWS_INDEX_ADDR);
50} 50}
51 51
52static unsigned int __intel_ring_space(unsigned int head,
53 unsigned int tail,
54 unsigned int size)
55{
56 /*
57 * "If the Ring Buffer Head Pointer and the Tail Pointer are on the
58 * same cacheline, the Head Pointer must not be greater than the Tail
59 * Pointer."
60 */
61 GEM_BUG_ON(!is_power_of_2(size));
62 return (head - tail - CACHELINE_BYTES) & (size - 1);
63}
64
65unsigned int intel_ring_update_space(struct intel_ring *ring) 52unsigned int intel_ring_update_space(struct intel_ring *ring)
66{ 53{
67 unsigned int space; 54 unsigned int space;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 4d4ea6963a72..710ffb221775 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -832,6 +832,18 @@ intel_ring_set_tail(struct intel_ring *ring, unsigned int tail)
832 return tail; 832 return tail;
833} 833}
834 834
835static inline unsigned int
836__intel_ring_space(unsigned int head, unsigned int tail, unsigned int size)
837{
838 /*
839 * "If the Ring Buffer Head Pointer and the Tail Pointer are on the
840 * same cacheline, the Head Pointer must not be greater than the Tail
841 * Pointer."
842 */
843 GEM_BUG_ON(!is_power_of_2(size));
844 return (head - tail - CACHELINE_BYTES) & (size - 1);
845}
846
835void intel_engine_write_global_seqno(struct intel_engine_cs *engine, u32 seqno); 847void intel_engine_write_global_seqno(struct intel_engine_cs *engine, u32 seqno);
836 848
837int intel_engine_setup_common(struct intel_engine_cs *engine); 849int intel_engine_setup_common(struct intel_engine_cs *engine);