forked from Minki/linux
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: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
1f9a99e0e7
commit
def0c5f6b0
@ -2002,11 +2002,35 @@ static int init_phys_status_page(struct intel_engine_cs *ring)
|
||||
|
||||
void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
|
||||
{
|
||||
iounmap(ringbuf->virtual_start);
|
||||
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,21 +2038,39 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
|
||||
struct drm_i915_gem_object *obj = ringbuf->obj;
|
||||
int ret;
|
||||
|
||||
ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
|
||||
if (ret)
|
||||
return 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_gtt_domain(obj, true);
|
||||
if (ret) {
|
||||
i915_gem_object_ggtt_unpin(obj);
|
||||
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 = ioremap_wc(dev_priv->gtt.mappable_base +
|
||||
i915_gem_obj_ggtt_offset(obj), ringbuf->size);
|
||||
if (ringbuf->virtual_start == NULL) {
|
||||
i915_gem_object_ggtt_unpin(obj);
|
||||
return -EINVAL;
|
||||
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;
|
||||
|
||||
ret = i915_gem_object_set_to_gtt_domain(obj, true);
|
||||
if (ret) {
|
||||
i915_gem_object_ggtt_unpin(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base +
|
||||
i915_gem_obj_ggtt_offset(obj), ringbuf->size);
|
||||
if (ringbuf->virtual_start == NULL) {
|
||||
i915_gem_object_ggtt_unpin(obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user