|
@@ -3100,6 +3100,9 @@ search_free:
|
|
|
|
|
|
goto err_unpin;
|
|
|
}
|
|
|
+
|
|
|
+ GEM_BUG_ON(vma->node.start < start);
|
|
|
+ GEM_BUG_ON(vma->node.start + vma->node.size > end);
|
|
|
}
|
|
|
GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
|
|
|
|
|
@@ -3798,7 +3801,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
|
|
|
u64 alignment,
|
|
|
u64 flags)
|
|
|
{
|
|
|
- struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
|
|
+ struct i915_address_space *vm = &dev_priv->ggtt.base;
|
|
|
struct i915_vma *vma;
|
|
|
int ret;
|
|
|
|
|
@@ -3811,6 +3815,41 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
|
|
|
(i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
|
|
|
return ERR_PTR(-ENOSPC);
|
|
|
|
|
|
+ if (flags & PIN_MAPPABLE) {
|
|
|
+ u32 fence_size;
|
|
|
+
|
|
|
+ fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
|
|
|
+ i915_gem_object_get_tiling(obj));
|
|
|
+ /* If the required space is larger than the available
|
|
|
+ * aperture, we will not able to find a slot for the
|
|
|
+ * object and unbinding the object now will be in
|
|
|
+ * vain. Worse, doing so may cause us to ping-pong
|
|
|
+ * the object in and out of the Global GTT and
|
|
|
+ * waste a lot of cycles under the mutex.
|
|
|
+ */
|
|
|
+ if (fence_size > dev_priv->ggtt.mappable_end)
|
|
|
+ return ERR_PTR(-E2BIG);
|
|
|
+
|
|
|
+ /* If NONBLOCK is set the caller is optimistically
|
|
|
+ * trying to cache the full object within the mappable
|
|
|
+ * aperture, and *must* have a fallback in place for
|
|
|
+ * situations where we cannot bind the object. We
|
|
|
+ * can be a little more lax here and use the fallback
|
|
|
+ * more often to avoid costly migrations of ourselves
|
|
|
+ * and other objects within the aperture.
|
|
|
+ *
|
|
|
+ * Half-the-aperture is used as a simple heuristic.
|
|
|
+ * More interesting would to do search for a free
|
|
|
+ * block prior to making the commitment to unbind.
|
|
|
+ * That caters for the self-harm case, and with a
|
|
|
+ * little more heuristics (e.g. NOFAULT, NOEVICT)
|
|
|
+ * we could try to minimise harm to others.
|
|
|
+ */
|
|
|
+ if (flags & PIN_NONBLOCK &&
|
|
|
+ fence_size > dev_priv->ggtt.mappable_end / 2)
|
|
|
+ return ERR_PTR(-ENOSPC);
|
|
|
+ }
|
|
|
+
|
|
|
WARN(i915_vma_is_pinned(vma),
|
|
|
"bo is already pinned in ggtt with incorrect alignment:"
|
|
|
" offset=%08x, req.alignment=%llx,"
|