1 // SPDX-License-Identifier: MIT
3 * Copyright © 2021 Intel Corporation
6 #include "xe_hw_engine.h"
8 #include <drm/drm_managed.h>
10 #include "regs/xe_engine_regs.h"
11 #include "regs/xe_gt_regs.h"
12 #include "regs/xe_regs.h"
13 #include "xe_assert.h"
15 #include "xe_device.h"
16 #include "xe_execlist.h"
17 #include "xe_force_wake.h"
19 #include "xe_gt_topology.h"
20 #include "xe_hw_fence.h"
23 #include "xe_macros.h"
25 #include "xe_reg_sr.h"
27 #include "xe_sched_job.h"
28 #include "xe_tuning.h"
31 #define MAX_MMIO_BASES 3
34 unsigned int class : 8;
35 unsigned int instance : 8;
36 enum xe_force_wake_domains domain;
40 static const struct engine_info engine_infos[] = {
41 [XE_HW_ENGINE_RCS0] = {
43 .class = XE_ENGINE_CLASS_RENDER,
45 .domain = XE_FW_RENDER,
46 .mmio_base = RENDER_RING_BASE,
48 [XE_HW_ENGINE_BCS0] = {
50 .class = XE_ENGINE_CLASS_COPY,
52 .domain = XE_FW_RENDER,
53 .mmio_base = BLT_RING_BASE,
55 [XE_HW_ENGINE_BCS1] = {
57 .class = XE_ENGINE_CLASS_COPY,
59 .domain = XE_FW_RENDER,
60 .mmio_base = XEHPC_BCS1_RING_BASE,
62 [XE_HW_ENGINE_BCS2] = {
64 .class = XE_ENGINE_CLASS_COPY,
66 .domain = XE_FW_RENDER,
67 .mmio_base = XEHPC_BCS2_RING_BASE,
69 [XE_HW_ENGINE_BCS3] = {
71 .class = XE_ENGINE_CLASS_COPY,
73 .domain = XE_FW_RENDER,
74 .mmio_base = XEHPC_BCS3_RING_BASE,
76 [XE_HW_ENGINE_BCS4] = {
78 .class = XE_ENGINE_CLASS_COPY,
80 .domain = XE_FW_RENDER,
81 .mmio_base = XEHPC_BCS4_RING_BASE,
83 [XE_HW_ENGINE_BCS5] = {
85 .class = XE_ENGINE_CLASS_COPY,
87 .domain = XE_FW_RENDER,
88 .mmio_base = XEHPC_BCS5_RING_BASE,
90 [XE_HW_ENGINE_BCS6] = {
92 .class = XE_ENGINE_CLASS_COPY,
94 .domain = XE_FW_RENDER,
95 .mmio_base = XEHPC_BCS6_RING_BASE,
97 [XE_HW_ENGINE_BCS7] = {
99 .class = XE_ENGINE_CLASS_COPY,
101 .domain = XE_FW_RENDER,
102 .mmio_base = XEHPC_BCS7_RING_BASE,
104 [XE_HW_ENGINE_BCS8] = {
106 .class = XE_ENGINE_CLASS_COPY,
108 .domain = XE_FW_RENDER,
109 .mmio_base = XEHPC_BCS8_RING_BASE,
112 [XE_HW_ENGINE_VCS0] = {
114 .class = XE_ENGINE_CLASS_VIDEO_DECODE,
116 .domain = XE_FW_MEDIA_VDBOX0,
117 .mmio_base = BSD_RING_BASE,
119 [XE_HW_ENGINE_VCS1] = {
121 .class = XE_ENGINE_CLASS_VIDEO_DECODE,
123 .domain = XE_FW_MEDIA_VDBOX1,
124 .mmio_base = BSD2_RING_BASE,
126 [XE_HW_ENGINE_VCS2] = {
128 .class = XE_ENGINE_CLASS_VIDEO_DECODE,
130 .domain = XE_FW_MEDIA_VDBOX2,
131 .mmio_base = BSD3_RING_BASE,
133 [XE_HW_ENGINE_VCS3] = {
135 .class = XE_ENGINE_CLASS_VIDEO_DECODE,
137 .domain = XE_FW_MEDIA_VDBOX3,
138 .mmio_base = BSD4_RING_BASE,
140 [XE_HW_ENGINE_VCS4] = {
142 .class = XE_ENGINE_CLASS_VIDEO_DECODE,
144 .domain = XE_FW_MEDIA_VDBOX4,
145 .mmio_base = XEHP_BSD5_RING_BASE,
147 [XE_HW_ENGINE_VCS5] = {
149 .class = XE_ENGINE_CLASS_VIDEO_DECODE,
151 .domain = XE_FW_MEDIA_VDBOX5,
152 .mmio_base = XEHP_BSD6_RING_BASE,
154 [XE_HW_ENGINE_VCS6] = {
156 .class = XE_ENGINE_CLASS_VIDEO_DECODE,
158 .domain = XE_FW_MEDIA_VDBOX6,
159 .mmio_base = XEHP_BSD7_RING_BASE,
161 [XE_HW_ENGINE_VCS7] = {
163 .class = XE_ENGINE_CLASS_VIDEO_DECODE,
165 .domain = XE_FW_MEDIA_VDBOX7,
166 .mmio_base = XEHP_BSD8_RING_BASE,
168 [XE_HW_ENGINE_VECS0] = {
170 .class = XE_ENGINE_CLASS_VIDEO_ENHANCE,
172 .domain = XE_FW_MEDIA_VEBOX0,
173 .mmio_base = VEBOX_RING_BASE,
175 [XE_HW_ENGINE_VECS1] = {
177 .class = XE_ENGINE_CLASS_VIDEO_ENHANCE,
179 .domain = XE_FW_MEDIA_VEBOX1,
180 .mmio_base = VEBOX2_RING_BASE,
182 [XE_HW_ENGINE_VECS2] = {
184 .class = XE_ENGINE_CLASS_VIDEO_ENHANCE,
186 .domain = XE_FW_MEDIA_VEBOX2,
187 .mmio_base = XEHP_VEBOX3_RING_BASE,
189 [XE_HW_ENGINE_VECS3] = {
191 .class = XE_ENGINE_CLASS_VIDEO_ENHANCE,
193 .domain = XE_FW_MEDIA_VEBOX3,
194 .mmio_base = XEHP_VEBOX4_RING_BASE,
196 [XE_HW_ENGINE_CCS0] = {
198 .class = XE_ENGINE_CLASS_COMPUTE,
200 .domain = XE_FW_RENDER,
201 .mmio_base = COMPUTE0_RING_BASE,
203 [XE_HW_ENGINE_CCS1] = {
205 .class = XE_ENGINE_CLASS_COMPUTE,
207 .domain = XE_FW_RENDER,
208 .mmio_base = COMPUTE1_RING_BASE,
210 [XE_HW_ENGINE_CCS2] = {
212 .class = XE_ENGINE_CLASS_COMPUTE,
214 .domain = XE_FW_RENDER,
215 .mmio_base = COMPUTE2_RING_BASE,
217 [XE_HW_ENGINE_CCS3] = {
219 .class = XE_ENGINE_CLASS_COMPUTE,
221 .domain = XE_FW_RENDER,
222 .mmio_base = COMPUTE3_RING_BASE,
224 [XE_HW_ENGINE_GSCCS0] = {
226 .class = XE_ENGINE_CLASS_OTHER,
227 .instance = OTHER_GSC_INSTANCE,
229 .mmio_base = GSCCS_RING_BASE,
233 static void hw_engine_fini(struct drm_device *drm, void *arg)
235 struct xe_hw_engine *hwe = arg;
238 xe_execlist_port_destroy(hwe->exl_port);
239 xe_lrc_finish(&hwe->kernel_lrc);
241 xe_bo_unpin_map_no_vm(hwe->hwsp);
246 static void hw_engine_mmio_write32(struct xe_hw_engine *hwe, struct xe_reg reg,
249 xe_gt_assert(hwe->gt, !(reg.addr & hwe->mmio_base));
250 xe_force_wake_assert_held(gt_to_fw(hwe->gt), hwe->domain);
252 reg.addr += hwe->mmio_base;
254 xe_mmio_write32(hwe->gt, reg, val);
257 static u32 hw_engine_mmio_read32(struct xe_hw_engine *hwe, struct xe_reg reg)
259 xe_gt_assert(hwe->gt, !(reg.addr & hwe->mmio_base));
260 xe_force_wake_assert_held(gt_to_fw(hwe->gt), hwe->domain);
262 reg.addr += hwe->mmio_base;
264 return xe_mmio_read32(hwe->gt, reg);
267 void xe_hw_engine_enable_ring(struct xe_hw_engine *hwe)
270 xe_hw_engine_mask_per_class(hwe->gt, XE_ENGINE_CLASS_COMPUTE);
272 if (hwe->class == XE_ENGINE_CLASS_COMPUTE && ccs_mask)
273 xe_mmio_write32(hwe->gt, RCU_MODE,
274 _MASKED_BIT_ENABLE(RCU_MODE_CCS_ENABLE));
276 hw_engine_mmio_write32(hwe, RING_HWSTAM(0), ~0x0);
277 hw_engine_mmio_write32(hwe, RING_HWS_PGA(0),
278 xe_bo_ggtt_addr(hwe->hwsp));
279 hw_engine_mmio_write32(hwe, RING_MODE(0),
280 _MASKED_BIT_ENABLE(GFX_DISABLE_LEGACY_MODE));
281 hw_engine_mmio_write32(hwe, RING_MI_MODE(0),
282 _MASKED_BIT_DISABLE(STOP_RING));
283 hw_engine_mmio_read32(hwe, RING_MI_MODE(0));
287 xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
289 struct xe_gt *gt = hwe->gt;
290 const u8 mocs_write_idx = gt->mocs.uc_index;
291 const u8 mocs_read_idx = gt->mocs.uc_index;
292 u32 blit_cctl_val = REG_FIELD_PREP(BLIT_CCTL_DST_MOCS_MASK, mocs_write_idx) |
293 REG_FIELD_PREP(BLIT_CCTL_SRC_MOCS_MASK, mocs_read_idx);
294 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
295 const struct xe_rtp_entry_sr lrc_was[] = {
297 * Some blitter commands do not have a field for MOCS, those
298 * commands will use MOCS index pointed by BLIT_CCTL.
299 * BLIT_CCTL registers are needed to be programmed to un-cached.
301 { XE_RTP_NAME("BLIT_CCTL_default_MOCS"),
302 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED),
304 XE_RTP_ACTIONS(FIELD_SET(BLIT_CCTL(0),
305 BLIT_CCTL_DST_MOCS_MASK |
306 BLIT_CCTL_SRC_MOCS_MASK,
308 XE_RTP_ACTION_FLAG(ENGINE_BASE)))
313 xe_rtp_process_to_sr(&ctx, lrc_was, &hwe->reg_lrc);
317 hw_engine_setup_default_state(struct xe_hw_engine *hwe)
319 struct xe_gt *gt = hwe->gt;
320 struct xe_device *xe = gt_to_xe(gt);
322 * RING_CMD_CCTL specifies the default MOCS entry that will be
323 * used by the command streamer when executing commands that
324 * don't have a way to explicitly specify a MOCS setting.
325 * The default should usually reference whichever MOCS entry
326 * corresponds to uncached behavior, although use of a WB cached
327 * entry is recommended by the spec in certain circumstances on
328 * specific platforms.
331 const u8 mocs_write_idx = gt->mocs.uc_index;
332 const u8 mocs_read_idx = hwe->class == XE_ENGINE_CLASS_COMPUTE &&
333 (GRAPHICS_VER(xe) >= 20 || xe->info.platform == XE_PVC) ?
334 gt->mocs.wb_index : gt->mocs.uc_index;
335 u32 ring_cmd_cctl_val = REG_FIELD_PREP(CMD_CCTL_WRITE_OVERRIDE_MASK, mocs_write_idx) |
336 REG_FIELD_PREP(CMD_CCTL_READ_OVERRIDE_MASK, mocs_read_idx);
337 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
338 const struct xe_rtp_entry_sr engine_entries[] = {
339 { XE_RTP_NAME("RING_CMD_CCTL_default_MOCS"),
340 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED)),
341 XE_RTP_ACTIONS(FIELD_SET(RING_CMD_CCTL(0),
342 CMD_CCTL_WRITE_OVERRIDE_MASK |
343 CMD_CCTL_READ_OVERRIDE_MASK,
345 XE_RTP_ACTION_FLAG(ENGINE_BASE)))
348 * To allow the GSC engine to go idle on MTL we need to enable
349 * idle messaging and set the hysteresis value (we use 0xA=5us
350 * as recommended in spec). On platforms after MTL this is
351 * enabled by default.
353 { XE_RTP_NAME("MTL GSCCS IDLE MSG enable"),
354 XE_RTP_RULES(MEDIA_VERSION(1300), ENGINE_CLASS(OTHER)),
355 XE_RTP_ACTIONS(CLR(RING_PSMI_CTL(0),
357 XE_RTP_ACTION_FLAG(ENGINE_BASE)),
358 FIELD_SET(RING_PWRCTX_MAXCNT(0),
361 XE_RTP_ACTION_FLAG(ENGINE_BASE)))
366 xe_rtp_process_to_sr(&ctx, engine_entries, &hwe->reg_sr);
369 static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe,
370 enum xe_hw_engine_id id)
372 const struct engine_info *info;
374 if (WARN_ON(id >= ARRAY_SIZE(engine_infos) || !engine_infos[id].name))
377 if (!(gt->info.engine_mask & BIT(id)))
380 info = &engine_infos[id];
382 xe_gt_assert(gt, !hwe->gt);
385 hwe->class = info->class;
386 hwe->instance = info->instance;
387 hwe->mmio_base = info->mmio_base;
388 hwe->domain = info->domain;
389 hwe->name = info->name;
390 hwe->fence_irq = >->fence_irq[info->class];
393 hwe->eclass = >->eclass[hwe->class];
394 if (!hwe->eclass->sched_props.job_timeout_ms) {
395 hwe->eclass->sched_props.job_timeout_ms = 5 * 1000;
396 hwe->eclass->sched_props.job_timeout_min = XE_HW_ENGINE_JOB_TIMEOUT_MIN;
397 hwe->eclass->sched_props.job_timeout_max = XE_HW_ENGINE_JOB_TIMEOUT_MAX;
398 hwe->eclass->sched_props.timeslice_us = 1 * 1000;
399 hwe->eclass->sched_props.timeslice_min = XE_HW_ENGINE_TIMESLICE_MIN;
400 hwe->eclass->sched_props.timeslice_max = XE_HW_ENGINE_TIMESLICE_MAX;
401 hwe->eclass->sched_props.preempt_timeout_us = XE_HW_ENGINE_PREEMPT_TIMEOUT;
402 hwe->eclass->sched_props.preempt_timeout_min = XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN;
403 hwe->eclass->sched_props.preempt_timeout_max = XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX;
404 /* Record default props */
405 hwe->eclass->defaults = hwe->eclass->sched_props;
408 xe_reg_sr_init(&hwe->reg_sr, hwe->name, gt_to_xe(gt));
409 xe_tuning_process_engine(hwe);
410 xe_wa_process_engine(hwe);
411 hw_engine_setup_default_state(hwe);
413 xe_reg_sr_init(&hwe->reg_whitelist, hwe->name, gt_to_xe(gt));
414 xe_reg_whitelist_process_engine(hwe);
417 static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe,
418 enum xe_hw_engine_id id)
420 struct xe_device *xe = gt_to_xe(gt);
421 struct xe_tile *tile = gt_to_tile(gt);
424 xe_gt_assert(gt, id < ARRAY_SIZE(engine_infos) && engine_infos[id].name);
425 xe_gt_assert(gt, gt->info.engine_mask & BIT(id));
427 xe_reg_sr_apply_mmio(&hwe->reg_sr, gt);
428 xe_reg_sr_apply_whitelist(hwe);
430 hwe->hwsp = xe_bo_create_pin_map(xe, tile, NULL, SZ_4K, ttm_bo_type_kernel,
431 XE_BO_CREATE_VRAM_IF_DGFX(tile) |
432 XE_BO_CREATE_GGTT_BIT);
433 if (IS_ERR(hwe->hwsp)) {
434 err = PTR_ERR(hwe->hwsp);
438 err = xe_lrc_init(&hwe->kernel_lrc, hwe, NULL, NULL, SZ_16K);
442 if (!xe_device_uc_enabled(xe)) {
443 hwe->exl_port = xe_execlist_port_create(xe, hwe);
444 if (IS_ERR(hwe->exl_port)) {
445 err = PTR_ERR(hwe->exl_port);
450 if (xe_device_uc_enabled(xe))
451 xe_hw_engine_enable_ring(hwe);
453 /* We reserve the highest BCS instance for USM */
454 if (xe->info.supports_usm && hwe->class == XE_ENGINE_CLASS_COPY)
455 gt->usm.reserved_bcs_instance = hwe->instance;
457 err = drmm_add_action_or_reset(&xe->drm, hw_engine_fini, hwe);
464 xe_lrc_finish(&hwe->kernel_lrc);
466 xe_bo_unpin_map_no_vm(hwe->hwsp);
473 static void hw_engine_setup_logical_mapping(struct xe_gt *gt)
477 /* FIXME: Doing a simple logical mapping that works for most hardware */
478 for (class = 0; class < XE_ENGINE_CLASS_MAX; ++class) {
479 struct xe_hw_engine *hwe;
480 enum xe_hw_engine_id id;
481 int logical_instance = 0;
483 for_each_hw_engine(hwe, gt, id)
484 if (hwe->class == class)
485 hwe->logical_instance = logical_instance++;
489 static void read_media_fuses(struct xe_gt *gt)
491 struct xe_device *xe = gt_to_xe(gt);
497 xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT);
499 media_fuse = xe_mmio_read32(gt, GT_VEBOX_VDBOX_DISABLE);
502 * Pre-Xe_HP platforms had register bits representing absent engines,
503 * whereas Xe_HP and beyond have bits representing present engines.
504 * Invert the polarity on old platforms so that we can use common
507 if (GRAPHICS_VERx100(xe) < 1250)
508 media_fuse = ~media_fuse;
510 vdbox_mask = REG_FIELD_GET(GT_VDBOX_DISABLE_MASK, media_fuse);
511 vebox_mask = REG_FIELD_GET(GT_VEBOX_DISABLE_MASK, media_fuse);
513 for (i = XE_HW_ENGINE_VCS0, j = 0; i <= XE_HW_ENGINE_VCS7; ++i, ++j) {
514 if (!(gt->info.engine_mask & BIT(i)))
517 if (!(BIT(j) & vdbox_mask)) {
518 gt->info.engine_mask &= ~BIT(i);
519 drm_info(&xe->drm, "vcs%u fused off\n", j);
523 for (i = XE_HW_ENGINE_VECS0, j = 0; i <= XE_HW_ENGINE_VECS3; ++i, ++j) {
524 if (!(gt->info.engine_mask & BIT(i)))
527 if (!(BIT(j) & vebox_mask)) {
528 gt->info.engine_mask &= ~BIT(i);
529 drm_info(&xe->drm, "vecs%u fused off\n", j);
534 static void read_copy_fuses(struct xe_gt *gt)
536 struct xe_device *xe = gt_to_xe(gt);
539 if (GRAPHICS_VERx100(xe) < 1260 || GRAPHICS_VERx100(xe) >= 1270)
542 xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT);
544 bcs_mask = xe_mmio_read32(gt, MIRROR_FUSE3);
545 bcs_mask = REG_FIELD_GET(MEML3_EN_MASK, bcs_mask);
547 /* BCS0 is always present; only BCS1-BCS8 may be fused off */
548 for (int i = XE_HW_ENGINE_BCS1, j = 0; i <= XE_HW_ENGINE_BCS8; ++i, ++j) {
549 if (!(gt->info.engine_mask & BIT(i)))
552 if (!(BIT(j / 2) & bcs_mask)) {
553 gt->info.engine_mask &= ~BIT(i);
554 drm_info(&xe->drm, "bcs%u fused off\n", j);
559 static void read_compute_fuses_from_dss(struct xe_gt *gt)
561 struct xe_device *xe = gt_to_xe(gt);
564 * CCS fusing based on DSS masks only applies to platforms that can
565 * have more than one CCS.
567 if (hweight64(gt->info.engine_mask &
568 GENMASK_ULL(XE_HW_ENGINE_CCS3, XE_HW_ENGINE_CCS0)) <= 1)
572 * CCS availability on Xe_HP is inferred from the presence of DSS in
575 for (int i = XE_HW_ENGINE_CCS0, j = 0; i <= XE_HW_ENGINE_CCS3; ++i, ++j) {
576 if (!(gt->info.engine_mask & BIT(i)))
579 if (!xe_gt_topology_has_dss_in_quadrant(gt, j)) {
580 gt->info.engine_mask &= ~BIT(i);
581 drm_info(&xe->drm, "ccs%u fused off\n", j);
586 static void read_compute_fuses_from_reg(struct xe_gt *gt)
588 struct xe_device *xe = gt_to_xe(gt);
591 ccs_mask = xe_mmio_read32(gt, XEHP_FUSE4);
592 ccs_mask = REG_FIELD_GET(CCS_EN_MASK, ccs_mask);
594 for (int i = XE_HW_ENGINE_CCS0, j = 0; i <= XE_HW_ENGINE_CCS3; ++i, ++j) {
595 if (!(gt->info.engine_mask & BIT(i)))
598 if ((ccs_mask & BIT(j)) == 0) {
599 gt->info.engine_mask &= ~BIT(i);
600 drm_info(&xe->drm, "ccs%u fused off\n", j);
605 static void read_compute_fuses(struct xe_gt *gt)
607 if (GRAPHICS_VER(gt_to_xe(gt)) >= 20)
608 read_compute_fuses_from_reg(gt);
610 read_compute_fuses_from_dss(gt);
613 int xe_hw_engines_init_early(struct xe_gt *gt)
617 read_media_fuses(gt);
619 read_compute_fuses(gt);
621 BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT < XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN);
622 BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT > XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX);
624 for (i = 0; i < ARRAY_SIZE(gt->hw_engines); i++)
625 hw_engine_init_early(gt, >->hw_engines[i], i);
630 int xe_hw_engines_init(struct xe_gt *gt)
633 struct xe_hw_engine *hwe;
634 enum xe_hw_engine_id id;
636 for_each_hw_engine(hwe, gt, id) {
637 err = hw_engine_init(gt, hwe, id);
642 hw_engine_setup_logical_mapping(gt);
647 void xe_hw_engine_handle_irq(struct xe_hw_engine *hwe, u16 intr_vec)
649 wake_up_all(>_to_xe(hwe->gt)->ufence_wq);
651 if (hwe->irq_handler)
652 hwe->irq_handler(hwe, intr_vec);
654 if (intr_vec & GT_RENDER_USER_INTERRUPT)
655 xe_hw_fence_irq_run(hwe->fence_irq);
659 * xe_hw_engine_snapshot_capture - Take a quick snapshot of the HW Engine.
660 * @hwe: Xe HW Engine.
662 * This can be printed out in a later stage like during dev_coredump
665 * Returns: a Xe HW Engine snapshot object that must be freed by the
666 * caller, using `xe_hw_engine_snapshot_free`.
668 struct xe_hw_engine_snapshot *
669 xe_hw_engine_snapshot_capture(struct xe_hw_engine *hwe)
671 struct xe_hw_engine_snapshot *snapshot;
674 if (!xe_hw_engine_is_valid(hwe))
677 snapshot = kzalloc(sizeof(*snapshot), GFP_ATOMIC);
682 len = strlen(hwe->name) + 1;
683 snapshot->name = kzalloc(len, GFP_ATOMIC);
685 strscpy(snapshot->name, hwe->name, len);
687 snapshot->class = hwe->class;
688 snapshot->logical_instance = hwe->logical_instance;
689 snapshot->forcewake.domain = hwe->domain;
690 snapshot->forcewake.ref = xe_force_wake_ref(gt_to_fw(hwe->gt),
692 snapshot->mmio_base = hwe->mmio_base;
694 snapshot->reg.ring_hwstam = hw_engine_mmio_read32(hwe, RING_HWSTAM(0));
695 snapshot->reg.ring_hws_pga = hw_engine_mmio_read32(hwe,
697 snapshot->reg.ring_execlist_status_lo =
698 hw_engine_mmio_read32(hwe, RING_EXECLIST_STATUS_LO(0));
699 snapshot->reg.ring_execlist_status_hi =
700 hw_engine_mmio_read32(hwe, RING_EXECLIST_STATUS_HI(0));
701 snapshot->reg.ring_execlist_sq_contents_lo =
702 hw_engine_mmio_read32(hwe,
703 RING_EXECLIST_SQ_CONTENTS_LO(0));
704 snapshot->reg.ring_execlist_sq_contents_hi =
705 hw_engine_mmio_read32(hwe,
706 RING_EXECLIST_SQ_CONTENTS_HI(0));
707 snapshot->reg.ring_start = hw_engine_mmio_read32(hwe, RING_START(0));
708 snapshot->reg.ring_head =
709 hw_engine_mmio_read32(hwe, RING_HEAD(0)) & HEAD_ADDR;
710 snapshot->reg.ring_tail =
711 hw_engine_mmio_read32(hwe, RING_TAIL(0)) & TAIL_ADDR;
712 snapshot->reg.ring_ctl = hw_engine_mmio_read32(hwe, RING_CTL(0));
713 snapshot->reg.ring_mi_mode =
714 hw_engine_mmio_read32(hwe, RING_MI_MODE(0));
715 snapshot->reg.ring_mode = hw_engine_mmio_read32(hwe, RING_MODE(0));
716 snapshot->reg.ring_imr = hw_engine_mmio_read32(hwe, RING_IMR(0));
717 snapshot->reg.ring_esr = hw_engine_mmio_read32(hwe, RING_ESR(0));
718 snapshot->reg.ring_emr = hw_engine_mmio_read32(hwe, RING_EMR(0));
719 snapshot->reg.ring_eir = hw_engine_mmio_read32(hwe, RING_EIR(0));
720 snapshot->reg.ring_acthd_udw =
721 hw_engine_mmio_read32(hwe, RING_ACTHD_UDW(0));
722 snapshot->reg.ring_acthd = hw_engine_mmio_read32(hwe, RING_ACTHD(0));
723 snapshot->reg.ring_bbaddr_udw =
724 hw_engine_mmio_read32(hwe, RING_BBADDR_UDW(0));
725 snapshot->reg.ring_bbaddr = hw_engine_mmio_read32(hwe, RING_BBADDR(0));
726 snapshot->reg.ring_dma_fadd_udw =
727 hw_engine_mmio_read32(hwe, RING_DMA_FADD_UDW(0));
728 snapshot->reg.ring_dma_fadd =
729 hw_engine_mmio_read32(hwe, RING_DMA_FADD(0));
730 snapshot->reg.ipehr = hw_engine_mmio_read32(hwe, RING_IPEHR(0));
732 if (snapshot->class == XE_ENGINE_CLASS_COMPUTE)
733 snapshot->reg.rcu_mode = xe_mmio_read32(hwe->gt, RCU_MODE);
739 * xe_hw_engine_snapshot_print - Print out a given Xe HW Engine snapshot.
740 * @snapshot: Xe HW Engine snapshot object.
741 * @p: drm_printer where it will be printed out.
743 * This function prints out a given Xe HW Engine snapshot object.
745 void xe_hw_engine_snapshot_print(struct xe_hw_engine_snapshot *snapshot,
746 struct drm_printer *p)
751 drm_printf(p, "%s (physical), logical instance=%d\n",
752 snapshot->name ? snapshot->name : "",
753 snapshot->logical_instance);
754 drm_printf(p, "\tForcewake: domain 0x%x, ref %d\n",
755 snapshot->forcewake.domain, snapshot->forcewake.ref);
756 drm_printf(p, "\tHWSTAM: 0x%08x\n", snapshot->reg.ring_hwstam);
757 drm_printf(p, "\tRING_HWS_PGA: 0x%08x\n", snapshot->reg.ring_hws_pga);
758 drm_printf(p, "\tRING_EXECLIST_STATUS_LO: 0x%08x\n",
759 snapshot->reg.ring_execlist_status_lo);
760 drm_printf(p, "\tRING_EXECLIST_STATUS_HI: 0x%08x\n",
761 snapshot->reg.ring_execlist_status_hi);
762 drm_printf(p, "\tRING_EXECLIST_SQ_CONTENTS_LO: 0x%08x\n",
763 snapshot->reg.ring_execlist_sq_contents_lo);
764 drm_printf(p, "\tRING_EXECLIST_SQ_CONTENTS_HI: 0x%08x\n",
765 snapshot->reg.ring_execlist_sq_contents_hi);
766 drm_printf(p, "\tRING_START: 0x%08x\n", snapshot->reg.ring_start);
767 drm_printf(p, "\tRING_HEAD: 0x%08x\n", snapshot->reg.ring_head);
768 drm_printf(p, "\tRING_TAIL: 0x%08x\n", snapshot->reg.ring_tail);
769 drm_printf(p, "\tRING_CTL: 0x%08x\n", snapshot->reg.ring_ctl);
770 drm_printf(p, "\tRING_MI_MODE: 0x%08x\n", snapshot->reg.ring_mi_mode);
771 drm_printf(p, "\tRING_MODE: 0x%08x\n",
772 snapshot->reg.ring_mode);
773 drm_printf(p, "\tRING_IMR: 0x%08x\n", snapshot->reg.ring_imr);
774 drm_printf(p, "\tRING_ESR: 0x%08x\n", snapshot->reg.ring_esr);
775 drm_printf(p, "\tRING_EMR: 0x%08x\n", snapshot->reg.ring_emr);
776 drm_printf(p, "\tRING_EIR: 0x%08x\n", snapshot->reg.ring_eir);
777 drm_printf(p, "\tACTHD: 0x%08x_%08x\n", snapshot->reg.ring_acthd_udw,
778 snapshot->reg.ring_acthd);
779 drm_printf(p, "\tBBADDR: 0x%08x_%08x\n", snapshot->reg.ring_bbaddr_udw,
780 snapshot->reg.ring_bbaddr);
781 drm_printf(p, "\tDMA_FADDR: 0x%08x_%08x\n",
782 snapshot->reg.ring_dma_fadd_udw,
783 snapshot->reg.ring_dma_fadd);
784 drm_printf(p, "\tIPEHR: 0x%08x\n\n", snapshot->reg.ipehr);
785 if (snapshot->class == XE_ENGINE_CLASS_COMPUTE)
786 drm_printf(p, "\tRCU_MODE: 0x%08x\n",
787 snapshot->reg.rcu_mode);
791 * xe_hw_engine_snapshot_free - Free all allocated objects for a given snapshot.
792 * @snapshot: Xe HW Engine snapshot object.
794 * This function free all the memory that needed to be allocated at capture
797 void xe_hw_engine_snapshot_free(struct xe_hw_engine_snapshot *snapshot)
802 kfree(snapshot->name);
807 * xe_hw_engine_print - Xe HW Engine Print.
808 * @hwe: Hardware Engine.
811 * This function quickly capture a snapshot and immediately print it out.
813 void xe_hw_engine_print(struct xe_hw_engine *hwe, struct drm_printer *p)
815 struct xe_hw_engine_snapshot *snapshot;
817 snapshot = xe_hw_engine_snapshot_capture(hwe);
818 xe_hw_engine_snapshot_print(snapshot, p);
819 xe_hw_engine_snapshot_free(snapshot);
822 u32 xe_hw_engine_mask_per_class(struct xe_gt *gt,
823 enum xe_engine_class engine_class)
826 enum xe_hw_engine_id id;
828 for (id = 0; id < XE_NUM_HW_ENGINES; ++id) {
829 if (engine_infos[id].class == engine_class &&
830 gt->info.engine_mask & BIT(id))
831 mask |= BIT(engine_infos[id].instance);
836 bool xe_hw_engine_is_reserved(struct xe_hw_engine *hwe)
838 struct xe_gt *gt = hwe->gt;
839 struct xe_device *xe = gt_to_xe(gt);
841 if (hwe->class == XE_ENGINE_CLASS_OTHER)
844 return xe->info.supports_usm && hwe->class == XE_ENGINE_CLASS_COPY &&
845 hwe->instance == gt->usm.reserved_bcs_instance;