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