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 12 static const struct intel_renderstate_rodata * 13 render_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 48 static 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; 132 out: 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 140 int 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); 166 retry: 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 189 err_unpin: 190 i915_vma_unpin(so->vma); 191 err_context: 192 intel_context_unpin(ce); 193 err_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); 200 err_obj: 201 if (obj) 202 i915_gem_object_put(obj); 203 so->vma = NULL; 204 return err; 205 } 206 207 int 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 239 void 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 } 253