|
@@ -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;
|
|
|
}
|