drm/i915: add fence register management to execbuf
Adds code to set up fence registers at execbuf time on pre-965 chips as necessary. Also fixes up a few bugs in the pre-965 tile register support (get_order != ffs). The number of fences available to the kernel defaults to the hw limit minus 3 (for legacy X front/back/depth), but a new parameter allows userspace to override that as needed. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@linux.ie>
This commit is contained in:
committed by
Dave Airlie
parent
d9ddcb96e0
commit
0f973f2788
@@ -173,6 +173,73 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the size of the fence for a tiled object of the given size.
|
||||
*/
|
||||
static int
|
||||
i915_get_fence_size(struct drm_device *dev, int size)
|
||||
{
|
||||
int i;
|
||||
int start;
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
/* The 965 can have fences at any page boundary. */
|
||||
return ALIGN(size, 4096);
|
||||
} else {
|
||||
/* Align the size to a power of two greater than the smallest
|
||||
* fence size.
|
||||
*/
|
||||
if (IS_I9XX(dev))
|
||||
start = 1024 * 1024;
|
||||
else
|
||||
start = 512 * 1024;
|
||||
|
||||
for (i = start; i < size; i <<= 1)
|
||||
;
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check pitch constriants for all chips & tiling formats */
|
||||
static bool
|
||||
i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
||||
{
|
||||
int tile_width;
|
||||
|
||||
/* Linear is always fine */
|
||||
if (tiling_mode == I915_TILING_NONE)
|
||||
return true;
|
||||
|
||||
if (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
|
||||
tile_width = 128;
|
||||
else
|
||||
tile_width = 512;
|
||||
|
||||
/* 965+ just needs multiples of tile width */
|
||||
if (IS_I965G(dev)) {
|
||||
if (stride & (tile_width - 1))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Pre-965 needs power of two tile widths */
|
||||
if (stride < tile_width)
|
||||
return false;
|
||||
|
||||
if (stride & (stride - 1))
|
||||
return false;
|
||||
|
||||
/* We don't handle the aperture area covered by the fence being bigger
|
||||
* than the object size.
|
||||
*/
|
||||
if (i915_get_fence_size(dev, size) != size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tiling mode of an object, returning the required swizzling of
|
||||
* bit 6 of addresses in the object.
|
||||
@@ -191,6 +258,9 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
||||
return -EINVAL;
|
||||
obj_priv = obj->driver_private;
|
||||
|
||||
if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
if (args->tiling_mode == I915_TILING_NONE) {
|
||||
@@ -207,7 +277,23 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
||||
args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
|
||||
}
|
||||
}
|
||||
obj_priv->tiling_mode = args->tiling_mode;
|
||||
if (args->tiling_mode != obj_priv->tiling_mode) {
|
||||
int ret;
|
||||
|
||||
/* Unbind the object, as switching tiling means we're
|
||||
* switching the cache organization due to fencing, probably.
|
||||
*/
|
||||
ret = i915_gem_object_unbind(obj);
|
||||
if (ret != 0) {
|
||||
WARN(ret != -ERESTARTSYS,
|
||||
"failed to unbind object for tiling switch");
|
||||
args->tiling_mode = obj_priv->tiling_mode;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
obj_priv->tiling_mode = args->tiling_mode;
|
||||
}
|
||||
obj_priv->stride = args->stride;
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
Reference in New Issue
Block a user