Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit def0c5f6 authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter
Browse files

drm/i915: Map the ringbuffer using WB on LLC machines



If we have llc coherency, we can write directly into the ringbuffer
using ordinary cached writes rather than forcing WC access.

v2: An important consequence is that we can forgo the mappable request
for WB ringbuffers, allowing for many more simultaneous contexts.

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 1f9a99e0
Loading
Loading
Loading
Loading
+56 −14
Original line number Diff line number Diff line
@@ -2002,11 +2002,35 @@ static int init_phys_status_page(struct intel_engine_cs *ring)

void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
{
	if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen)
		vunmap(ringbuf->virtual_start);
	else
		iounmap(ringbuf->virtual_start);
	ringbuf->virtual_start = NULL;
	i915_gem_object_ggtt_unpin(ringbuf->obj);
}

static u32 *vmap_obj(struct drm_i915_gem_object *obj)
{
	struct sg_page_iter sg_iter;
	struct page **pages;
	void *addr;
	int i;

	pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
	if (pages == NULL)
		return NULL;

	i = 0;
	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
		pages[i++] = sg_page_iter_page(&sg_iter);

	addr = vmap(pages, i, 0, PAGE_KERNEL);
	drm_free_large(pages);

	return addr;
}

int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
				     struct intel_ringbuffer *ringbuf)
{
@@ -2014,6 +2038,23 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
	struct drm_i915_gem_object *obj = ringbuf->obj;
	int ret;

	if (HAS_LLC(dev_priv) && !obj->stolen) {
		ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 0);
		if (ret)
			return ret;

		ret = i915_gem_object_set_to_cpu_domain(obj, true);
		if (ret) {
			i915_gem_object_ggtt_unpin(obj);
			return ret;
		}

		ringbuf->virtual_start = vmap_obj(obj);
		if (ringbuf->virtual_start == NULL) {
			i915_gem_object_ggtt_unpin(obj);
			return -ENOMEM;
		}
	} else {
		ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
		if (ret)
			return ret;
@@ -2030,6 +2071,7 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
			i915_gem_object_ggtt_unpin(obj);
			return -EINVAL;
		}
	}

	return 0;
}