Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2014 Intel Corporation
  4 */
  5
  6#include "i915_drv.h"
  7#include "intel_renderstate.h"
  8#include "intel_context.h"
  9#include "intel_gpu_commands.h"
 10#include "intel_ring.h"
 11
 12static const struct intel_renderstate_rodata *
 13render_state_get_rodata(const struct intel_engine_cs *engine)
 14{
 15	if (engine->class != RENDER_CLASS)
 16		return NULL;
 17
 18	switch (GRAPHICS_VER(engine->i915)) {
 19	case 6:
 20		return &gen6_null_state;
 21	case 7:
 22		return &gen7_null_state;
 23	case 8:
 24		return &gen8_null_state;
 25	case 9:
 26		return &gen9_null_state;
 27	}
 28
 29	return NULL;
 30}
 31
 32/*
 33 * Macro to add commands to auxiliary batch.
 34 * This macro only checks for page overflow before inserting the commands,
 35 * this is sufficient as the null state generator makes the final batch
 36 * with two passes to build command and state separately. At this point
 37 * the size of both are known and it compacts them by relocating the state
 38 * right after the commands taking care of alignment so we should sufficient
 39 * space below them for adding new commands.
 40 */
 41#define OUT_BATCH(batch, i, val)				\
 42	do {							\
 43		if ((i) >= PAGE_SIZE / sizeof(u32))		\
 44			goto out;				\
 45		(batch)[(i)++] = (val);				\
 46	} while (0)
 47
 48static int render_state_setup(struct intel_renderstate *so,
 49			      struct drm_i915_private *i915)
 50{
 51	const struct intel_renderstate_rodata *rodata = so->rodata;
 52	unsigned int i = 0, reloc_index = 0;
 53	int ret = -EINVAL;
 54	u32 *d;
 55
 56	d = i915_gem_object_pin_map(so->vma->obj, I915_MAP_WB);
 57	if (IS_ERR(d))
 58		return PTR_ERR(d);
 59
 60	while (i < rodata->batch_items) {
 61		u32 s = rodata->batch[i];
 62
 63		if (i * 4  == rodata->reloc[reloc_index]) {
 64			u64 r = s + so->vma->node.start;
 65
 66			s = lower_32_bits(r);
 67			if (HAS_64BIT_RELOC(i915)) {
 68				if (i + 1 >= rodata->batch_items ||
 69				    rodata->batch[i + 1] != 0)
 70					goto out;
 71
 72				d[i++] = s;
 73				s = upper_32_bits(r);
 74			}
 75
 76			reloc_index++;
 77		}
 78
 79		d[i++] = s;
 80	}
 81
 82	if (rodata->reloc[reloc_index] != -1) {
 83		drm_err(&i915->drm, "only %d relocs resolved\n", reloc_index);
 84		goto out;
 85	}
 86
 87	so->batch_offset = i915_ggtt_offset(so->vma);
 88	so->batch_size = rodata->batch_items * sizeof(u32);
 89
 90	while (i % CACHELINE_DWORDS)
 91		OUT_BATCH(d, i, MI_NOOP);
 92
 93	so->aux_offset = i * sizeof(u32);
 94
 95	if (HAS_POOLED_EU(i915)) {
 96		/*
 97		 * We always program 3x6 pool config but depending upon which
 98		 * subslice is disabled HW drops down to appropriate config
 99		 * shown below.
100		 *
101		 * In the below table 2x6 config always refers to
102		 * fused-down version, native 2x6 is not available and can
103		 * be ignored
104		 *
105		 * SNo  subslices config                eu pool configuration
106		 * -----------------------------------------------------------
107		 * 1    3 subslices enabled (3x6)  -    0x00777000  (9+9)
108		 * 2    ss0 disabled (2x6)         -    0x00777000  (3+9)
109		 * 3    ss1 disabled (2x6)         -    0x00770000  (6+6)
110		 * 4    ss2 disabled (2x6)         -    0x00007000  (9+3)
111		 */
112		u32 eu_pool_config = 0x00777000;
113
114		OUT_BATCH(d, i, GEN9_MEDIA_POOL_STATE);
115		OUT_BATCH(d, i, GEN9_MEDIA_POOL_ENABLE);
116		OUT_BATCH(d, i, eu_pool_config);
117		OUT_BATCH(d, i, 0);
118		OUT_BATCH(d, i, 0);
119		OUT_BATCH(d, i, 0);
120	}
121
122	OUT_BATCH(d, i, MI_BATCH_BUFFER_END);
123	so->aux_size = i * sizeof(u32) - so->aux_offset;
124	so->aux_offset += so->batch_offset;
125	/*
126	 * Since we are sending length, we need to strictly conform to
127	 * all requirements. For Gen2 this must be a multiple of 8.
128	 */
129	so->aux_size = ALIGN(so->aux_size, 8);
130
131	ret = 0;
132out:
133	__i915_gem_object_flush_map(so->vma->obj, 0, i * sizeof(u32));
134	__i915_gem_object_release_map(so->vma->obj);
135	return ret;
136}
137
138#undef OUT_BATCH
139
140int intel_renderstate_init(struct intel_renderstate *so,
141			   struct intel_context *ce)
142{
143	struct intel_engine_cs *engine = ce->engine;
144	struct drm_i915_gem_object *obj = NULL;
145	int err;
146
147	memset(so, 0, sizeof(*so));
148
149	so->rodata = render_state_get_rodata(engine);
150	if (so->rodata) {
151		if (so->rodata->batch_items * 4 > PAGE_SIZE)
152			return -EINVAL;
153
154		obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
155		if (IS_ERR(obj))
156			return PTR_ERR(obj);
157
158		so->vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL);
159		if (IS_ERR(so->vma)) {
160			err = PTR_ERR(so->vma);
161			goto err_obj;
162		}
163	}
164
165	i915_gem_ww_ctx_init(&so->ww, true);
166retry:
167	err = intel_context_pin_ww(ce, &so->ww);
168	if (err)
169		goto err_fini;
170
171	/* return early if there's nothing to setup */
172	if (!err && !so->rodata)
173		return 0;
174
175	err = i915_gem_object_lock(so->vma->obj, &so->ww);
176	if (err)
177		goto err_context;
178
179	err = i915_vma_pin_ww(so->vma, &so->ww, 0, 0, PIN_GLOBAL | PIN_HIGH);
180	if (err)
181		goto err_context;
182
183	err = render_state_setup(so, engine->i915);
184	if (err)
185		goto err_unpin;
186
187	return 0;
188
189err_unpin:
190	i915_vma_unpin(so->vma);
191err_context:
192	intel_context_unpin(ce);
193err_fini:
194	if (err == -EDEADLK) {
195		err = i915_gem_ww_ctx_backoff(&so->ww);
196		if (!err)
197			goto retry;
198	}
199	i915_gem_ww_ctx_fini(&so->ww);
200err_obj:
201	if (obj)
202		i915_gem_object_put(obj);
203	so->vma = NULL;
204	return err;
205}
206
207int intel_renderstate_emit(struct intel_renderstate *so,
208			   struct i915_request *rq)
209{
210	struct intel_engine_cs *engine = rq->engine;
211	int err;
212
213	if (!so->vma)
214		return 0;
215
216	err = i915_request_await_object(rq, so->vma->obj, false);
217	if (err == 0)
218		err = i915_vma_move_to_active(so->vma, rq, 0);
219	if (err)
220		return err;
221
222	err = engine->emit_bb_start(rq,
223				    so->batch_offset, so->batch_size,
224				    I915_DISPATCH_SECURE);
225	if (err)
226		return err;
227
228	if (so->aux_size > 8) {
229		err = engine->emit_bb_start(rq,
230					    so->aux_offset, so->aux_size,
231					    I915_DISPATCH_SECURE);
232		if (err)
233			return err;
234	}
235
236	return 0;
237}
238
239void intel_renderstate_fini(struct intel_renderstate *so,
240			    struct intel_context *ce)
241{
242	if (so->vma) {
243		i915_vma_unpin(so->vma);
244		i915_vma_close(so->vma);
245	}
246
247	intel_context_unpin(ce);
248	i915_gem_ww_ctx_fini(&so->ww);
249
250	if (so->vma)
251		i915_gem_object_put(so->vma->obj);
252}