18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright © 2014 Intel Corporation 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next 128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 138c2ecf20Sopenharmony_ci * Software. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 218c2ecf20Sopenharmony_ci * IN THE SOFTWARE. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Authors: 248c2ecf20Sopenharmony_ci * Mika Kuoppala <mika.kuoppala@intel.com> 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include "i915_drv.h" 298c2ecf20Sopenharmony_ci#include "intel_renderstate.h" 308c2ecf20Sopenharmony_ci#include "gt/intel_context.h" 318c2ecf20Sopenharmony_ci#include "intel_ring.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic const struct intel_renderstate_rodata * 348c2ecf20Sopenharmony_cirender_state_get_rodata(const struct intel_engine_cs *engine) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci if (engine->class != RENDER_CLASS) 378c2ecf20Sopenharmony_ci return NULL; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci switch (INTEL_GEN(engine->i915)) { 408c2ecf20Sopenharmony_ci case 6: 418c2ecf20Sopenharmony_ci return &gen6_null_state; 428c2ecf20Sopenharmony_ci case 7: 438c2ecf20Sopenharmony_ci return &gen7_null_state; 448c2ecf20Sopenharmony_ci case 8: 458c2ecf20Sopenharmony_ci return &gen8_null_state; 468c2ecf20Sopenharmony_ci case 9: 478c2ecf20Sopenharmony_ci return &gen9_null_state; 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci return NULL; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* 548c2ecf20Sopenharmony_ci * Macro to add commands to auxiliary batch. 558c2ecf20Sopenharmony_ci * This macro only checks for page overflow before inserting the commands, 568c2ecf20Sopenharmony_ci * this is sufficient as the null state generator makes the final batch 578c2ecf20Sopenharmony_ci * with two passes to build command and state separately. At this point 588c2ecf20Sopenharmony_ci * the size of both are known and it compacts them by relocating the state 598c2ecf20Sopenharmony_ci * right after the commands taking care of alignment so we should sufficient 608c2ecf20Sopenharmony_ci * space below them for adding new commands. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci#define OUT_BATCH(batch, i, val) \ 638c2ecf20Sopenharmony_ci do { \ 648c2ecf20Sopenharmony_ci if ((i) >= PAGE_SIZE / sizeof(u32)) \ 658c2ecf20Sopenharmony_ci goto out; \ 668c2ecf20Sopenharmony_ci (batch)[(i)++] = (val); \ 678c2ecf20Sopenharmony_ci } while(0) 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic int render_state_setup(struct intel_renderstate *so, 708c2ecf20Sopenharmony_ci struct drm_i915_private *i915) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci const struct intel_renderstate_rodata *rodata = so->rodata; 738c2ecf20Sopenharmony_ci unsigned int i = 0, reloc_index = 0; 748c2ecf20Sopenharmony_ci int ret = -EINVAL; 758c2ecf20Sopenharmony_ci u32 *d; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci d = i915_gem_object_pin_map(so->vma->obj, I915_MAP_WB); 788c2ecf20Sopenharmony_ci if (IS_ERR(d)) 798c2ecf20Sopenharmony_ci return PTR_ERR(d); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci while (i < rodata->batch_items) { 828c2ecf20Sopenharmony_ci u32 s = rodata->batch[i]; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (i * 4 == rodata->reloc[reloc_index]) { 858c2ecf20Sopenharmony_ci u64 r = s + so->vma->node.start; 868c2ecf20Sopenharmony_ci s = lower_32_bits(r); 878c2ecf20Sopenharmony_ci if (HAS_64BIT_RELOC(i915)) { 888c2ecf20Sopenharmony_ci if (i + 1 >= rodata->batch_items || 898c2ecf20Sopenharmony_ci rodata->batch[i + 1] != 0) 908c2ecf20Sopenharmony_ci goto out; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci d[i++] = s; 938c2ecf20Sopenharmony_ci s = upper_32_bits(r); 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci reloc_index++; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci d[i++] = s; 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (rodata->reloc[reloc_index] != -1) { 1038c2ecf20Sopenharmony_ci drm_err(&i915->drm, "only %d relocs resolved\n", reloc_index); 1048c2ecf20Sopenharmony_ci goto out; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci so->batch_offset = i915_ggtt_offset(so->vma); 1088c2ecf20Sopenharmony_ci so->batch_size = rodata->batch_items * sizeof(u32); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci while (i % CACHELINE_DWORDS) 1118c2ecf20Sopenharmony_ci OUT_BATCH(d, i, MI_NOOP); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci so->aux_offset = i * sizeof(u32); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (HAS_POOLED_EU(i915)) { 1168c2ecf20Sopenharmony_ci /* 1178c2ecf20Sopenharmony_ci * We always program 3x6 pool config but depending upon which 1188c2ecf20Sopenharmony_ci * subslice is disabled HW drops down to appropriate config 1198c2ecf20Sopenharmony_ci * shown below. 1208c2ecf20Sopenharmony_ci * 1218c2ecf20Sopenharmony_ci * In the below table 2x6 config always refers to 1228c2ecf20Sopenharmony_ci * fused-down version, native 2x6 is not available and can 1238c2ecf20Sopenharmony_ci * be ignored 1248c2ecf20Sopenharmony_ci * 1258c2ecf20Sopenharmony_ci * SNo subslices config eu pool configuration 1268c2ecf20Sopenharmony_ci * ----------------------------------------------------------- 1278c2ecf20Sopenharmony_ci * 1 3 subslices enabled (3x6) - 0x00777000 (9+9) 1288c2ecf20Sopenharmony_ci * 2 ss0 disabled (2x6) - 0x00777000 (3+9) 1298c2ecf20Sopenharmony_ci * 3 ss1 disabled (2x6) - 0x00770000 (6+6) 1308c2ecf20Sopenharmony_ci * 4 ss2 disabled (2x6) - 0x00007000 (9+3) 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_ci u32 eu_pool_config = 0x00777000; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci OUT_BATCH(d, i, GEN9_MEDIA_POOL_STATE); 1358c2ecf20Sopenharmony_ci OUT_BATCH(d, i, GEN9_MEDIA_POOL_ENABLE); 1368c2ecf20Sopenharmony_ci OUT_BATCH(d, i, eu_pool_config); 1378c2ecf20Sopenharmony_ci OUT_BATCH(d, i, 0); 1388c2ecf20Sopenharmony_ci OUT_BATCH(d, i, 0); 1398c2ecf20Sopenharmony_ci OUT_BATCH(d, i, 0); 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci OUT_BATCH(d, i, MI_BATCH_BUFFER_END); 1438c2ecf20Sopenharmony_ci so->aux_size = i * sizeof(u32) - so->aux_offset; 1448c2ecf20Sopenharmony_ci so->aux_offset += so->batch_offset; 1458c2ecf20Sopenharmony_ci /* 1468c2ecf20Sopenharmony_ci * Since we are sending length, we need to strictly conform to 1478c2ecf20Sopenharmony_ci * all requirements. For Gen2 this must be a multiple of 8. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci so->aux_size = ALIGN(so->aux_size, 8); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci ret = 0; 1528c2ecf20Sopenharmony_ciout: 1538c2ecf20Sopenharmony_ci __i915_gem_object_flush_map(so->vma->obj, 0, i * sizeof(u32)); 1548c2ecf20Sopenharmony_ci __i915_gem_object_release_map(so->vma->obj); 1558c2ecf20Sopenharmony_ci return ret; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci#undef OUT_BATCH 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ciint intel_renderstate_init(struct intel_renderstate *so, 1618c2ecf20Sopenharmony_ci struct intel_context *ce) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci struct intel_engine_cs *engine = ce->engine; 1648c2ecf20Sopenharmony_ci struct drm_i915_gem_object *obj = NULL; 1658c2ecf20Sopenharmony_ci int err; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci memset(so, 0, sizeof(*so)); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci so->rodata = render_state_get_rodata(engine); 1708c2ecf20Sopenharmony_ci if (so->rodata) { 1718c2ecf20Sopenharmony_ci if (so->rodata->batch_items * 4 > PAGE_SIZE) 1728c2ecf20Sopenharmony_ci return -EINVAL; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); 1758c2ecf20Sopenharmony_ci if (IS_ERR(obj)) 1768c2ecf20Sopenharmony_ci return PTR_ERR(obj); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci so->vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL); 1798c2ecf20Sopenharmony_ci if (IS_ERR(so->vma)) { 1808c2ecf20Sopenharmony_ci err = PTR_ERR(so->vma); 1818c2ecf20Sopenharmony_ci goto err_obj; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci i915_gem_ww_ctx_init(&so->ww, true); 1868c2ecf20Sopenharmony_ciretry: 1878c2ecf20Sopenharmony_ci err = intel_context_pin_ww(ce, &so->ww); 1888c2ecf20Sopenharmony_ci if (err) 1898c2ecf20Sopenharmony_ci goto err_fini; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* return early if there's nothing to setup */ 1928c2ecf20Sopenharmony_ci if (!err && !so->rodata) 1938c2ecf20Sopenharmony_ci return 0; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci err = i915_gem_object_lock(so->vma->obj, &so->ww); 1968c2ecf20Sopenharmony_ci if (err) 1978c2ecf20Sopenharmony_ci goto err_context; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci err = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH); 2008c2ecf20Sopenharmony_ci if (err) 2018c2ecf20Sopenharmony_ci goto err_context; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci err = render_state_setup(so, engine->i915); 2048c2ecf20Sopenharmony_ci if (err) 2058c2ecf20Sopenharmony_ci goto err_unpin; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci return 0; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cierr_unpin: 2108c2ecf20Sopenharmony_ci i915_vma_unpin(so->vma); 2118c2ecf20Sopenharmony_cierr_context: 2128c2ecf20Sopenharmony_ci intel_context_unpin(ce); 2138c2ecf20Sopenharmony_cierr_fini: 2148c2ecf20Sopenharmony_ci if (err == -EDEADLK) { 2158c2ecf20Sopenharmony_ci err = i915_gem_ww_ctx_backoff(&so->ww); 2168c2ecf20Sopenharmony_ci if (!err) 2178c2ecf20Sopenharmony_ci goto retry; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci i915_gem_ww_ctx_fini(&so->ww); 2208c2ecf20Sopenharmony_cierr_obj: 2218c2ecf20Sopenharmony_ci if (obj) 2228c2ecf20Sopenharmony_ci i915_gem_object_put(obj); 2238c2ecf20Sopenharmony_ci so->vma = NULL; 2248c2ecf20Sopenharmony_ci return err; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciint intel_renderstate_emit(struct intel_renderstate *so, 2288c2ecf20Sopenharmony_ci struct i915_request *rq) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci struct intel_engine_cs *engine = rq->engine; 2318c2ecf20Sopenharmony_ci int err; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (!so->vma) 2348c2ecf20Sopenharmony_ci return 0; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci err = i915_request_await_object(rq, so->vma->obj, false); 2378c2ecf20Sopenharmony_ci if (err == 0) 2388c2ecf20Sopenharmony_ci err = i915_vma_move_to_active(so->vma, rq, 0); 2398c2ecf20Sopenharmony_ci if (err) 2408c2ecf20Sopenharmony_ci return err; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci err = engine->emit_bb_start(rq, 2438c2ecf20Sopenharmony_ci so->batch_offset, so->batch_size, 2448c2ecf20Sopenharmony_ci I915_DISPATCH_SECURE); 2458c2ecf20Sopenharmony_ci if (err) 2468c2ecf20Sopenharmony_ci return err; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (so->aux_size > 8) { 2498c2ecf20Sopenharmony_ci err = engine->emit_bb_start(rq, 2508c2ecf20Sopenharmony_ci so->aux_offset, so->aux_size, 2518c2ecf20Sopenharmony_ci I915_DISPATCH_SECURE); 2528c2ecf20Sopenharmony_ci if (err) 2538c2ecf20Sopenharmony_ci return err; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci return 0; 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_civoid intel_renderstate_fini(struct intel_renderstate *so, 2608c2ecf20Sopenharmony_ci struct intel_context *ce) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci if (so->vma) { 2638c2ecf20Sopenharmony_ci i915_vma_unpin(so->vma); 2648c2ecf20Sopenharmony_ci i915_vma_close(so->vma); 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci intel_context_unpin(ce); 2688c2ecf20Sopenharmony_ci i915_gem_ww_ctx_fini(&so->ww); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if (so->vma) 2718c2ecf20Sopenharmony_ci i915_gem_object_put(so->vma->obj); 2728c2ecf20Sopenharmony_ci} 273