forked from mirrors/linux
		
	drm/i915: Simplify processing of the golden render context state
Rewrite i915_gem_render_state.c for the purposes of clarity and compactness, in the process we can eliminate some dodgy math that did not handle 64bit addresses correctly. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Damien Lespiau <damien.lespiau@intel.com> Cc: Mika Kuoppala <mika.kuoppala@intel.com> Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
		
							parent
							
								
									6254b2042c
								
							
						
					
					
						commit
						1ce826d436
					
				
					 5 changed files with 69 additions and 97 deletions
				
			
		| 
						 | 
					@ -28,64 +28,13 @@
 | 
				
			||||||
#include "i915_drv.h"
 | 
					#include "i915_drv.h"
 | 
				
			||||||
#include "intel_renderstate.h"
 | 
					#include "intel_renderstate.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct i915_render_state {
 | 
					struct render_state {
 | 
				
			||||||
 | 
						const struct intel_renderstate_rodata *rodata;
 | 
				
			||||||
	struct drm_i915_gem_object *obj;
 | 
						struct drm_i915_gem_object *obj;
 | 
				
			||||||
	unsigned long ggtt_offset;
 | 
						u64 ggtt_offset;
 | 
				
			||||||
	void *batch;
 | 
						int gen;
 | 
				
			||||||
	u32 size;
 | 
					 | 
				
			||||||
	u32 len;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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 *
 | 
					static const struct intel_renderstate_rodata *
 | 
				
			||||||
render_state_get_rodata(struct drm_device *dev, const int gen)
 | 
					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;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int render_state_setup(const int gen,
 | 
					static int render_state_init(struct render_state *so, struct drm_device *dev)
 | 
				
			||||||
			      const struct intel_renderstate_rodata *rodata,
 | 
					 | 
				
			||||||
			      struct i915_render_state *so)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	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;
 | 
						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;
 | 
							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);
 | 
						ret = i915_gem_object_set_to_cpu_domain(so->obj, true);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						page = sg_page(so->obj->pages->sgl);
 | 
				
			||||||
 | 
						d = kmap(page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (i < rodata->batch_items) {
 | 
						while (i < rodata->batch_items) {
 | 
				
			||||||
		u32 s = rodata->batch[i];
 | 
							u32 s = rodata->batch[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (reloc_index < rodata->reloc_items &&
 | 
							if (i * 4  == rodata->reloc[reloc_index]) {
 | 
				
			||||||
		    i * 4  == rodata->reloc[reloc_index]) {
 | 
								u64 r = s + so->ggtt_offset;
 | 
				
			||||||
 | 
								s = lower_32_bits(r);
 | 
				
			||||||
			s += goffset & 0xffffffff;
 | 
								if (so->gen >= 8) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* We keep batch offsets max 32bit */
 | 
					 | 
				
			||||||
			if (gen >= 8) {
 | 
					 | 
				
			||||||
				if (i + 1 >= rodata->batch_items ||
 | 
									if (i + 1 >= rodata->batch_items ||
 | 
				
			||||||
				    rodata->batch[i + 1] != 0)
 | 
									    rodata->batch[i + 1] != 0)
 | 
				
			||||||
					return -EINVAL;
 | 
										return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				d[i] = s;
 | 
									d[i++] = s;
 | 
				
			||||||
				i++;
 | 
									s = upper_32_bits(r);
 | 
				
			||||||
				s = (goffset & 0xffffffff00000000ull) >> 32;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			reloc_index++;
 | 
								reloc_index++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		d[i] = s;
 | 
							d[i++] = s;
 | 
				
			||||||
		i++;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						kunmap(page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = i915_gem_object_set_to_gtt_domain(so->obj, false);
 | 
						ret = i915_gem_object_set_to_gtt_domain(so->obj, false);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rodata->reloc_items != reloc_index) {
 | 
						if (rodata->reloc[reloc_index] != -1) {
 | 
				
			||||||
		DRM_ERROR("not all relocs resolved, %d out of %d\n",
 | 
							DRM_ERROR("only %d relocs resolved\n", reloc_index);
 | 
				
			||||||
			  reloc_index, rodata->reloc_items);
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	so->len = rodata->batch_items * 4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						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)
 | 
					int i915_gem_render_state_init(struct intel_engine_cs *ring)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const int gen = INTEL_INFO(ring->dev)->gen;
 | 
						struct render_state so;
 | 
				
			||||||
	struct i915_render_state *so;
 | 
					 | 
				
			||||||
	const struct intel_renderstate_rodata *rodata;
 | 
					 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (WARN_ON(ring->id != RCS))
 | 
						if (WARN_ON(ring->id != RCS))
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rodata = render_state_get_rodata(ring->dev, gen);
 | 
						ret = render_state_init(&so, ring->dev);
 | 
				
			||||||
	if (rodata == NULL)
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (so.rodata == NULL)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	so = render_state_alloc(ring->dev);
 | 
						ret = render_state_setup(&so);
 | 
				
			||||||
	if (IS_ERR(so))
 | 
					 | 
				
			||||||
		return PTR_ERR(so);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = render_state_setup(gen, rodata, so);
 | 
					 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = ring->dispatch_execbuffer(ring,
 | 
						ret = ring->dispatch_execbuffer(ring,
 | 
				
			||||||
					i915_gem_obj_ggtt_offset(so->obj),
 | 
										so.ggtt_offset,
 | 
				
			||||||
					so->len,
 | 
										so.rodata->batch_items * 4,
 | 
				
			||||||
					I915_DISPATCH_SECURE);
 | 
										I915_DISPATCH_SECURE);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out;
 | 
							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 */
 | 
						/* __i915_add_request moves object to inactive if it fails */
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	render_state_free(so);
 | 
						render_state_fini(&so);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct intel_renderstate_rodata {
 | 
					struct intel_renderstate_rodata {
 | 
				
			||||||
	const u32 *reloc;
 | 
						const u32 *reloc;
 | 
				
			||||||
	const u32 reloc_items;
 | 
					 | 
				
			||||||
	const u32 *batch;
 | 
						const u32 *batch;
 | 
				
			||||||
	const u32 batch_items;
 | 
						const u32 batch_items;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -40,7 +39,6 @@ extern const struct intel_renderstate_rodata gen8_null_state;
 | 
				
			||||||
#define RO_RENDERSTATE(_g)						\
 | 
					#define RO_RENDERSTATE(_g)						\
 | 
				
			||||||
	const struct intel_renderstate_rodata gen ## _g ## _null_state = { \
 | 
						const struct intel_renderstate_rodata gen ## _g ## _null_state = { \
 | 
				
			||||||
		.reloc = gen ## _g ## _null_state_relocs,		\
 | 
							.reloc = gen ## _g ## _null_state_relocs,		\
 | 
				
			||||||
		.reloc_items = sizeof(gen ## _g ## _null_state_relocs)/4, \
 | 
					 | 
				
			||||||
		.batch = gen ## _g ## _null_state_batch,		\
 | 
							.batch = gen ## _g ## _null_state_batch,		\
 | 
				
			||||||
		.batch_items = sizeof(gen ## _g ## _null_state_batch)/4, \
 | 
							.batch_items = sizeof(gen ## _g ## _null_state_batch)/4, \
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ static const u32 gen6_null_state_relocs[] = {
 | 
				
			||||||
	0x0000002c,
 | 
						0x0000002c,
 | 
				
			||||||
	0x000001e0,
 | 
						0x000001e0,
 | 
				
			||||||
	0x000001e4,
 | 
						0x000001e4,
 | 
				
			||||||
 | 
						-1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const u32 gen6_null_state_batch[] = {
 | 
					static const u32 gen6_null_state_batch[] = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ static const u32 gen7_null_state_relocs[] = {
 | 
				
			||||||
	0x00000010,
 | 
						0x00000010,
 | 
				
			||||||
	0x00000018,
 | 
						0x00000018,
 | 
				
			||||||
	0x000001ec,
 | 
						0x000001ec,
 | 
				
			||||||
 | 
						-1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const u32 gen7_null_state_batch[] = {
 | 
					static const u32 gen7_null_state_batch[] = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ static const u32 gen8_null_state_relocs[] = {
 | 
				
			||||||
	0x00000050,
 | 
						0x00000050,
 | 
				
			||||||
	0x00000060,
 | 
						0x00000060,
 | 
				
			||||||
	0x000003ec,
 | 
						0x000003ec,
 | 
				
			||||||
 | 
						-1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const u32 gen8_null_state_batch[] = {
 | 
					static const u32 gen8_null_state_batch[] = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue