Branch data Line data Source code
1 : : /* SPDX-License-Identifier: MIT */
2 : : #ifndef _INTEL_RINGBUFFER_H_
3 : : #define _INTEL_RINGBUFFER_H_
4 : :
5 : : #include <drm/drm_util.h>
6 : :
7 : : #include <linux/hashtable.h>
8 : : #include <linux/irq_work.h>
9 : : #include <linux/random.h>
10 : : #include <linux/seqlock.h>
11 : :
12 : : #include "i915_pmu.h"
13 : : #include "i915_reg.h"
14 : : #include "i915_request.h"
15 : : #include "i915_selftest.h"
16 : : #include "gt/intel_timeline.h"
17 : : #include "intel_engine_types.h"
18 : : #include "intel_gpu_commands.h"
19 : : #include "intel_workarounds.h"
20 : :
21 : : struct drm_printer;
22 : : struct intel_gt;
23 : :
24 : : /* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill,
25 : : * but keeps the logic simple. Indeed, the whole purpose of this macro is just
26 : : * to give some inclination as to some of the magic values used in the various
27 : : * workarounds!
28 : : */
29 : : #define CACHELINE_BYTES 64
30 : : #define CACHELINE_DWORDS (CACHELINE_BYTES / sizeof(u32))
31 : :
32 : : #define ENGINE_TRACE(e, fmt, ...) do { \
33 : : const struct intel_engine_cs *e__ __maybe_unused = (e); \
34 : : GEM_TRACE("%s %s: " fmt, \
35 : : dev_name(e__->i915->drm.dev), e__->name, \
36 : : ##__VA_ARGS__); \
37 : : } while (0)
38 : :
39 : : /*
40 : : * The register defines to be used with the following macros need to accept a
41 : : * base param, e.g:
42 : : *
43 : : * REG_FOO(base) _MMIO((base) + <relative offset>)
44 : : * ENGINE_READ(engine, REG_FOO);
45 : : *
46 : : * register arrays are to be defined and accessed as follows:
47 : : *
48 : : * REG_BAR(base, i) _MMIO((base) + <relative offset> + (i) * <shift>)
49 : : * ENGINE_READ_IDX(engine, REG_BAR, i)
50 : : */
51 : :
52 : : #define __ENGINE_REG_OP(op__, engine__, ...) \
53 : : intel_uncore_##op__((engine__)->uncore, __VA_ARGS__)
54 : :
55 : : #define __ENGINE_READ_OP(op__, engine__, reg__) \
56 : : __ENGINE_REG_OP(op__, (engine__), reg__((engine__)->mmio_base))
57 : :
58 : : #define ENGINE_READ16(...) __ENGINE_READ_OP(read16, __VA_ARGS__)
59 : : #define ENGINE_READ(...) __ENGINE_READ_OP(read, __VA_ARGS__)
60 : : #define ENGINE_READ_FW(...) __ENGINE_READ_OP(read_fw, __VA_ARGS__)
61 : : #define ENGINE_POSTING_READ(...) __ENGINE_READ_OP(posting_read_fw, __VA_ARGS__)
62 : : #define ENGINE_POSTING_READ16(...) __ENGINE_READ_OP(posting_read16, __VA_ARGS__)
63 : :
64 : : #define ENGINE_READ64(engine__, lower_reg__, upper_reg__) \
65 : : __ENGINE_REG_OP(read64_2x32, (engine__), \
66 : : lower_reg__((engine__)->mmio_base), \
67 : : upper_reg__((engine__)->mmio_base))
68 : :
69 : : #define ENGINE_READ_IDX(engine__, reg__, idx__) \
70 : : __ENGINE_REG_OP(read, (engine__), reg__((engine__)->mmio_base, (idx__)))
71 : :
72 : : #define __ENGINE_WRITE_OP(op__, engine__, reg__, val__) \
73 : : __ENGINE_REG_OP(op__, (engine__), reg__((engine__)->mmio_base), (val__))
74 : :
75 : : #define ENGINE_WRITE16(...) __ENGINE_WRITE_OP(write16, __VA_ARGS__)
76 : : #define ENGINE_WRITE(...) __ENGINE_WRITE_OP(write, __VA_ARGS__)
77 : : #define ENGINE_WRITE_FW(...) __ENGINE_WRITE_OP(write_fw, __VA_ARGS__)
78 : :
79 : : #define GEN6_RING_FAULT_REG_READ(engine__) \
80 : : intel_uncore_read((engine__)->uncore, RING_FAULT_REG(engine__))
81 : :
82 : : #define GEN6_RING_FAULT_REG_POSTING_READ(engine__) \
83 : : intel_uncore_posting_read((engine__)->uncore, RING_FAULT_REG(engine__))
84 : :
85 : : #define GEN6_RING_FAULT_REG_RMW(engine__, clear__, set__) \
86 : : ({ \
87 : : u32 __val; \
88 : : \
89 : : __val = intel_uncore_read((engine__)->uncore, \
90 : : RING_FAULT_REG(engine__)); \
91 : : __val &= ~(clear__); \
92 : : __val |= (set__); \
93 : : intel_uncore_write((engine__)->uncore, RING_FAULT_REG(engine__), \
94 : : __val); \
95 : : })
96 : :
97 : : /* seqno size is actually only a uint32, but since we plan to use MI_FLUSH_DW to
98 : : * do the writes, and that must have qw aligned offsets, simply pretend it's 8b.
99 : : */
100 : :
101 : : static inline unsigned int
102 : 0 : execlists_num_ports(const struct intel_engine_execlists * const execlists)
103 : : {
104 : 0 : return execlists->port_mask + 1;
105 : : }
106 : :
107 : : static inline struct i915_request *
108 : 0 : execlists_active(const struct intel_engine_execlists *execlists)
109 : : {
110 [ # # # # ]: 0 : return *READ_ONCE(execlists->active);
111 : : }
112 : :
113 : : static inline void
114 : 0 : execlists_active_lock_bh(struct intel_engine_execlists *execlists)
115 : : {
116 : 0 : local_bh_disable(); /* prevent local softirq and lock recursion */
117 : 0 : tasklet_lock(&execlists->tasklet);
118 : 0 : }
119 : :
120 : : static inline void
121 : 0 : execlists_active_unlock_bh(struct intel_engine_execlists *execlists)
122 : : {
123 : 0 : tasklet_unlock(&execlists->tasklet);
124 : 0 : local_bh_enable(); /* restore softirq, and kick ksoftirqd! */
125 : : }
126 : :
127 : : struct i915_request *
128 : : execlists_unwind_incomplete_requests(struct intel_engine_execlists *execlists);
129 : :
130 : : static inline u32
131 : : intel_read_status_page(const struct intel_engine_cs *engine, int reg)
132 : : {
133 : : /* Ensure that the compiler doesn't optimize away the load. */
134 : : return READ_ONCE(engine->status_page.addr[reg]);
135 : : }
136 : :
137 : : static inline void
138 : : intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
139 : : {
140 : : /* Writing into the status page should be done sparingly. Since
141 : : * we do when we are uncertain of the device state, we take a bit
142 : : * of extra paranoia to try and ensure that the HWS takes the value
143 : : * we give and that it doesn't end up trapped inside the CPU!
144 : : */
145 : : if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
146 : : mb();
147 : : clflush(&engine->status_page.addr[reg]);
148 : : engine->status_page.addr[reg] = value;
149 : : clflush(&engine->status_page.addr[reg]);
150 : : mb();
151 : : } else {
152 : : WRITE_ONCE(engine->status_page.addr[reg], value);
153 : : }
154 : : }
155 : :
156 : : /*
157 : : * Reads a dword out of the status page, which is written to from the command
158 : : * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
159 : : * MI_STORE_DATA_IMM.
160 : : *
161 : : * The following dwords have a reserved meaning:
162 : : * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
163 : : * 0x04: ring 0 head pointer
164 : : * 0x05: ring 1 head pointer (915-class)
165 : : * 0x06: ring 2 head pointer (915-class)
166 : : * 0x10-0x1b: Context status DWords (GM45)
167 : : * 0x1f: Last written status offset. (GM45)
168 : : * 0x20-0x2f: Reserved (Gen6+)
169 : : *
170 : : * The area from dword 0x30 to 0x3ff is available for driver usage.
171 : : */
172 : : #define I915_GEM_HWS_PREEMPT 0x32
173 : : #define I915_GEM_HWS_PREEMPT_ADDR (I915_GEM_HWS_PREEMPT * sizeof(u32))
174 : : #define I915_GEM_HWS_SEQNO 0x40
175 : : #define I915_GEM_HWS_SEQNO_ADDR (I915_GEM_HWS_SEQNO * sizeof(u32))
176 : : #define I915_GEM_HWS_SCRATCH 0x80
177 : : #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH * sizeof(u32))
178 : :
179 : : #define I915_HWS_CSB_BUF0_INDEX 0x10
180 : : #define I915_HWS_CSB_WRITE_INDEX 0x1f
181 : : #define CNL_HWS_CSB_WRITE_INDEX 0x2f
182 : :
183 : : void intel_engine_stop(struct intel_engine_cs *engine);
184 : : void intel_engine_cleanup(struct intel_engine_cs *engine);
185 : :
186 : : int intel_engines_init_mmio(struct intel_gt *gt);
187 : : int intel_engines_init(struct intel_gt *gt);
188 : :
189 : : void intel_engines_release(struct intel_gt *gt);
190 : : void intel_engines_free(struct intel_gt *gt);
191 : :
192 : : int intel_engine_init_common(struct intel_engine_cs *engine);
193 : : void intel_engine_cleanup_common(struct intel_engine_cs *engine);
194 : :
195 : : int intel_ring_submission_setup(struct intel_engine_cs *engine);
196 : :
197 : : int intel_engine_stop_cs(struct intel_engine_cs *engine);
198 : : void intel_engine_cancel_stop_cs(struct intel_engine_cs *engine);
199 : :
200 : : void intel_engine_set_hwsp_writemask(struct intel_engine_cs *engine, u32 mask);
201 : :
202 : : u64 intel_engine_get_active_head(const struct intel_engine_cs *engine);
203 : : u64 intel_engine_get_last_batch_head(const struct intel_engine_cs *engine);
204 : :
205 : : void intel_engine_get_instdone(const struct intel_engine_cs *engine,
206 : : struct intel_instdone *instdone);
207 : :
208 : : void intel_engine_init_execlists(struct intel_engine_cs *engine);
209 : :
210 : : void intel_engine_init_breadcrumbs(struct intel_engine_cs *engine);
211 : : void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
212 : :
213 : : void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine);
214 : :
215 : : static inline void
216 : 0 : intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine)
217 : : {
218 : 0 : irq_work_queue(&engine->breadcrumbs.irq_work);
219 : 0 : }
220 : :
221 : : void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine);
222 : : void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
223 : :
224 : : void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine,
225 : : struct drm_printer *p);
226 : :
227 : 0 : static inline u32 *gen8_emit_pipe_control(u32 *batch, u32 flags, u32 offset)
228 : : {
229 : 0 : memset(batch, 0, 6 * sizeof(u32));
230 : :
231 : 0 : batch[0] = GFX_OP_PIPE_CONTROL(6);
232 : 0 : batch[1] = flags;
233 : 0 : batch[2] = offset;
234 : :
235 [ # # # # ]: 0 : return batch + 6;
236 : : }
237 : :
238 : : static inline u32 *
239 : 0 : gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
240 : : {
241 : : /* We're using qword write, offset should be aligned to 8 bytes. */
242 : 0 : GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
243 : :
244 : : /* w/a for post sync ops following a GPGPU operation we
245 : : * need a prior CS_STALL, which is emitted by the flush
246 : : * following the batch.
247 : : */
248 : 0 : *cs++ = GFX_OP_PIPE_CONTROL(6);
249 : 0 : *cs++ = flags | PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_GLOBAL_GTT_IVB;
250 : 0 : *cs++ = gtt_offset;
251 : 0 : *cs++ = 0;
252 : 0 : *cs++ = value;
253 : : /* We're thrashing one dword of HWS. */
254 : 0 : *cs++ = 0;
255 : :
256 [ # # # # : 0 : return cs;
# # ]
257 : : }
258 : :
259 : : static inline u32 *
260 : 0 : gen8_emit_ggtt_write(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
261 : : {
262 : : /* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */
263 : 0 : GEM_BUG_ON(gtt_offset & (1 << 5));
264 : : /* Offset should be aligned to 8 bytes for both (QW/DW) write types */
265 : 0 : GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
266 : :
267 : 0 : *cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW | flags;
268 : 0 : *cs++ = gtt_offset | MI_FLUSH_DW_USE_GTT;
269 : 0 : *cs++ = 0;
270 : 0 : *cs++ = value;
271 : :
272 [ # # # # ]: 0 : return cs;
273 : : }
274 : :
275 : 0 : static inline void __intel_engine_reset(struct intel_engine_cs *engine,
276 : : bool stalled)
277 : : {
278 [ # # # # ]: 0 : if (engine->reset.rewind)
279 : 0 : engine->reset.rewind(engine, stalled);
280 : 0 : engine->serial++; /* contexts lost */
281 : 0 : }
282 : :
283 : : bool intel_engines_are_idle(struct intel_gt *gt);
284 : : bool intel_engine_is_idle(struct intel_engine_cs *engine);
285 : : void intel_engine_flush_submission(struct intel_engine_cs *engine);
286 : :
287 : : void intel_engines_reset_default_submission(struct intel_gt *gt);
288 : :
289 : : bool intel_engine_can_store_dword(struct intel_engine_cs *engine);
290 : :
291 : : __printf(3, 4)
292 : : void intel_engine_dump(struct intel_engine_cs *engine,
293 : : struct drm_printer *m,
294 : : const char *header, ...);
295 : :
296 : : int intel_enable_engine_stats(struct intel_engine_cs *engine);
297 : : void intel_disable_engine_stats(struct intel_engine_cs *engine);
298 : :
299 : : ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine);
300 : :
301 : : struct i915_request *
302 : : intel_engine_find_active_request(struct intel_engine_cs *engine);
303 : :
304 : : u32 intel_engine_context_size(struct intel_gt *gt, u8 class);
305 : :
306 : : #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
307 : :
308 : : static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists)
309 : : {
310 : : if (!execlists->preempt_hang.inject_hang)
311 : : return false;
312 : :
313 : : complete(&execlists->preempt_hang.completion);
314 : : return true;
315 : : }
316 : :
317 : : #else
318 : :
319 : 0 : static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists)
320 : : {
321 : 0 : return false;
322 : : }
323 : :
324 : : #endif
325 : :
326 : : void intel_engine_init_active(struct intel_engine_cs *engine,
327 : : unsigned int subclass);
328 : : #define ENGINE_PHYSICAL 0
329 : : #define ENGINE_MOCK 1
330 : : #define ENGINE_VIRTUAL 2
331 : :
332 : : static inline bool
333 : 0 : intel_engine_has_preempt_reset(const struct intel_engine_cs *engine)
334 : : {
335 : 0 : if (!IS_ACTIVE(CONFIG_DRM_I915_PREEMPT_TIMEOUT))
336 : : return false;
337 : :
338 [ # # ]: 0 : return intel_engine_has_preemption(engine);
339 : : }
340 : :
341 : : static inline bool
342 : 0 : intel_engine_has_timeslices(const struct intel_engine_cs *engine)
343 : : {
344 : 0 : if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
345 : : return false;
346 : :
347 [ # # # # ]: 0 : return intel_engine_has_semaphores(engine);
348 : : }
349 : :
350 : : #endif /* _INTEL_RINGBUFFER_H_ */
|