1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2019 Intel Corporation 4 */ 5 6 #include "i915_drv.h" 7 #include "i915_vma.h" 8 #include "intel_context.h" 9 #include "intel_engine_pm.h" 10 #include "intel_gpu_commands.h" 11 #include "intel_lrc.h" 12 #include "intel_lrc_reg.h" 13 #include "intel_ring.h" 14 #include "intel_sseu.h" 15 16 static int gen8_emit_rpcs_config(struct i915_request *rq, 17 const struct intel_context *ce, 18 const struct intel_sseu sseu) 19 { 20 u64 offset; 21 u32 *cs; 22 23 cs = intel_ring_begin(rq, 4); 24 if (IS_ERR(cs)) 25 return PTR_ERR(cs); 26 27 offset = i915_ggtt_offset(ce->state) + 28 LRC_STATE_PN * PAGE_SIZE + 29 CTX_R_PWR_CLK_STATE * 4; 30 31 *cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT; 32 *cs++ = lower_32_bits(offset); 33 *cs++ = upper_32_bits(offset); 34 *cs++ = intel_sseu_make_rpcs(rq->i915, &sseu); 35 36 intel_ring_advance(rq, cs); 37 38 return 0; 39 } 40 41 static int 42 gen8_modify_rpcs(struct intel_context *ce, const struct intel_sseu sseu) 43 { 44 struct i915_request *rq; 45 int ret; 46 47 lockdep_assert_held(&ce->pin_mutex); 48 49 /* 50 * If the context is not idle, we have to submit an ordered request to 51 * modify its context image via the kernel context (writing to our own 52 * image, or into the registers directory, does not stick). Pristine 53 * and idle contexts will be configured on pinning. 54 */ 55 if (!intel_context_pin_if_active(ce)) 56 return 0; 57 58 rq = intel_engine_create_kernel_request(ce->engine); 59 if (IS_ERR(rq)) { 60 ret = PTR_ERR(rq); 61 goto out_unpin; 62 } 63 64 /* Serialise with the remote context */ 65 ret = intel_context_prepare_remote_request(ce, rq); 66 if (ret == 0) 67 ret = gen8_emit_rpcs_config(rq, ce, sseu); 68 69 i915_request_add(rq); 70 out_unpin: 71 intel_context_unpin(ce); 72 return ret; 73 } 74 75 int 76 intel_context_reconfigure_sseu(struct intel_context *ce, 77 const struct intel_sseu sseu) 78 { 79 int ret; 80 81 GEM_BUG_ON(INTEL_GEN(ce->engine->i915) < 8); 82 83 ret = intel_context_lock_pinned(ce); 84 if (ret) 85 return ret; 86 87 /* Nothing to do if unmodified. */ 88 if (!memcmp(&ce->sseu, &sseu, sizeof(sseu))) 89 goto unlock; 90 91 ret = gen8_modify_rpcs(ce, sseu); 92 if (!ret) 93 ce->sseu = sseu; 94 95 unlock: 96 intel_context_unlock_pinned(ce); 97 return ret; 98 } 99