@@ -1110,8 +1110,12 @@ struct drm_i915_gem_object_ops {
* will therefore most likely be called when the object itself is
* being released or under memory pressure (where we attempt to
* reap pages for the shrinker).
+ *
+ * max is the maximum size an sg entry can be. Usually it is
+ * PAGE_SIZE but if the backend (IOMMU) can deal with larger
+ * then a larger value might be used as well.
*/
- int (*get_pages)(struct drm_i915_gem_object *);
+ int (*get_pages)(struct drm_i915_gem_object *, unsigned long max);
void (*put_pages)(struct drm_i915_gem_object *);
};
@@ -1738,7 +1738,7 @@ i915_gem_shrink_all(struct drm_i915_private *dev_priv)
}
static int
-i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
+i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, unsigned long max)
{
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
int page_count, i;
@@ -1809,7 +1809,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
continue;
}
#endif
- if (!i || page_to_pfn(page) != last_pfn + 1) {
+ if ((!i || (page_to_pfn(page) != last_pfn + 1)) && (sg->length < max)) {
if (i)
sg = sg_next(sg);
st->nents++;
@@ -1847,7 +1847,7 @@ err_pages:
* or as the object is itself released.
*/
int
-i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
+i915_gem_object_get_pages(struct drm_i915_gem_object *obj, unsigned int max)
{
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
const struct drm_i915_gem_object_ops *ops = obj->ops;
@@ -1863,7 +1863,7 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
BUG_ON(obj->pages_pin_count);
- ret = ops->get_pages(obj);
+ ret = ops->get_pages(obj, max);
if (ret)
return ret;
@@ -2942,7 +2942,12 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
u32 size, fence_size, fence_alignment, unfenced_alignment;
bool mappable, fenceable;
int ret;
+ static unsigned int max_size = 4 * 1024 * 1024; /* 4MB */
+#ifdef CONFIG_SWIOTLB
+ if (swiotlb_nr_tbl())
+ max_size = PAGE_SIZE;
+#endif
fence_size = i915_gem_get_gtt_size(dev,
obj->base.size,
obj->tiling_mode);
@@ -2972,8 +2977,8 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
DRM_ERROR("Attempting to bind an object larger than the aperture\n");
return -E2BIG;
}
-
- ret = i915_gem_object_get_pages(obj);
+ retry:
+ ret = i915_gem_object_get_pages(obj, max_size);
if (ret)
return ret;
@@ -3015,6 +3020,10 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
if (ret) {
i915_gem_object_unpin_pages(obj);
drm_mm_put_block(node);
+ if (max_size > PAGE_SIZE) {
+ max_size >> 1;
+ goto retry;
+ }
return ret;
}
@@ -230,7 +230,8 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, flags);
}
-static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
+static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj,
+ unsigned long max)
{
struct sg_table *sg;
@@ -231,7 +231,8 @@ i915_pages_create_for_stolen(struct drm_device *dev,
return st;
}
-static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
+static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj,
+ unsigned long max)
{
BUG();
return -EINVAL;