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, num_dwords: 4); |
24 | if (IS_ERR(ptr: cs)) |
25 | return PTR_ERR(ptr: cs); |
26 | |
27 | offset = i915_ggtt_offset(vma: 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(gt: rq->engine->gt, req_sseu: &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(engine: ce->engine); |
58 | if (IS_ERR(ptr: rq)) { |
59 | ret = PTR_ERR(ptr: 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(GRAPHICS_VER(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(p: &ce->sseu, q: &sseu, size: 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 | |