diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 156 |
1 files changed, 110 insertions, 46 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c79c0b62ef60..3dfc848ff755 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, |
@@ -1935,6 +1935,8 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
1935 | { | 1935 | { |
1936 | drm_i915_private_t *dev_priv; | 1936 | drm_i915_private_t *dev_priv; |
1937 | struct drm_device *dev; | 1937 | struct drm_device *dev; |
1938 | bool idle; | ||
1939 | int i; | ||
1938 | 1940 | ||
1939 | dev_priv = container_of(work, drm_i915_private_t, | 1941 | dev_priv = container_of(work, drm_i915_private_t, |
1940 | mm.retire_work.work); | 1942 | mm.retire_work.work); |
@@ -1948,11 +1950,31 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
1948 | 1950 | ||
1949 | i915_gem_retire_requests(dev); | 1951 | i915_gem_retire_requests(dev); |
1950 | 1952 | ||
1951 | if (!dev_priv->mm.suspended && | 1953 | /* Send a periodic flush down the ring so we don't hold onto GEM |
1952 | (!list_empty(&dev_priv->ring[RCS].request_list) || | 1954 | * objects indefinitely. |
1953 | !list_empty(&dev_priv->ring[VCS].request_list) || | 1955 | */ |
1954 | !list_empty(&dev_priv->ring[BCS].request_list))) | 1956 | idle = true; |
1957 | for (i = 0; i < I915_NUM_RINGS; i++) { | ||
1958 | struct intel_ring_buffer *ring = &dev_priv->ring[i]; | ||
1959 | |||
1960 | if (!list_empty(&ring->gpu_write_list)) { | ||
1961 | struct drm_i915_gem_request *request; | ||
1962 | int ret; | ||
1963 | |||
1964 | ret = i915_gem_flush_ring(dev, ring, 0, | ||
1965 | I915_GEM_GPU_DOMAINS); | ||
1966 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
1967 | if (ret || request == NULL || | ||
1968 | i915_add_request(dev, NULL, request, ring)) | ||
1969 | kfree(request); | ||
1970 | } | ||
1971 | |||
1972 | idle &= list_empty(&ring->request_list); | ||
1973 | } | ||
1974 | |||
1975 | if (!dev_priv->mm.suspended && !idle) | ||
1955 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); | 1976 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); |
1977 | |||
1956 | mutex_unlock(&dev->struct_mutex); | 1978 | mutex_unlock(&dev->struct_mutex); |
1957 | } | 1979 | } |
1958 | 1980 | ||
@@ -2142,25 +2164,37 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj) | |||
2142 | return ret; | 2164 | return ret; |
2143 | } | 2165 | } |
2144 | 2166 | ||
2145 | void | 2167 | int |
2146 | i915_gem_flush_ring(struct drm_device *dev, | 2168 | i915_gem_flush_ring(struct drm_device *dev, |
2147 | struct intel_ring_buffer *ring, | 2169 | struct intel_ring_buffer *ring, |
2148 | uint32_t invalidate_domains, | 2170 | uint32_t invalidate_domains, |
2149 | uint32_t flush_domains) | 2171 | uint32_t flush_domains) |
2150 | { | 2172 | { |
2151 | ring->flush(ring, invalidate_domains, flush_domains); | 2173 | int ret; |
2174 | |||
2175 | ret = ring->flush(ring, invalidate_domains, flush_domains); | ||
2176 | if (ret) | ||
2177 | return ret; | ||
2178 | |||
2152 | i915_gem_process_flushing_list(dev, flush_domains, ring); | 2179 | i915_gem_process_flushing_list(dev, flush_domains, ring); |
2180 | return 0; | ||
2153 | } | 2181 | } |
2154 | 2182 | ||
2155 | static int i915_ring_idle(struct drm_device *dev, | 2183 | static int i915_ring_idle(struct drm_device *dev, |
2156 | struct intel_ring_buffer *ring) | 2184 | struct intel_ring_buffer *ring) |
2157 | { | 2185 | { |
2186 | int ret; | ||
2187 | |||
2158 | if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list)) | 2188 | if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list)) |
2159 | return 0; | 2189 | return 0; |
2160 | 2190 | ||
2161 | if (!list_empty(&ring->gpu_write_list)) | 2191 | if (!list_empty(&ring->gpu_write_list)) { |
2162 | i915_gem_flush_ring(dev, ring, | 2192 | ret = i915_gem_flush_ring(dev, ring, |
2163 | I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); | 2193 | I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); |
2194 | if (ret) | ||
2195 | return ret; | ||
2196 | } | ||
2197 | |||
2164 | return i915_wait_request(dev, | 2198 | return i915_wait_request(dev, |
2165 | i915_gem_next_request_seqno(dev, ring), | 2199 | i915_gem_next_request_seqno(dev, ring), |
2166 | ring); | 2200 | ring); |
@@ -2370,10 +2404,13 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj, | |||
2370 | int ret; | 2404 | int ret; |
2371 | 2405 | ||
2372 | if (obj->fenced_gpu_access) { | 2406 | if (obj->fenced_gpu_access) { |
2373 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) | 2407 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
2374 | i915_gem_flush_ring(obj->base.dev, | 2408 | ret = i915_gem_flush_ring(obj->base.dev, |
2375 | obj->last_fenced_ring, | 2409 | obj->last_fenced_ring, |
2376 | 0, obj->base.write_domain); | 2410 | 0, obj->base.write_domain); |
2411 | if (ret) | ||
2412 | return ret; | ||
2413 | } | ||
2377 | 2414 | ||
2378 | obj->fenced_gpu_access = false; | 2415 | obj->fenced_gpu_access = false; |
2379 | } | 2416 | } |
@@ -2393,6 +2430,12 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj, | |||
2393 | obj->last_fenced_ring = NULL; | 2430 | obj->last_fenced_ring = NULL; |
2394 | } | 2431 | } |
2395 | 2432 | ||
2433 | /* Ensure that all CPU reads are completed before installing a fence | ||
2434 | * and all writes before removing the fence. | ||
2435 | */ | ||
2436 | if (obj->base.read_domains & I915_GEM_DOMAIN_GTT) | ||
2437 | mb(); | ||
2438 | |||
2396 | return 0; | 2439 | return 0; |
2397 | } | 2440 | } |
2398 | 2441 | ||
@@ -2523,9 +2566,12 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | |||
2523 | return ret; | 2566 | return ret; |
2524 | } else if (obj->tiling_changed) { | 2567 | } else if (obj->tiling_changed) { |
2525 | if (obj->fenced_gpu_access) { | 2568 | if (obj->fenced_gpu_access) { |
2526 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) | 2569 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
2527 | i915_gem_flush_ring(obj->base.dev, obj->ring, | 2570 | ret = i915_gem_flush_ring(obj->base.dev, obj->ring, |
2528 | 0, obj->base.write_domain); | 2571 | 0, obj->base.write_domain); |
2572 | if (ret) | ||
2573 | return ret; | ||
2574 | } | ||
2529 | 2575 | ||
2530 | obj->fenced_gpu_access = false; | 2576 | obj->fenced_gpu_access = false; |
2531 | } | 2577 | } |
@@ -2736,10 +2782,8 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
2736 | obj->gtt_space = NULL; | 2782 | obj->gtt_space = NULL; |
2737 | 2783 | ||
2738 | if (ret == -ENOMEM) { | 2784 | if (ret == -ENOMEM) { |
2739 | /* first try to clear up some space from the GTT */ | 2785 | /* first try to reclaim some memory by clearing the GTT */ |
2740 | ret = i915_gem_evict_something(dev, size, | 2786 | ret = i915_gem_evict_everything(dev, false); |
2741 | alignment, | ||
2742 | map_and_fenceable); | ||
2743 | if (ret) { | 2787 | if (ret) { |
2744 | /* now try to shrink everyone else */ | 2788 | /* now try to shrink everyone else */ |
2745 | if (gfpmask) { | 2789 | if (gfpmask) { |
@@ -2747,7 +2791,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
2747 | goto search_free; | 2791 | goto search_free; |
2748 | } | 2792 | } |
2749 | 2793 | ||
2750 | return ret; | 2794 | return -ENOMEM; |
2751 | } | 2795 | } |
2752 | 2796 | ||
2753 | goto search_free; | 2797 | goto search_free; |
@@ -2762,9 +2806,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
2762 | drm_mm_put_block(obj->gtt_space); | 2806 | drm_mm_put_block(obj->gtt_space); |
2763 | obj->gtt_space = NULL; | 2807 | obj->gtt_space = NULL; |
2764 | 2808 | ||
2765 | ret = i915_gem_evict_something(dev, size, | 2809 | if (i915_gem_evict_everything(dev, false)) |
2766 | alignment, map_and_fenceable); | ||
2767 | if (ret) | ||
2768 | return ret; | 2810 | return ret; |
2769 | 2811 | ||
2770 | goto search_free; | 2812 | goto search_free; |
@@ -2811,17 +2853,16 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj) | |||
2811 | } | 2853 | } |
2812 | 2854 | ||
2813 | /** Flushes any GPU write domain for the object if it's dirty. */ | 2855 | /** Flushes any GPU write domain for the object if it's dirty. */ |
2814 | static void | 2856 | static int |
2815 | i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj) | 2857 | i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj) |
2816 | { | 2858 | { |
2817 | struct drm_device *dev = obj->base.dev; | 2859 | struct drm_device *dev = obj->base.dev; |
2818 | 2860 | ||
2819 | if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) | 2861 | if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) |
2820 | return; | 2862 | return 0; |
2821 | 2863 | ||
2822 | /* Queue the GPU write cache flushing we need. */ | 2864 | /* Queue the GPU write cache flushing we need. */ |
2823 | i915_gem_flush_ring(dev, obj->ring, 0, obj->base.write_domain); | 2865 | return i915_gem_flush_ring(dev, obj->ring, 0, obj->base.write_domain); |
2824 | BUG_ON(obj->base.write_domain); | ||
2825 | } | 2866 | } |
2826 | 2867 | ||
2827 | /** Flushes the GTT write domain for the object if it's dirty. */ | 2868 | /** Flushes the GTT write domain for the object if it's dirty. */ |
@@ -2833,10 +2874,16 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj) | |||
2833 | if (obj->base.write_domain != I915_GEM_DOMAIN_GTT) | 2874 | if (obj->base.write_domain != I915_GEM_DOMAIN_GTT) |
2834 | return; | 2875 | return; |
2835 | 2876 | ||
2836 | /* No actual flushing is required for the GTT write domain. Writes | 2877 | /* No actual flushing is required for the GTT write domain. Writes |
2837 | * to it immediately go to main memory as far as we know, so there's | 2878 | * to it immediately go to main memory as far as we know, so there's |
2838 | * no chipset flush. It also doesn't land in render cache. | 2879 | * no chipset flush. It also doesn't land in render cache. |
2880 | * | ||
2881 | * However, we do have to enforce the order so that all writes through | ||
2882 | * the GTT land before any writes to the device, such as updates to | ||
2883 | * the GATT itself. | ||
2839 | */ | 2884 | */ |
2885 | wmb(); | ||
2886 | |||
2840 | i915_gem_release_mmap(obj); | 2887 | i915_gem_release_mmap(obj); |
2841 | 2888 | ||
2842 | old_write_domain = obj->base.write_domain; | 2889 | old_write_domain = obj->base.write_domain; |
@@ -2882,7 +2929,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) | |||
2882 | if (obj->gtt_space == NULL) | 2929 | if (obj->gtt_space == NULL) |
2883 | return -EINVAL; | 2930 | return -EINVAL; |
2884 | 2931 | ||
2885 | i915_gem_object_flush_gpu_write_domain(obj); | 2932 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
2933 | if (ret) | ||
2934 | return ret; | ||
2935 | |||
2886 | if (obj->pending_gpu_write || write) { | 2936 | if (obj->pending_gpu_write || write) { |
2887 | ret = i915_gem_object_wait_rendering(obj, true); | 2937 | ret = i915_gem_object_wait_rendering(obj, true); |
2888 | if (ret) | 2938 | if (ret) |
@@ -2927,7 +2977,10 @@ i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj, | |||
2927 | if (obj->gtt_space == NULL) | 2977 | if (obj->gtt_space == NULL) |
2928 | return -EINVAL; | 2978 | return -EINVAL; |
2929 | 2979 | ||
2930 | i915_gem_object_flush_gpu_write_domain(obj); | 2980 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
2981 | if (ret) | ||
2982 | return ret; | ||
2983 | |||
2931 | 2984 | ||
2932 | /* Currently, we are always called from an non-interruptible context. */ | 2985 | /* Currently, we are always called from an non-interruptible context. */ |
2933 | if (pipelined != obj->ring) { | 2986 | if (pipelined != obj->ring) { |
@@ -2952,12 +3005,17 @@ int | |||
2952 | i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, | 3005 | i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, |
2953 | bool interruptible) | 3006 | bool interruptible) |
2954 | { | 3007 | { |
3008 | int ret; | ||
3009 | |||
2955 | if (!obj->active) | 3010 | if (!obj->active) |
2956 | return 0; | 3011 | return 0; |
2957 | 3012 | ||
2958 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) | 3013 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
2959 | i915_gem_flush_ring(obj->base.dev, obj->ring, | 3014 | ret = i915_gem_flush_ring(obj->base.dev, obj->ring, |
2960 | 0, obj->base.write_domain); | 3015 | 0, obj->base.write_domain); |
3016 | if (ret) | ||
3017 | return ret; | ||
3018 | } | ||
2961 | 3019 | ||
2962 | return i915_gem_object_wait_rendering(obj, interruptible); | 3020 | return i915_gem_object_wait_rendering(obj, interruptible); |
2963 | } | 3021 | } |
@@ -2974,7 +3032,10 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write) | |||
2974 | uint32_t old_write_domain, old_read_domains; | 3032 | uint32_t old_write_domain, old_read_domains; |
2975 | int ret; | 3033 | int ret; |
2976 | 3034 | ||
2977 | i915_gem_object_flush_gpu_write_domain(obj); | 3035 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
3036 | if (ret) | ||
3037 | return ret; | ||
3038 | |||
2978 | ret = i915_gem_object_wait_rendering(obj, true); | 3039 | ret = i915_gem_object_wait_rendering(obj, true); |
2979 | if (ret) | 3040 | if (ret) |
2980 | return ret; | 3041 | return ret; |
@@ -3069,7 +3130,10 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj, | |||
3069 | if (offset == 0 && size == obj->base.size) | 3130 | if (offset == 0 && size == obj->base.size) |
3070 | return i915_gem_object_set_to_cpu_domain(obj, 0); | 3131 | return i915_gem_object_set_to_cpu_domain(obj, 0); |
3071 | 3132 | ||
3072 | i915_gem_object_flush_gpu_write_domain(obj); | 3133 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
3134 | if (ret) | ||
3135 | return ret; | ||
3136 | |||
3073 | ret = i915_gem_object_wait_rendering(obj, true); | 3137 | ret = i915_gem_object_wait_rendering(obj, true); |
3074 | if (ret) | 3138 | if (ret) |
3075 | return ret; | 3139 | return ret; |
@@ -3362,8 +3426,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
3362 | * flush earlier is beneficial. | 3426 | * flush earlier is beneficial. |
3363 | */ | 3427 | */ |
3364 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { | 3428 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
3365 | i915_gem_flush_ring(dev, obj->ring, | 3429 | ret = i915_gem_flush_ring(dev, obj->ring, |
3366 | 0, obj->base.write_domain); | 3430 | 0, obj->base.write_domain); |
3367 | } else if (obj->ring->outstanding_lazy_request == | 3431 | } else if (obj->ring->outstanding_lazy_request == |
3368 | obj->last_rendering_seqno) { | 3432 | obj->last_rendering_seqno) { |
3369 | struct drm_i915_gem_request *request; | 3433 | struct drm_i915_gem_request *request; |