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