summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-08-16 03:46:35 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2019-08-16 04:51:11 -0400
commit8e7cb1799b4f8bde3e7d9c80bf689e5408add271 (patch)
tree16dfa5a166b59520734e411c14ec0f403bd35c26
parente5dadff4b09376e8ed92ecc0c12f1b9b3b1fbd19 (diff)
drm/i915: Extract intel_frontbuffer active tracking
Move the active tracking for the frontbuffer operations out of the i915_gem_object and into its own first class (refcounted) object. In the process of detangling, we switch from low level request tracking to the easier i915_active -- with the plan that this avoids any potential atomic callbacks as the frontbuffer tracking wishes to sleep as it flushes. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190816074635.26062-1-chris@chris-wilson.co.uk
-rw-r--r--Documentation/gpu/i915.rst3
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c70
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbdev.c40
-rw-r--r--drivers/gpu/drm/i915/display/intel_frontbuffer.c255
-rw-r--r--drivers/gpu/drm/i915/display/intel_frontbuffer.h70
-rw-r--r--drivers/gpu/drm/i915/display/intel_overlay.c8
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_clflush.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_domain.c14
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_mman.c4
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.c27
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.h2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object_types.h8
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c5
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h4
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c47
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c6
17 files changed, 306 insertions, 260 deletions
diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 0e322688be5c..3415255ad3dc 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -91,9 +91,6 @@ Frontbuffer Tracking
91.. kernel-doc:: drivers/gpu/drm/i915/display/intel_frontbuffer.c 91.. kernel-doc:: drivers/gpu/drm/i915/display/intel_frontbuffer.c
92 :internal: 92 :internal:
93 93
94.. kernel-doc:: drivers/gpu/drm/i915/i915_gem.c
95 :functions: i915_gem_track_fb
96
97Display FIFO Underrun Reporting 94Display FIFO Underrun Reporting
98------------------------------- 95-------------------------------
99 96
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 3916c697ffab..59e1988dd362 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3049,12 +3049,13 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
3049{ 3049{
3050 struct drm_device *dev = crtc->base.dev; 3050 struct drm_device *dev = crtc->base.dev;
3051 struct drm_i915_private *dev_priv = to_i915(dev); 3051 struct drm_i915_private *dev_priv = to_i915(dev);
3052 struct drm_i915_gem_object *obj = NULL;
3053 struct drm_mode_fb_cmd2 mode_cmd = { 0 }; 3052 struct drm_mode_fb_cmd2 mode_cmd = { 0 };
3054 struct drm_framebuffer *fb = &plane_config->fb->base; 3053 struct drm_framebuffer *fb = &plane_config->fb->base;
3055 u32 base_aligned = round_down(plane_config->base, PAGE_SIZE); 3054 u32 base_aligned = round_down(plane_config->base, PAGE_SIZE);
3056 u32 size_aligned = round_up(plane_config->base + plane_config->size, 3055 u32 size_aligned = round_up(plane_config->base + plane_config->size,
3057 PAGE_SIZE); 3056 PAGE_SIZE);
3057 struct drm_i915_gem_object *obj;
3058 bool ret = false;
3058 3059
3059 size_aligned -= base_aligned; 3060 size_aligned -= base_aligned;
3060 3061
@@ -3096,7 +3097,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
3096 break; 3097 break;
3097 default: 3098 default:
3098 MISSING_CASE(plane_config->tiling); 3099 MISSING_CASE(plane_config->tiling);
3099 return false; 3100 goto out;
3100 } 3101 }
3101 3102
3102 mode_cmd.pixel_format = fb->format->format; 3103 mode_cmd.pixel_format = fb->format->format;
@@ -3108,16 +3109,15 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
3108 3109
3109 if (intel_framebuffer_init(to_intel_framebuffer(fb), obj, &mode_cmd)) { 3110 if (intel_framebuffer_init(to_intel_framebuffer(fb), obj, &mode_cmd)) {
3110 DRM_DEBUG_KMS("intel fb init failed\n"); 3111 DRM_DEBUG_KMS("intel fb init failed\n");
3111 goto out_unref_obj; 3112 goto out;
3112 } 3113 }
3113 3114
3114 3115
3115 DRM_DEBUG_KMS("initial plane fb obj %p\n", obj); 3116 DRM_DEBUG_KMS("initial plane fb obj %p\n", obj);
3116 return true; 3117 ret = true;
3117 3118out:
3118out_unref_obj:
3119 i915_gem_object_put(obj); 3119 i915_gem_object_put(obj);
3120 return false; 3120 return ret;
3121} 3121}
3122 3122
3123static void 3123static void
@@ -3174,6 +3174,12 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
3174 intel_disable_plane(plane, crtc_state); 3174 intel_disable_plane(plane, crtc_state);
3175} 3175}
3176 3176
3177static struct intel_frontbuffer *
3178to_intel_frontbuffer(struct drm_framebuffer *fb)
3179{
3180 return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
3181}
3182
3177static void 3183static void
3178intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, 3184intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
3179 struct intel_initial_plane_config *plane_config) 3185 struct intel_initial_plane_config *plane_config)
@@ -3181,7 +3187,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
3181 struct drm_device *dev = intel_crtc->base.dev; 3187 struct drm_device *dev = intel_crtc->base.dev;
3182 struct drm_i915_private *dev_priv = to_i915(dev); 3188 struct drm_i915_private *dev_priv = to_i915(dev);
3183 struct drm_crtc *c; 3189 struct drm_crtc *c;
3184 struct drm_i915_gem_object *obj;
3185 struct drm_plane *primary = intel_crtc->base.primary; 3190 struct drm_plane *primary = intel_crtc->base.primary;
3186 struct drm_plane_state *plane_state = primary->state; 3191 struct drm_plane_state *plane_state = primary->state;
3187 struct intel_plane *intel_plane = to_intel_plane(primary); 3192 struct intel_plane *intel_plane = to_intel_plane(primary);
@@ -3257,8 +3262,7 @@ valid_fb:
3257 return; 3262 return;
3258 } 3263 }
3259 3264
3260 obj = intel_fb_obj(fb); 3265 intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB);
3261 intel_fb_obj_flush(obj, ORIGIN_DIRTYFB);
3262 3266
3263 plane_state->src_x = 0; 3267 plane_state->src_x = 0;
3264 plane_state->src_y = 0; 3268 plane_state->src_y = 0;
@@ -3273,14 +3277,14 @@ valid_fb:
3273 intel_state->base.src = drm_plane_state_src(plane_state); 3277 intel_state->base.src = drm_plane_state_src(plane_state);
3274 intel_state->base.dst = drm_plane_state_dest(plane_state); 3278 intel_state->base.dst = drm_plane_state_dest(plane_state);
3275 3279
3276 if (i915_gem_object_is_tiled(obj)) 3280 if (plane_config->tiling)
3277 dev_priv->preserve_bios_swizzle = true; 3281 dev_priv->preserve_bios_swizzle = true;
3278 3282
3279 plane_state->fb = fb; 3283 plane_state->fb = fb;
3280 plane_state->crtc = &intel_crtc->base; 3284 plane_state->crtc = &intel_crtc->base;
3281 3285
3282 atomic_or(to_intel_plane(primary)->frontbuffer_bit, 3286 atomic_or(to_intel_plane(primary)->frontbuffer_bit,
3283 &obj->frontbuffer_bits); 3287 &to_intel_frontbuffer(fb)->bits);
3284} 3288}
3285 3289
3286static int skl_max_plane_width(const struct drm_framebuffer *fb, 3290static int skl_max_plane_width(const struct drm_framebuffer *fb,
@@ -14132,9 +14136,9 @@ static void intel_atomic_track_fbs(struct intel_atomic_state *state)
14132 14136
14133 for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state, 14137 for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
14134 new_plane_state, i) 14138 new_plane_state, i)
14135 i915_gem_track_fb(intel_fb_obj(old_plane_state->base.fb), 14139 intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->base.fb),
14136 intel_fb_obj(new_plane_state->base.fb), 14140 to_intel_frontbuffer(new_plane_state->base.fb),
14137 plane->frontbuffer_bit); 14141 plane->frontbuffer_bit);
14138} 14142}
14139 14143
14140static int intel_atomic_commit(struct drm_device *dev, 14144static int intel_atomic_commit(struct drm_device *dev,
@@ -14418,7 +14422,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
14418 return ret; 14422 return ret;
14419 14423
14420 fb_obj_bump_render_priority(obj); 14424 fb_obj_bump_render_priority(obj);
14421 intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); 14425 intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB);
14422 14426
14423 if (!new_state->fence) { /* implicit fencing */ 14427 if (!new_state->fence) { /* implicit fencing */
14424 struct dma_fence *fence; 14428 struct dma_fence *fence;
@@ -14681,13 +14685,12 @@ intel_legacy_cursor_update(struct drm_plane *plane,
14681 struct drm_modeset_acquire_ctx *ctx) 14685 struct drm_modeset_acquire_ctx *ctx)
14682{ 14686{
14683 struct drm_i915_private *dev_priv = to_i915(crtc->dev); 14687 struct drm_i915_private *dev_priv = to_i915(crtc->dev);
14684 int ret;
14685 struct drm_plane_state *old_plane_state, *new_plane_state; 14688 struct drm_plane_state *old_plane_state, *new_plane_state;
14686 struct intel_plane *intel_plane = to_intel_plane(plane); 14689 struct intel_plane *intel_plane = to_intel_plane(plane);
14687 struct drm_framebuffer *old_fb;
14688 struct intel_crtc_state *crtc_state = 14690 struct intel_crtc_state *crtc_state =
14689 to_intel_crtc_state(crtc->state); 14691 to_intel_crtc_state(crtc->state);
14690 struct intel_crtc_state *new_crtc_state; 14692 struct intel_crtc_state *new_crtc_state;
14693 int ret;
14691 14694
14692 /* 14695 /*
14693 * When crtc is inactive or there is a modeset pending, 14696 * When crtc is inactive or there is a modeset pending,
@@ -14755,11 +14758,10 @@ intel_legacy_cursor_update(struct drm_plane *plane,
14755 if (ret) 14758 if (ret)
14756 goto out_unlock; 14759 goto out_unlock;
14757 14760
14758 intel_fb_obj_flush(intel_fb_obj(fb), ORIGIN_FLIP); 14761 intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_FLIP);
14759 14762 intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->fb),
14760 old_fb = old_plane_state->fb; 14763 to_intel_frontbuffer(fb),
14761 i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb), 14764 intel_plane->frontbuffer_bit);
14762 intel_plane->frontbuffer_bit);
14763 14765
14764 /* Swap plane state */ 14766 /* Swap plane state */
14765 plane->state = new_plane_state; 14767 plane->state = new_plane_state;
@@ -15540,15 +15542,9 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
15540static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) 15542static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
15541{ 15543{
15542 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 15544 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
15543 struct drm_i915_gem_object *obj = intel_fb_obj(fb);
15544 15545
15545 drm_framebuffer_cleanup(fb); 15546 drm_framebuffer_cleanup(fb);
15546 15547 intel_frontbuffer_put(intel_fb->frontbuffer);
15547 i915_gem_object_lock(obj);
15548 WARN_ON(!obj->framebuffer_references--);
15549 i915_gem_object_unlock(obj);
15550
15551 i915_gem_object_put(obj);
15552 15548
15553 kfree(intel_fb); 15549 kfree(intel_fb);
15554} 15550}
@@ -15576,7 +15572,7 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
15576 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 15572 struct drm_i915_gem_object *obj = intel_fb_obj(fb);
15577 15573
15578 i915_gem_object_flush_if_display(obj); 15574 i915_gem_object_flush_if_display(obj);
15579 intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); 15575 intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB);
15580 15576
15581 return 0; 15577 return 0;
15582} 15578}
@@ -15598,8 +15594,11 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
15598 int ret = -EINVAL; 15594 int ret = -EINVAL;
15599 int i; 15595 int i;
15600 15596
15597 intel_fb->frontbuffer = intel_frontbuffer_get(obj);
15598 if (!intel_fb->frontbuffer)
15599 return -ENOMEM;
15600
15601 i915_gem_object_lock(obj); 15601 i915_gem_object_lock(obj);
15602 obj->framebuffer_references++;
15603 tiling = i915_gem_object_get_tiling(obj); 15602 tiling = i915_gem_object_get_tiling(obj);
15604 stride = i915_gem_object_get_stride(obj); 15603 stride = i915_gem_object_get_stride(obj);
15605 i915_gem_object_unlock(obj); 15604 i915_gem_object_unlock(obj);
@@ -15716,9 +15715,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
15716 return 0; 15715 return 0;
15717 15716
15718err: 15717err:
15719 i915_gem_object_lock(obj); 15718 intel_frontbuffer_put(intel_fb->frontbuffer);
15720 obj->framebuffer_references--;
15721 i915_gem_object_unlock(obj);
15722 return ret; 15719 return ret;
15723} 15720}
15724 15721
@@ -15736,8 +15733,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
15736 return ERR_PTR(-ENOENT); 15733 return ERR_PTR(-ENOENT);
15737 15734
15738 fb = intel_framebuffer_create(obj, &mode_cmd); 15735 fb = intel_framebuffer_create(obj, &mode_cmd);
15739 if (IS_ERR(fb)) 15736 i915_gem_object_put(obj);
15740 i915_gem_object_put(obj);
15741 15737
15742 return fb; 15738 return fb;
15743} 15739}
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index a88ec9aa9ca0..3c1a5f3e1d22 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -84,6 +84,7 @@ enum intel_broadcast_rgb {
84 84
85struct intel_framebuffer { 85struct intel_framebuffer {
86 struct drm_framebuffer base; 86 struct drm_framebuffer base;
87 struct intel_frontbuffer *frontbuffer;
87 struct intel_rotation_info rot_info; 88 struct intel_rotation_info rot_info;
88 89
89 /* for each plane in the normal GTT view */ 90 /* for each plane in the normal GTT view */
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index 2d74c33a504d..d59eee5c5d9c 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -47,13 +47,14 @@
47#include "intel_fbdev.h" 47#include "intel_fbdev.h"
48#include "intel_frontbuffer.h" 48#include "intel_frontbuffer.h"
49 49
50static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev) 50static struct intel_frontbuffer *to_frontbuffer(struct intel_fbdev *ifbdev)
51{ 51{
52 struct drm_i915_gem_object *obj = intel_fb_obj(&ifbdev->fb->base); 52 return ifbdev->fb->frontbuffer;
53 unsigned int origin = 53}
54 ifbdev->vma_flags & PLANE_HAS_FENCE ? ORIGIN_GTT : ORIGIN_CPU;
55 54
56 intel_fb_obj_invalidate(obj, origin); 55static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
56{
57 intel_frontbuffer_invalidate(to_frontbuffer(ifbdev), ORIGIN_CPU);
57} 58}
58 59
59static int intel_fbdev_set_par(struct fb_info *info) 60static int intel_fbdev_set_par(struct fb_info *info)
@@ -120,7 +121,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
120 struct drm_i915_private *dev_priv = to_i915(dev); 121 struct drm_i915_private *dev_priv = to_i915(dev);
121 struct drm_mode_fb_cmd2 mode_cmd = {}; 122 struct drm_mode_fb_cmd2 mode_cmd = {};
122 struct drm_i915_gem_object *obj; 123 struct drm_i915_gem_object *obj;
123 int size, ret; 124 int size;
124 125
125 /* we don't do packed 24bpp */ 126 /* we don't do packed 24bpp */
126 if (sizes->surface_bpp == 24) 127 if (sizes->surface_bpp == 24)
@@ -147,24 +148,16 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
147 obj = i915_gem_object_create_shmem(dev_priv, size); 148 obj = i915_gem_object_create_shmem(dev_priv, size);
148 if (IS_ERR(obj)) { 149 if (IS_ERR(obj)) {
149 DRM_ERROR("failed to allocate framebuffer\n"); 150 DRM_ERROR("failed to allocate framebuffer\n");
150 ret = PTR_ERR(obj); 151 return PTR_ERR(obj);
151 goto err;
152 } 152 }
153 153
154 fb = intel_framebuffer_create(obj, &mode_cmd); 154 fb = intel_framebuffer_create(obj, &mode_cmd);
155 if (IS_ERR(fb)) { 155 i915_gem_object_put(obj);
156 ret = PTR_ERR(fb); 156 if (IS_ERR(fb))
157 goto err_obj; 157 return PTR_ERR(fb);
158 }
159 158
160 ifbdev->fb = to_intel_framebuffer(fb); 159 ifbdev->fb = to_intel_framebuffer(fb);
161
162 return 0; 160 return 0;
163
164err_obj:
165 i915_gem_object_put(obj);
166err:
167 return ret;
168} 161}
169 162
170static int intelfb_create(struct drm_fb_helper *helper, 163static int intelfb_create(struct drm_fb_helper *helper,
@@ -180,7 +173,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
180 const struct i915_ggtt_view view = { 173 const struct i915_ggtt_view view = {
181 .type = I915_GGTT_VIEW_NORMAL, 174 .type = I915_GGTT_VIEW_NORMAL,
182 }; 175 };
183 struct drm_framebuffer *fb;
184 intel_wakeref_t wakeref; 176 intel_wakeref_t wakeref;
185 struct fb_info *info; 177 struct fb_info *info;
186 struct i915_vma *vma; 178 struct i915_vma *vma;
@@ -226,8 +218,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
226 goto out_unlock; 218 goto out_unlock;
227 } 219 }
228 220
229 fb = &ifbdev->fb->base; 221 intel_frontbuffer_flush(to_frontbuffer(ifbdev), ORIGIN_DIRTYFB);
230 intel_fb_obj_flush(intel_fb_obj(fb), ORIGIN_DIRTYFB);
231 222
232 info = drm_fb_helper_alloc_fbi(helper); 223 info = drm_fb_helper_alloc_fbi(helper);
233 if (IS_ERR(info)) { 224 if (IS_ERR(info)) {
@@ -236,7 +227,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
236 goto out_unpin; 227 goto out_unpin;
237 } 228 }
238 229
239 ifbdev->helper.fb = fb; 230 ifbdev->helper.fb = &ifbdev->fb->base;
240 231
241 info->fbops = &intelfb_ops; 232 info->fbops = &intelfb_ops;
242 233
@@ -263,13 +254,14 @@ static int intelfb_create(struct drm_fb_helper *helper,
263 * If the object is stolen however, it will be full of whatever 254 * If the object is stolen however, it will be full of whatever
264 * garbage was left in there. 255 * garbage was left in there.
265 */ 256 */
266 if (intel_fb_obj(fb)->stolen && !prealloc) 257 if (vma->obj->stolen && !prealloc)
267 memset_io(info->screen_base, 0, info->screen_size); 258 memset_io(info->screen_base, 0, info->screen_size);
268 259
269 /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ 260 /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
270 261
271 DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n", 262 DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n",
272 fb->width, fb->height, i915_ggtt_offset(vma)); 263 ifbdev->fb->base.width, ifbdev->fb->base.height,
264 i915_ggtt_offset(vma));
273 ifbdev->vma = vma; 265 ifbdev->vma = vma;
274 ifbdev->vma_flags = flags; 266 ifbdev->vma_flags = flags;
275 267
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
index 9cda88e41d29..719379774fa5 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
@@ -30,11 +30,11 @@
30 * Many features require us to track changes to the currently active 30 * Many features require us to track changes to the currently active
31 * frontbuffer, especially rendering targeted at the frontbuffer. 31 * frontbuffer, especially rendering targeted at the frontbuffer.
32 * 32 *
33 * To be able to do so GEM tracks frontbuffers using a bitmask for all possible 33 * To be able to do so we track frontbuffers using a bitmask for all possible
34 * frontbuffer slots through i915_gem_track_fb(). The function in this file are 34 * frontbuffer slots through intel_frontbuffer_track(). The functions in this
35 * then called when the contents of the frontbuffer are invalidated, when 35 * file are then called when the contents of the frontbuffer are invalidated,
36 * frontbuffer rendering has stopped again to flush out all the changes and when 36 * when frontbuffer rendering has stopped again to flush out all the changes
37 * the frontbuffer is exchanged with a flip. Subsystems interested in 37 * and when the frontbuffer is exchanged with a flip. Subsystems interested in
38 * frontbuffer changes (e.g. PSR, FBC, DRRS) should directly put their callbacks 38 * frontbuffer changes (e.g. PSR, FBC, DRRS) should directly put their callbacks
39 * into the relevant places and filter for the frontbuffer slots that they are 39 * into the relevant places and filter for the frontbuffer slots that they are
40 * interested int. 40 * interested int.
@@ -63,28 +63,9 @@
63#include "intel_frontbuffer.h" 63#include "intel_frontbuffer.h"
64#include "intel_psr.h" 64#include "intel_psr.h"
65 65
66void __intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
67 enum fb_op_origin origin,
68 unsigned int frontbuffer_bits)
69{
70 struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
71
72 if (origin == ORIGIN_CS) {
73 spin_lock(&dev_priv->fb_tracking.lock);
74 dev_priv->fb_tracking.busy_bits |= frontbuffer_bits;
75 dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits;
76 spin_unlock(&dev_priv->fb_tracking.lock);
77 }
78
79 might_sleep();
80 intel_psr_invalidate(dev_priv, frontbuffer_bits, origin);
81 intel_edp_drrs_invalidate(dev_priv, frontbuffer_bits);
82 intel_fbc_invalidate(dev_priv, frontbuffer_bits, origin);
83}
84
85/** 66/**
86 * intel_frontbuffer_flush - flush frontbuffer 67 * frontbuffer_flush - flush frontbuffer
87 * @dev_priv: i915 device 68 * @i915: i915 device
88 * @frontbuffer_bits: frontbuffer plane tracking bits 69 * @frontbuffer_bits: frontbuffer plane tracking bits
89 * @origin: which operation caused the flush 70 * @origin: which operation caused the flush
90 * 71 *
@@ -94,45 +75,27 @@ void __intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
94 * 75 *
95 * Can be called without any locks held. 76 * Can be called without any locks held.
96 */ 77 */
97static void intel_frontbuffer_flush(struct drm_i915_private *dev_priv, 78static void frontbuffer_flush(struct drm_i915_private *i915,
98 unsigned frontbuffer_bits, 79 unsigned int frontbuffer_bits,
99 enum fb_op_origin origin) 80 enum fb_op_origin origin)
100{ 81{
101 /* Delay flushing when rings are still busy.*/ 82 /* Delay flushing when rings are still busy.*/
102 spin_lock(&dev_priv->fb_tracking.lock); 83 spin_lock(&i915->fb_tracking.lock);
103 frontbuffer_bits &= ~dev_priv->fb_tracking.busy_bits; 84 frontbuffer_bits &= ~i915->fb_tracking.busy_bits;
104 spin_unlock(&dev_priv->fb_tracking.lock); 85 spin_unlock(&i915->fb_tracking.lock);
105 86
106 if (!frontbuffer_bits) 87 if (!frontbuffer_bits)
107 return; 88 return;
108 89
109 might_sleep(); 90 might_sleep();
110 intel_edp_drrs_flush(dev_priv, frontbuffer_bits); 91 intel_edp_drrs_flush(i915, frontbuffer_bits);
111 intel_psr_flush(dev_priv, frontbuffer_bits, origin); 92 intel_psr_flush(i915, frontbuffer_bits, origin);
112 intel_fbc_flush(dev_priv, frontbuffer_bits, origin); 93 intel_fbc_flush(i915, frontbuffer_bits, origin);
113}
114
115void __intel_fb_obj_flush(struct drm_i915_gem_object *obj,
116 enum fb_op_origin origin,
117 unsigned int frontbuffer_bits)
118{
119 struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
120
121 if (origin == ORIGIN_CS) {
122 spin_lock(&dev_priv->fb_tracking.lock);
123 /* Filter out new bits since rendering started. */
124 frontbuffer_bits &= dev_priv->fb_tracking.busy_bits;
125 dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
126 spin_unlock(&dev_priv->fb_tracking.lock);
127 }
128
129 if (frontbuffer_bits)
130 intel_frontbuffer_flush(dev_priv, frontbuffer_bits, origin);
131} 94}
132 95
133/** 96/**
134 * intel_frontbuffer_flip_prepare - prepare asynchronous frontbuffer flip 97 * intel_frontbuffer_flip_prepare - prepare asynchronous frontbuffer flip
135 * @dev_priv: i915 device 98 * @i915: i915 device
136 * @frontbuffer_bits: frontbuffer plane tracking bits 99 * @frontbuffer_bits: frontbuffer plane tracking bits
137 * 100 *
138 * This function gets called after scheduling a flip on @obj. The actual 101 * This function gets called after scheduling a flip on @obj. The actual
@@ -142,19 +105,19 @@ void __intel_fb_obj_flush(struct drm_i915_gem_object *obj,
142 * 105 *
143 * Can be called without any locks held. 106 * Can be called without any locks held.
144 */ 107 */
145void intel_frontbuffer_flip_prepare(struct drm_i915_private *dev_priv, 108void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
146 unsigned frontbuffer_bits) 109 unsigned frontbuffer_bits)
147{ 110{
148 spin_lock(&dev_priv->fb_tracking.lock); 111 spin_lock(&i915->fb_tracking.lock);
149 dev_priv->fb_tracking.flip_bits |= frontbuffer_bits; 112 i915->fb_tracking.flip_bits |= frontbuffer_bits;
150 /* Remove stale busy bits due to the old buffer. */ 113 /* Remove stale busy bits due to the old buffer. */
151 dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; 114 i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
152 spin_unlock(&dev_priv->fb_tracking.lock); 115 spin_unlock(&i915->fb_tracking.lock);
153} 116}
154 117
155/** 118/**
156 * intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flip 119 * intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flip
157 * @dev_priv: i915 device 120 * @i915: i915 device
158 * @frontbuffer_bits: frontbuffer plane tracking bits 121 * @frontbuffer_bits: frontbuffer plane tracking bits
159 * 122 *
160 * This function gets called after the flip has been latched and will complete 123 * This function gets called after the flip has been latched and will complete
@@ -162,23 +125,22 @@ void intel_frontbuffer_flip_prepare(struct drm_i915_private *dev_priv,
162 * 125 *
163 * Can be called without any locks held. 126 * Can be called without any locks held.
164 */ 127 */
165void intel_frontbuffer_flip_complete(struct drm_i915_private *dev_priv, 128void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
166 unsigned frontbuffer_bits) 129 unsigned frontbuffer_bits)
167{ 130{
168 spin_lock(&dev_priv->fb_tracking.lock); 131 spin_lock(&i915->fb_tracking.lock);
169 /* Mask any cancelled flips. */ 132 /* Mask any cancelled flips. */
170 frontbuffer_bits &= dev_priv->fb_tracking.flip_bits; 133 frontbuffer_bits &= i915->fb_tracking.flip_bits;
171 dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits; 134 i915->fb_tracking.flip_bits &= ~frontbuffer_bits;
172 spin_unlock(&dev_priv->fb_tracking.lock); 135 spin_unlock(&i915->fb_tracking.lock);
173 136
174 if (frontbuffer_bits) 137 if (frontbuffer_bits)
175 intel_frontbuffer_flush(dev_priv, 138 frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
176 frontbuffer_bits, ORIGIN_FLIP);
177} 139}
178 140
179/** 141/**
180 * intel_frontbuffer_flip - synchronous frontbuffer flip 142 * intel_frontbuffer_flip - synchronous frontbuffer flip
181 * @dev_priv: i915 device 143 * @i915: i915 device
182 * @frontbuffer_bits: frontbuffer plane tracking bits 144 * @frontbuffer_bits: frontbuffer plane tracking bits
183 * 145 *
184 * This function gets called after scheduling a flip on @obj. This is for 146 * This function gets called after scheduling a flip on @obj. This is for
@@ -187,13 +149,160 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *dev_priv,
187 * 149 *
188 * Can be called without any locks held. 150 * Can be called without any locks held.
189 */ 151 */
190void intel_frontbuffer_flip(struct drm_i915_private *dev_priv, 152void intel_frontbuffer_flip(struct drm_i915_private *i915,
191 unsigned frontbuffer_bits) 153 unsigned frontbuffer_bits)
192{ 154{
193 spin_lock(&dev_priv->fb_tracking.lock); 155 spin_lock(&i915->fb_tracking.lock);
194 /* Remove stale busy bits due to the old buffer. */ 156 /* Remove stale busy bits due to the old buffer. */
195 dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; 157 i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
196 spin_unlock(&dev_priv->fb_tracking.lock); 158 spin_unlock(&i915->fb_tracking.lock);
197 159
198 intel_frontbuffer_flush(dev_priv, frontbuffer_bits, ORIGIN_FLIP); 160 frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
161}
162
163void __intel_fb_invalidate(struct intel_frontbuffer *front,
164 enum fb_op_origin origin,
165 unsigned int frontbuffer_bits)
166{
167 struct drm_i915_private *i915 = to_i915(front->obj->base.dev);
168
169 if (origin == ORIGIN_CS) {
170 spin_lock(&i915->fb_tracking.lock);
171 i915->fb_tracking.busy_bits |= frontbuffer_bits;
172 i915->fb_tracking.flip_bits &= ~frontbuffer_bits;
173 spin_unlock(&i915->fb_tracking.lock);
174 }
175
176 might_sleep();
177 intel_psr_invalidate(i915, frontbuffer_bits, origin);
178 intel_edp_drrs_invalidate(i915, frontbuffer_bits);
179 intel_fbc_invalidate(i915, frontbuffer_bits, origin);
180}
181
182void __intel_fb_flush(struct intel_frontbuffer *front,
183 enum fb_op_origin origin,
184 unsigned int frontbuffer_bits)
185{
186 struct drm_i915_private *i915 = to_i915(front->obj->base.dev);
187
188 if (origin == ORIGIN_CS) {
189 spin_lock(&i915->fb_tracking.lock);
190 /* Filter out new bits since rendering started. */
191 frontbuffer_bits &= i915->fb_tracking.busy_bits;
192 i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
193 spin_unlock(&i915->fb_tracking.lock);
194 }
195
196 if (frontbuffer_bits)
197 frontbuffer_flush(i915, frontbuffer_bits, origin);
198}
199
200static int frontbuffer_active(struct i915_active *ref)
201{
202 struct intel_frontbuffer *front =
203 container_of(ref, typeof(*front), write);
204
205 kref_get(&front->ref);
206 return 0;
207}
208
209static void frontbuffer_retire(struct i915_active *ref)
210{
211 struct intel_frontbuffer *front =
212 container_of(ref, typeof(*front), write);
213
214 intel_frontbuffer_flush(front, ORIGIN_CS);
215 intel_frontbuffer_put(front);
216}
217
218static void frontbuffer_release(struct kref *ref)
219 __releases(&to_i915(front->obj->base.dev)->fb_tracking.lock)
220{
221 struct intel_frontbuffer *front =
222 container_of(ref, typeof(*front), ref);
223
224 front->obj->frontbuffer = NULL;
225 spin_unlock(&to_i915(front->obj->base.dev)->fb_tracking.lock);
226
227 i915_gem_object_put(front->obj);
228 kfree(front);
229}
230
231struct intel_frontbuffer *
232intel_frontbuffer_get(struct drm_i915_gem_object *obj)
233{
234 struct drm_i915_private *i915 = to_i915(obj->base.dev);
235 struct intel_frontbuffer *front;
236
237 spin_lock(&i915->fb_tracking.lock);
238 front = obj->frontbuffer;
239 if (front)
240 kref_get(&front->ref);
241 spin_unlock(&i915->fb_tracking.lock);
242 if (front)
243 return front;
244
245 front = kmalloc(sizeof(*front), GFP_KERNEL);
246 if (!front)
247 return NULL;
248
249 front->obj = obj;
250 kref_init(&front->ref);
251 atomic_set(&front->bits, 0);
252 i915_active_init(i915, &front->write,
253 frontbuffer_active, frontbuffer_retire);
254
255 spin_lock(&i915->fb_tracking.lock);
256 if (obj->frontbuffer) {
257 kfree(front);
258 front = obj->frontbuffer;
259 kref_get(&front->ref);
260 } else {
261 i915_gem_object_get(obj);
262 obj->frontbuffer = front;
263 }
264 spin_unlock(&i915->fb_tracking.lock);
265
266 return front;
267}
268
269void intel_frontbuffer_put(struct intel_frontbuffer *front)
270{
271 kref_put_lock(&front->ref,
272 frontbuffer_release,
273 &to_i915(front->obj->base.dev)->fb_tracking.lock);
274}
275
276/**
277 * intel_frontbuffer_track - update frontbuffer tracking
278 * @old: current buffer for the frontbuffer slots
279 * @new: new buffer for the frontbuffer slots
280 * @frontbuffer_bits: bitmask of frontbuffer slots
281 *
282 * This updates the frontbuffer tracking bits @frontbuffer_bits by clearing them
283 * from @old and setting them in @new. Both @old and @new can be NULL.
284 */
285void intel_frontbuffer_track(struct intel_frontbuffer *old,
286 struct intel_frontbuffer *new,
287 unsigned int frontbuffer_bits)
288{
289 /*
290 * Control of individual bits within the mask are guarded by
291 * the owning plane->mutex, i.e. we can never see concurrent
292 * manipulation of individual bits. But since the bitfield as a whole
293 * is updated using RMW, we need to use atomics in order to update
294 * the bits.
295 */
296 BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES >
297 BITS_PER_TYPE(atomic_t));
298
299 if (old) {
300 WARN_ON(!(atomic_read(&old->bits) & frontbuffer_bits));
301 atomic_andnot(frontbuffer_bits, &old->bits);
302 }
303
304 if (new) {
305 WARN_ON(atomic_read(&new->bits) & frontbuffer_bits);
306 atomic_or(frontbuffer_bits, &new->bits);
307 }
199} 308}
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.h b/drivers/gpu/drm/i915/display/intel_frontbuffer.h
index 5727320c8084..adc64d61a4a5 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.h
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.h
@@ -24,7 +24,10 @@
24#ifndef __INTEL_FRONTBUFFER_H__ 24#ifndef __INTEL_FRONTBUFFER_H__
25#define __INTEL_FRONTBUFFER_H__ 25#define __INTEL_FRONTBUFFER_H__
26 26
27#include "gem/i915_gem_object.h" 27#include <linux/atomic.h>
28#include <linux/kref.h>
29
30#include "i915_active.h"
28 31
29struct drm_i915_private; 32struct drm_i915_private;
30struct drm_i915_gem_object; 33struct drm_i915_gem_object;
@@ -37,23 +40,30 @@ enum fb_op_origin {
37 ORIGIN_DIRTYFB, 40 ORIGIN_DIRTYFB,
38}; 41};
39 42
40void intel_frontbuffer_flip_prepare(struct drm_i915_private *dev_priv, 43struct intel_frontbuffer {
44 struct kref ref;
45 atomic_t bits;
46 struct i915_active write;
47 struct drm_i915_gem_object *obj;
48};
49
50void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
41 unsigned frontbuffer_bits); 51 unsigned frontbuffer_bits);
42void intel_frontbuffer_flip_complete(struct drm_i915_private *dev_priv, 52void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
43 unsigned frontbuffer_bits); 53 unsigned frontbuffer_bits);
44void intel_frontbuffer_flip(struct drm_i915_private *dev_priv, 54void intel_frontbuffer_flip(struct drm_i915_private *i915,
45 unsigned frontbuffer_bits); 55 unsigned frontbuffer_bits);
46 56
47void __intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, 57struct intel_frontbuffer *
48 enum fb_op_origin origin, 58intel_frontbuffer_get(struct drm_i915_gem_object *obj);
49 unsigned int frontbuffer_bits); 59
50void __intel_fb_obj_flush(struct drm_i915_gem_object *obj, 60void __intel_fb_invalidate(struct intel_frontbuffer *front,
51 enum fb_op_origin origin, 61 enum fb_op_origin origin,
52 unsigned int frontbuffer_bits); 62 unsigned int frontbuffer_bits);
53 63
54/** 64/**
55 * intel_fb_obj_invalidate - invalidate frontbuffer object 65 * intel_frontbuffer_invalidate - invalidate frontbuffer object
56 * @obj: GEM object to invalidate 66 * @front: GEM object to invalidate
57 * @origin: which operation caused the invalidation 67 * @origin: which operation caused the invalidation
58 * 68 *
59 * This function gets called every time rendering on the given object starts and 69 * This function gets called every time rendering on the given object starts and
@@ -62,37 +72,53 @@ void __intel_fb_obj_flush(struct drm_i915_gem_object *obj,
62 * until the rendering completes or a flip on this frontbuffer plane is 72 * until the rendering completes or a flip on this frontbuffer plane is
63 * scheduled. 73 * scheduled.
64 */ 74 */
65static inline bool intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, 75static inline bool intel_frontbuffer_invalidate(struct intel_frontbuffer *front,
66 enum fb_op_origin origin) 76 enum fb_op_origin origin)
67{ 77{
68 unsigned int frontbuffer_bits; 78 unsigned int frontbuffer_bits;
69 79
70 frontbuffer_bits = atomic_read(&obj->frontbuffer_bits); 80 if (!front)
81 return false;
82
83 frontbuffer_bits = atomic_read(&front->bits);
71 if (!frontbuffer_bits) 84 if (!frontbuffer_bits)
72 return false; 85 return false;
73 86
74 __intel_fb_obj_invalidate(obj, origin, frontbuffer_bits); 87 __intel_fb_invalidate(front, origin, frontbuffer_bits);
75 return true; 88 return true;
76} 89}
77 90
91void __intel_fb_flush(struct intel_frontbuffer *front,
92 enum fb_op_origin origin,
93 unsigned int frontbuffer_bits);
94
78/** 95/**
79 * intel_fb_obj_flush - flush frontbuffer object 96 * intel_frontbuffer_flush - flush frontbuffer object
80 * @obj: GEM object to flush 97 * @front: GEM object to flush
81 * @origin: which operation caused the flush 98 * @origin: which operation caused the flush
82 * 99 *
83 * This function gets called every time rendering on the given object has 100 * This function gets called every time rendering on the given object has
84 * completed and frontbuffer caching can be started again. 101 * completed and frontbuffer caching can be started again.
85 */ 102 */
86static inline void intel_fb_obj_flush(struct drm_i915_gem_object *obj, 103static inline void intel_frontbuffer_flush(struct intel_frontbuffer *front,
87 enum fb_op_origin origin) 104 enum fb_op_origin origin)
88{ 105{
89 unsigned int frontbuffer_bits; 106 unsigned int frontbuffer_bits;
90 107
91 frontbuffer_bits = atomic_read(&obj->frontbuffer_bits); 108 if (!front)
109 return;
110
111 frontbuffer_bits = atomic_read(&front->bits);
92 if (!frontbuffer_bits) 112 if (!frontbuffer_bits)
93 return; 113 return;
94 114
95 __intel_fb_obj_flush(obj, origin, frontbuffer_bits); 115 __intel_fb_flush(front, origin, frontbuffer_bits);
96} 116}
97 117
118void intel_frontbuffer_track(struct intel_frontbuffer *old,
119 struct intel_frontbuffer *new,
120 unsigned int frontbuffer_bits);
121
122void intel_frontbuffer_put(struct intel_frontbuffer *front);
123
98#endif /* __INTEL_FRONTBUFFER_H__ */ 124#endif /* __INTEL_FRONTBUFFER_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c
index 4f78586ee05e..e1248eace0e1 100644
--- a/drivers/gpu/drm/i915/display/intel_overlay.c
+++ b/drivers/gpu/drm/i915/display/intel_overlay.c
@@ -281,9 +281,9 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
281 281
282 WARN_ON(overlay->old_vma); 282 WARN_ON(overlay->old_vma);
283 283
284 i915_gem_track_fb(overlay->vma ? overlay->vma->obj : NULL, 284 intel_frontbuffer_track(overlay->vma ? overlay->vma->obj->frontbuffer : NULL,
285 vma ? vma->obj : NULL, 285 vma ? vma->obj->frontbuffer : NULL,
286 INTEL_FRONTBUFFER_OVERLAY(pipe)); 286 INTEL_FRONTBUFFER_OVERLAY(pipe));
287 287
288 intel_frontbuffer_flip_prepare(overlay->i915, 288 intel_frontbuffer_flip_prepare(overlay->i915,
289 INTEL_FRONTBUFFER_OVERLAY(pipe)); 289 INTEL_FRONTBUFFER_OVERLAY(pipe));
@@ -768,7 +768,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
768 ret = PTR_ERR(vma); 768 ret = PTR_ERR(vma);
769 goto out_pin_section; 769 goto out_pin_section;
770 } 770 }
771 intel_fb_obj_flush(new_bo, ORIGIN_DIRTYFB); 771 intel_frontbuffer_flush(new_bo->frontbuffer, ORIGIN_DIRTYFB);
772 772
773 ret = i915_vma_put_fence(vma); 773 ret = i915_vma_put_fence(vma);
774 if (ret) 774 if (ret)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
index c31684682eaa..77944950d4c9 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
@@ -49,7 +49,7 @@ static void __i915_do_clflush(struct drm_i915_gem_object *obj)
49{ 49{
50 GEM_BUG_ON(!i915_gem_object_has_pages(obj)); 50 GEM_BUG_ON(!i915_gem_object_has_pages(obj));
51 drm_clflush_sg(obj->mm.pages); 51 drm_clflush_sg(obj->mm.pages);
52 intel_fb_obj_flush(obj, ORIGIN_CPU); 52 intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
53} 53}
54 54
55static void i915_clflush_work(struct work_struct *work) 55static void i915_clflush_work(struct work_struct *work)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index 2e3ce2a69653..a1afc2690e9e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -551,13 +551,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
551 return 0; 551 return 0;
552} 552}
553 553
554static inline enum fb_op_origin
555fb_write_origin(struct drm_i915_gem_object *obj, unsigned int domain)
556{
557 return (domain == I915_GEM_DOMAIN_GTT ?
558 obj->frontbuffer_ggtt_origin : ORIGIN_CPU);
559}
560
561/** 554/**
562 * Called when user space prepares to use an object with the CPU, either 555 * Called when user space prepares to use an object with the CPU, either
563 * through the mmap ioctl's mapping or a GTT mapping. 556 * through the mmap ioctl's mapping or a GTT mapping.
@@ -661,9 +654,8 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
661 654
662 i915_gem_object_unlock(obj); 655 i915_gem_object_unlock(obj);
663 656
664 if (write_domain != 0) 657 if (write_domain)
665 intel_fb_obj_invalidate(obj, 658 intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
666 fb_write_origin(obj, write_domain));
667 659
668out_unpin: 660out_unpin:
669 i915_gem_object_unpin_pages(obj); 661 i915_gem_object_unpin_pages(obj);
@@ -783,7 +775,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj,
783 } 775 }
784 776
785out: 777out:
786 intel_fb_obj_invalidate(obj, ORIGIN_CPU); 778 intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
787 obj->mm.dirty = true; 779 obj->mm.dirty = true;
788 /* return with the pages pinned */ 780 /* return with the pages pinned */
789 return 0; 781 return 0;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index cfaedb4b70bd..501ab55f1280 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -101,9 +101,6 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
101 up_write(&mm->mmap_sem); 101 up_write(&mm->mmap_sem);
102 if (IS_ERR_VALUE(addr)) 102 if (IS_ERR_VALUE(addr))
103 goto err; 103 goto err;
104
105 /* This may race, but that's ok, it only gets set */
106 WRITE_ONCE(obj->frontbuffer_ggtt_origin, ORIGIN_CPU);
107 } 104 }
108 i915_gem_object_put(obj); 105 i915_gem_object_put(obj);
109 106
@@ -283,7 +280,6 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
283 * Userspace is now writing through an untracked VMA, abandon 280 * Userspace is now writing through an untracked VMA, abandon
284 * all hope that the hardware is able to track future writes. 281 * all hope that the hardware is able to track future writes.
285 */ 282 */
286 obj->frontbuffer_ggtt_origin = ORIGIN_CPU;
287 283
288 vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags); 284 vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags);
289 if (IS_ERR(vma) && !view.type) { 285 if (IS_ERR(vma) && !view.type) {
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 3929c3a6b281..0807bb5464cf 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -46,16 +46,6 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj)
46 return kmem_cache_free(global.slab_objects, obj); 46 return kmem_cache_free(global.slab_objects, obj);
47} 47}
48 48
49static void
50frontbuffer_retire(struct i915_active_request *active,
51 struct i915_request *request)
52{
53 struct drm_i915_gem_object *obj =
54 container_of(active, typeof(*obj), frontbuffer_write);
55
56 intel_fb_obj_flush(obj, ORIGIN_CS);
57}
58
59void i915_gem_object_init(struct drm_i915_gem_object *obj, 49void i915_gem_object_init(struct drm_i915_gem_object *obj,
60 const struct drm_i915_gem_object_ops *ops) 50 const struct drm_i915_gem_object_ops *ops)
61{ 51{
@@ -72,10 +62,6 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
72 62
73 obj->ops = ops; 63 obj->ops = ops;
74 64
75 obj->frontbuffer_ggtt_origin = ORIGIN_GTT;
76 i915_active_request_init(&obj->frontbuffer_write,
77 NULL, frontbuffer_retire);
78
79 obj->mm.madv = I915_MADV_WILLNEED; 65 obj->mm.madv = I915_MADV_WILLNEED;
80 INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN); 66 INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN);
81 mutex_init(&obj->mm.get_page.lock); 67 mutex_init(&obj->mm.get_page.lock);
@@ -187,7 +173,6 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
187 173
188 GEM_BUG_ON(atomic_read(&obj->bind_count)); 174 GEM_BUG_ON(atomic_read(&obj->bind_count));
189 GEM_BUG_ON(obj->userfault_count); 175 GEM_BUG_ON(obj->userfault_count);
190 GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits));
191 GEM_BUG_ON(!list_empty(&obj->lut_list)); 176 GEM_BUG_ON(!list_empty(&obj->lut_list));
192 177
193 atomic_set(&obj->mm.pages_pin_count, 0); 178 atomic_set(&obj->mm.pages_pin_count, 0);
@@ -230,6 +215,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
230 struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); 215 struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
231 struct drm_i915_private *i915 = to_i915(obj->base.dev); 216 struct drm_i915_private *i915 = to_i915(obj->base.dev);
232 217
218 GEM_BUG_ON(i915_gem_object_is_framebuffer(obj));
219
233 /* 220 /*
234 * Before we free the object, make sure any pure RCU-only 221 * Before we free the object, make sure any pure RCU-only
235 * read-side critical sections are complete, e.g. 222 * read-side critical sections are complete, e.g.
@@ -261,13 +248,6 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
261 queue_work(i915->wq, &i915->mm.free_work); 248 queue_work(i915->wq, &i915->mm.free_work);
262} 249}
263 250
264static inline enum fb_op_origin
265fb_write_origin(struct drm_i915_gem_object *obj, unsigned int domain)
266{
267 return (domain == I915_GEM_DOMAIN_GTT ?
268 obj->frontbuffer_ggtt_origin : ORIGIN_CPU);
269}
270
271static bool gpu_write_needs_clflush(struct drm_i915_gem_object *obj) 251static bool gpu_write_needs_clflush(struct drm_i915_gem_object *obj)
272{ 252{
273 return !(obj->cache_level == I915_CACHE_NONE || 253 return !(obj->cache_level == I915_CACHE_NONE ||
@@ -290,8 +270,7 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,
290 for_each_ggtt_vma(vma, obj) 270 for_each_ggtt_vma(vma, obj)
291 intel_gt_flush_ggtt_writes(vma->vm->gt); 271 intel_gt_flush_ggtt_writes(vma->vm->gt);
292 272
293 intel_fb_obj_flush(obj, 273 intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
294 fb_write_origin(obj, I915_GEM_DOMAIN_GTT));
295 274
296 for_each_ggtt_vma(vma, obj) { 275 for_each_ggtt_vma(vma, obj) {
297 if (vma->iomap) 276 if (vma->iomap)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 3714cf234d64..abc23e7e13a7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -161,7 +161,7 @@ i915_gem_object_needs_async_cancel(const struct drm_i915_gem_object *obj)
161static inline bool 161static inline bool
162i915_gem_object_is_framebuffer(const struct drm_i915_gem_object *obj) 162i915_gem_object_is_framebuffer(const struct drm_i915_gem_object *obj)
163{ 163{
164 return READ_ONCE(obj->framebuffer_references); 164 return READ_ONCE(obj->frontbuffer);
165} 165}
166 166
167static inline unsigned int 167static inline unsigned int
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index d474c6ac4100..ede0eb4218a8 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -13,6 +13,7 @@
13#include "i915_selftest.h" 13#include "i915_selftest.h"
14 14
15struct drm_i915_gem_object; 15struct drm_i915_gem_object;
16struct intel_fronbuffer;
16 17
17/* 18/*
18 * struct i915_lut_handle tracks the fast lookups from handle to vma used 19 * struct i915_lut_handle tracks the fast lookups from handle to vma used
@@ -141,9 +142,7 @@ struct drm_i915_gem_object {
141 */ 142 */
142 u16 write_domain; 143 u16 write_domain;
143 144
144 atomic_t frontbuffer_bits; 145 struct intel_frontbuffer *frontbuffer;
145 unsigned int frontbuffer_ggtt_origin; /* write once */
146 struct i915_active_request frontbuffer_write;
147 146
148 /** Current tiling stride for the object, if it's tiled. */ 147 /** Current tiling stride for the object, if it's tiled. */
149 unsigned int tiling_and_stride; 148 unsigned int tiling_and_stride;
@@ -224,9 +223,6 @@ struct drm_i915_gem_object {
224 bool quirked:1; 223 bool quirked:1;
225 } mm; 224 } mm;
226 225
227 /** References from framebuffers, locks out tiling changes. */
228 unsigned int framebuffer_references;
229
230 /** Record of address bit 17 of each page at last unbind. */ 226 /** Record of address bit 17 of each page at last unbind. */
231 unsigned long *bit_17; 227 unsigned long *bit_17;
232 228
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index ef4f84e060ee..e7ce739fe545 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -138,7 +138,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
138 struct drm_i915_private *dev_priv = to_i915(obj->base.dev); 138 struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
139 struct intel_engine_cs *engine; 139 struct intel_engine_cs *engine;
140 struct i915_vma *vma; 140 struct i915_vma *vma;
141 unsigned int frontbuffer_bits;
142 int pin_count = 0; 141 int pin_count = 0;
143 142
144 seq_printf(m, "%pK: %c%c%c%c %8zdKiB %02x %02x %s%s%s", 143 seq_printf(m, "%pK: %c%c%c%c %8zdKiB %02x %02x %s%s%s",
@@ -228,10 +227,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
228 engine = i915_gem_object_last_write_engine(obj); 227 engine = i915_gem_object_last_write_engine(obj);
229 if (engine) 228 if (engine)
230 seq_printf(m, " (%s)", engine->name); 229 seq_printf(m, " (%s)", engine->name);
231
232 frontbuffer_bits = atomic_read(&obj->frontbuffer_bits);
233 if (frontbuffer_bits)
234 seq_printf(m, " (frontbuffer: 0x%03x)", frontbuffer_bits);
235} 230}
236 231
237struct file_stats { 232struct file_stats {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 50effdccc76c..b6beae12cd21 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2355,10 +2355,6 @@ int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
2355 u32 handle, u64 *offset); 2355 u32 handle, u64 *offset);
2356int i915_gem_mmap_gtt_version(void); 2356int i915_gem_mmap_gtt_version(void);
2357 2357
2358void i915_gem_track_fb(struct drm_i915_gem_object *old,
2359 struct drm_i915_gem_object *new,
2360 unsigned frontbuffer_bits);
2361
2362int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno); 2358int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno);
2363 2359
2364static inline u32 i915_reset_count(struct i915_gpu_error *error) 2360static inline u32 i915_reset_count(struct i915_gpu_error *error)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 29be25a7aade..71ee4c710252 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -139,17 +139,19 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
139 void *vaddr = obj->phys_handle->vaddr + args->offset; 139 void *vaddr = obj->phys_handle->vaddr + args->offset;
140 char __user *user_data = u64_to_user_ptr(args->data_ptr); 140 char __user *user_data = u64_to_user_ptr(args->data_ptr);
141 141
142 /* We manually control the domain here and pretend that it 142 /*
143 * We manually control the domain here and pretend that it
143 * remains coherent i.e. in the GTT domain, like shmem_pwrite. 144 * remains coherent i.e. in the GTT domain, like shmem_pwrite.
144 */ 145 */
145 intel_fb_obj_invalidate(obj, ORIGIN_CPU); 146 intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
147
146 if (copy_from_user(vaddr, user_data, args->size)) 148 if (copy_from_user(vaddr, user_data, args->size))
147 return -EFAULT; 149 return -EFAULT;
148 150
149 drm_clflush_virt_range(vaddr, args->size); 151 drm_clflush_virt_range(vaddr, args->size);
150 intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt); 152 intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
151 153
152 intel_fb_obj_flush(obj, ORIGIN_CPU); 154 intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
153 return 0; 155 return 0;
154} 156}
155 157
@@ -594,7 +596,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
594 goto out_unpin; 596 goto out_unpin;
595 } 597 }
596 598
597 intel_fb_obj_invalidate(obj, ORIGIN_CPU); 599 intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
598 600
599 user_data = u64_to_user_ptr(args->data_ptr); 601 user_data = u64_to_user_ptr(args->data_ptr);
600 offset = args->offset; 602 offset = args->offset;
@@ -636,7 +638,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
636 user_data += page_length; 638 user_data += page_length;
637 offset += page_length; 639 offset += page_length;
638 } 640 }
639 intel_fb_obj_flush(obj, ORIGIN_CPU); 641 intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
640 642
641 i915_gem_object_unlock_fence(obj, fence); 643 i915_gem_object_unlock_fence(obj, fence);
642out_unpin: 644out_unpin:
@@ -729,7 +731,7 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
729 offset = 0; 731 offset = 0;
730 } 732 }
731 733
732 intel_fb_obj_flush(obj, ORIGIN_CPU); 734 intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
733 i915_gem_object_unlock_fence(obj, fence); 735 i915_gem_object_unlock_fence(obj, fence);
734 736
735 return ret; 737 return ret;
@@ -1763,39 +1765,6 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file)
1763 return ret; 1765 return ret;
1764} 1766}
1765 1767
1766/**
1767 * i915_gem_track_fb - update frontbuffer tracking
1768 * @old: current GEM buffer for the frontbuffer slots
1769 * @new: new GEM buffer for the frontbuffer slots
1770 * @frontbuffer_bits: bitmask of frontbuffer slots
1771 *
1772 * This updates the frontbuffer tracking bits @frontbuffer_bits by clearing them
1773 * from @old and setting them in @new. Both @old and @new can be NULL.
1774 */
1775void i915_gem_track_fb(struct drm_i915_gem_object *old,
1776 struct drm_i915_gem_object *new,
1777 unsigned frontbuffer_bits)
1778{
1779 /* Control of individual bits within the mask are guarded by
1780 * the owning plane->mutex, i.e. we can never see concurrent
1781 * manipulation of individual bits. But since the bitfield as a whole
1782 * is updated using RMW, we need to use atomics in order to update
1783 * the bits.
1784 */
1785 BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES >
1786 BITS_PER_TYPE(atomic_t));
1787
1788 if (old) {
1789 WARN_ON(!(atomic_read(&old->frontbuffer_bits) & frontbuffer_bits));
1790 atomic_andnot(frontbuffer_bits, &old->frontbuffer_bits);
1791 }
1792
1793 if (new) {
1794 WARN_ON(atomic_read(&new->frontbuffer_bits) & frontbuffer_bits);
1795 atomic_or(frontbuffer_bits, &new->frontbuffer_bits);
1796 }
1797}
1798
1799#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) 1768#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
1800#include "selftests/mock_gem_device.c" 1769#include "selftests/mock_gem_device.c"
1801#include "selftests/i915_gem.c" 1770#include "selftests/i915_gem.c"
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index 8be1bbef40e5..d38ef2ef3ce4 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -908,8 +908,10 @@ int i915_vma_move_to_active(struct i915_vma *vma,
908 return err; 908 return err;
909 909
910 if (flags & EXEC_OBJECT_WRITE) { 910 if (flags & EXEC_OBJECT_WRITE) {
911 if (intel_fb_obj_invalidate(obj, ORIGIN_CS)) 911 if (intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CS))
912 __i915_active_request_set(&obj->frontbuffer_write, rq); 912 i915_active_ref(&obj->frontbuffer->write,
913 rq->fence.context,
914 rq);
913 915
914 reservation_object_add_excl_fence(vma->resv, &rq->fence); 916 reservation_object_add_excl_fence(vma->resv, &rq->fence);
915 obj->write_domain = I915_GEM_DOMAIN_RENDER; 917 obj->write_domain = I915_GEM_DOMAIN_RENDER;