瀏覽代碼

drm/i915: Add a partial GGTT view type

Partial view type allows manipulating parts of huge BOs through the GGTT,
which was not previously possible due to constraint that whole object had
to be mapped for any access to it through GGTT.

v2:
- Retain error value from sg_alloc_table (Tvrtko Ursulin)
- Do not zero already zeroed variable (Tvrtko Ursulin)
- Use more common variable types for page size/offset (Tvrtko Ursulin)
v3:
- Only compare additional view parameters when need to (Tvrtko Ursulin)
v4:
- Do zero out the variable that needs to be (bug introduced in v2).

Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Joonas Lahtinen 10 年之前
父節點
當前提交
8bd7ef1638
共有 2 個文件被更改,包括 60 次插入2 次删除
  1. 46 0
      drivers/gpu/drm/i915/i915_gem_gtt.c
  2. 14 2
      drivers/gpu/drm/i915/i915_gem_gtt.h

+ 46 - 0
drivers/gpu/drm/i915/i915_gem_gtt.c

@@ -2753,6 +2753,47 @@ err_st_alloc:
 	return ERR_PTR(ret);
 	return ERR_PTR(ret);
 }
 }
 
 
+static struct sg_table *
+intel_partial_pages(const struct i915_ggtt_view *view,
+		    struct drm_i915_gem_object *obj)
+{
+	struct sg_table *st;
+	struct scatterlist *sg;
+	struct sg_page_iter obj_sg_iter;
+	int ret = -ENOMEM;
+
+	st = kmalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		goto err_st_alloc;
+
+	ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL);
+	if (ret)
+		goto err_sg_alloc;
+
+	sg = st->sgl;
+	st->nents = 0;
+	for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents,
+		view->params.partial.offset)
+	{
+		if (st->nents >= view->params.partial.size)
+			break;
+
+		sg_set_page(sg, NULL, PAGE_SIZE, 0);
+		sg_dma_address(sg) = sg_page_iter_dma_address(&obj_sg_iter);
+		sg_dma_len(sg) = PAGE_SIZE;
+
+		sg = sg_next(sg);
+		st->nents++;
+	}
+
+	return st;
+
+err_sg_alloc:
+	kfree(st);
+err_st_alloc:
+	return ERR_PTR(ret);
+}
+
 static int
 static int
 i915_get_ggtt_vma_pages(struct i915_vma *vma)
 i915_get_ggtt_vma_pages(struct i915_vma *vma)
 {
 {
@@ -2766,6 +2807,9 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma)
 	else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
 	else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
 		vma->ggtt_view.pages =
 		vma->ggtt_view.pages =
 			intel_rotate_fb_obj_pages(&vma->ggtt_view, vma->obj);
 			intel_rotate_fb_obj_pages(&vma->ggtt_view, vma->obj);
+	else if (vma->ggtt_view.type == I915_GGTT_VIEW_PARTIAL)
+		vma->ggtt_view.pages =
+			intel_partial_pages(&vma->ggtt_view, vma->obj);
 	else
 	else
 		WARN_ONCE(1, "GGTT view %u not implemented!\n",
 		WARN_ONCE(1, "GGTT view %u not implemented!\n",
 			  vma->ggtt_view.type);
 			  vma->ggtt_view.type);
@@ -2853,6 +2897,8 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
 	if (view->type == I915_GGTT_VIEW_NORMAL ||
 	if (view->type == I915_GGTT_VIEW_NORMAL ||
 	    view->type == I915_GGTT_VIEW_ROTATED) {
 	    view->type == I915_GGTT_VIEW_ROTATED) {
 		return obj->base.size;
 		return obj->base.size;
+	} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
+		return view->params.partial.size << PAGE_SHIFT;
 	} else {
 	} else {
 		WARN_ONCE(1, "GGTT view %u not implemented!\n", view->type);
 		WARN_ONCE(1, "GGTT view %u not implemented!\n", view->type);
 		return obj->base.size;
 		return obj->base.size;

+ 14 - 2
drivers/gpu/drm/i915/i915_gem_gtt.h

@@ -117,7 +117,8 @@ typedef uint64_t gen8_pde_t;
 
 
 enum i915_ggtt_view_type {
 enum i915_ggtt_view_type {
 	I915_GGTT_VIEW_NORMAL = 0,
 	I915_GGTT_VIEW_NORMAL = 0,
-	I915_GGTT_VIEW_ROTATED
+	I915_GGTT_VIEW_ROTATED,
+	I915_GGTT_VIEW_PARTIAL,
 };
 };
 
 
 struct intel_rotation_info {
 struct intel_rotation_info {
@@ -130,6 +131,13 @@ struct intel_rotation_info {
 struct i915_ggtt_view {
 struct i915_ggtt_view {
 	enum i915_ggtt_view_type type;
 	enum i915_ggtt_view_type type;
 
 
+	union {
+		struct {
+			unsigned long offset;
+			unsigned int size;
+		} partial;
+	} params;
+
 	struct sg_table *pages;
 	struct sg_table *pages;
 
 
 	union {
 	union {
@@ -495,7 +503,11 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
 	if (WARN_ON(!a || !b))
 	if (WARN_ON(!a || !b))
 		return false;
 		return false;
 
 
-	return a->type == b->type;
+	if (a->type != b->type)
+		return false;
+	if (a->type == I915_GGTT_VIEW_PARTIAL)
+		return !memcmp(&a->params, &b->params, sizeof(a->params));
+	return true;
 }
 }
 
 
 size_t
 size_t