summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/drm/i915_drv.c47
-rw-r--r--sys/dev/pci/drm/i915_drv.h1
2 files changed, 32 insertions, 16 deletions
diff --git a/sys/dev/pci/drm/i915_drv.c b/sys/dev/pci/drm/i915_drv.c
index 8db348f5c9d..ea650513445 100644
--- a/sys/dev/pci/drm/i915_drv.c
+++ b/sys/dev/pci/drm/i915_drv.c
@@ -2125,6 +2125,7 @@ i915_gem_object_put_fence_reg(struct drm_obj *obj, int interruptible)
reg->obj = NULL;
TAILQ_REMOVE(&dev_priv->mm.fence_list, reg, list);
obj_priv->fence_reg = I915_FENCE_REG_NONE;
+ atomic_clearbits_int(&obj_priv->io_flags, I915_FENCE_INVALID);
return (0);
}
@@ -2146,6 +2147,19 @@ inteldrm_fault(struct drm_obj *obj, struct uvm_faultinfo *ufi, off_t offset,
* XXX this locking is wrong, must be fixed. uvm using simple_locks
* saves us for now.
*/
+ if (obj_priv->dmamap != NULL &&
+ (obj_priv->gtt_offset & (i915_gem_get_gtt_alignment(obj) - 1) ||
+ (!i915_gem_object_fence_offset_ok(obj, obj_priv->tiling_mode)))) {
+ if (obj_priv->pin_count == 0) {
+ ret = i915_gem_object_unbind(obj, 0);
+ if (ret)
+ goto error;
+ } else {
+ DRM_ERROR("fault on pinned object with bad alignment\n");
+ return (EINVAL);
+ }
+ }
+
if (obj_priv->dmamap == NULL) {
ret = i915_gem_object_bind_to_gtt(obj, 0, 0);
if (ret) {
@@ -2377,6 +2391,11 @@ i915_gem_object_set_to_gtt_domain(struct drm_obj *obj, int write,
/* We're accessing through the gpu, so grab a new fence register or
* update the LRU.
*/
+ if (obj_priv->io_flags & I915_FENCE_INVALID) {
+ ret = i915_gem_object_put_fence_reg(obj, interruptible);
+ if (ret)
+ return (ret);
+ }
if (obj_priv->tiling_mode != I915_TILING_NONE)
ret = i915_gem_get_fence_reg(obj, interruptible);
@@ -3185,8 +3204,8 @@ i915_gem_object_pin(struct drm_obj *obj, uint32_t alignment, int needs_fence)
return (ret);
} else {
DRM_ERROR("repinning an object with bad alignment\n");
- }
return (EINVAL);
+ }
}
if (obj_priv->dmamap == NULL) {
@@ -3202,6 +3221,12 @@ i915_gem_object_pin(struct drm_obj *obj, uint32_t alignment, int needs_fence)
* With execbuf2 support we don't always need it, but if we do grab
* it.
*/
+ /* if we need a fence now, check that the one we may have is correct */
+ if (needs_fence && obj_priv->io_flags & I915_FENCE_INVALID) {
+ ret= i915_gem_object_put_fence_reg(obj, 1);
+ if (ret)
+ return (ret);
+ }
if (needs_fence && obj_priv->tiling_mode != I915_TILING_NONE &&
(ret = i915_gem_get_fence_reg(obj, 1)) != 0)
return (ret);
@@ -4512,21 +4537,11 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
* mode. Otherwise we can leave it alone, but must clear any
* fence register.
*/
- if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode)) {
- if (obj_priv->pin_count)
- ret = EINVAL;
- else
- ret = i915_gem_object_unbind(obj, 1);
- } else if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
- ret = i915_gem_object_put_fence_reg(obj, 1);
- } else {
- inteldrm_wipe_mappings(obj);
- }
- if (ret != 0) {
- args->tiling_mode = obj_priv->tiling_mode;
- args->stride = obj_priv->stride;
- goto out;
- }
+ /* fence may no longer be correct, wipe it */
+ inteldrm_wipe_mappings(obj);
+ if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
+ atomic_setbits_int(&obj_priv->io_flags,
+ I915_FENCE_INVALID);
obj_priv->tiling_mode = args->tiling_mode;
obj_priv->stride = args->stride;
}
diff --git a/sys/dev/pci/drm/i915_drv.h b/sys/dev/pci/drm/i915_drv.h
index dae028ceaec..cdf9d1b76d7 100644
--- a/sys/dev/pci/drm/i915_drv.h
+++ b/sys/dev/pci/drm/i915_drv.h
@@ -381,6 +381,7 @@ struct inteldrm_obj {
#define I915_DIRTY 0x0040 /* BO written to since last bound */
#define I915_EXEC_NEEDS_FENCE 0x0080 /* being processed but will need fence*/
#define I915_FENCED_EXEC 0x0100 /* Most recent exec needs fence */
+#define I915_FENCE_INVALID 0x0200 /* fence has been lazily invalidated */
int io_flags;
/* extra flags to bus_dma */
int dma_flags;