diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_render_state.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_render_state.c | 161 |
1 files changed, 66 insertions, 95 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 3521f998a178..e60be3f552a6 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -28,64 +28,13 @@ #include "i915_drv.h" #include "intel_renderstate.h" -struct i915_render_state { +struct render_state { + const struct intel_renderstate_rodata *rodata; struct drm_i915_gem_object *obj; - unsigned long ggtt_offset; - void *batch; - u32 size; - u32 len; + u64 ggtt_offset; + int gen; }; -static struct i915_render_state *render_state_alloc(struct drm_device *dev) -{ - struct i915_render_state *so; - struct page *page; - int ret; - - so = kzalloc(sizeof(*so), GFP_KERNEL); - if (!so) - return ERR_PTR(-ENOMEM); - - so->obj = i915_gem_alloc_object(dev, 4096); - if (so->obj == NULL) { - ret = -ENOMEM; - goto free; - } - so->size = 4096; - - ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0); - if (ret) - goto free_gem; - - BUG_ON(so->obj->pages->nents != 1); - page = sg_page(so->obj->pages->sgl); - - so->batch = kmap(page); - if (!so->batch) { - ret = -ENOMEM; - goto unpin; - } - - so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj); - - return so; -unpin: - i915_gem_object_ggtt_unpin(so->obj); -free_gem: - drm_gem_object_unreference(&so->obj->base); -free: - kfree(so); - return ERR_PTR(ret); -} - -static void render_state_free(struct i915_render_state *so) -{ - kunmap(so->batch); - i915_gem_object_ggtt_unpin(so->obj); - drm_gem_object_unreference(&so->obj->base); - kfree(so); -} - static const struct intel_renderstate_rodata * render_state_get_rodata(struct drm_device *dev, const int gen) { @@ -101,98 +50,120 @@ render_state_get_rodata(struct drm_device *dev, const int gen) return NULL; } -static int render_state_setup(const int gen, - const struct intel_renderstate_rodata *rodata, - struct i915_render_state *so) +static int render_state_init(struct render_state *so, struct drm_device *dev) { - const u64 goffset = i915_gem_obj_ggtt_offset(so->obj); - u32 reloc_index = 0; - u32 * const d = so->batch; - unsigned int i = 0; int ret; - if (!rodata || rodata->batch_items * 4 > so->size) + so->gen = INTEL_INFO(dev)->gen; + so->rodata = render_state_get_rodata(dev, so->gen); + if (so->rodata == NULL) + return 0; + + if (so->rodata->batch_items * 4 > 4096) return -EINVAL; + so->obj = i915_gem_alloc_object(dev, 4096); + if (so->obj == NULL) + return -ENOMEM; + + ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0); + if (ret) + goto free_gem; + + so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj); + return 0; + +free_gem: + drm_gem_object_unreference(&so->obj->base); + return ret; +} + +static int render_state_setup(struct render_state *so) +{ + const struct intel_renderstate_rodata *rodata = so->rodata; + unsigned int i = 0, reloc_index = 0; + struct page *page; + u32 *d; + int ret; + ret = i915_gem_object_set_to_cpu_domain(so->obj, true); if (ret) return ret; + page = sg_page(so->obj->pages->sgl); + d = kmap(page); + while (i < rodata->batch_items) { u32 s = rodata->batch[i]; - if (reloc_index < rodata->reloc_items && - i * 4 == rodata->reloc[reloc_index]) { - - s += goffset & 0xffffffff; - - /* We keep batch offsets max 32bit */ - if (gen >= 8) { + if (i * 4 == rodata->reloc[reloc_index]) { + u64 r = s + so->ggtt_offset; + s = lower_32_bits(r); + if (so->gen >= 8) { if (i + 1 >= rodata->batch_items || rodata->batch[i + 1] != 0) return -EINVAL; - d[i] = s; - i++; - s = (goffset & 0xffffffff00000000ull) >> 32; + d[i++] = s; + s = upper_32_bits(r); } reloc_index++; } - d[i] = s; - i++; + d[i++] = s; } + kunmap(page); ret = i915_gem_object_set_to_gtt_domain(so->obj, false); if (ret) return ret; - if (rodata->reloc_items != reloc_index) { - DRM_ERROR("not all relocs resolved, %d out of %d\n", - reloc_index, rodata->reloc_items); + if (rodata->reloc[reloc_index] != -1) { + DRM_ERROR("only %d relocs resolved\n", reloc_index); return -EINVAL; } - so->len = rodata->batch_items * 4; - return 0; } +static void render_state_fini(struct render_state *so) +{ + i915_gem_object_ggtt_unpin(so->obj); + drm_gem_object_unreference(&so->obj->base); +} + int i915_gem_render_state_init(struct intel_engine_cs *ring) { - const int gen = INTEL_INFO(ring->dev)->gen; - struct i915_render_state *so; - const struct intel_renderstate_rodata *rodata; + struct render_state so; int ret; if (WARN_ON(ring->id != RCS)) return -ENOENT; - rodata = render_state_get_rodata(ring->dev, gen); - if (rodata == NULL) - return 0; + ret = render_state_init(&so, ring->dev); + if (ret) + return ret; - so = render_state_alloc(ring->dev); - if (IS_ERR(so)) - return PTR_ERR(so); + if (so.rodata == NULL) + return 0; - ret = render_state_setup(gen, rodata, so); + ret = render_state_setup(&so); if (ret) goto out; ret = ring->dispatch_execbuffer(ring, - i915_gem_obj_ggtt_offset(so->obj), - so->len, + so.ggtt_offset, + so.rodata->batch_items * 4, I915_DISPATCH_SECURE); if (ret) goto out; - i915_vma_move_to_active(i915_gem_obj_to_ggtt(so->obj), ring); + i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), ring); - ret = __i915_add_request(ring, NULL, so->obj, NULL); + ret = __i915_add_request(ring, NULL, so.obj, NULL); /* __i915_add_request moves object to inactive if it fails */ out: - render_state_free(so); + render_state_fini(&so); return ret; } |