diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 67 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 12 |
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 | ||
756 | static 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 | |||
785 | static 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 | |||
756 | static int eb_lookup_vmas(struct i915_execbuffer *eb) | 818 | static 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: | |||
2435 | err_vma: | 2501 | err_vma: |
2436 | if (eb.exec) | 2502 | if (eb.exec) |
2437 | eb_release_vmas(&eb); | 2503 | eb_release_vmas(&eb); |
2504 | err_unlock: | ||
2438 | mutex_unlock(&dev->struct_mutex); | 2505 | mutex_unlock(&dev->struct_mutex); |
2439 | err_rpm: | 2506 | err_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 | ||
52 | static 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 | |||
65 | unsigned int intel_ring_update_space(struct intel_ring *ring) | 52 | unsigned 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 | ||
835 | static 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 | |||
835 | void intel_engine_write_global_seqno(struct intel_engine_cs *engine, u32 seqno); | 847 | void intel_engine_write_global_seqno(struct intel_engine_cs *engine, u32 seqno); |
836 | 848 | ||
837 | int intel_engine_setup_common(struct intel_engine_cs *engine); | 849 | int intel_engine_setup_common(struct intel_engine_cs *engine); |