drm/i915: Rebind the buffer if its alignment constraints changes with tiling

Early gen3 and gen2 chipset do not have the relaxed per-surface tiling
constraints of the later chipsets, so we need to check that the GTT
alignment is correct for the new tiling. If it is not, we need to
rebind.

Reported-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

+21 -5
+3
drivers/gpu/drm/i915/i915_drv.h
··· 1178 void i915_gem_free_all_phys_object(struct drm_device *dev); 1179 void i915_gem_release(struct drm_device *dev, struct drm_file *file); 1180 1181 /* i915_gem_gtt.c */ 1182 void i915_gem_restore_gtt_mappings(struct drm_device *dev); 1183 int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
··· 1178 void i915_gem_free_all_phys_object(struct drm_device *dev); 1179 void i915_gem_release(struct drm_device *dev, struct drm_file *file); 1180 1181 + uint32_t 1182 + i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj); 1183 + 1184 /* i915_gem_gtt.c */ 1185 void i915_gem_restore_gtt_mappings(struct drm_device *dev); 1186 int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
+1 -1
drivers/gpu/drm/i915/i915_gem.c
··· 1398 * Return the required GTT alignment for an object, only taking into account 1399 * unfenced tiled surface requirements. 1400 */ 1401 - static uint32_t 1402 i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj) 1403 { 1404 struct drm_device *dev = obj->base.dev;
··· 1398 * Return the required GTT alignment for an object, only taking into account 1399 * unfenced tiled surface requirements. 1400 */ 1401 + uint32_t 1402 i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj) 1403 { 1404 struct drm_device *dev = obj->base.dev;
+17 -4
drivers/gpu/drm/i915/i915_gem_tiling.c
··· 349 (obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end && 350 i915_gem_object_fence_ok(obj, args->tiling_mode)); 351 352 - obj->tiling_changed = true; 353 - obj->tiling_mode = args->tiling_mode; 354 - obj->stride = args->stride; 355 } 356 drm_gem_object_unreference(&obj->base); 357 mutex_unlock(&dev->struct_mutex); 358 359 - return 0; 360 } 361 362 /**
··· 349 (obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end && 350 i915_gem_object_fence_ok(obj, args->tiling_mode)); 351 352 + /* Rebind if we need a change of alignment */ 353 + if (!obj->map_and_fenceable) { 354 + u32 unfenced_alignment = 355 + i915_gem_get_unfenced_gtt_alignment(obj); 356 + if (obj->gtt_offset & (unfenced_alignment - 1)) 357 + ret = i915_gem_object_unbind(obj); 358 + } 359 + 360 + if (ret == 0) { 361 + obj->tiling_changed = true; 362 + obj->tiling_mode = args->tiling_mode; 363 + obj->stride = args->stride; 364 + } 365 } 366 + /* we have to maintain this existing ABI... */ 367 + args->stride = obj->stride; 368 + args->tiling_mode = obj->tiling_mode; 369 drm_gem_object_unreference(&obj->base); 370 mutex_unlock(&dev->struct_mutex); 371 372 + return ret; 373 } 374 375 /**