aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-03-01 10:41:28 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2017-03-01 12:57:17 -0500
commitdd689287b977597a46adf8c3de19d40212f0ea9f (patch)
tree664a82cf91a448de269dd57939cbc40ad14ceb4f
parent9aceb5c15d84d4b960f5f80fba846c753554d092 (diff)
drm/i915: Prevent concurrent tiling/framebuffer modifications
Reintroduce a lock around tiling vs framebuffer creation to prevent modification of the obj->tiling_and_stride whilst the framebuffer is being created. Rather than use struct_mutex once again, use the per-object lock - this will also be required in future to prevent changing the tiling whilst submitting rendering. Reported-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Fixes: 24dbf51a5517 ("drm/i915: struct_mutex is not required for allocating the framebuffer") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170301154128.2841-2-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/i915/i915_gem_object.h18
-rw-r--r--drivers/gpu/drm/i915/i915_gem_shrinker.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c9
-rw-r--r--drivers/gpu/drm/i915/intel_display.c25
4 files changed, 42 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h
index 2fb30a5eb510..1495eeb03382 100644
--- a/drivers/gpu/drm/i915/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/i915_gem_object.h
@@ -165,7 +165,7 @@ struct drm_i915_gem_object {
165 struct reservation_object *resv; 165 struct reservation_object *resv;
166 166
167 /** References from framebuffers, locks out tiling changes. */ 167 /** References from framebuffers, locks out tiling changes. */
168 atomic_t framebuffer_references; 168 unsigned int framebuffer_references;
169 169
170 /** Record of address bit 17 of each page at last unbind. */ 170 /** Record of address bit 17 of each page at last unbind. */
171 unsigned long *bit_17; 171 unsigned long *bit_17;
@@ -260,6 +260,16 @@ extern void drm_gem_object_unreference(struct drm_gem_object *);
260__deprecated 260__deprecated
261extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *); 261extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *);
262 262
263static inline void i915_gem_object_lock(struct drm_i915_gem_object *obj)
264{
265 reservation_object_lock(obj->resv, NULL);
266}
267
268static inline void i915_gem_object_unlock(struct drm_i915_gem_object *obj)
269{
270 reservation_object_unlock(obj->resv);
271}
272
263static inline bool 273static inline bool
264i915_gem_object_is_dead(const struct drm_i915_gem_object *obj) 274i915_gem_object_is_dead(const struct drm_i915_gem_object *obj)
265{ 275{
@@ -306,6 +316,12 @@ i915_gem_object_clear_active_reference(struct drm_i915_gem_object *obj)
306 316
307void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj); 317void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj);
308 318
319static inline bool
320i915_gem_object_is_framebuffer(const struct drm_i915_gem_object *obj)
321{
322 return READ_ONCE(obj->framebuffer_references);
323}
324
309static inline unsigned int 325static inline unsigned int
310i915_gem_object_get_tiling(struct drm_i915_gem_object *obj) 326i915_gem_object_get_tiling(struct drm_i915_gem_object *obj)
311{ 327{
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 8bc515e8b2a2..006a8b908f77 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -207,7 +207,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
207 207
208 if (!(flags & I915_SHRINK_ACTIVE) && 208 if (!(flags & I915_SHRINK_ACTIVE) &&
209 (i915_gem_object_is_active(obj) || 209 (i915_gem_object_is_active(obj) ||
210 atomic_read(&obj->framebuffer_references))) 210 i915_gem_object_is_framebuffer(obj)))
211 continue; 211 continue;
212 212
213 if (!can_release_pages(obj)) 213 if (!can_release_pages(obj))
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 46ade36dcee6..a0d6d4317a49 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -238,7 +238,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
238 if ((tiling | stride) == obj->tiling_and_stride) 238 if ((tiling | stride) == obj->tiling_and_stride)
239 return 0; 239 return 0;
240 240
241 if (atomic_read(&obj->framebuffer_references)) 241 if (i915_gem_object_is_framebuffer(obj))
242 return -EBUSY; 242 return -EBUSY;
243 243
244 /* We need to rebind the object if its current allocation 244 /* We need to rebind the object if its current allocation
@@ -258,6 +258,12 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
258 if (err) 258 if (err)
259 return err; 259 return err;
260 260
261 i915_gem_object_lock(obj);
262 if (i915_gem_object_is_framebuffer(obj)) {
263 i915_gem_object_unlock(obj);
264 return -EBUSY;
265 }
266
261 /* If the memory has unknown (i.e. varying) swizzling, we pin the 267 /* If the memory has unknown (i.e. varying) swizzling, we pin the
262 * pages to prevent them being swapped out and causing corruption 268 * pages to prevent them being swapped out and causing corruption
263 * due to the change in swizzling. 269 * due to the change in swizzling.
@@ -294,6 +300,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
294 } 300 }
295 301
296 obj->tiling_and_stride = tiling | stride; 302 obj->tiling_and_stride = tiling | stride;
303 i915_gem_object_unlock(obj);
297 304
298 /* Force the fence to be reacquired for GTT access */ 305 /* Force the fence to be reacquired for GTT access */
299 i915_gem_release_mmap(obj); 306 i915_gem_release_mmap(obj);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6d2597a4a45f..9d8c08c4b105 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14185,7 +14185,10 @@ static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
14185 14185
14186 drm_framebuffer_cleanup(fb); 14186 drm_framebuffer_cleanup(fb);
14187 14187
14188 WARN_ON(atomic_dec_return(&intel_fb->obj->framebuffer_references) < 0); 14188 i915_gem_object_lock(intel_fb->obj);
14189 WARN_ON(!intel_fb->obj->framebuffer_references--);
14190 i915_gem_object_unlock(intel_fb->obj);
14191
14189 i915_gem_object_put(intel_fb->obj); 14192 i915_gem_object_put(intel_fb->obj);
14190 14193
14191 kfree(intel_fb); 14194 kfree(intel_fb);
@@ -14262,12 +14265,16 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
14262 struct drm_mode_fb_cmd2 *mode_cmd) 14265 struct drm_mode_fb_cmd2 *mode_cmd)
14263{ 14266{
14264 struct drm_i915_private *dev_priv = to_i915(obj->base.dev); 14267 struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
14265 unsigned int tiling = i915_gem_object_get_tiling(obj);
14266 u32 pitch_limit, stride_alignment;
14267 struct drm_format_name_buf format_name; 14268 struct drm_format_name_buf format_name;
14269 u32 pitch_limit, stride_alignment;
14270 unsigned int tiling, stride;
14268 int ret = -EINVAL; 14271 int ret = -EINVAL;
14269 14272
14270 atomic_inc(&obj->framebuffer_references); 14273 i915_gem_object_lock(obj);
14274 obj->framebuffer_references++;
14275 tiling = i915_gem_object_get_tiling(obj);
14276 stride = i915_gem_object_get_stride(obj);
14277 i915_gem_object_unlock(obj);
14271 14278
14272 if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) { 14279 if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
14273 /* 14280 /*
@@ -14339,11 +14346,9 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
14339 * If there's a fence, enforce that 14346 * If there's a fence, enforce that
14340 * the fb pitch and fence stride match. 14347 * the fb pitch and fence stride match.
14341 */ 14348 */
14342 if (tiling != I915_TILING_NONE && 14349 if (tiling != I915_TILING_NONE && mode_cmd->pitches[0] != stride) {
14343 mode_cmd->pitches[0] != i915_gem_object_get_stride(obj)) {
14344 DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n", 14350 DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
14345 mode_cmd->pitches[0], 14351 mode_cmd->pitches[0], stride);
14346 i915_gem_object_get_stride(obj));
14347 goto err; 14352 goto err;
14348 } 14353 }
14349 14354
@@ -14424,7 +14429,9 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
14424 return 0; 14429 return 0;
14425 14430
14426err: 14431err:
14427 atomic_dec(&obj->framebuffer_references); 14432 i915_gem_object_lock(obj);
14433 obj->framebuffer_references--;
14434 i915_gem_object_unlock(obj);
14428 return ret; 14435 return ret;
14429} 14436}
14430 14437