Skip to content

Commit dd68928

Browse files
committed
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: 24dbf51 ("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
1 parent 9aceb5c commit dd68928

File tree

4 files changed

+42
-12
lines changed

4 files changed

+42
-12
lines changed

drivers/gpu/drm/i915/i915_gem_object.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ struct drm_i915_gem_object {
165165
struct reservation_object *resv;
166166

167167
/** References from framebuffers, locks out tiling changes. */
168-
atomic_t framebuffer_references;
168+
unsigned int framebuffer_references;
169169

170170
/** Record of address bit 17 of each page at last unbind. */
171171
unsigned long *bit_17;
@@ -260,6 +260,16 @@ extern void drm_gem_object_unreference(struct drm_gem_object *);
260260
__deprecated
261261
extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *);
262262

263+
static inline void i915_gem_object_lock(struct drm_i915_gem_object *obj)
264+
{
265+
reservation_object_lock(obj->resv, NULL);
266+
}
267+
268+
static inline void i915_gem_object_unlock(struct drm_i915_gem_object *obj)
269+
{
270+
reservation_object_unlock(obj->resv);
271+
}
272+
263273
static inline bool
264274
i915_gem_object_is_dead(const struct drm_i915_gem_object *obj)
265275
{
@@ -306,6 +316,12 @@ i915_gem_object_clear_active_reference(struct drm_i915_gem_object *obj)
306316

307317
void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj);
308318

319+
static inline bool
320+
i915_gem_object_is_framebuffer(const struct drm_i915_gem_object *obj)
321+
{
322+
return READ_ONCE(obj->framebuffer_references);
323+
}
324+
309325
static inline unsigned int
310326
i915_gem_object_get_tiling(struct drm_i915_gem_object *obj)
311327
{

drivers/gpu/drm/i915/i915_gem_shrinker.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
207207

208208
if (!(flags & I915_SHRINK_ACTIVE) &&
209209
(i915_gem_object_is_active(obj) ||
210-
atomic_read(&obj->framebuffer_references)))
210+
i915_gem_object_is_framebuffer(obj)))
211211
continue;
212212

213213
if (!can_release_pages(obj))

drivers/gpu/drm/i915/i915_gem_tiling.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
238238
if ((tiling | stride) == obj->tiling_and_stride)
239239
return 0;
240240

241-
if (atomic_read(&obj->framebuffer_references))
241+
if (i915_gem_object_is_framebuffer(obj))
242242
return -EBUSY;
243243

244244
/* 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,
258258
if (err)
259259
return err;
260260

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+
261267
/* If the memory has unknown (i.e. varying) swizzling, we pin the
262268
* pages to prevent them being swapped out and causing corruption
263269
* due to the change in swizzling.
@@ -294,6 +300,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
294300
}
295301

296302
obj->tiling_and_stride = tiling | stride;
303+
i915_gem_object_unlock(obj);
297304

298305
/* Force the fence to be reacquired for GTT access */
299306
i915_gem_release_mmap(obj);

drivers/gpu/drm/i915/intel_display.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14185,7 +14185,10 @@ static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
1418514185

1418614186
drm_framebuffer_cleanup(fb);
1418714187

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+
1418914192
i915_gem_object_put(intel_fb->obj);
1419014193

1419114194
kfree(intel_fb);
@@ -14262,12 +14265,16 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
1426214265
struct drm_mode_fb_cmd2 *mode_cmd)
1426314266
{
1426414267
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;
1426714268
struct drm_format_name_buf format_name;
14269+
u32 pitch_limit, stride_alignment;
14270+
unsigned int tiling, stride;
1426814271
int ret = -EINVAL;
1426914272

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);
1427114278

1427214279
if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
1427314280
/*
@@ -14339,11 +14346,9 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
1433914346
* If there's a fence, enforce that
1434014347
* the fb pitch and fence stride match.
1434114348
*/
14342-
if (tiling != I915_TILING_NONE &&
14343-
mode_cmd->pitches[0] != i915_gem_object_get_stride(obj)) {
14349+
if (tiling != I915_TILING_NONE && mode_cmd->pitches[0] != stride) {
1434414350
DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
14345-
mode_cmd->pitches[0],
14346-
i915_gem_object_get_stride(obj));
14351+
mode_cmd->pitches[0], stride);
1434714352
goto err;
1434814353
}
1434914354

@@ -14424,7 +14429,9 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
1442414429
return 0;
1442514430

1442614431
err:
14427-
atomic_dec(&obj->framebuffer_references);
14432+
i915_gem_object_lock(obj);
14433+
obj->framebuffer_references--;
14434+
i915_gem_object_unlock(obj);
1442814435
return ret;
1442914436
}
1443014437

0 commit comments

Comments
 (0)