diff options
| author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-01-07 12:09:48 -0500 |
|---|---|---|
| committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-01-11 15:44:50 -0500 |
| commit | 882417851a0f2e09e110038a13e88e9b5a100800 (patch) | |
| tree | 6c96e700acb948aabbc7857f823bb8ad114b3b44 /drivers/gpu | |
| parent | 776ad8062bb77697b8728a9794e3a394b28cf885 (diff) | |
drm/i915: Propagate error from flushing the ring
... in order to avoid a BUG() and potential unbounded waits.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 102 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 28 |
3 files changed, 90 insertions, 48 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 455260067ff7..3e78314514a2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -1086,10 +1086,10 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | |||
| 1086 | struct drm_file *file_priv); | 1086 | struct drm_file *file_priv); |
| 1087 | void i915_gem_load(struct drm_device *dev); | 1087 | void i915_gem_load(struct drm_device *dev); |
| 1088 | int i915_gem_init_object(struct drm_gem_object *obj); | 1088 | int i915_gem_init_object(struct drm_gem_object *obj); |
| 1089 | void i915_gem_flush_ring(struct drm_device *dev, | 1089 | int __must_check i915_gem_flush_ring(struct drm_device *dev, |
| 1090 | struct intel_ring_buffer *ring, | 1090 | struct intel_ring_buffer *ring, |
| 1091 | uint32_t invalidate_domains, | 1091 | uint32_t invalidate_domains, |
| 1092 | uint32_t flush_domains); | 1092 | uint32_t flush_domains); |
| 1093 | struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, | 1093 | struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, |
| 1094 | size_t size); | 1094 | size_t size); |
| 1095 | void i915_gem_free_object(struct drm_gem_object *obj); | 1095 | void i915_gem_free_object(struct drm_gem_object *obj); |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 07b62449b9e1..2873d068eb1f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -35,18 +35,18 @@ | |||
| 35 | #include <linux/swap.h> | 35 | #include <linux/swap.h> |
| 36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
| 37 | 37 | ||
| 38 | static void i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj); | 38 | static __must_check int i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj); |
| 39 | static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj); | 39 | static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj); |
| 40 | static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj); | 40 | static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj); |
| 41 | static int i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, | 41 | static __must_check int i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, |
| 42 | bool write); | 42 | bool write); |
| 43 | static int i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj, | 43 | static __must_check int i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj, |
| 44 | uint64_t offset, | 44 | uint64_t offset, |
| 45 | uint64_t size); | 45 | uint64_t size); |
| 46 | static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj); | 46 | static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj); |
| 47 | static int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | 47 | static __must_check int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, |
| 48 | unsigned alignment, | 48 | unsigned alignment, |
| 49 | bool map_and_fenceable); | 49 | bool map_and_fenceable); |
| 50 | static void i915_gem_clear_fence_reg(struct drm_device *dev, | 50 | static void i915_gem_clear_fence_reg(struct drm_device *dev, |
| 51 | struct drm_i915_fence_reg *reg); | 51 | struct drm_i915_fence_reg *reg); |
| 52 | static int i915_gem_phys_pwrite(struct drm_device *dev, | 52 | static int i915_gem_phys_pwrite(struct drm_device *dev, |
| @@ -2142,25 +2142,37 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj) | |||
| 2142 | return ret; | 2142 | return ret; |
| 2143 | } | 2143 | } |
| 2144 | 2144 | ||
| 2145 | void | 2145 | int |
| 2146 | i915_gem_flush_ring(struct drm_device *dev, | 2146 | i915_gem_flush_ring(struct drm_device *dev, |
| 2147 | struct intel_ring_buffer *ring, | 2147 | struct intel_ring_buffer *ring, |
| 2148 | uint32_t invalidate_domains, | 2148 | uint32_t invalidate_domains, |
| 2149 | uint32_t flush_domains) | 2149 | uint32_t flush_domains) |
| 2150 | { | 2150 | { |
| 2151 | if (ring->flush(ring, invalidate_domains, flush_domains) == 0) | 2151 | int ret; |
| 2152 | i915_gem_process_flushing_list(dev, flush_domains, ring); | 2152 | |
| 2153 | ret = ring->flush(ring, invalidate_domains, flush_domains); | ||
| 2154 | if (ret) | ||
| 2155 | return ret; | ||
| 2156 | |||
| 2157 | i915_gem_process_flushing_list(dev, flush_domains, ring); | ||
| 2158 | return 0; | ||
| 2153 | } | 2159 | } |
| 2154 | 2160 | ||
| 2155 | static int i915_ring_idle(struct drm_device *dev, | 2161 | static int i915_ring_idle(struct drm_device *dev, |
| 2156 | struct intel_ring_buffer *ring) | 2162 | struct intel_ring_buffer *ring) |
| 2157 | { | 2163 | { |
| 2164 | int ret; | ||
| 2165 | |||
| 2158 | if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list)) | 2166 | if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list)) |
| 2159 | return 0; | 2167 | return 0; |
| 2160 | 2168 | ||
| 2161 | if (!list_empty(&ring->gpu_write_list)) | 2169 | if (!list_empty(&ring->gpu_write_list)) { |
| 2162 | i915_gem_flush_ring(dev, ring, | 2170 | ret = i915_gem_flush_ring(dev, ring, |
| 2163 | I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); | 2171 | I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); |
| 2172 | if (ret) | ||
| 2173 | return ret; | ||
| 2174 | } | ||
| 2175 | |||
| 2164 | return i915_wait_request(dev, | 2176 | return i915_wait_request(dev, |
| 2165 | i915_gem_next_request_seqno(dev, ring), | 2177 | i915_gem_next_request_seqno(dev, ring), |
| 2166 | ring); | 2178 | ring); |
| @@ -2370,10 +2382,13 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj, | |||
| 2370 | int ret; | 2382 | int ret; |
| 2371 | 2383 | ||
| 2372 | if (obj->fenced_gpu_access) { | 2384 | if (obj->fenced_gpu_access) { |
| 2373 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) | 2385 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
| 2374 | i915_gem_flush_ring(obj->base.dev, | 2386 | ret = i915_gem_flush_ring(obj->base.dev, |
| 2375 | obj->last_fenced_ring, | 2387 | obj->last_fenced_ring, |
| 2376 | 0, obj->base.write_domain); | 2388 | 0, obj->base.write_domain); |
| 2389 | if (ret) | ||
| 2390 | return ret; | ||
| 2391 | } | ||
| 2377 | 2392 | ||
| 2378 | obj->fenced_gpu_access = false; | 2393 | obj->fenced_gpu_access = false; |
| 2379 | } | 2394 | } |
| @@ -2529,9 +2544,12 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | |||
| 2529 | return ret; | 2544 | return ret; |
| 2530 | } else if (obj->tiling_changed) { | 2545 | } else if (obj->tiling_changed) { |
| 2531 | if (obj->fenced_gpu_access) { | 2546 | if (obj->fenced_gpu_access) { |
| 2532 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) | 2547 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
| 2533 | i915_gem_flush_ring(obj->base.dev, obj->ring, | 2548 | ret = i915_gem_flush_ring(obj->base.dev, obj->ring, |
| 2534 | 0, obj->base.write_domain); | 2549 | 0, obj->base.write_domain); |
| 2550 | if (ret) | ||
| 2551 | return ret; | ||
| 2552 | } | ||
| 2535 | 2553 | ||
| 2536 | obj->fenced_gpu_access = false; | 2554 | obj->fenced_gpu_access = false; |
| 2537 | } | 2555 | } |
| @@ -2817,17 +2835,16 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj) | |||
| 2817 | } | 2835 | } |
| 2818 | 2836 | ||
| 2819 | /** Flushes any GPU write domain for the object if it's dirty. */ | 2837 | /** Flushes any GPU write domain for the object if it's dirty. */ |
| 2820 | static void | 2838 | static int |
| 2821 | i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj) | 2839 | i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj) |
| 2822 | { | 2840 | { |
| 2823 | struct drm_device *dev = obj->base.dev; | 2841 | struct drm_device *dev = obj->base.dev; |
| 2824 | 2842 | ||
| 2825 | if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) | 2843 | if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) |
| 2826 | return; | 2844 | return 0; |
| 2827 | 2845 | ||
| 2828 | /* Queue the GPU write cache flushing we need. */ | 2846 | /* Queue the GPU write cache flushing we need. */ |
| 2829 | i915_gem_flush_ring(dev, obj->ring, 0, obj->base.write_domain); | 2847 | return i915_gem_flush_ring(dev, obj->ring, 0, obj->base.write_domain); |
| 2830 | BUG_ON(obj->base.write_domain); | ||
| 2831 | } | 2848 | } |
| 2832 | 2849 | ||
| 2833 | /** Flushes the GTT write domain for the object if it's dirty. */ | 2850 | /** Flushes the GTT write domain for the object if it's dirty. */ |
| @@ -2894,7 +2911,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) | |||
| 2894 | if (obj->gtt_space == NULL) | 2911 | if (obj->gtt_space == NULL) |
| 2895 | return -EINVAL; | 2912 | return -EINVAL; |
| 2896 | 2913 | ||
| 2897 | i915_gem_object_flush_gpu_write_domain(obj); | 2914 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2915 | if (ret) | ||
| 2916 | return ret; | ||
| 2917 | |||
| 2898 | if (obj->pending_gpu_write || write) { | 2918 | if (obj->pending_gpu_write || write) { |
| 2899 | ret = i915_gem_object_wait_rendering(obj, true); | 2919 | ret = i915_gem_object_wait_rendering(obj, true); |
| 2900 | if (ret) | 2920 | if (ret) |
| @@ -2939,7 +2959,10 @@ i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj, | |||
| 2939 | if (obj->gtt_space == NULL) | 2959 | if (obj->gtt_space == NULL) |
| 2940 | return -EINVAL; | 2960 | return -EINVAL; |
| 2941 | 2961 | ||
| 2942 | i915_gem_object_flush_gpu_write_domain(obj); | 2962 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2963 | if (ret) | ||
| 2964 | return ret; | ||
| 2965 | |||
| 2943 | 2966 | ||
| 2944 | /* Currently, we are always called from an non-interruptible context. */ | 2967 | /* Currently, we are always called from an non-interruptible context. */ |
| 2945 | if (pipelined != obj->ring) { | 2968 | if (pipelined != obj->ring) { |
| @@ -2964,12 +2987,17 @@ int | |||
| 2964 | i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, | 2987 | i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, |
| 2965 | bool interruptible) | 2988 | bool interruptible) |
| 2966 | { | 2989 | { |
| 2990 | int ret; | ||
| 2991 | |||
| 2967 | if (!obj->active) | 2992 | if (!obj->active) |
| 2968 | return 0; | 2993 | return 0; |
| 2969 | 2994 | ||
| 2970 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) | 2995 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
| 2971 | i915_gem_flush_ring(obj->base.dev, obj->ring, | 2996 | ret = i915_gem_flush_ring(obj->base.dev, obj->ring, |
| 2972 | 0, obj->base.write_domain); | 2997 | 0, obj->base.write_domain); |
| 2998 | if (ret) | ||
| 2999 | return ret; | ||
| 3000 | } | ||
| 2973 | 3001 | ||
| 2974 | return i915_gem_object_wait_rendering(obj, interruptible); | 3002 | return i915_gem_object_wait_rendering(obj, interruptible); |
| 2975 | } | 3003 | } |
| @@ -2986,7 +3014,10 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write) | |||
| 2986 | uint32_t old_write_domain, old_read_domains; | 3014 | uint32_t old_write_domain, old_read_domains; |
| 2987 | int ret; | 3015 | int ret; |
| 2988 | 3016 | ||
| 2989 | i915_gem_object_flush_gpu_write_domain(obj); | 3017 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 3018 | if (ret) | ||
| 3019 | return ret; | ||
| 3020 | |||
| 2990 | ret = i915_gem_object_wait_rendering(obj, true); | 3021 | ret = i915_gem_object_wait_rendering(obj, true); |
| 2991 | if (ret) | 3022 | if (ret) |
| 2992 | return ret; | 3023 | return ret; |
| @@ -3081,7 +3112,10 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj, | |||
| 3081 | if (offset == 0 && size == obj->base.size) | 3112 | if (offset == 0 && size == obj->base.size) |
| 3082 | return i915_gem_object_set_to_cpu_domain(obj, 0); | 3113 | return i915_gem_object_set_to_cpu_domain(obj, 0); |
| 3083 | 3114 | ||
| 3084 | i915_gem_object_flush_gpu_write_domain(obj); | 3115 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 3116 | if (ret) | ||
| 3117 | return ret; | ||
| 3118 | |||
| 3085 | ret = i915_gem_object_wait_rendering(obj, true); | 3119 | ret = i915_gem_object_wait_rendering(obj, true); |
| 3086 | if (ret) | 3120 | if (ret) |
| 3087 | return ret; | 3121 | return ret; |
| @@ -3374,8 +3408,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
| 3374 | * flush earlier is beneficial. | 3408 | * flush earlier is beneficial. |
| 3375 | */ | 3409 | */ |
| 3376 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { | 3410 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
| 3377 | i915_gem_flush_ring(dev, obj->ring, | 3411 | ret = i915_gem_flush_ring(dev, obj->ring, |
| 3378 | 0, obj->base.write_domain); | 3412 | 0, obj->base.write_domain); |
| 3379 | } else if (obj->ring->outstanding_lazy_request == | 3413 | } else if (obj->ring->outstanding_lazy_request == |
| 3380 | obj->last_rendering_seqno) { | 3414 | obj->last_rendering_seqno) { |
| 3381 | struct drm_i915_gem_request *request; | 3415 | struct drm_i915_gem_request *request; |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 1b78b66dd77e..97d5fbd8ea13 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -713,14 +713,14 @@ err: | |||
| 713 | return ret; | 713 | return ret; |
| 714 | } | 714 | } |
| 715 | 715 | ||
| 716 | static void | 716 | static int |
| 717 | i915_gem_execbuffer_flush(struct drm_device *dev, | 717 | i915_gem_execbuffer_flush(struct drm_device *dev, |
| 718 | uint32_t invalidate_domains, | 718 | uint32_t invalidate_domains, |
| 719 | uint32_t flush_domains, | 719 | uint32_t flush_domains, |
| 720 | uint32_t flush_rings) | 720 | uint32_t flush_rings) |
| 721 | { | 721 | { |
| 722 | drm_i915_private_t *dev_priv = dev->dev_private; | 722 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 723 | int i; | 723 | int i, ret; |
| 724 | 724 | ||
| 725 | if (flush_domains & I915_GEM_DOMAIN_CPU) | 725 | if (flush_domains & I915_GEM_DOMAIN_CPU) |
| 726 | intel_gtt_chipset_flush(); | 726 | intel_gtt_chipset_flush(); |
| @@ -730,11 +730,17 @@ i915_gem_execbuffer_flush(struct drm_device *dev, | |||
| 730 | 730 | ||
| 731 | if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { | 731 | if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { |
| 732 | for (i = 0; i < I915_NUM_RINGS; i++) | 732 | for (i = 0; i < I915_NUM_RINGS; i++) |
| 733 | if (flush_rings & (1 << i)) | 733 | if (flush_rings & (1 << i)) { |
| 734 | i915_gem_flush_ring(dev, &dev_priv->ring[i], | 734 | ret = i915_gem_flush_ring(dev, |
| 735 | invalidate_domains, | 735 | &dev_priv->ring[i], |
| 736 | flush_domains); | 736 | invalidate_domains, |
| 737 | flush_domains); | ||
| 738 | if (ret) | ||
| 739 | return ret; | ||
| 740 | } | ||
| 737 | } | 741 | } |
| 742 | |||
| 743 | return 0; | ||
| 738 | } | 744 | } |
| 739 | 745 | ||
| 740 | static int | 746 | static int |
| @@ -798,10 +804,12 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, | |||
| 798 | cd.invalidate_domains, | 804 | cd.invalidate_domains, |
| 799 | cd.flush_domains); | 805 | cd.flush_domains); |
| 800 | #endif | 806 | #endif |
| 801 | i915_gem_execbuffer_flush(ring->dev, | 807 | ret = i915_gem_execbuffer_flush(ring->dev, |
| 802 | cd.invalidate_domains, | 808 | cd.invalidate_domains, |
| 803 | cd.flush_domains, | 809 | cd.flush_domains, |
| 804 | cd.flush_rings); | 810 | cd.flush_rings); |
| 811 | if (ret) | ||
| 812 | return ret; | ||
| 805 | } | 813 | } |
| 806 | 814 | ||
| 807 | list_for_each_entry(obj, objects, exec_list) { | 815 | list_for_each_entry(obj, objects, exec_list) { |
