History

Merge tag 'drm-xe-next-2025-12-19' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next

[airlied: fix guc submit double definition] UAPI Changes: - Multi-Queue support (Niranjana) - Add DRM_XE_EXEC_QUEUE_SET_HANG_REPLAY_STATE (Brost) - Add NO_COMPRESSION BO flag and query capability (Sanjay) - Add gt_id to struct drm_xe_oa_unit (Ashutosh) - Expose MERT OA unit (Ashutosh) - Sysfs Survivability refactor (Riana) Cross-subsystem Changes: - VFIO: Add device specific vfio_pci driver variant for Intel graphics (Winiarski) Driver Changes: - MAINTAINERS update (Lucas -> Matt) - Add helper to query compression enable status (Xin) - Xe_VM fixes and updates (Shuicheng, Himal) - Documentation fixes (Winiarski, Swaraj, Niranjana) - Kunit fix (Roper) - Fix potential leaks, uaf, null derref, and oversized allocations (Shuicheng, Sanjay, Mika, Tapani) - Other minor fixes like kbuild duplication and sysfs_emit (Shuicheng, Madhur) - Handle msix vector0 interrupt (Venkata) - Scope-based forcewake and runtime PM (Roper, Raag) - GuC/HuC related fixes and refactors (Lucas, Zhanjun, Brost, Julia, Wajdeczko) - Fix conversion from clock ticks to milliseconds (Harish) - SRIOV PF PF: Add support for MERT (Lukasz) - Enable SR-IOV VF migration and other SRIOV updates (Winiarski, Satya, Brost, Wajdeczko, Piotr, Tomasz, Daniele) - Optimize runtime suspend/resume and other PM improvements (Raag) - Some W/a additions and updates (Bala, Harish, Roper) - Use for_each_tlb_inval() to calculate invalidation fences (Roper) - Fix VFIO link error (Arnd) - Fix ix drm_gpusvm_init() arguments (Arnd) - Other OA refactor (Ashutosh) - Refactor PAT and expose debugfs (Xin) - Enable Indirect Ring State for xe3p_xpc (Niranjana) - MEI interrupt fix (Junxiao) - Add stats for mode switching on hw_engine_group (Francois) - DMA-Buf related changes (Thomas) - Multi Queue feature support (Niranjana) - Enable I2C controller for Crescent Island (Raag) - Enable NVM for Crescent Island (Sasha) - Increase TDF timeout (Jagmeet) - Restore engine registers before restarting schedulers after GT reset (Jan) - Page Reclamation Support for Xe3p Platforms (Brian, Brost, Oak) - Fix performance when pagefaults and 3d/display share resources (Brost) - More OA MERT work (Ashutosh) - Fix return values (Dan) - Some log level and messages improvements (Brost) Signed-off-by: Dave Airlie <airlied@redhat.com>

Dave Airlie committed 10 months ago

Commit 9ec3c8e2 parents c5fb82d 844758b152 files · +5329 −1498Browse files

Unified · Split

152 files
  1. .mailmap +1 −0
  2. Documentation/ABI/testing/sysfs-driver-intel-xe-sriov +1 −1
  3. Documentation/gpu/xe/xe_exec_queue.rst +14 −0
  4. MAINTAINERS +1 −1
  5. drivers/gpu/drm/drm_gpusvm.c +3 −0
  6. drivers/gpu/drm/xe/Makefile +2 −0
  7. drivers/gpu/drm/xe/abi/guc_actions_abi.h +6 −0
  8. drivers/gpu/drm/xe/abi/guc_actions_sriov_abi.h +57 −10
  9. drivers/gpu/drm/xe/abi/guc_klvs_abi.h +9 −0
  10. drivers/gpu/drm/xe/abi/guc_lfd_abi.h +171 −0
  11. drivers/gpu/drm/xe/abi/guc_lic_abi.h +77 −0
  12. drivers/gpu/drm/xe/abi/guc_log_abi.h +38 −4
  13. drivers/gpu/drm/xe/display/xe_fb_pin.c +9 −14
  14. drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +9 −22
  15. drivers/gpu/drm/xe/instructions/xe_gpu_commands.h +1 −0
  16. drivers/gpu/drm/xe/regs/xe_gt_regs.h +3 −0
  17. drivers/gpu/drm/xe/regs/xe_gtt_defs.h +1 −0
  18. drivers/gpu/drm/xe/regs/xe_guc_regs.h +3 −0
  19. drivers/gpu/drm/xe/regs/xe_irq_regs.h +1 −0
  20. drivers/gpu/drm/xe/regs/xe_mert_regs.h +21 −0
  21. drivers/gpu/drm/xe/regs/xe_oa_regs.h +17 −0
  22. drivers/gpu/drm/xe/tests/xe_args_test.c +54 −0
  23. drivers/gpu/drm/xe/tests/xe_bo.c +2 −8
  24. drivers/gpu/drm/xe/tests/xe_dma_buf.c +1 −2
  25. drivers/gpu/drm/xe/tests/xe_migrate.c +2 −8
  26. drivers/gpu/drm/xe/tests/xe_mocs.c +8 −19
  27. drivers/gpu/drm/xe/xe_args.h +27 −0
  28. drivers/gpu/drm/xe/xe_bo.c +16 −10
  29. drivers/gpu/drm/xe/xe_bo.h +1 −0
  30. drivers/gpu/drm/xe/xe_debugfs.c +121 −22
  31. drivers/gpu/drm/xe/xe_devcoredump.c +12 −18
  32. drivers/gpu/drm/xe/xe_device.c +77 −23
  33. drivers/gpu/drm/xe/xe_device.h +5 −0
  34. drivers/gpu/drm/xe/xe_device_sysfs.c +13 −20
  35. drivers/gpu/drm/xe/xe_device_types.h +27 −0
  36. drivers/gpu/drm/xe/xe_drm_client.c +31 −36
  37. drivers/gpu/drm/xe/xe_exec.c +7 −2
  38. drivers/gpu/drm/xe/xe_exec_queue.c +441 −14
  39. drivers/gpu/drm/xe/xe_exec_queue.h +68 −0
  40. drivers/gpu/drm/xe/xe_exec_queue_types.h +62 −0
  41. drivers/gpu/drm/xe/xe_execlist.c +1 −1
  42. drivers/gpu/drm/xe/xe_force_wake.c +7 −0
  43. drivers/gpu/drm/xe/xe_force_wake.h +40 −0
  44. drivers/gpu/drm/xe/xe_ggtt.c +1 −2
  45. drivers/gpu/drm/xe/xe_gsc.c +6 −15
  46. drivers/gpu/drm/xe/xe_gsc_debugfs.c +1 −2
  47. drivers/gpu/drm/xe/xe_gsc_proxy.c +7 −10
  48. drivers/gpu/drm/xe/xe_gt.c +87 −87
  49. drivers/gpu/drm/xe/xe_gt.h +2 −0
  50. drivers/gpu/drm/xe/xe_gt_debugfs.c +9 −21
  51. drivers/gpu/drm/xe/xe_gt_freq.c +9 −18
  52. drivers/gpu/drm/xe/xe_gt_idle.c +12 −29
  53. drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +12 −7
  54. drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c +10 −11
  55. drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c +1 −1
  56. drivers/gpu/drm/xe/xe_gt_sriov_vf.c +126 −44
  57. drivers/gpu/drm/xe/xe_gt_sriov_vf_debugfs.c +12 −0
  58. drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h +13 −0
  59. drivers/gpu/drm/xe/xe_gt_stats.c +10 −0
  60. drivers/gpu/drm/xe/xe_gt_stats.h +32 −0
  61. drivers/gpu/drm/xe/xe_gt_stats_types.h +5 −0
  62. drivers/gpu/drm/xe/xe_gt_throttle.c +3 −6
  63. drivers/gpu/drm/xe/xe_gt_types.h +5 −0
  64. drivers/gpu/drm/xe/xe_guc.c +60 −20
  65. drivers/gpu/drm/xe/xe_guc.h +23 −0
  66. drivers/gpu/drm/xe/xe_guc_ads.c +3 −3
  67. drivers/gpu/drm/xe/xe_guc_buf.c +1 −1
  68. drivers/gpu/drm/xe/xe_guc_capture.c +8 −8
  69. drivers/gpu/drm/xe/xe_guc_ct.c +170 −103
  70. drivers/gpu/drm/xe/xe_guc_ct.h +2 −0
  71. drivers/gpu/drm/xe/xe_guc_debugfs.c +9 −6
  72. drivers/gpu/drm/xe/xe_guc_fwif.h +7 −3
  73. drivers/gpu/drm/xe/xe_guc_klv_thresholds_set_types.h +6 −0
  74. drivers/gpu/drm/xe/xe_guc_log.c +406 −101
  75. drivers/gpu/drm/xe/xe_guc_log.h +20 −10
  76. drivers/gpu/drm/xe/xe_guc_pc.c +19 −47
  77. drivers/gpu/drm/xe/xe_guc_submit.c +637 −68
  78. drivers/gpu/drm/xe/xe_guc_submit.h +7 −2
  79. drivers/gpu/drm/xe/xe_guc_submit_types.h +13 −0
  80. drivers/gpu/drm/xe/xe_guc_tlb_inval.c +31 −10
  81. drivers/gpu/drm/xe/xe_huc.c +2 −5
  82. drivers/gpu/drm/xe/xe_huc_debugfs.c +1 −2
  83. drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c +6 −10
  84. drivers/gpu/drm/xe/xe_hw_engine_group.c +71 −8
  85. drivers/gpu/drm/xe/xe_hw_engine_group.h +3 −1
  86. drivers/gpu/drm/xe/xe_hwmon.c +14 −38
  87. drivers/gpu/drm/xe/xe_i2c.c +1 −1
  88. drivers/gpu/drm/xe/xe_irq.c +2 −0
  89. drivers/gpu/drm/xe/xe_lmtt.c +22 −3
  90. drivers/gpu/drm/xe/xe_lrc.c +63 −10
  91. drivers/gpu/drm/xe/xe_lrc.h +6 −1
  92. drivers/gpu/drm/xe/xe_lrc_types.h +3 −0
  93. drivers/gpu/drm/xe/xe_mert.c +82 −0
  94. drivers/gpu/drm/xe/xe_mert.h +32 −0
  95. drivers/gpu/drm/xe/xe_migrate.c +54 −3
  96. drivers/gpu/drm/xe/xe_migrate.h +3 −0
  97. drivers/gpu/drm/xe/xe_mocs.c +6 −12
  98. drivers/gpu/drm/xe/xe_nvm.c +23 −11
  99. drivers/gpu/drm/xe/xe_oa.c +65 −29
  100. drivers/gpu/drm/xe/xe_oa_types.h +1 −0
  101. drivers/gpu/drm/xe/xe_page_reclaim.c +136 −0
  102. drivers/gpu/drm/xe/xe_page_reclaim.h +105 −0
  103. drivers/gpu/drm/xe/xe_pagefault.c +18 −18
  104. drivers/gpu/drm/xe/xe_pat.c +152 −68
  105. drivers/gpu/drm/xe/xe_pat.h +21 −0
  106. drivers/gpu/drm/xe/xe_pci.c +29 −0
  107. drivers/gpu/drm/xe/xe_pci_sriov.c +3 −7
  108. drivers/gpu/drm/xe/xe_pci_types.h +6 −0
  109. drivers/gpu/drm/xe/xe_pcode_api.h +2 −0
  110. drivers/gpu/drm/xe/xe_pm.c +5 −5
  111. drivers/gpu/drm/xe/xe_pmu.c +1 −1
  112. drivers/gpu/drm/xe/xe_pt.c +134 −1
  113. drivers/gpu/drm/xe/xe_pt_types.h +5 −0
  114. drivers/gpu/drm/xe/xe_pxp.c +18 −37
  115. drivers/gpu/drm/xe/xe_query.c +12 −11
  116. drivers/gpu/drm/xe/xe_reg_sr.c +5 −12
  117. drivers/gpu/drm/xe/xe_reg_whitelist.c +59 −22
  118. drivers/gpu/drm/xe/xe_ring_ops.c +34 −34
  119. drivers/gpu/drm/xe/xe_sa.c +66 −1
  120. drivers/gpu/drm/xe/xe_sa.h +18 −2
  121. drivers/gpu/drm/xe/xe_sa_types.h +3 −0
  122. drivers/gpu/drm/xe/xe_sriov_packet.c +1 −1
  123. drivers/gpu/drm/xe/xe_sriov_pf.c +4 −0
  124. drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c +2 −4
  125. drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c +4 −12
  126. drivers/gpu/drm/xe/xe_sriov_vf.c +80 −4
  127. drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +19 −8
  128. drivers/gpu/drm/xe/xe_sriov_vf_ccs.h +1 −0
  129. drivers/gpu/drm/xe/xe_survivability_mode.c +180 −93
  130. drivers/gpu/drm/xe/xe_survivability_mode_types.h +20 −8
  131. drivers/gpu/drm/xe/xe_svm.c +42 −46
  132. drivers/gpu/drm/xe/xe_sync.c +31 −2
  133. drivers/gpu/drm/xe/xe_sync.h +2 −0
  134. drivers/gpu/drm/xe/xe_tile.c +5 −0
  135. drivers/gpu/drm/xe/xe_tile_debugfs.c +11 −6
  136. drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c +1 −2
  137. drivers/gpu/drm/xe/xe_tlb_inval.c +24 −3
  138. drivers/gpu/drm/xe/xe_tlb_inval.h +1 −1
  139. drivers/gpu/drm/xe/xe_tlb_inval_job.c +35 −1
  140. drivers/gpu/drm/xe/xe_tlb_inval_job.h +4 −0
  141. drivers/gpu/drm/xe/xe_tlb_inval_types.h +4 −1
  142. drivers/gpu/drm/xe/xe_trace.h +46 −0
  143. drivers/gpu/drm/xe/xe_uc.c +33 −2
  144. drivers/gpu/drm/xe/xe_uc.h +2 −0
  145. drivers/gpu/drm/xe/xe_uc_fw.c +5 −5
  146. drivers/gpu/drm/xe/xe_vm.c +136 −18
  147. drivers/gpu/drm/xe/xe_vm.h +3 −0
  148. drivers/gpu/drm/xe/xe_vm_types.h +1 −0
  149. drivers/gpu/drm/xe/xe_vram.c +2 −4
  150. drivers/gpu/drm/xe/xe_wa.c +6 −46
  151. drivers/gpu/drm/xe/xe_wa_oob.rules +1 −5
  152. include/uapi/drm/xe_drm.h +78 −3
.mailmap+1−0
@@ -481,6 +481,7 @@ Lorenzo Pieralisi <lpieralisi@kernel.org> <lorenzo.pieralisi@arm.com> · 480 unmodified lines
481481 Lorenzo Stoakes <lorenzo.stoakes@oracle.com> <lstoakes@gmail.com>
482482 Luca Ceresoli <luca.ceresoli@bootlin.com> <luca@lucaceresoli.net>
483483 Luca Weiss <luca@lucaweiss.eu> <luca@z3ntu.xyz>
484+Lucas De Marchi <demarchi@kernel.org> <lucas.demarchi@intel.com>
484485 Lukasz Luba <lukasz.luba@arm.com> <l.luba@partner.samsung.com>
485486 Luo Jie <quic_luoj@quicinc.com> <luoj@codeaurora.org>
486487 Lance Yang <lance.yang@linux.dev> <ioworker0@gmail.com>
Documentation/ABI/testing/sysfs-driver-intel-xe-sriov+1−1
@@ -119,7 +119,7 @@ Description: · 118 unmodified lines
119119 The GT preemption timeout (PT) in [us] to be applied to all functions.
120120 See sriov_admin/{pf,vf<N>}/profile/preempt_timeout_us for more details.
121121
122− sched_priority: (RW/RO) string
122+ sched_priority: (WO) string
123123 The GT scheduling priority to be applied for all functions.
124124 See sriov_admin/{pf,vf<N>}/profile/sched_priority for more details.
125125
Documentation/gpu/xe/xe_exec_queue.rst+14−0
@@ -7,6 +7,20 @@ Execution Queue · 6 unmodified lines
77 .. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c
88 :doc: Execution Queue
99
10+Multi Queue Group
11+=================
12+
13+.. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c
14+ :doc: Multi Queue Group
15+
16+.. _multi-queue-group-guc-interface:
17+
18+Multi Queue Group GuC interface
19+===============================
20+
21+.. kernel-doc:: drivers/gpu/drm/xe/xe_guc_submit.c
22+ :doc: Multi Queue Group GuC interface
23+
1024 Internal API
1125 ============
1226
MAINTAINERS+1−1
@@ -12640,7 +12640,7 @@ F: include/drm/intel/ · 12639 unmodified lines
1264012640 F: include/uapi/drm/i915_drm.h
1264112641
1264212642 INTEL DRM XE DRIVER (Lunar Lake and newer)
12643−M: Lucas De Marchi <lucas.demarchi@intel.com>
12643+M: Matthew Brost <matthew.brost@intel.com>
1264412644 M: Thomas Hellström <thomas.hellstrom@linux.intel.com>
1264512645 M: Rodrigo Vivi <rodrigo.vivi@intel.com>
1264612646 L: intel-xe@lists.freedesktop.org
drivers/gpu/drm/drm_gpusvm.c+3−0
@@ -1288,6 +1288,9 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, · 1287 unmodified lines
12881288 DMA_BIDIRECTIONAL;
12891289
12901290 retry:
1291+ if (time_after(jiffies, timeout))
1292+ return -EBUSY;
1293+
12911294 hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
12921295 if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages))
12931296 goto set_seqno;
drivers/gpu/drm/xe/Makefile+2−0
@@ -95,6 +95,7 @@ xe-y += xe_bb.o \ · 94 unmodified lines
9595 xe_oa.o \
9696 xe_observation.o \
9797 xe_pagefault.o \
98+ xe_page_reclaim.o \
9899 xe_pat.o \
99100 xe_pci.o \
100101 xe_pcode.o \
@@ -173,6 +174,7 @@ xe-$(CONFIG_PCI_IOV) += \ · 72 unmodified lines
173174 xe_lmtt.o \
174175 xe_lmtt_2l.o \
175176 xe_lmtt_ml.o \
177+ xe_mert.o \
176178 xe_pci_sriov.o \
177179 xe_sriov_packet.o \
178180 xe_sriov_pf.o \
drivers/gpu/drm/xe/abi/guc_actions_abi.h+6−0
@@ -139,6 +139,10 @@ enum xe_guc_action { · 138 unmodified lines
139139 XE_GUC_ACTION_DEREGISTER_G2G = 0x4508,
140140 XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE = 0x4600,
141141 XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC = 0x4601,
142+ XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE = 0x4602,
143+ XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC = 0x4603,
144+ XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE = 0x4604,
145+ XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CGP_CONTEXT_ERROR = 0x4605,
142146 XE_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507,
143147 XE_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A,
144148 XE_GUC_ACTION_SET_DEVICE_ENGINE_ACTIVITY_BUFFER = 0x550C,
@@ -151,6 +155,8 @@ enum xe_guc_action { · 6 unmodified lines
151155 XE_GUC_ACTION_TLB_INVALIDATION = 0x7000,
152156 XE_GUC_ACTION_TLB_INVALIDATION_DONE = 0x7001,
153157 XE_GUC_ACTION_TLB_INVALIDATION_ALL = 0x7002,
158+ XE_GUC_ACTION_PAGE_RECLAMATION = 0x7003,
159+ XE_GUC_ACTION_PAGE_RECLAMATION_DONE = 0x7004,
154160 XE_GUC_ACTION_STATE_CAPTURE_NOTIFICATION = 0x8002,
155161 XE_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE = 0x8003,
156162 XE_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED = 0x8004,
drivers/gpu/drm/xe/abi/guc_actions_sriov_abi.h+57−10
@@ -502,13 +502,17 @@ · 501 unmodified lines
502502 #define VF2GUC_VF_RESET_RESPONSE_MSG_0_MBZ GUC_HXG_RESPONSE_MSG_0_DATA0
503503
504504 /**
505− * DOC: VF2GUC_NOTIFY_RESFIX_DONE
505+ * DOC: VF2GUC_RESFIX_DONE
506506 *
507− * This action is used by VF to notify the GuC that the VF KMD has completed
508− * post-migration recovery steps.
507+ * This action is used by VF to inform the GuC that the VF KMD has completed
508+ * post-migration recovery steps. From GuC VF compatibility 1.27.0 onwards, it
509+ * shall only be sent after posting RESFIX_START and that both @MARKER fields
510+ * must match.
509511 *
510512 * This message must be sent as `MMIO HXG Message`_.
511513 *
514+ * Updated since GuC VF compatibility 1.27.0.
515+ *
512516 * +---+-------+--------------------------------------------------------------+
513517 * | | Bits | Description |
514518 * +===+=======+==============================================================+
@@ -516,9 +520,11 @@ · 1 unmodified line
516520 * | +-------+--------------------------------------------------------------+
517521 * | | 30:28 | TYPE = GUC_HXG_TYPE_REQUEST_ |
518522 * | +-------+--------------------------------------------------------------+
519− * | | 27:16 | DATA0 = MBZ |
523+ * | | 27:16 | DATA0 = MARKER = MBZ (only prior 1.27.0) |
520524 * | +-------+--------------------------------------------------------------+
521− * | | 15:0 | ACTION = _`GUC_ACTION_VF2GUC_NOTIFY_RESFIX_DONE` = 0x5508 |
525+ * | | 27:16 | DATA0 = MARKER - can't be zero (1.27.0+) |
526+ * | +-------+--------------------------------------------------------------+
527+ * | | 15:0 | ACTION = _`GUC_ACTION_VF2GUC_RESFIX_DONE` = 0x5508 |
522528 * +---+-------+--------------------------------------------------------------+
523529 *
524530 * +---+-------+--------------------------------------------------------------+
@@ -531,13 +537,13 @@ · 6 unmodified lines
531537 * | | 27:0 | DATA0 = MBZ |
532538 * +---+-------+--------------------------------------------------------------+
533539 */
534−#define GUC_ACTION_VF2GUC_NOTIFY_RESFIX_DONE 0x5508u
540+#define GUC_ACTION_VF2GUC_RESFIX_DONE 0x5508u
535541
536−#define VF2GUC_NOTIFY_RESFIX_DONE_REQUEST_MSG_LEN GUC_HXG_REQUEST_MSG_MIN_LEN
537−#define VF2GUC_NOTIFY_RESFIX_DONE_REQUEST_MSG_0_MBZ GUC_HXG_REQUEST_MSG_0_DATA0
542+#define VF2GUC_RESFIX_DONE_REQUEST_MSG_LEN GUC_HXG_REQUEST_MSG_MIN_LEN
543+#define VF2GUC_RESFIX_DONE_REQUEST_MSG_0_MARKER GUC_HXG_REQUEST_MSG_0_DATA0
538544
539−#define VF2GUC_NOTIFY_RESFIX_DONE_RESPONSE_MSG_LEN GUC_HXG_RESPONSE_MSG_MIN_LEN
540−#define VF2GUC_NOTIFY_RESFIX_DONE_RESPONSE_MSG_0_MBZ GUC_HXG_RESPONSE_MSG_0_DATA0
545+#define VF2GUC_RESFIX_DONE_RESPONSE_MSG_LEN GUC_HXG_RESPONSE_MSG_MIN_LEN
546+#define VF2GUC_RESFIX_DONE_RESPONSE_MSG_0_MBZ GUC_HXG_RESPONSE_MSG_0_DATA0
541547
542548 /**
543549 * DOC: VF2GUC_QUERY_SINGLE_KLV
@@ -656,4 +662,45 @@ · 112 unmodified lines
656662 #define PF2GUC_SAVE_RESTORE_VF_RESPONSE_MSG_LEN GUC_HXG_RESPONSE_MSG_MIN_LEN
657663 #define PF2GUC_SAVE_RESTORE_VF_RESPONSE_MSG_0_USED GUC_HXG_RESPONSE_MSG_0_DATA0
658664
665+/**
666+ * DOC: VF2GUC_RESFIX_START
667+ *
668+ * This action is used by VF to inform the GuC that the VF KMD will be starting
669+ * post-migration recovery fixups. The @MARKER sent with this action must match
670+ * with the MARKER posted in the VF2GUC_RESFIX_DONE message.
671+ *
672+ * This message must be sent as `MMIO HXG Message`_.
673+ *
674+ * Available since GuC VF compatibility 1.27.0.
675+ *
676+ * +---+-------+--------------------------------------------------------------+
677+ * | | Bits | Description |
678+ * +===+=======+==============================================================+
679+ * | 0 | 31 | ORIGIN = GUC_HXG_ORIGIN_HOST_ |
680+ * | +-------+--------------------------------------------------------------+
681+ * | | 30:28 | TYPE = GUC_HXG_TYPE_REQUEST_ |
682+ * | +-------+--------------------------------------------------------------+
683+ * | | 27:16 | DATA0 = MARKER - can't be zero |
684+ * | +-------+--------------------------------------------------------------+
685+ * | | 15:0 | ACTION = _`GUC_ACTION_VF2GUC_RESFIX_START` = 0x550F |
686+ * +---+-------+--------------------------------------------------------------+
687+ *
688+ * +---+-------+--------------------------------------------------------------+
689+ * | | Bits | Description |
690+ * +===+=======+==============================================================+
691+ * | 0 | 31 | ORIGIN = GUC_HXG_ORIGIN_GUC_ |
692+ * | +-------+--------------------------------------------------------------+
693+ * | | 30:28 | TYPE = GUC_HXG_TYPE_RESPONSE_SUCCESS_ |
694+ * | +-------+--------------------------------------------------------------+
695+ * | | 27:0 | DATA0 = MBZ |
696+ * +---+-------+--------------------------------------------------------------+
697+ */
698+#define GUC_ACTION_VF2GUC_RESFIX_START 0x550Fu
699+
700+#define VF2GUC_RESFIX_START_REQUEST_MSG_LEN GUC_HXG_REQUEST_MSG_MIN_LEN
701+#define VF2GUC_RESFIX_START_REQUEST_MSG_0_MARKER GUC_HXG_REQUEST_MSG_0_DATA0
702+
703+#define VF2GUC_RESFIX_START_RESPONSE_MSG_LEN GUC_HXG_RESPONSE_MSG_MIN_LEN
704+#define VF2GUC_RESFIX_START_RESPONSE_MSG_0_MBZ GUC_HXG_RESPONSE_MSG_0_DATA0
705+
659706 #endif
drivers/gpu/drm/xe/abi/guc_klvs_abi.h+9−0
@@ -352,6 +352,12 @@ enum { · 351 unmodified lines
352352 * :1: NORMAL = schedule VF always, irrespective of whether it has work or not
353353 * :2: HIGH = schedule VF in the next time-slice after current active
354354 * time-slice completes if it has active work
355+ *
356+ * _`GUC_KLV_VF_CFG_THRESHOLD_MULTI_LRC_COUNT` : 0x8A0D
357+ * Given that multi-LRC contexts are incompatible with SRIOV scheduler
358+ * groups and cause the latter to be turned off when registered with the
359+ * GuC, this config allows the PF to set a threshold for multi-LRC context
360+ * registrations by VFs to monitor their behavior.
355361 */
356362
357363 #define GUC_KLV_VF_CFG_GGTT_START_KEY 0x0001
@@ -410,6 +416,9 @@ enum { · 52 unmodified lines
410416 #define GUC_SCHED_PRIORITY_NORMAL 1u
411417 #define GUC_SCHED_PRIORITY_HIGH 2u
412418
419+#define GUC_KLV_VF_CFG_THRESHOLD_MULTI_LRC_COUNT_KEY 0x8a0d
420+#define GUC_KLV_VF_CFG_THRESHOLD_MULTI_LRC_COUNT_LEN 1u
421+
413422 /*
414423 * Workaround keys:
415424 */
drivers/gpu/drm/xe/abi/guc_lfd_abi.h+171−0
@@ -0,0 +1,171 @@
1+/* SPDX-License-Identifier: MIT */
2+/*
3+ * Copyright © 2025 Intel Corporation
4+ */
5+
6+#ifndef _ABI_GUC_LFD_ABI_H_
7+#define _ABI_GUC_LFD_ABI_H_
8+
9+#include <linux/types.h>
10+
11+#include "guc_lic_abi.h"
12+
13+/* The current major version of GuC-Log-File format. */
14+#define GUC_LFD_FORMAT_VERSION_MAJOR 0x0001
15+/* The current minor version of GuC-Log-File format. */
16+#define GUC_LFD_FORMAT_VERSION_MINOR 0x0000
17+
18+/** enum guc_lfd_type - Log format descriptor type */
19+enum guc_lfd_type {
20+ /**
21+ * @GUC_LFD_TYPE_FW_REQUIRED_RANGE_START: Start of range for
22+ * required LFDs from GuC
23+ * @GUC_LFD_TYPE_FW_VERSION: GuC Firmware Version structure.
24+ * @GUC_LFD_TYPE_GUC_DEVICE_ID: GuC microcontroller device ID.
25+ * @GUC_LFD_TYPE_TSC_FREQUENCY: Frequency of GuC timestamps.
26+ * @GUC_LFD_TYPE_GMD_ID: HW GMD ID.
27+ * @GUC_LFD_TYPE_BUILD_PLATFORM_ID: GuC build platform ID.
28+ * @GUC_LFD_TYPE_FW_REQUIRED_RANGE_END: End of range for
29+ * required LFDs from GuC
30+ */
31+ GUC_LFD_TYPE_FW_REQUIRED_RANGE_START = 0x1,
32+ GUC_LFD_TYPE_FW_VERSION = 0x1,
33+ GUC_LFD_TYPE_GUC_DEVICE_ID = 0x2,
34+ GUC_LFD_TYPE_TSC_FREQUENCY = 0x3,
35+ GUC_LFD_TYPE_GMD_ID = 0x4,
36+ GUC_LFD_TYPE_BUILD_PLATFORM_ID = 0x5,
37+ GUC_LFD_TYPE_FW_REQUIRED_RANGE_END = 0x1FFF,
38+
39+ /**
40+ * @GUC_LFD_TYPE_FW_OPTIONAL_RANGE_START: Start of range for
41+ * optional LFDs from GuC
42+ * @GUC_LFD_TYPE_LOG_EVENTS_BUFFER: Log-event-entries buffer.
43+ * @GUC_LFD_TYPE_FW_CRASH_DUMP: GuC generated crash-dump blob.
44+ * @GUC_LFD_TYPE_FW_OPTIONAL_RANGE_END: End of range for
45+ * optional LFDs from GuC
46+ */
47+ GUC_LFD_TYPE_FW_OPTIONAL_RANGE_START = 0x2000,
48+ GUC_LFD_TYPE_LOG_EVENTS_BUFFER = 0x2000,
49+ GUC_LFD_TYPE_FW_CRASH_DUMP = 0x2001,
50+ GUC_LFD_TYPE_FW_OPTIONAL_RANGE_END = 0x3FFF,
51+
52+ /**
53+ * @GUC_LFD_TYPE_KMD_REQUIRED_RANGE_START: Start of range for
54+ * required KMD LFDs
55+ * @GUC_LFD_TYPE_OS_ID: An identifier for the OS.
56+ * @GUC_LFD_TYPE_KMD_REQUIRED_RANGE_END: End of this range for
57+ * required KMD LFDs
58+ */
59+ GUC_LFD_TYPE_KMD_REQUIRED_RANGE_START = 0x4000,
60+ GUC_LFD_TYPE_OS_ID = 0x4000,
61+ GUC_LFD_TYPE_KMD_REQUIRED_RANGE_END = 0x5FFF,
62+
63+ /**
64+ * @GUC_LFD_TYPE_KMD_OPTIONAL_RANGE_START: Start of range for
65+ * optional KMD LFDs
66+ * @GUC_LFD_TYPE_BINARY_SCHEMA_FORMAT: Binary representation of
67+ * GuC log-events schema.
68+ * @GUC_LFD_TYPE_HOST_COMMENT: ASCII string containing comments
69+ * from the host/KMD.
70+ * @GUC_LFD_TYPE_TIMESTAMP_ANCHOR: A timestamp anchor, to convert
71+ * between host and GuC timestamp.
72+ * @GUC_LFD_TYPE_TIMESTAMP_ANCHOR_CONFIG: Timestamp anchor
73+ * configuration, definition of timestamp frequency and bit width.
74+ * @GUC_LFD_TYPE_KMD_OPTIONAL_RANGE_END: End of this range for
75+ * optional KMD LFDs
76+ */
77+ GUC_LFD_TYPE_KMD_OPTIONAL_RANGE_START = 0x6000,
78+ GUC_LFD_TYPE_BINARY_SCHEMA_FORMAT = 0x6000,
79+ GUC_LFD_TYPE_HOST_COMMENT = 0x6001,
80+ GUC_LFD_TYPE_TIMESTAMP_ANCHOR = 0x6002,
81+ GUC_LFD_TYPE_TIMESTAMP_ANCHOR_CONFIG = 0x6003,
82+ GUC_LFD_TYPE_KMD_OPTIONAL_RANGE_END = 0x7FFF,
83+
84+ /*
85+ * @GUC_LFD_TYPE_RESERVED_RANGE_START: Start of reserved range
86+ * @GUC_LFD_TYPE_RESERVED_RANGE_END: End of reserved range
87+ */
88+ GUC_LFD_TYPE_RESERVED_RANGE_START = 0x8000,
89+ GUC_LFD_TYPE_RESERVED_RANGE_END = 0xFFFF,
90+};
91+
92+/** enum guc_lfd_os_type - OS Type LFD-ID */
93+enum guc_lfd_os_type {
94+ /** @GUC_LFD_OS_TYPE_OSID_WIN: Windows OS */
95+ GUC_LFD_OS_TYPE_OSID_WIN = 0x1,
96+ /** @GUC_LFD_OS_TYPE_OSID_LIN: Linux OS */
97+ GUC_LFD_OS_TYPE_OSID_LIN = 0x2,
98+ /** @GUC_LFD_OS_TYPE_OSID_VMW: VMWare OS */
99+ GUC_LFD_OS_TYPE_OSID_VMW = 0x3,
100+ /** @GUC_LFD_OS_TYPE_OSID_OTHER: Other */
101+ GUC_LFD_OS_TYPE_OSID_OTHER = 0x4,
102+};
103+
104+/** struct guc_lfd_data - A generic header structure for all LFD blocks */
105+struct guc_lfd_data {
106+ /** @header: A 32 bits dword, contains multiple bit fields */
107+ u32 header;
108+ /* LFD type. See guc_lfd_type */
109+#define GUC_LFD_DATA_HEADER_MASK_TYPE GENMASK(31, 16)
110+#define GUC_LFD_DATA_HEADER_MASK_MAGIC GENMASK(15, 0)
111+
112+ /** @data_count: Number of dwords the `data` field contains. */
113+ u32 data_count;
114+ /** @data: Data defined by GUC_LFD_DATA_HEADER_MASK_TYPE */
115+ u32 data[] __counted_by(data_count);
116+} __packed;
117+
118+/**
119+ * struct guc_lfd_data_log_events_buf - GuC Log Events Buffer.
120+ * This is optional fw LFD data
121+ */
122+struct guc_lfd_data_log_events_buf {
123+ /**
124+ * @log_events_format_version: version of GuC log format of buffer
125+ */
126+ u32 log_events_format_version;
127+ /**
128+ * @log_event: The log event data.
129+ * Size in dwords is LFD block size - 1.
130+ */
131+ u32 log_event[];
132+} __packed;
133+
134+/** struct guc_lfd_data_os_info - OS Version Information. */
135+struct guc_lfd_data_os_info {
136+ /**
137+ * @os_id: enum values to identify the OS brand.
138+ * See guc_lfd_os_type for the range of types
139+ */
140+ u32 os_id;
141+ /**
142+ * @build_version: ASCII string containing OS build version
143+ * information based on os_id. String is padded with null
144+ * characters to ensure its DWORD aligned.
145+ * Size in dwords is LFD block size - 1.
146+ */
147+ char build_version[];
148+} __packed;
149+
150+/**
151+ * struct guc_logfile_header - Header of GuC Log Streaming-LFD-File Format.
152+ * This structure encapsulates the layout of the guc-log-file format
153+ */
154+struct guc_lfd_file_header {
155+ /**
156+ * @magic: A magic number set by producer of a GuC log file to
157+ * identify that file is a valid guc-log-file containing a stream
158+ * of LFDs.
159+ */
160+ u64 magic;
161+ /** @version: Version of this file format layout */
162+ u32 version;
163+#define GUC_LFD_FILE_HEADER_VERSION_MASK_MAJOR GENMASK(31, 16)
164+#define GUC_LFD_FILE_HEADER_VERSION_MASK_MINOR GENMASK(15, 0)
165+
166+ /** @stream: A stream of one or more guc_lfd_data LFD blocks
167+ */
168+ u32 stream[];
169+} __packed;
170+
171+#endif
drivers/gpu/drm/xe/abi/guc_lic_abi.h+77−0
@@ -0,0 +1,77 @@
1+/* SPDX-License-Identifier: MIT */
2+/*
3+ * Copyright © 2025 Intel Corporation
4+ */
5+
6+#ifndef _ABI_GUC_LIC_ABI_H_
7+#define _ABI_GUC_LIC_ABI_H_
8+
9+#include <linux/types.h>
10+
11+/**
12+ * enum guc_lic_type - Log Init Config KLV IDs.
13+ */
14+enum guc_lic_type {
15+ /**
16+ * @GUC_LIC_TYPE_GUC_SW_VERSION: GuC firmware version. Value
17+ * is a 32 bit number represented by guc_sw_version.
18+ */
19+ GUC_LIC_TYPE_GUC_SW_VERSION = 0x1,
20+ /**
21+ * @GUC_LIC_TYPE_GUC_DEVICE_ID: GuC device id. Value is a 32
22+ * bit.
23+ */
24+ GUC_LIC_TYPE_GUC_DEVICE_ID = 0x2,
25+ /**
26+ * @GUC_LIC_TYPE_TSC_FREQUENCY: GuC timestamp counter
27+ * frequency. Value is a 32 bit number representing frequency in
28+ * kHz. This timestamp is utilized in log entries, timer and
29+ * for engine utilization tracking.
30+ */
31+ GUC_LIC_TYPE_TSC_FREQUENCY = 0x3,
32+ /**
33+ * @GUC_LIC_TYPE_GMD_ID: HW GMD ID. Value is a 32 bit number
34+ * representing graphics, media and display HW architecture IDs.
35+ */
36+ GUC_LIC_TYPE_GMD_ID = 0x4,
37+ /**
38+ * @GUC_LIC_TYPE_BUILD_PLATFORM_ID: GuC build platform ID.
39+ * Value is 32 bits.
40+ */
41+ GUC_LIC_TYPE_BUILD_PLATFORM_ID = 0x5,
42+};
43+
44+/**
45+ * struct guc_lic - GuC LIC (Log-Init-Config) structure.
46+ *
47+ * This is populated by the GUC at log init time and is located in the log
48+ * buffer memory allocation.
49+ */
50+struct guc_lic {
51+ /**
52+ * @magic: A magic number set by GuC to identify that this
53+ * structure contains valid information: magic = GUC_LIC_MAGIC.
54+ */
55+ u32 magic;
56+#define GUC_LIC_MAGIC 0x8086900D
57+ /**
58+ * @version: The version of the this structure.
59+ * Major and minor version number are represented as bit fields.
60+ */
61+ u32 version;
62+#define GUC_LIC_VERSION_MASK_MAJOR GENMASK(31, 16)
63+#define GUC_LIC_VERSION_MASK_MINOR GENMASK(15, 0)
64+
65+#define GUC_LIC_VERSION_MAJOR 1u
66+#define GUC_LIC_VERSION_MINOR 0u
67+
68+ /** @data_count: Number of dwords the `data` array contains. */
69+ u32 data_count;
70+ /**
71+ * @data: Array of dwords representing a list of LIC KLVs of
72+ * type guc_klv_generic with keys represented by guc_lic_type
73+ */
74+ u32 data[] __counted_by(data_count);
75+} __packed;
76+
77+#endif
drivers/gpu/drm/xe/abi/guc_log_abi.h+38−4
@@ -8,11 +8,45 @@ · 7 unmodified lines
88
99 #include <linux/types.h>
1010
11+/**
12+ * DOC: GuC Log buffer Layout
13+ *
14+ * The in-memory log buffer layout is as follows::
15+ *
16+ * +===============================+ 0000h
17+ * | Crash dump state header | ^
18+ * +-------------------------------+ 32B |
19+ * | Debug state header | |
20+ * +-------------------------------+ 64B 4KB
21+ * | Capture state header | |
22+ * +-------------------------------+ 96B |
23+ * | | v
24+ * +===============================+ <--- EVENT_DATA_OFFSET
25+ * | Event logs(raw data) | ^
26+ * | | |
27+ * | | EVENT_DATA_BUFFER_SIZE
28+ * | | |
29+ * | | v
30+ * +===============================+ <--- CRASH_DUMP_OFFSET
31+ * | Crash Dump(raw data) | ^
32+ * | | |
33+ * | | CRASH_DUMP_BUFFER_SIZE
34+ * | | |
35+ * | | v
36+ * +===============================+ <--- STATE_CAPTURE_OFFSET
37+ * | Error state capture(raw data) | ^
38+ * | | |
39+ * | | STATE_CAPTURE_BUFFER_SIZE
40+ * | | |
41+ * | | v
42+ * +===============================+ Total: GUC_LOG_SIZE
43+ */
44+
1145 /* GuC logging buffer types */
12−enum guc_log_buffer_type {
13− GUC_LOG_BUFFER_CRASH_DUMP,
14− GUC_LOG_BUFFER_DEBUG,
15− GUC_LOG_BUFFER_CAPTURE,
46+enum guc_log_type {
47+ GUC_LOG_TYPE_EVENT_DATA,
48+ GUC_LOG_TYPE_CRASH_DUMP,
49+ GUC_LOG_TYPE_STATE_CAPTURE,
1650 };
1751
1852 #define GUC_LOG_BUFFER_TYPE_MAX 3
drivers/gpu/drm/xe/display/xe_fb_pin.c+9−14
@@ -210,10 +210,11 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, · 209 unmodified lines
210210 /* TODO: Consider sharing framebuffer mapping?
211211 * embed i915_vma inside intel_framebuffer
212212 */
213− xe_pm_runtime_get_noresume(xe);
214− ret = mutex_lock_interruptible(&ggtt->lock);
213+ guard(xe_pm_runtime_noresume)(xe);
214+ ACQUIRE(mutex_intr, lock)(&ggtt->lock);
215+ ret = ACQUIRE_ERR(mutex_intr, &lock);
215216 if (ret)
216− goto out;
217+ return ret;
217218
218219 align = XE_PAGE_SIZE;
219220 if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K)
@@ -223,15 +224,13 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, · 3 unmodified lines
223224 vma->node = bo->ggtt_node[tile0->id];
224225 } else if (view->type == I915_GTT_VIEW_NORMAL) {
225226 vma->node = xe_ggtt_node_init(ggtt);
226− if (IS_ERR(vma->node)) {
227− ret = PTR_ERR(vma->node);
228− goto out_unlock;
229− }
227+ if (IS_ERR(vma->node))
228+ return PTR_ERR(vma->node);
230229
231230 ret = xe_ggtt_node_insert_locked(vma->node, xe_bo_size(bo), align, 0);
232231 if (ret) {
233232 xe_ggtt_node_fini(vma->node);
234− goto out_unlock;
233+ return ret;
235234 }
236235
237236 xe_ggtt_map_bo(ggtt, vma->node, bo, xe->pat.idx[XE_CACHE_NONE]);
@@ -245,13 +244,13 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, · 7 unmodified lines
245244 vma->node = xe_ggtt_node_init(ggtt);
246245 if (IS_ERR(vma->node)) {
247246 ret = PTR_ERR(vma->node);
248− goto out_unlock;
247+ return ret;
249248 }
250249
251250 ret = xe_ggtt_node_insert_locked(vma->node, size, align, 0);
252251 if (ret) {
253252 xe_ggtt_node_fini(vma->node);
254− goto out_unlock;
253+ return ret;
255254 }
256255
257256 ggtt_ofs = vma->node->base.start;
@@ -265,10 +264,6 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, · 7 unmodified lines
265264 rot_info->plane[i].dst_stride);
266265 }
267266
268−out_unlock:
269− mutex_unlock(&ggtt->lock);
270−out:
271− xe_pm_runtime_put(xe);
272267 return ret;
273268 }
274269
drivers/gpu/drm/xe/display/xe_hdcp_gsc.c+9−22
@@ -38,8 +38,6 @@ static bool intel_hdcp_gsc_check_status(struct drm_device *drm) · 37 unmodified lines
3838 struct xe_tile *tile = xe_device_get_root_tile(xe);
3939 struct xe_gt *gt = tile->media_gt;
4040 struct xe_gsc *gsc = &gt->uc.gsc;
41− bool ret = true;
42− unsigned int fw_ref;
4341
4442 if (!gsc || !xe_uc_fw_is_enabled(&gsc->fw)) {
4543 drm_dbg_kms(&xe->drm,
@@ -47,22 +45,15 @@ static bool intel_hdcp_gsc_check_status(struct drm_device *drm) · 1 unmodified line
4745 return false;
4846 }
4947
50− xe_pm_runtime_get(xe);
51− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
52− if (!fw_ref) {
48+ guard(xe_pm_runtime)(xe);
49+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC);
50+ if (!fw_ref.domains) {
5351 drm_dbg_kms(&xe->drm,
5452 "failed to get forcewake to check proxy status\n");
55− ret = false;
56− goto out;
53+ return false;
5754 }
5855
59− if (!xe_gsc_proxy_init_done(gsc))
60− ret = false;
61−
62− xe_force_wake_put(gt_to_fw(gt), fw_ref);
63−out:
64− xe_pm_runtime_put(xe);
65− return ret;
56+ return xe_gsc_proxy_init_done(gsc);
6657 }
6758
6859 /*This function helps allocate memory for the command that we will send to gsc cs */
@@ -168,17 +159,15 @@ static ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_contex · 99 unmodified lines
168159 u32 addr_out_off, addr_in_wr_off = 0;
169160 int ret, tries = 0;
170161
171− if (msg_in_len > max_msg_size || msg_out_len > max_msg_size) {
172− ret = -ENOSPC;
173− goto out;
174− }
162+ if (msg_in_len > max_msg_size || msg_out_len > max_msg_size)
163+ return -ENOSPC;
175164
176165 msg_size_in = msg_in_len + HDCP_GSC_HEADER_SIZE;
177166 msg_size_out = msg_out_len + HDCP_GSC_HEADER_SIZE;
178167 addr_out_off = PAGE_SIZE;
179168
180169 host_session_id = xe_gsc_create_host_session_id();
181− xe_pm_runtime_get_noresume(xe);
170+ guard(xe_pm_runtime_noresume)(xe);
182171 addr_in_wr_off = xe_gsc_emit_header(xe, &gsc_context->hdcp_bo->vmap,
183172 addr_in_wr_off, HECI_MEADDRESS_HDCP,
184173 host_session_id, msg_in_len);
@@ -203,14 +192,12 @@ static ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_contex · 18 unmodified lines
203192 } while (++tries < 20);
204193
205194 if (ret)
206− goto out;
195+ return ret;
207196
208197 xe_map_memcpy_from(xe, msg_out, &gsc_context->hdcp_bo->vmap,
209198 addr_out_off + HDCP_GSC_HEADER_SIZE,
210199 msg_out_len);
211200
212−out:
213− xe_pm_runtime_put(xe);
214201 return ret;
215202 }
216203
drivers/gpu/drm/xe/instructions/xe_gpu_commands.h+1−0
@@ -47,6 +47,7 @@ · 46 unmodified lines
4747
4848 #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2))
4949
50+#define PIPE_CONTROL0_QUEUE_DRAIN_MODE BIT(12)
5051 #define PIPE_CONTROL0_L3_READ_ONLY_CACHE_INVALIDATE BIT(10) /* gen12 */
5152 #define PIPE_CONTROL0_HDC_PIPELINE_FLUSH BIT(9) /* gen12 */
5253
drivers/gpu/drm/xe/regs/xe_gt_regs.h+3−0
@@ -227,6 +227,9 @@ · 226 unmodified lines
227227
228228 #define MIRROR_FUSE1 XE_REG(0x911c)
229229
230+#define FUSE2 XE_REG(0x9120)
231+#define PRODUCTION_HW REG_BIT(2)
232+
230233 #define MIRROR_L3BANK_ENABLE XE_REG(0x9130)
231234 #define XE3_L3BANK_ENABLE REG_GENMASK(31, 0)
232235
drivers/gpu/drm/xe/regs/xe_gtt_defs.h+1−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #define XELPG_GGTT_PTE_PAT0 BIT_ULL(52)
1010 #define XELPG_GGTT_PTE_PAT1 BIT_ULL(53)
1111
12+#define XE_PTE_ADDR_MASK GENMASK_ULL(51, 12)
1213 #define GGTT_PTE_VFID GENMASK_ULL(11, 2)
1314
1415 #define GUC_GGTT_TOP 0xFEE00000
drivers/gpu/drm/xe/regs/xe_guc_regs.h+3−0
@@ -90,6 +90,9 @@ · 89 unmodified lines
9090 #define GUC_SEND_INTERRUPT XE_REG(0xc4c8)
9191 #define GUC_SEND_TRIGGER REG_BIT(0)
9292
93+#define GUC_INTR_CHICKEN XE_REG(0xc50c)
94+#define DISABLE_SIGNALING_ENGINES REG_BIT(1)
95+
9396 #define GUC_BCS_RCS_IER XE_REG(0xc550)
9497 #define GUC_VCS2_VCS1_IER XE_REG(0xc554)
9598 #define GUC_WD_VECS_IER XE_REG(0xc558)
drivers/gpu/drm/xe/regs/xe_irq_regs.h+1−0
@@ -20,6 +20,7 @@ · 19 unmodified lines
2020 #define GU_MISC_IRQ REG_BIT(29)
2121 #define ERROR_IRQ(x) REG_BIT(26 + (x))
2222 #define DISPLAY_IRQ REG_BIT(16)
23+#define SOC_H2DMEMINT_IRQ REG_BIT(13)
2324 #define I2C_IRQ REG_BIT(12)
2425 #define GT_DW_IRQ(x) REG_BIT(x)
2526
drivers/gpu/drm/xe/regs/xe_mert_regs.h+21−0
@@ -0,0 +1,21 @@
1+/* SPDX-License-Identifier: MIT */
2+/*
3+ * Copyright © 2025 Intel Corporation
4+ */
5+
6+#ifndef _XE_MERT_REGS_H_
7+#define _XE_MERT_REGS_H_
8+
9+#include "regs/xe_reg_defs.h"
10+
11+#define MERT_LMEM_CFG XE_REG(0x1448b0)
12+
13+#define MERT_TLB_CT_INTR_ERR_ID_PORT XE_REG(0x145190)
14+#define MERT_TLB_CT_VFID_MASK REG_GENMASK(16, 9)
15+#define MERT_TLB_CT_ERROR_MASK REG_GENMASK(5, 0)
16+#define MERT_TLB_CT_LMTT_FAULT 0x05
17+
18+#define MERT_TLB_INV_DESC_A XE_REG(0x14cf7c)
19+#define MERT_TLB_INV_DESC_A_VALID REG_BIT(0)
20+
21+#endif /* _XE_MERT_REGS_H_ */
drivers/gpu/drm/xe/regs/xe_oa_regs.h+17−0
@@ -100,4 +100,21 @@ · 99 unmodified lines
100100 #define OAM_COMPRESSION_T3_CONTROL XE_REG(0x1c2e00)
101101 #define OAM_LAT_MEASURE_ENABLE REG_BIT(4)
102102
103+/* Actual address is MEDIA_GT_GSI_OFFSET + the base addr below */
104+#define XE_OAM_SAG_BASE 0x13000
105+#define XE_OAM_SCMI_0_BASE 0x14000
106+#define XE_OAM_SCMI_1_BASE 0x14800
107+#define XE_OAM_SAG_BASE_ADJ (MEDIA_GT_GSI_OFFSET + XE_OAM_SAG_BASE)
108+#define XE_OAM_SCMI_0_BASE_ADJ (MEDIA_GT_GSI_OFFSET + XE_OAM_SCMI_0_BASE)
109+#define XE_OAM_SCMI_1_BASE_ADJ (MEDIA_GT_GSI_OFFSET + XE_OAM_SCMI_1_BASE)
110+
111+#define OAMERT_CONTROL XE_REG(0x1453a0)
112+#define OAMERT_DEBUG XE_REG(0x1453a4)
113+#define OAMERT_STATUS XE_REG(0x1453a8)
114+#define OAMERT_HEAD_POINTER XE_REG(0x1453ac)
115+#define OAMERT_TAIL_POINTER XE_REG(0x1453b0)
116+#define OAMERT_BUFFER XE_REG(0x1453b4)
117+#define OAMERT_CONTEXT_CONTROL XE_REG(0x1453c8)
118+#define OAMERT_MMIO_TRG XE_REG(0x1453cc)
119+
103120 #endif
drivers/gpu/drm/xe/tests/xe_args_test.c+54−0
@@ -78,6 +78,24 @@ static void pick_arg_example(struct kunit *test) · 77 unmodified lines
7878 #undef buz
7979 }
8080
81+static void if_args_example(struct kunit *test)
82+{
83+ enum { Z = 1, Q };
84+
85+#define foo X, Y
86+#define bar IF_ARGS(Z, Q, foo)
87+#define buz IF_ARGS(Z, Q, DROP_FIRST_ARG(FIRST_ARG(foo)))
88+
89+ KUNIT_EXPECT_EQ(test, bar, Z);
90+ KUNIT_EXPECT_EQ(test, buz, Q);
91+ KUNIT_EXPECT_STREQ(test, __stringify(bar), "Z");
92+ KUNIT_EXPECT_STREQ(test, __stringify(buz), "Q");
93+
94+#undef foo
95+#undef bar
96+#undef buz
97+}
98+
8199 static void sep_comma_example(struct kunit *test)
82100 {
83101 #define foo(f) f(X) f(Y) f(Z) f(Q)
@@ -198,6 +216,40 @@ static void last_arg_test(struct kunit *test) · 114 unmodified lines
198216 KUNIT_EXPECT_STREQ(test, __stringify(LAST_ARG(MAX_ARGS)), "-12");
199217 }
200218
219+static void if_args_test(struct kunit *test)
220+{
221+ bool with_args = true;
222+ bool no_args = false;
223+ enum { X = 100 };
224+
225+ KUNIT_EXPECT_TRUE(test, IF_ARGS(true, false, FOO_ARGS));
226+ KUNIT_EXPECT_FALSE(test, IF_ARGS(true, false, NO_ARGS));
227+
228+ KUNIT_EXPECT_TRUE(test, CONCATENATE(IF_ARGS(with, no, FOO_ARGS), _args));
229+ KUNIT_EXPECT_FALSE(test, CONCATENATE(IF_ARGS(with, no, NO_ARGS), _args));
230+
231+ KUNIT_EXPECT_STREQ(test, __stringify(IF_ARGS(yes, no, FOO_ARGS)), "yes");
232+ KUNIT_EXPECT_STREQ(test, __stringify(IF_ARGS(yes, no, NO_ARGS)), "no");
233+
234+ KUNIT_EXPECT_EQ(test, IF_ARGS(CALL_ARGS(COUNT_ARGS, FOO_ARGS), -1, FOO_ARGS), 4);
235+ KUNIT_EXPECT_EQ(test, IF_ARGS(CALL_ARGS(COUNT_ARGS, FOO_ARGS), -1, NO_ARGS), -1);
236+ KUNIT_EXPECT_EQ(test, IF_ARGS(CALL_ARGS(COUNT_ARGS, NO_ARGS), -1, FOO_ARGS), 0);
237+ KUNIT_EXPECT_EQ(test, IF_ARGS(CALL_ARGS(COUNT_ARGS, NO_ARGS), -1, NO_ARGS), -1);
238+
239+ KUNIT_EXPECT_EQ(test,
240+ CALL_ARGS(FIRST_ARG,
241+ CALL_ARGS(CONCATENATE, IF_ARGS(FOO, MAX, FOO_ARGS), _ARGS)), X);
242+ KUNIT_EXPECT_EQ(test,
243+ CALL_ARGS(FIRST_ARG,
244+ CALL_ARGS(CONCATENATE, IF_ARGS(FOO, MAX, NO_ARGS), _ARGS)), -1);
245+ KUNIT_EXPECT_EQ(test,
246+ CALL_ARGS(COUNT_ARGS,
247+ CALL_ARGS(CONCATENATE, IF_ARGS(FOO, MAX, FOO_ARGS), _ARGS)), 4);
248+ KUNIT_EXPECT_EQ(test,
249+ CALL_ARGS(COUNT_ARGS,
250+ CALL_ARGS(CONCATENATE, IF_ARGS(FOO, MAX, NO_ARGS), _ARGS)), 12);
251+}
252+
201253 static struct kunit_case args_tests[] = {
202254 KUNIT_CASE(count_args_test),
203255 KUNIT_CASE(call_args_example),
@@ -209,6 +261,8 @@ static struct kunit_case args_tests[] = { · 5 unmodified lines
209261 KUNIT_CASE(last_arg_example),
210262 KUNIT_CASE(last_arg_test),
211263 KUNIT_CASE(pick_arg_example),
264+ KUNIT_CASE(if_args_example),
265+ KUNIT_CASE(if_args_test),
212266 KUNIT_CASE(sep_comma_example),
213267 {}
214268 };
drivers/gpu/drm/xe/tests/xe_bo.c+2−8
@@ -185,8 +185,7 @@ static int ccs_test_run_device(struct xe_device *xe) · 184 unmodified lines
185185 return 0;
186186 }
187187
188− xe_pm_runtime_get(xe);
189−
188+ guard(xe_pm_runtime)(xe);
190189 for_each_tile(tile, xe, id) {
191190 /* For igfx run only for primary tile */
192191 if (!IS_DGFX(xe) && id > 0)
@@ -194,8 +193,6 @@ static int ccs_test_run_device(struct xe_device *xe) · 1 unmodified line
194193 ccs_test_run_tile(xe, tile, test);
195194 }
196195
197− xe_pm_runtime_put(xe);
198−
199196 return 0;
200197 }
201198
@@ -356,13 +353,10 @@ static int evict_test_run_device(struct xe_device *xe) · 154 unmodified lines
356353 return 0;
357354 }
358355
359− xe_pm_runtime_get(xe);
360−
356+ guard(xe_pm_runtime)(xe);
361357 for_each_tile(tile, xe, id)
362358 evict_test_run_tile(xe, tile, test);
363359
364− xe_pm_runtime_put(xe);
365−
366360 return 0;
367361 }
368362
drivers/gpu/drm/xe/tests/xe_dma_buf.c+1−2
@@ -266,7 +266,7 @@ static int dma_buf_run_device(struct xe_device *xe) · 265 unmodified lines
266266 const struct dma_buf_test_params *params;
267267 struct kunit *test = kunit_get_current_test();
268268
269− xe_pm_runtime_get(xe);
269+ guard(xe_pm_runtime)(xe);
270270 for (params = test_params; params->mem_mask; ++params) {
271271 struct dma_buf_test_params p = *params;
272272
@@ -274,7 +274,6 @@ static int dma_buf_run_device(struct xe_device *xe) · 1 unmodified line
274274 test->priv = &p;
275275 xe_test_dmabuf_import_same_driver(xe);
276276 }
277− xe_pm_runtime_put(xe);
278277
279278 /* A non-zero return would halt iteration over driver devices */
280279 return 0;
drivers/gpu/drm/xe/tests/xe_migrate.c+2−8
@@ -344,8 +344,7 @@ static int migrate_test_run_device(struct xe_device *xe) · 343 unmodified lines
344344 struct xe_tile *tile;
345345 int id;
346346
347− xe_pm_runtime_get(xe);
348−
347+ guard(xe_pm_runtime)(xe);
349348 for_each_tile(tile, xe, id) {
350349 struct xe_migrate *m = tile->migrate;
351350 struct drm_exec *exec = XE_VALIDATION_OPT_OUT;
@@ -356,8 +355,6 @@ static int migrate_test_run_device(struct xe_device *xe) · 4 unmodified lines
356355 xe_vm_unlock(m->q->vm);
357356 }
358357
359− xe_pm_runtime_put(xe);
360−
361358 return 0;
362359 }
363360
@@ -759,13 +756,10 @@ static int validate_ccs_test_run_device(struct xe_device *xe) · 395 unmodified lines
759756 return 0;
760757 }
761758
762− xe_pm_runtime_get(xe);
763−
759+ guard(xe_pm_runtime)(xe);
764760 for_each_tile(tile, xe, id)
765761 validate_ccs_test_run_tile(xe, tile, test);
766762
767− xe_pm_runtime_put(xe);
768−
769763 return 0;
770764 }
771765
drivers/gpu/drm/xe/tests/xe_mocs.c+8−19
@@ -43,14 +43,12 @@ static void read_l3cc_table(struct xe_gt *gt, · 42 unmodified lines
4343 {
4444 struct kunit *test = kunit_get_current_test();
4545 u32 l3cc, l3cc_expected;
46− unsigned int fw_ref, i;
46+ unsigned int i;
4747 u32 reg_val;
4848
49− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
50− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) {
51− xe_force_wake_put(gt_to_fw(gt), fw_ref);
49+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
50+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL))
5251 KUNIT_FAIL_AND_ABORT(test, "Forcewake Failed.\n");
53− }
5452
5553 for (i = 0; i < info->num_mocs_regs; i++) {
5654 if (!(i & 1)) {
@@ -74,7 +72,6 @@ static void read_l3cc_table(struct xe_gt *gt, · 17 unmodified lines
7472 KUNIT_EXPECT_EQ_MSG(test, l3cc_expected, l3cc,
7573 "l3cc idx=%u has incorrect val.\n", i);
7674 }
77− xe_force_wake_put(gt_to_fw(gt), fw_ref);
7875 }
7976
8077 static void read_mocs_table(struct xe_gt *gt,
@@ -82,14 +79,14 @@ static void read_mocs_table(struct xe_gt *gt, · 1 unmodified line
8279 {
8380 struct kunit *test = kunit_get_current_test();
8481 u32 mocs, mocs_expected;
85− unsigned int fw_ref, i;
82+ unsigned int i;
8683 u32 reg_val;
8784
8885 KUNIT_EXPECT_TRUE_MSG(test, info->unused_entries_index,
8986 "Unused entries index should have been defined\n");
9087
91− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
92− KUNIT_ASSERT_NE_MSG(test, fw_ref, 0, "Forcewake Failed.\n");
88+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
89+ KUNIT_ASSERT_NE_MSG(test, fw_ref.domains, 0, "Forcewake Failed.\n");
9390
9491 for (i = 0; i < info->num_mocs_regs; i++) {
9592 if (regs_are_mcr(gt))
@@ -106,8 +103,6 @@ static void read_mocs_table(struct xe_gt *gt, · 10 unmodified lines
106103 KUNIT_EXPECT_EQ_MSG(test, mocs_expected, mocs,
107104 "mocs reg 0x%x has incorrect val.\n", i);
108105 }
109−
110− xe_force_wake_put(gt_to_fw(gt), fw_ref);
111106 }
112107
113108 static int mocs_kernel_test_run_device(struct xe_device *xe)
@@ -120,8 +115,7 @@ static int mocs_kernel_test_run_device(struct xe_device *xe) · 6 unmodified lines
120115 unsigned int flags;
121116 int id;
122117
123− xe_pm_runtime_get(xe);
124−
118+ guard(xe_pm_runtime)(xe);
125119 for_each_gt(gt, xe, id) {
126120 flags = live_mocs_init(&mocs, gt);
127121 if (flags & HAS_GLOBAL_MOCS)
@@ -130,8 +124,6 @@ static int mocs_kernel_test_run_device(struct xe_device *xe) · 2 unmodified lines
130124 read_l3cc_table(gt, &mocs.table);
131125 }
132126
133− xe_pm_runtime_put(xe);
134−
135127 return 0;
136128 }
137129
@@ -155,8 +147,7 @@ static int mocs_reset_test_run_device(struct xe_device *xe) · 17 unmodified lines
155147 int id;
156148 struct kunit *test = kunit_get_current_test();
157149
158− xe_pm_runtime_get(xe);
159−
150+ guard(xe_pm_runtime)(xe);
160151 for_each_gt(gt, xe, id) {
161152 flags = live_mocs_init(&mocs, gt);
162153 kunit_info(test, "mocs_reset_test before reset\n");
@@ -174,8 +165,6 @@ static int mocs_reset_test_run_device(struct xe_device *xe) · 11 unmodified lines
174165 read_l3cc_table(gt, &mocs.table);
175166 }
176167
177− xe_pm_runtime_put(xe);
178−
179168 return 0;
180169 }
181170
drivers/gpu/drm/xe/xe_args.h+27−0
@@ -121,6 +121,33 @@ · 120 unmodified lines
121121 #define PICK_ARG11(args...) PICK_ARG10(DROP_FIRST_ARG(args))
122122 #define PICK_ARG12(args...) PICK_ARG11(DROP_FIRST_ARG(args))
123123
124+/**
125+ * IF_ARGS() - Make selection based on optional argument list.
126+ * @then: token to return if arguments are present
127+ * @else: token to return if arguments are empty
128+ * @...: arguments to check (optional)
129+ *
130+ * This macro allows to select a token based on the presence of the argument list.
131+ *
132+ * Example:
133+ *
134+ * #define foo X, Y
135+ * #define bar IF_ARGS(Z, Q, foo)
136+ * #define buz IF_ARGS(Z, Q, DROP_FIRST_ARG(FIRST_ARG(foo)))
137+ *
138+ * With above definitions bar expands to Z while buz expands to Q.
139+ */
140+#if defined(CONFIG_CC_IS_CLANG) || GCC_VERSION >= 100100
141+#define IF_ARGS(then, else, ...) FIRST_ARG(__VA_OPT__(then,) else)
142+#else
143+#define IF_ARGS(then, else, ...) _IF_ARGS(then, else, CALL_ARGS(FIRST_ARG, __VA_ARGS__))
144+#define _IF_ARGS(then, else, ...) __IF_ARGS(then, else, CALL_ARGS(COUNT_ARGS, __VA_ARGS__))
145+#define __IF_ARGS(then, else, n) ___IF_ARGS(then, else, CALL_ARGS(CONCATENATE, ___IF_ARG, n))
146+#define ___IF_ARGS(then, else, if) CALL_ARGS(if, then, else)
147+#define ___IF_ARG1(then, else) then
148+#define ___IF_ARG0(then, else) else
149+#endif
150+
124151 /**
125152 * ARGS_SEP_COMMA - Definition of a comma character.
126153 *
drivers/gpu/drm/xe/xe_bo.c+16−10
@@ -516,8 +516,7 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo, · 515 unmodified lines
516516 * non-coherent and require a CPU:WC mapping.
517517 */
518518 if ((!bo->cpu_caching && bo->flags & XE_BO_FLAG_SCANOUT) ||
519− (xe->info.graphics_verx100 >= 1270 &&
520− bo->flags & XE_BO_FLAG_PAGETABLE))
519+ (!xe->info.has_cached_pt && bo->flags & XE_BO_FLAG_PAGETABLE))
521520 caching = ttm_write_combined;
522521 }
523522
@@ -2026,13 +2025,9 @@ static int xe_bo_vm_access(struct vm_area_struct *vma, unsigned long addr, · 1502 unmodified lines
20262025 struct ttm_buffer_object *ttm_bo = vma->vm_private_data;
20272026 struct xe_bo *bo = ttm_to_xe_bo(ttm_bo);
20282027 struct xe_device *xe = xe_bo_device(bo);
2029− int ret;
2030−
2031− xe_pm_runtime_get(xe);
2032− ret = ttm_bo_vm_access(vma, addr, buf, len, write);
2033− xe_pm_runtime_put(xe);
20342028
2035− return ret;
2029+ guard(xe_pm_runtime)(xe);
2030+ return ttm_bo_vm_access(vma, addr, buf, len, write);
20362031 }
20372032
20382033 /**
@@ -3176,7 +3171,8 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, · 1137 unmodified lines
31763171 if (XE_IOCTL_DBG(xe, args->flags &
31773172 ~(DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING |
31783173 DRM_XE_GEM_CREATE_FLAG_SCANOUT |
3179− DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM)))
3174+ DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM |
3175+ DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION)))
31803176 return -EINVAL;
31813177
31823178 if (XE_IOCTL_DBG(xe, args->handle))
@@ -3198,6 +3194,12 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, · 15 unmodified lines
31983194 if (args->flags & DRM_XE_GEM_CREATE_FLAG_SCANOUT)
31993195 bo_flags |= XE_BO_FLAG_SCANOUT;
32003196
3197+ if (args->flags & DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION) {
3198+ if (XE_IOCTL_DBG(xe, GRAPHICS_VER(xe) < 20))
3199+ return -EOPNOTSUPP;
3200+ bo_flags |= XE_BO_FLAG_NO_COMPRESSION;
3201+ }
3202+
32013203 bo_flags |= args->placement << (ffs(XE_BO_FLAG_SYSTEM) - 1);
32023204
32033205 /* CCS formats need physical placement at a 64K alignment in VRAM. */
@@ -3519,8 +3521,12 @@ bool xe_bo_needs_ccs_pages(struct xe_bo *bo) · 315 unmodified lines
35193521 * Compression implies coh_none, therefore we know for sure that WB
35203522 * memory can't currently use compression, which is likely one of the
35213523 * common cases.
3524+ * Additionally, userspace may explicitly request no compression via the
3525+ * DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION flag, which should also disable
3526+ * CCS usage.
35223527 */
3523− if (bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB)
3528+ if (bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB ||
3529+ bo->flags & XE_BO_FLAG_NO_COMPRESSION)
35243530 return false;
35253531
35263532 return true;
drivers/gpu/drm/xe/xe_bo.h+1−0
@@ -50,6 +50,7 @@ · 49 unmodified lines
5050 #define XE_BO_FLAG_GGTT3 BIT(23)
5151 #define XE_BO_FLAG_CPU_ADDR_MIRROR BIT(24)
5252 #define XE_BO_FLAG_FORCE_USER_VRAM BIT(25)
53+#define XE_BO_FLAG_NO_COMPRESSION BIT(26)
5354
5455 /* this one is trigger internally only */
5556 #define XE_BO_FLAG_INTERNAL_TEST BIT(30)
drivers/gpu/drm/xe/xe_debugfs.c+121−22
@@ -68,7 +68,7 @@ static int info(struct seq_file *m, void *data) · 67 unmodified lines
6868 struct xe_gt *gt;
6969 u8 id;
7070
71− xe_pm_runtime_get(xe);
71+ guard(xe_pm_runtime)(xe);
7272
7373 drm_printf(&p, "graphics_verx100 %d\n", xe->info.graphics_verx100);
7474 drm_printf(&p, "media_verx100 %d\n", xe->info.media_verx100);
@@ -93,9 +93,10 @@ static int info(struct seq_file *m, void *data) · 18 unmodified lines
9393 xe_force_wake_ref(gt_to_fw(gt), XE_FW_GT));
9494 drm_printf(&p, "gt%d engine_mask 0x%llx\n", id,
9595 gt->info.engine_mask);
96+ drm_printf(&p, "gt%d multi_queue_engine_class_mask 0x%x\n", id,
97+ gt->info.multi_queue_engine_class_mask);
9698 }
9799
98− xe_pm_runtime_put(xe);
99100 return 0;
100101 }
101102
@@ -110,9 +111,8 @@ static int sriov_info(struct seq_file *m, void *data) · 8 unmodified lines
110111
111112 static int workarounds(struct xe_device *xe, struct drm_printer *p)
112113 {
113− xe_pm_runtime_get(xe);
114+ guard(xe_pm_runtime)(xe);
114115 xe_wa_device_dump(xe, p);
115− xe_pm_runtime_put(xe);
116116
117117 return 0;
118118 }
@@ -134,7 +134,7 @@ static int dgfx_pkg_residencies_show(struct seq_file *m, void *data) · 15 unmodified lines
134134
135135 xe = node_to_xe(m->private);
136136 p = drm_seq_file_printer(m);
137− xe_pm_runtime_get(xe);
137+ guard(xe_pm_runtime)(xe);
138138 mmio = xe_root_tile_mmio(xe);
139139 static const struct {
140140 u32 offset;
@@ -151,7 +151,6 @@ static int dgfx_pkg_residencies_show(struct seq_file *m, void *data) · 10 unmodified lines
151151 for (int i = 0; i < ARRAY_SIZE(residencies); i++)
152152 read_residency_counter(xe, mmio, residencies[i].offset, residencies[i].name, &p);
153153
154− xe_pm_runtime_put(xe);
155154 return 0;
156155 }
157156
@@ -163,7 +162,7 @@ static int dgfx_pcie_link_residencies_show(struct seq_file *m, void *data) · 5 unmodified lines
163162
164163 xe = node_to_xe(m->private);
165164 p = drm_seq_file_printer(m);
166− xe_pm_runtime_get(xe);
165+ guard(xe_pm_runtime)(xe);
167166 mmio = xe_root_tile_mmio(xe);
168167
169168 static const struct {
@@ -178,7 +177,6 @@ static int dgfx_pcie_link_residencies_show(struct seq_file *m, void *data) · 8 unmodified lines
178177 for (int i = 0; i < ARRAY_SIZE(residencies); i++)
179178 read_residency_counter(xe, mmio, residencies[i].offset, residencies[i].name, &p);
180179
181− xe_pm_runtime_put(xe);
182180 return 0;
183181 }
184182
@@ -277,16 +275,14 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, · 92 unmodified lines
277275
278276 xe->wedged.mode = wedged_mode;
279277
280− xe_pm_runtime_get(xe);
278+ guard(xe_pm_runtime)(xe);
281279 for_each_gt(gt, xe, id) {
282280 ret = xe_guc_ads_scheduler_policy_toggle_reset(&gt->uc.guc.ads);
283281 if (ret) {
284282 xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n");
285− xe_pm_runtime_put(xe);
286283 return -EIO;
287284 }
288285 }
289− xe_pm_runtime_put(xe);
290286
291287 return size;
292288 }
@@ -297,6 +293,39 @@ static const struct file_operations wedged_mode_fops = { · 4 unmodified lines
297293 .write = wedged_mode_set,
298294 };
299295
296+static ssize_t page_reclaim_hw_assist_show(struct file *f, char __user *ubuf,
297+ size_t size, loff_t *pos)
298+{
299+ struct xe_device *xe = file_inode(f)->i_private;
300+ char buf[8];
301+ int len;
302+
303+ len = scnprintf(buf, sizeof(buf), "%d\n", xe->info.has_page_reclaim_hw_assist);
304+ return simple_read_from_buffer(ubuf, size, pos, buf, len);
305+}
306+
307+static ssize_t page_reclaim_hw_assist_set(struct file *f, const char __user *ubuf,
308+ size_t size, loff_t *pos)
309+{
310+ struct xe_device *xe = file_inode(f)->i_private;
311+ bool val;
312+ ssize_t ret;
313+
314+ ret = kstrtobool_from_user(ubuf, size, &val);
315+ if (ret)
316+ return ret;
317+
318+ xe->info.has_page_reclaim_hw_assist = val;
319+
320+ return size;
321+}
322+
323+static const struct file_operations page_reclaim_hw_assist_fops = {
324+ .owner = THIS_MODULE,
325+ .read = page_reclaim_hw_assist_show,
326+ .write = page_reclaim_hw_assist_set,
327+};
328+
300329 static ssize_t atomic_svm_timeslice_ms_show(struct file *f, char __user *ubuf,
301330 size_t size, loff_t *pos)
302331 {
@@ -332,6 +361,74 @@ static const struct file_operations atomic_svm_timeslice_ms_fops = { · 29 unmodified lines
332361 .write = atomic_svm_timeslice_ms_set,
333362 };
334363
364+static ssize_t min_run_period_lr_ms_show(struct file *f, char __user *ubuf,
365+ size_t size, loff_t *pos)
366+{
367+ struct xe_device *xe = file_inode(f)->i_private;
368+ char buf[32];
369+ int len = 0;
370+
371+ len = scnprintf(buf, sizeof(buf), "%d\n", xe->min_run_period_lr_ms);
372+
373+ return simple_read_from_buffer(ubuf, size, pos, buf, len);
374+}
375+
376+static ssize_t min_run_period_lr_ms_set(struct file *f, const char __user *ubuf,
377+ size_t size, loff_t *pos)
378+{
379+ struct xe_device *xe = file_inode(f)->i_private;
380+ u32 min_run_period_lr_ms;
381+ ssize_t ret;
382+
383+ ret = kstrtouint_from_user(ubuf, size, 0, &min_run_period_lr_ms);
384+ if (ret)
385+ return ret;
386+
387+ xe->min_run_period_lr_ms = min_run_period_lr_ms;
388+
389+ return size;
390+}
391+
392+static const struct file_operations min_run_period_lr_ms_fops = {
393+ .owner = THIS_MODULE,
394+ .read = min_run_period_lr_ms_show,
395+ .write = min_run_period_lr_ms_set,
396+};
397+
398+static ssize_t min_run_period_pf_ms_show(struct file *f, char __user *ubuf,
399+ size_t size, loff_t *pos)
400+{
401+ struct xe_device *xe = file_inode(f)->i_private;
402+ char buf[32];
403+ int len = 0;
404+
405+ len = scnprintf(buf, sizeof(buf), "%d\n", xe->min_run_period_pf_ms);
406+
407+ return simple_read_from_buffer(ubuf, size, pos, buf, len);
408+}
409+
410+static ssize_t min_run_period_pf_ms_set(struct file *f, const char __user *ubuf,
411+ size_t size, loff_t *pos)
412+{
413+ struct xe_device *xe = file_inode(f)->i_private;
414+ u32 min_run_period_pf_ms;
415+ ssize_t ret;
416+
417+ ret = kstrtouint_from_user(ubuf, size, 0, &min_run_period_pf_ms);
418+ if (ret)
419+ return ret;
420+
421+ xe->min_run_period_pf_ms = min_run_period_pf_ms;
422+
423+ return size;
424+}
425+
426+static const struct file_operations min_run_period_pf_ms_fops = {
427+ .owner = THIS_MODULE,
428+ .read = min_run_period_pf_ms_show,
429+ .write = min_run_period_pf_ms_set,
430+};
431+
335432 static ssize_t disable_late_binding_show(struct file *f, char __user *ubuf,
336433 size_t size, loff_t *pos)
337434 {
@@ -375,7 +472,6 @@ void xe_debugfs_register(struct xe_device *xe) · 37 unmodified lines
375472 struct ttm_resource_manager *man;
376473 struct xe_tile *tile;
377474 struct xe_gt *gt;
378− u32 mem_type;
379475 u8 tile_id;
380476 u8 id;
381477
@@ -400,19 +496,22 @@ void xe_debugfs_register(struct xe_device *xe) · 18 unmodified lines
400496 debugfs_create_file("atomic_svm_timeslice_ms", 0600, root, xe,
401497 &atomic_svm_timeslice_ms_fops);
402498
403− debugfs_create_file("disable_late_binding", 0600, root, xe,
404− &disable_late_binding_fops);
499+ debugfs_create_file("min_run_period_lr_ms", 0600, root, xe,
500+ &min_run_period_lr_ms_fops);
405501
406− for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) {
407− man = ttm_manager_type(bdev, mem_type);
502+ debugfs_create_file("min_run_period_pf_ms", 0600, root, xe,
503+ &min_run_period_pf_ms_fops);
408504
409− if (man) {
410− char name[16];
505+ debugfs_create_file("disable_late_binding", 0600, root, xe,
506+ &disable_late_binding_fops);
411507
412− snprintf(name, sizeof(name), "vram%d_mm", mem_type - XE_PL_VRAM0);
413− ttm_resource_manager_create_debugfs(man, root, name);
414− }
415− }
508+ /*
509+ * Don't expose page reclaim configuration file if not supported by the
510+ * hardware initially.
511+ */
512+ if (xe->info.has_page_reclaim_hw_assist)
513+ debugfs_create_file("page_reclaim_hw_assist", 0600, root, xe,
514+ &page_reclaim_hw_assist_fops);
416515
417516 man = ttm_manager_type(bdev, XE_PL_TT);
418517 ttm_resource_manager_create_debugfs(man, root, "gtt_mm");
drivers/gpu/drm/xe/xe_devcoredump.c+12−18
@@ -276,7 +276,6 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work) · 275 unmodified lines
276276 struct xe_devcoredump_snapshot *ss = container_of(work, typeof(*ss), work);
277277 struct xe_devcoredump *coredump = container_of(ss, typeof(*coredump), snapshot);
278278 struct xe_device *xe = coredump_to_xe(coredump);
279− unsigned int fw_ref;
280279
281280 /*
282281 * NB: Despite passing a GFP_ flags parameter here, more allocations are done
@@ -287,15 +286,15 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work) · 4 unmodified lines
287286 xe_devcoredump_read, xe_devcoredump_free,
288287 XE_COREDUMP_TIMEOUT_JIFFIES);
289288
290− xe_pm_runtime_get(xe);
289+ guard(xe_pm_runtime)(xe);
291290
292291 /* keep going if fw fails as we still want to save the memory and SW data */
293− fw_ref = xe_force_wake_get(gt_to_fw(ss->gt), XE_FORCEWAKE_ALL);
294− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
295− xe_gt_info(ss->gt, "failed to get forcewake for coredump capture\n");
296− xe_vm_snapshot_capture_delayed(ss->vm);
297− xe_guc_exec_queue_snapshot_capture_delayed(ss->ge);
298− xe_force_wake_put(gt_to_fw(ss->gt), fw_ref);
292+ xe_with_force_wake(fw_ref, gt_to_fw(ss->gt), XE_FORCEWAKE_ALL) {
293+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL))
294+ xe_gt_info(ss->gt, "failed to get forcewake for coredump capture\n");
295+ xe_vm_snapshot_capture_delayed(ss->vm);
296+ xe_guc_exec_queue_snapshot_capture_delayed(ss->ge);
297+ }
299298
300299 ss->read.chunk_position = 0;
301300
@@ -306,7 +305,7 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work) · 4 unmodified lines
306305 ss->read.buffer = kvmalloc(XE_DEVCOREDUMP_CHUNK_MAX,
307306 GFP_USER);
308307 if (!ss->read.buffer)
309− goto put_pm;
308+ return;
310309
311310 __xe_devcoredump_read(ss->read.buffer,
312311 XE_DEVCOREDUMP_CHUNK_MAX,
@@ -314,15 +313,12 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work) · 1 unmodified line
314313 } else {
315314 ss->read.buffer = kvmalloc(ss->read.size, GFP_USER);
316315 if (!ss->read.buffer)
317− goto put_pm;
316+ return;
318317
319318 __xe_devcoredump_read(ss->read.buffer, ss->read.size, 0,
320319 coredump);
321320 xe_devcoredump_snapshot_free(ss);
322321 }
323−
324−put_pm:
325− xe_pm_runtime_put(xe);
326322 }
327323
328324 static void devcoredump_snapshot(struct xe_devcoredump *coredump,
@@ -332,7 +328,6 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump, · 3 unmodified lines
332328 struct xe_devcoredump_snapshot *ss = &coredump->snapshot;
333329 struct xe_guc *guc = exec_queue_to_guc(q);
334330 const char *process_name = "no process";
335− unsigned int fw_ref;
336331 bool cookie;
337332
338333 ss->snapshot_time = ktime_get_real();
@@ -348,10 +343,10 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump, · 9 unmodified lines
348343 ss->gt = q->gt;
349344 INIT_WORK(&ss->work, xe_devcoredump_deferred_snap_work);
350345
351− cookie = dma_fence_begin_signalling();
352−
353346 /* keep going if fw fails as we still want to save the memory and SW data */
354− fw_ref = xe_force_wake_get(gt_to_fw(q->gt), XE_FORCEWAKE_ALL);
347+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(q->gt), XE_FORCEWAKE_ALL);
348+
349+ cookie = dma_fence_begin_signalling();
355350
356351 ss->guc.log = xe_guc_log_snapshot_capture(&guc->log, true);
357352 ss->guc.ct = xe_guc_ct_snapshot_capture(&guc->ct);
@@ -364,7 +359,6 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump, · 6 unmodified lines
364359
365360 queue_work(system_unbound_wq, &ss->work);
366361
367− xe_force_wake_put(gt_to_fw(q->gt), fw_ref);
368362 dma_fence_end_signalling(cookie);
369363 }
370364
drivers/gpu/drm/xe/xe_device.c+77−23
@@ -166,7 +166,7 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file) · 165 unmodified lines
166166 struct xe_exec_queue *q;
167167 unsigned long idx;
168168
169− xe_pm_runtime_get(xe);
169+ guard(xe_pm_runtime)(xe);
170170
171171 /*
172172 * No need for exec_queue.lock here as there is no contention for it
@@ -177,15 +177,18 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file) · 4 unmodified lines
177177 xa_for_each(&xef->exec_queue.xa, idx, q) {
178178 if (q->vm && q->hwe->hw_engine_group)
179179 xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q);
180− xe_exec_queue_kill(q);
180+
181+ if (xe_exec_queue_is_multi_queue_primary(q))
182+ xe_exec_queue_group_kill_put(q->multi_queue.group);
183+ else
184+ xe_exec_queue_kill(q);
185+
181186 xe_exec_queue_put(q);
182187 }
183188 xa_for_each(&xef->vm.xa, idx, vm)
184189 xe_vm_close_and_put(vm);
185190
186191 xe_file_put(xef);
187−
188− xe_pm_runtime_put(xe);
189192 }
190193
191194 static const struct drm_ioctl_desc xe_ioctls[] = {
@@ -209,6 +212,8 @@ static const struct drm_ioctl_desc xe_ioctls[] = { · 17 unmodified lines
209212 DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl, DRM_RENDER_ALLOW),
210213 DRM_IOCTL_DEF_DRV(XE_VM_QUERY_MEM_RANGE_ATTRS, xe_vm_query_vmas_attrs_ioctl,
211214 DRM_RENDER_ALLOW),
215+ DRM_IOCTL_DEF_DRV(XE_EXEC_QUEUE_SET_PROPERTY, xe_exec_queue_set_property_ioctl,
216+ DRM_RENDER_ALLOW),
212217 };
213218
214219 static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -220,10 +225,10 @@ static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 5 unmodified lines
220225 if (xe_device_wedged(xe))
221226 return -ECANCELED;
222227
223− ret = xe_pm_runtime_get_ioctl(xe);
228+ ACQUIRE(xe_pm_runtime_ioctl, pm)(xe);
229+ ret = ACQUIRE_ERR(xe_pm_runtime_ioctl, &pm);
224230 if (ret >= 0)
225231 ret = drm_ioctl(file, cmd, arg);
226− xe_pm_runtime_put(xe);
227232
228233 return ret;
229234 }
@@ -238,10 +243,10 @@ static long xe_drm_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo · 8 unmodified lines
238243 if (xe_device_wedged(xe))
239244 return -ECANCELED;
240245
241− ret = xe_pm_runtime_get_ioctl(xe);
246+ ACQUIRE(xe_pm_runtime_ioctl, pm)(xe);
247+ ret = ACQUIRE_ERR(xe_pm_runtime_ioctl, &pm);
242248 if (ret >= 0)
243249 ret = drm_compat_ioctl(file, cmd, arg);
244− xe_pm_runtime_put(xe);
245250
246251 return ret;
247252 }
@@ -455,6 +460,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, · 207 unmodified lines
455460 xe->info.revid = pdev->revision;
456461 xe->info.force_execlist = xe_modparam.force_execlist;
457462 xe->atomic_svm_timeslice_ms = 5;
463+ xe->min_run_period_lr_ms = 5;
458464
459465 err = xe_irq_init(xe);
460466 if (err)
@@ -775,7 +781,6 @@ ALLOW_ERROR_INJECTION(xe_device_probe_early, ERRNO); /* See xe_pci_probe() */ · 314 unmodified lines
775781 static int probe_has_flat_ccs(struct xe_device *xe)
776782 {
777783 struct xe_gt *gt;
778− unsigned int fw_ref;
779784 u32 reg;
780785
781786 /* Always enabled/disabled, no runtime check to do */
@@ -786,8 +791,8 @@ static int probe_has_flat_ccs(struct xe_device *xe) · 4 unmodified lines
786791 if (!gt)
787792 return 0;
788793
789− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
790− if (!fw_ref)
794+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
795+ if (!fw_ref.domains)
791796 return -ETIMEDOUT;
792797
793798 reg = xe_gt_mcr_unicast_read_any(gt, XE2_FLAT_CCS_BASE_RANGE_LOWER);
@@ -797,11 +802,64 @@ static int probe_has_flat_ccs(struct xe_device *xe) · 3 unmodified lines
797802 drm_dbg(&xe->drm,
798803 "Flat CCS has been disabled in bios, May lead to performance impact");
799804
800− xe_force_wake_put(gt_to_fw(gt), fw_ref);
801−
802805 return 0;
803806 }
804807
808+/*
809+ * Detect if the driver is being run on pre-production hardware. We don't
810+ * keep workarounds for pre-production hardware long term, so print an
811+ * error and add taint if we're being loaded on a pre-production platform
812+ * for which the pre-prod workarounds have already been removed.
813+ *
814+ * The general policy is that we'll remove any workarounds that only apply to
815+ * pre-production hardware around the time force_probe restrictions are lifted
816+ * for a platform of the next major IP generation (for example, Xe2 pre-prod
817+ * workarounds should be removed around the time the first Xe3 platforms have
818+ * force_probe lifted).
819+ */
820+static void detect_preproduction_hw(struct xe_device *xe)
821+{
822+ struct xe_gt *gt;
823+ int id;
824+
825+ /*
826+ * SR-IOV VFs don't have access to the FUSE2 register, so we can't
827+ * check pre-production status there. But the host OS will notice
828+ * and report the pre-production status, which should be enough to
829+ * help us catch mistaken use of pre-production hardware.
830+ */
831+ if (IS_SRIOV_VF(xe))
832+ return;
833+
834+ /*
835+ * The "SW_CAP" fuse contains a bit indicating whether the device is a
836+ * production or pre-production device. This fuse is reflected through
837+ * the GT "FUSE2" register, even though the contents of the fuse are
838+ * not GT-specific. Every GT's reflection of this fuse should show the
839+ * same value, so we'll just use the first available GT for lookup.
840+ */
841+ for_each_gt(gt, xe, id)
842+ break;
843+
844+ if (!gt)
845+ return;
846+
847+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
848+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT)) {
849+ xe_gt_err(gt, "Forcewake failure; cannot determine production/pre-production hw status.\n");
850+ return;
851+ }
852+
853+ if (xe_mmio_read32(&gt->mmio, FUSE2) & PRODUCTION_HW)
854+ return;
855+
856+ xe_info(xe, "Pre-production hardware detected.\n");
857+ if (!xe->info.has_pre_prod_wa) {
858+ xe_err(xe, "Pre-production workarounds for this platform have already been removed.\n");
859+ add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK);
860+ }
861+}
862+
805863 int xe_device_probe(struct xe_device *xe)
806864 {
807865 struct xe_tile *tile;
@@ -972,6 +1030,8 @@ int xe_device_probe(struct xe_device *xe) · 164 unmodified lines
9721030 if (err)
9731031 goto err_unregister_display;
9741032
1033+ detect_preproduction_hw(xe);
1034+
9751035 return devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe);
9761036
9771037 err_unregister_display:
@@ -1034,7 +1094,6 @@ void xe_device_wmb(struct xe_device *xe) · 56 unmodified lines
10341094 */
10351095 static void tdf_request_sync(struct xe_device *xe)
10361096 {
1037− unsigned int fw_ref;
10381097 struct xe_gt *gt;
10391098 u8 id;
10401099
@@ -1042,8 +1101,8 @@ static void tdf_request_sync(struct xe_device *xe) · 1 unmodified line
10421101 if (xe_gt_is_media_type(gt))
10431102 continue;
10441103
1045− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
1046− if (!fw_ref)
1104+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
1105+ if (!fw_ref.domains)
10471106 return;
10481107
10491108 xe_mmio_write32(&gt->mmio, XE2_TDF_CTRL, TRANSIENT_FLUSH_REQUEST);
@@ -1058,15 +1117,12 @@ static void tdf_request_sync(struct xe_device *xe) · 8 unmodified lines
10581117 if (xe_mmio_wait32(&gt->mmio, XE2_TDF_CTRL, TRANSIENT_FLUSH_REQUEST, 0,
10591118 300, NULL, false))
10601119 xe_gt_err_once(gt, "TD flush timeout\n");
1061−
1062− xe_force_wake_put(gt_to_fw(gt), fw_ref);
10631120 }
10641121 }
10651122
10661123 void xe_device_l2_flush(struct xe_device *xe)
10671124 {
10681125 struct xe_gt *gt;
1069− unsigned int fw_ref;
10701126
10711127 gt = xe_root_mmio_gt(xe);
10721128 if (!gt)
@@ -1075,8 +1131,8 @@ void xe_device_l2_flush(struct xe_device *xe) · 2 unmodified lines
10751131 if (!XE_GT_WA(gt, 16023588340))
10761132 return;
10771133
1078− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
1079− if (!fw_ref)
1134+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
1135+ if (!fw_ref.domains)
10801136 return;
10811137
10821138 spin_lock(&gt->global_invl_lock);
@@ -1086,8 +1142,6 @@ void xe_device_l2_flush(struct xe_device *xe) · 3 unmodified lines
10861142 xe_gt_err_once(gt, "Global invalidation timeout\n");
10871143
10881144 spin_unlock(&gt->global_invl_lock);
1089−
1090− xe_force_wake_put(gt_to_fw(gt), fw_ref);
10911145 }
10921146
10931147 /**
drivers/gpu/drm/xe/xe_device.h+5−0
@@ -172,6 +172,11 @@ static inline bool xe_device_has_lmtt(struct xe_device *xe) · 171 unmodified lines
172172 return IS_DGFX(xe);
173173 }
174174
175+static inline bool xe_device_has_mert(struct xe_device *xe)
176+{
177+ return xe->info.has_mert;
178+}
179+
175180 u32 xe_device_ccs_bytes(struct xe_device *xe, u64 size);
176181
177182 void xe_device_snapshot_print(struct xe_device *xe, struct drm_printer *p);
drivers/gpu/drm/xe/xe_device_sysfs.c+13−20
@@ -57,9 +57,8 @@ vram_d3cold_threshold_store(struct device *dev, struct device_attribute *attr, · 56 unmodified lines
5757
5858 drm_dbg(&xe->drm, "vram_d3cold_threshold: %u\n", vram_d3cold_threshold);
5959
60− xe_pm_runtime_get(xe);
60+ guard(xe_pm_runtime)(xe);
6161 ret = xe_pm_set_vram_threshold(xe, vram_d3cold_threshold);
62− xe_pm_runtime_put(xe);
6362
6463 return ret ?: count;
6564 }
@@ -84,33 +83,31 @@ lb_fan_control_version_show(struct device *dev, struct device_attribute *attr, c · 18 unmodified lines
8483 u16 major = 0, minor = 0, hotfix = 0, build = 0;
8584 int ret;
8685
87− xe_pm_runtime_get(xe);
86+ guard(xe_pm_runtime)(xe);
8887
8988 ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_CAPABILITY_STATUS, 0),
9089 &cap, NULL);
9190 if (ret)
92− goto out;
91+ return ret;
9392
9493 if (REG_FIELD_GET(V1_FAN_PROVISIONED, cap)) {
9594 ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_VERSION_LOW, 0),
9695 &ver_low, NULL);
9796 if (ret)
98− goto out;
97+ return ret;
9998
10099 ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_VERSION_HIGH, 0),
101100 &ver_high, NULL);
102101 if (ret)
103− goto out;
102+ return ret;
104103
105104 major = REG_FIELD_GET(MAJOR_VERSION_MASK, ver_low);
106105 minor = REG_FIELD_GET(MINOR_VERSION_MASK, ver_low);
107106 hotfix = REG_FIELD_GET(HOTFIX_VERSION_MASK, ver_high);
108107 build = REG_FIELD_GET(BUILD_VERSION_MASK, ver_high);
109108 }
110−out:
111− xe_pm_runtime_put(xe);
112109
113− return ret ?: sysfs_emit(buf, "%u.%u.%u.%u\n", major, minor, hotfix, build);
110+ return sysfs_emit(buf, "%u.%u.%u.%u\n", major, minor, hotfix, build);
114111 }
115112 static DEVICE_ATTR_ADMIN_RO(lb_fan_control_version);
116113
@@ -123,33 +120,31 @@ lb_voltage_regulator_version_show(struct device *dev, struct device_attribute *a · 6 unmodified lines
123120 u16 major = 0, minor = 0, hotfix = 0, build = 0;
124121 int ret;
125122
126− xe_pm_runtime_get(xe);
123+ guard(xe_pm_runtime)(xe);
127124
128125 ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_CAPABILITY_STATUS, 0),
129126 &cap, NULL);
130127 if (ret)
131− goto out;
128+ return ret;
132129
133130 if (REG_FIELD_GET(VR_PARAMS_PROVISIONED, cap)) {
134131 ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_VERSION_LOW, 0),
135132 &ver_low, NULL);
136133 if (ret)
137− goto out;
134+ return ret;
138135
139136 ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_VERSION_HIGH, 0),
140137 &ver_high, NULL);
141138 if (ret)
142− goto out;
139+ return ret;
143140
144141 major = REG_FIELD_GET(MAJOR_VERSION_MASK, ver_low);
145142 minor = REG_FIELD_GET(MINOR_VERSION_MASK, ver_low);
146143 hotfix = REG_FIELD_GET(HOTFIX_VERSION_MASK, ver_high);
147144 build = REG_FIELD_GET(BUILD_VERSION_MASK, ver_high);
148145 }
149−out:
150− xe_pm_runtime_put(xe);
151146
152− return ret ?: sysfs_emit(buf, "%u.%u.%u.%u\n", major, minor, hotfix, build);
147+ return sysfs_emit(buf, "%u.%u.%u.%u\n", major, minor, hotfix, build);
153148 }
154149 static DEVICE_ATTR_ADMIN_RO(lb_voltage_regulator_version);
155150
@@ -233,9 +228,8 @@ auto_link_downgrade_capable_show(struct device *dev, struct device_attribute *at · 77 unmodified lines
233228 struct xe_device *xe = pdev_to_xe_device(pdev);
234229 u32 cap, val;
235230
236− xe_pm_runtime_get(xe);
231+ guard(xe_pm_runtime)(xe);
237232 val = xe_mmio_read32(xe_root_tile_mmio(xe), BMG_PCIE_CAP);
238− xe_pm_runtime_put(xe);
239233
240234 cap = REG_FIELD_GET(LINK_DOWNGRADE, val);
241235 return sysfs_emit(buf, "%u\n", cap == DOWNGRADE_CAPABLE);
@@ -251,11 +245,10 @@ auto_link_downgrade_status_show(struct device *dev, struct device_attribute *att · 9 unmodified lines
251245 u32 val = 0;
252246 int ret;
253247
254− xe_pm_runtime_get(xe);
248+ guard(xe_pm_runtime)(xe);
255249 ret = xe_pcode_read(xe_device_get_root_tile(xe),
256250 PCODE_MBOX(DGFX_PCODE_STATUS, DGFX_GET_INIT_STATUS, 0),
257251 &val, NULL);
258− xe_pm_runtime_put(xe);
259252
260253 return ret ?: sysfs_emit(buf, "%u\n", REG_FIELD_GET(DGFX_LINK_DOWNGRADE_STATUS, val));
261254 }
drivers/gpu/drm/xe/xe_device_types.h+27−0
@@ -17,6 +17,7 @@ · 16 unmodified lines
1717 #include "xe_late_bind_fw_types.h"
1818 #include "xe_lmtt_types.h"
1919 #include "xe_memirq_types.h"
20+#include "xe_mert.h"
2021 #include "xe_oa_types.h"
2122 #include "xe_pagefault_types.h"
2223 #include "xe_platform_types.h"
@@ -183,6 +184,13 @@ struct xe_tile { · 160 unmodified lines
183184 * Media GT shares a pool with its primary GT.
184185 */
185186 struct xe_sa_manager *kernel_bb_pool;
187+
188+ /**
189+ * @mem.reclaim_pool: Pool for PRLs allocated.
190+ *
191+ * Only main GT has page reclaim list allocations.
192+ */
193+ struct xe_sa_manager *reclaim_pool;
186194 } mem;
187195
188196 /** @sriov: tile level virtualization data */
@@ -219,6 +227,9 @@ struct xe_tile { · 30 unmodified lines
219227
220228 /** @debugfs: debugfs directory associated with this tile */
221229 struct dentry *debugfs;
230+
231+ /** @mert: MERT-related data */
232+ struct xe_mert mert;
222233 };
223234
224235 /**
@@ -285,6 +296,8 @@ struct xe_device { · 60 unmodified lines
285296 u8 has_asid:1;
286297 /** @info.has_atomic_enable_pte_bit: Device has atomic enable PTE bit */
287298 u8 has_atomic_enable_pte_bit:1;
299+ /** @info.has_cached_pt: Supports caching pagetable */
300+ u8 has_cached_pt:1;
288301 /** @info.has_device_atomics_on_smem: Supports device atomics on SMEM */
289302 u8 has_device_atomics_on_smem:1;
290303 /** @info.has_fan_control: Device supports fan control */
@@ -297,6 +310,8 @@ struct xe_device { · 6 unmodified lines
297310 u8 has_heci_cscfi:1;
298311 /** @info.has_heci_gscfi: device has heci gscfi */
299312 u8 has_heci_gscfi:1;
313+ /** @info.has_i2c: Device has I2C controller */
314+ u8 has_i2c:1;
300315 /** @info.has_late_bind: Device has firmware late binding support */
301316 u8 has_late_bind:1;
302317 /** @info.has_llc: Device has a shared CPU+GPU last level cache */
@@ -307,6 +322,12 @@ struct xe_device { · 4 unmodified lines
307322 u8 has_mbx_power_limits:1;
308323 /** @info.has_mem_copy_instr: Device supports MEM_COPY instruction */
309324 u8 has_mem_copy_instr:1;
325+ /** @info.has_mert: Device has standalone MERT */
326+ u8 has_mert:1;
327+ /** @info.has_page_reclaim_hw_assist: Device supports page reclamation feature */
328+ u8 has_page_reclaim_hw_assist:1;
329+ /** @info.has_pre_prod_wa: Pre-production workarounds still present in driver */
330+ u8 has_pre_prod_wa:1;
310331 /** @info.has_pxp: Device has PXP support */
311332 u8 has_pxp:1;
312333 /** @info.has_range_tlb_inval: Has range based TLB invalidations */
@@ -605,6 +626,12 @@ struct xe_device { · 292 unmodified lines
605626 /** @atomic_svm_timeslice_ms: Atomic SVM fault timeslice MS */
606627 u32 atomic_svm_timeslice_ms;
607628
629+ /** @min_run_period_lr_ms: LR VM (preempt fence mode) timeslice */
630+ u32 min_run_period_lr_ms;
631+
632+ /** @min_run_period_pf_ms: LR VM (page fault mode) timeslice */
633+ u32 min_run_period_pf_ms;
634+
608635 #ifdef TEST_VM_OPS_ERROR
609636 /**
610637 * @vm_inject_error_position: inject errors at different places in VM
drivers/gpu/drm/xe/xe_drm_client.c+31−36
@@ -285,32 +285,31 @@ static struct xe_hw_engine *any_engine(struct xe_device *xe) · 284 unmodified lines
285285 return NULL;
286286 }
287287
288−static bool force_wake_get_any_engine(struct xe_device *xe,
289− struct xe_hw_engine **phwe,
290− unsigned int *pfw_ref)
288+/*
289+ * Pick any engine and grab its forcewake. On error phwe will be NULL and
290+ * the returned forcewake reference will be invalid. Callers should check
291+ * phwe against NULL.
292+ */
293+static struct xe_force_wake_ref force_wake_get_any_engine(struct xe_device *xe,
294+ struct xe_hw_engine **phwe)
291295 {
292296 enum xe_force_wake_domains domain;
293− unsigned int fw_ref;
297+ struct xe_force_wake_ref fw_ref = {};
294298 struct xe_hw_engine *hwe;
295− struct xe_force_wake *fw;
299+
300+ *phwe = NULL;
296301
297302 hwe = any_engine(xe);
298303 if (!hwe)
299− return false;
304+ return fw_ref; /* will be invalid */
300305
301306 domain = xe_hw_engine_to_fw_domain(hwe);
302− fw = gt_to_fw(hwe->gt);
303−
304− fw_ref = xe_force_wake_get(fw, domain);
305− if (!xe_force_wake_ref_has_domain(fw_ref, domain)) {
306− xe_force_wake_put(fw, fw_ref);
307− return false;
308− }
309307
310− *phwe = hwe;
311− *pfw_ref = fw_ref;
308+ fw_ref = xe_force_wake_constructor(gt_to_fw(hwe->gt), domain);
309+ if (xe_force_wake_ref_has_domain(fw_ref.domains, domain))
310+ *phwe = hwe; /* valid forcewake */
312311
313− return true;
312+ return fw_ref;
314313 }
315314
316315 static void show_run_ticks(struct drm_printer *p, struct drm_file *file)
@@ -322,7 +321,6 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) · 5 unmodified lines
322321 struct xe_hw_engine *hwe;
323322 struct xe_exec_queue *q;
324323 u64 gpu_timestamp;
325− unsigned int fw_ref;
326324
327325 /*
328326 * RING_TIMESTAMP registers are inaccessible in VF mode.
@@ -339,29 +337,26 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) · 10 unmodified lines
339337 wait_var_event(&xef->exec_queue.pending_removal,
340338 !atomic_read(&xef->exec_queue.pending_removal));
341339
342− xe_pm_runtime_get(xe);
343− if (!force_wake_get_any_engine(xe, &hwe, &fw_ref)) {
344− xe_pm_runtime_put(xe);
345− return;
346− }
347−
348− /* Accumulate all the exec queues from this client */
349− mutex_lock(&xef->exec_queue.lock);
350− xa_for_each(&xef->exec_queue.xa, i, q) {
351− xe_exec_queue_get(q);
352− mutex_unlock(&xef->exec_queue.lock);
353−
354− xe_exec_queue_update_run_ticks(q);
340+ scoped_guard(xe_pm_runtime, xe) {
341+ CLASS(xe_force_wake_release_only, fw_ref)(force_wake_get_any_engine(xe, &hwe));
342+ if (!hwe)
343+ return;
355344
345+ /* Accumulate all the exec queues from this client */
356346 mutex_lock(&xef->exec_queue.lock);
357− xe_exec_queue_put(q);
358− }
359− mutex_unlock(&xef->exec_queue.lock);
347+ xa_for_each(&xef->exec_queue.xa, i, q) {
348+ xe_exec_queue_get(q);
349+ mutex_unlock(&xef->exec_queue.lock);
360350
361− gpu_timestamp = xe_hw_engine_read_timestamp(hwe);
351+ xe_exec_queue_update_run_ticks(q);
362352
363− xe_force_wake_put(gt_to_fw(hwe->gt), fw_ref);
364− xe_pm_runtime_put(xe);
353+ mutex_lock(&xef->exec_queue.lock);
354+ xe_exec_queue_put(q);
355+ }
356+ mutex_unlock(&xef->exec_queue.lock);
357+
358+ gpu_timestamp = xe_hw_engine_read_timestamp(hwe);
359+ }
365360
366361 for (class = 0; class < XE_ENGINE_CLASS_MAX; class++) {
367362 const char *class_name;
drivers/gpu/drm/xe/xe_exec.c+7−2
@@ -121,7 +121,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 120 unmodified lines
121121 u64 addresses[XE_HW_ENGINE_MAX_INSTANCE];
122122 struct drm_gpuvm_exec vm_exec = {.extra.fn = xe_exec_fn};
123123 struct drm_exec *exec = &vm_exec.exec;
124− u32 i, num_syncs, num_ufence = 0;
124+ u32 i, num_syncs, num_in_sync = 0, num_ufence = 0;
125125 struct xe_validation_ctx ctx;
126126 struct xe_sched_job *job;
127127 struct xe_vm *vm;
@@ -183,6 +183,9 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 55 unmodified lines
183183
184184 if (xe_sync_is_ufence(&syncs[num_syncs]))
185185 num_ufence++;
186+
187+ if (!num_in_sync && xe_sync_needs_wait(&syncs[num_syncs]))
188+ num_in_sync++;
186189 }
187190
188191 if (XE_IOCTL_DBG(xe, num_ufence > 1)) {
@@ -203,7 +206,9 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 14 unmodified lines
203206 mode = xe_hw_engine_group_find_exec_mode(q);
204207
205208 if (mode == EXEC_MODE_DMA_FENCE) {
206− err = xe_hw_engine_group_get_mode(group, mode, &previous_mode);
209+ err = xe_hw_engine_group_get_mode(group, mode, &previous_mode,
210+ syncs, num_in_sync ?
211+ num_syncs : 0);
207212 if (err)
208213 goto err_syncs;
209214 }
drivers/gpu/drm/xe/xe_exec_queue.c+441−14
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313 #include <drm/drm_syncobj.h>
1414 #include <uapi/drm/xe_drm.h>
1515
16+#include "xe_bo.h"
1617 #include "xe_dep_scheduler.h"
1718 #include "xe_device.h"
1819 #include "xe_gt.h"
@@ -53,6 +54,54 @@ · 34 unmodified lines
5354 * the ring operations the different engine classes support.
5455 */
5556
57+/**
58+ * DOC: Multi Queue Group
59+ *
60+ * Multi Queue Group is another mode of execution supported by the compute
61+ * and blitter copy command streamers (CCS and BCS, respectively). It is
62+ * an enhancement of the existing hardware architecture and leverages the
63+ * same submission model. It enables support for efficient, parallel
64+ * execution of multiple queues within a single shared context. The multi
65+ * queue group functionality is only supported with GuC submission backend.
66+ * All the queues of a group must use the same address space (VM).
67+ *
68+ * The DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE execution queue property
69+ * supports creating a multi queue group and adding queues to a queue group.
70+ *
71+ * The XE_EXEC_QUEUE_CREATE ioctl call with above property with value field
72+ * set to DRM_XE_MULTI_GROUP_CREATE, will create a new multi queue group with
73+ * the queue being created as the primary queue (aka q0) of the group. To add
74+ * secondary queues to the group, they need to be created with the above
75+ * property with id of the primary queue as the value. The properties of
76+ * the primary queue (like priority, time slice) applies to the whole group.
77+ * So, these properties can't be set for secondary queues of a group.
78+ *
79+ * The hardware does not support removing a queue from a multi-queue group.
80+ * However, queues can be dynamically added to the group. A group can have
81+ * up to 64 queues. To support this, XeKMD holds references to LRCs of the
82+ * queues even after the queues are destroyed by the user until the whole
83+ * group is destroyed. The secondary queues hold a reference to the primary
84+ * queue thus preventing the group from being destroyed when user destroys
85+ * the primary queue. Once the primary queue is destroyed, secondary queues
86+ * can't be added to the queue group, but they can continue to submit the
87+ * jobs if the DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag is set during the multi
88+ * queue group creation.
89+ *
90+ * The queues of a multi queue group can set their priority within the group
91+ * through the DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY property.
92+ * This multi queue priority can also be set dynamically through the
93+ * XE_EXEC_QUEUE_SET_PROPERTY ioctl. This is the only other property
94+ * supported by the secondary queues of a multi queue group, other than
95+ * DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE.
96+ *
97+ * When GuC reports an error on any of the queues of a multi queue group,
98+ * the queue cleanup mechanism is invoked for all the queues of the group
99+ * as hardware cannot make progress on the multi queue context.
100+ *
101+ * Refer :ref:`multi-queue-group-guc-interface` for multi queue group GuC
102+ * interface.
103+ */
104+
56105 enum xe_exec_queue_sched_prop {
57106 XE_EXEC_QUEUE_JOB_TIMEOUT = 0,
58107 XE_EXEC_QUEUE_TIMESLICE = 1,
@@ -61,7 +110,35 @@ enum xe_exec_queue_sched_prop { · 2 unmodified lines
61110 };
62111
63112 static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
64− u64 extensions, int ext_number);
113+ u64 extensions);
114+
115+static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
116+{
117+ struct xe_exec_queue_group *group = q->multi_queue.group;
118+ struct xe_lrc *lrc;
119+ unsigned long idx;
120+
121+ if (xe_exec_queue_is_multi_queue_secondary(q)) {
122+ /*
123+ * Put pairs with get from xe_exec_queue_lookup() call
124+ * in xe_exec_queue_group_validate().
125+ */
126+ xe_exec_queue_put(xe_exec_queue_multi_queue_primary(q));
127+ return;
128+ }
129+
130+ if (!group)
131+ return;
132+
133+ /* Primary queue cleanup */
134+ xa_for_each(&group->xa, idx, lrc)
135+ xe_lrc_put(lrc);
136+
137+ xa_destroy(&group->xa);
138+ mutex_destroy(&group->list_lock);
139+ xe_bo_unpin_map_no_vm(group->cgp_bo);
140+ kfree(group);
141+}
65142
66143 static void __xe_exec_queue_free(struct xe_exec_queue *q)
67144 {
@@ -73,12 +150,17 @@ static void __xe_exec_queue_free(struct xe_exec_queue *q) · 5 unmodified lines
73150
74151 if (xe_exec_queue_uses_pxp(q))
75152 xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q);
153+
154+ if (xe_exec_queue_is_multi_queue(q))
155+ xe_exec_queue_group_cleanup(q);
156+
76157 if (q->vm)
77158 xe_vm_put(q->vm);
78159
79160 if (q->xef)
80161 xe_file_put(q->xef);
81162
163+ kvfree(q->replay_state);
82164 kfree(q);
83165 }
84166
@@ -147,6 +229,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe, · 62 unmodified lines
147229 INIT_LIST_HEAD(&q->multi_gt_link);
148230 INIT_LIST_HEAD(&q->hw_engine_group_link);
149231 INIT_LIST_HEAD(&q->pxp.link);
232+ q->multi_queue.priority = XE_MULTI_QUEUE_PRIORITY_NORMAL;
150233
151234 q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us;
152235 q->sched_props.preempt_timeout_us =
@@ -175,7 +258,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe, · 22 unmodified lines
175258 * may set q->usm, must come before xe_lrc_create(),
176259 * may overwrite q->sched_props, must come before q->ops->init()
177260 */
178− err = exec_queue_user_extensions(xe, q, extensions, 0);
261+ err = exec_queue_user_extensions(xe, q, extensions);
179262 if (err) {
180263 __xe_exec_queue_free(q);
181264 return ERR_PTR(err);
@@ -225,8 +308,8 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q, u32 exec_queue_flags) · 43 unmodified lines
225308 struct xe_lrc *lrc;
226309
227310 xe_gt_sriov_vf_wait_valid_ggtt(q->gt);
228− lrc = xe_lrc_create(q->hwe, q->vm, xe_lrc_ring_size(),
229− q->msix_vec, flags);
311+ lrc = xe_lrc_create(q->hwe, q->vm, q->replay_state,
312+ xe_lrc_ring_size(), q->msix_vec, flags);
230313 if (IS_ERR(lrc)) {
231314 err = PTR_ERR(lrc);
232315 goto err_lrc;
@@ -383,6 +466,26 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe, · 150 unmodified lines
383466 }
384467 ALLOW_ERROR_INJECTION(xe_exec_queue_create_bind, ERRNO);
385468
469+static void xe_exec_queue_group_kill(struct kref *ref)
470+{
471+ struct xe_exec_queue_group *group = container_of(ref, struct xe_exec_queue_group,
472+ kill_refcount);
473+ xe_exec_queue_kill(group->primary);
474+}
475+
476+static inline void xe_exec_queue_group_kill_get(struct xe_exec_queue_group *group)
477+{
478+ kref_get(&group->kill_refcount);
479+}
480+
481+void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group)
482+{
483+ if (!group)
484+ return;
485+
486+ kref_put(&group->kill_refcount, xe_exec_queue_group_kill);
487+}
488+
386489 void xe_exec_queue_destroy(struct kref *ref)
387490 {
388491 struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount);
@@ -567,6 +670,217 @@ exec_queue_set_pxp_type(struct xe_device *xe, struct xe_exec_queue *q, u64 value · 178 unmodified lines
567670 return xe_pxp_exec_queue_set_type(xe->pxp, q, DRM_XE_PXP_TYPE_HWDRM);
568671 }
569672
673+static int exec_queue_set_hang_replay_state(struct xe_device *xe,
674+ struct xe_exec_queue *q,
675+ u64 value)
676+{
677+ size_t size = xe_gt_lrc_hang_replay_size(q->gt, q->class);
678+ u64 __user *address = u64_to_user_ptr(value);
679+ void *ptr;
680+
681+ ptr = vmemdup_user(address, size);
682+ if (XE_IOCTL_DBG(xe, IS_ERR(ptr)))
683+ return PTR_ERR(ptr);
684+
685+ q->replay_state = ptr;
686+
687+ return 0;
688+}
689+
690+static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *q)
691+{
692+ struct xe_tile *tile = gt_to_tile(q->gt);
693+ struct xe_exec_queue_group *group;
694+ struct xe_bo *bo;
695+
696+ group = kzalloc(sizeof(*group), GFP_KERNEL);
697+ if (!group)
698+ return -ENOMEM;
699+
700+ bo = xe_bo_create_pin_map_novm(xe, tile, SZ_4K, ttm_bo_type_kernel,
701+ XE_BO_FLAG_VRAM_IF_DGFX(tile) |
702+ XE_BO_FLAG_PINNED_LATE_RESTORE |
703+ XE_BO_FLAG_FORCE_USER_VRAM |
704+ XE_BO_FLAG_GGTT_INVALIDATE |
705+ XE_BO_FLAG_GGTT, false);
706+ if (IS_ERR(bo)) {
707+ drm_err(&xe->drm, "CGP bo allocation for queue group failed: %ld\n",
708+ PTR_ERR(bo));
709+ kfree(group);
710+ return PTR_ERR(bo);
711+ }
712+
713+ xe_map_memset(xe, &bo->vmap, 0, 0, SZ_4K);
714+
715+ group->primary = q;
716+ group->cgp_bo = bo;
717+ INIT_LIST_HEAD(&group->list);
718+ kref_init(&group->kill_refcount);
719+ xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
720+ mutex_init(&group->list_lock);
721+ q->multi_queue.group = group;
722+
723+ /* group->list_lock is used in submission backend */
724+ if (IS_ENABLED(CONFIG_LOCKDEP)) {
725+ fs_reclaim_acquire(GFP_KERNEL);
726+ might_lock(&group->list_lock);
727+ fs_reclaim_release(GFP_KERNEL);
728+ }
729+
730+ return 0;
731+}
732+
733+static inline bool xe_exec_queue_supports_multi_queue(struct xe_exec_queue *q)
734+{
735+ return q->gt->info.multi_queue_engine_class_mask & BIT(q->class);
736+}
737+
738+static int xe_exec_queue_group_validate(struct xe_device *xe, struct xe_exec_queue *q,
739+ u32 primary_id)
740+{
741+ struct xe_exec_queue_group *group;
742+ struct xe_exec_queue *primary;
743+ int ret;
744+
745+ /*
746+ * Get from below xe_exec_queue_lookup() pairs with put
747+ * in xe_exec_queue_group_cleanup().
748+ */
749+ primary = xe_exec_queue_lookup(q->vm->xef, primary_id);
750+ if (XE_IOCTL_DBG(xe, !primary))
751+ return -ENOENT;
752+
753+ if (XE_IOCTL_DBG(xe, !xe_exec_queue_is_multi_queue_primary(primary)) ||
754+ XE_IOCTL_DBG(xe, q->vm != primary->vm) ||
755+ XE_IOCTL_DBG(xe, q->logical_mask != primary->logical_mask)) {
756+ ret = -EINVAL;
757+ goto put_primary;
758+ }
759+
760+ group = primary->multi_queue.group;
761+ q->multi_queue.valid = true;
762+ q->multi_queue.group = group;
763+
764+ return 0;
765+put_primary:
766+ xe_exec_queue_put(primary);
767+ return ret;
768+}
769+
770+#define XE_MAX_GROUP_SIZE 64
771+static int xe_exec_queue_group_add(struct xe_device *xe, struct xe_exec_queue *q)
772+{
773+ struct xe_exec_queue_group *group = q->multi_queue.group;
774+ u32 pos;
775+ int err;
776+
777+ xe_assert(xe, xe_exec_queue_is_multi_queue_secondary(q));
778+
779+ /* Primary queue holds a reference to LRCs of all secondary queues */
780+ err = xa_alloc(&group->xa, &pos, xe_lrc_get(q->lrc[0]),
781+ XA_LIMIT(1, XE_MAX_GROUP_SIZE - 1), GFP_KERNEL);
782+ if (XE_IOCTL_DBG(xe, err)) {
783+ xe_lrc_put(q->lrc[0]);
784+
785+ /* It is invalid if queue group limit is exceeded */
786+ if (err == -EBUSY)
787+ err = -EINVAL;
788+
789+ return err;
790+ }
791+
792+ q->multi_queue.pos = pos;
793+
794+ if (group->primary->multi_queue.keep_active) {
795+ xe_exec_queue_group_kill_get(group);
796+ q->multi_queue.keep_active = true;
797+ }
798+
799+ return 0;
800+}
801+
802+static void xe_exec_queue_group_delete(struct xe_device *xe, struct xe_exec_queue *q)
803+{
804+ struct xe_exec_queue_group *group = q->multi_queue.group;
805+ struct xe_lrc *lrc;
806+
807+ xe_assert(xe, xe_exec_queue_is_multi_queue_secondary(q));
808+
809+ lrc = xa_erase(&group->xa, q->multi_queue.pos);
810+ xe_assert(xe, lrc);
811+ xe_lrc_put(lrc);
812+
813+ if (q->multi_queue.keep_active) {
814+ xe_exec_queue_group_kill_put(group);
815+ q->multi_queue.keep_active = false;
816+ }
817+}
818+
819+static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue *q,
820+ u64 value)
821+{
822+ if (XE_IOCTL_DBG(xe, !xe_exec_queue_supports_multi_queue(q)))
823+ return -ENODEV;
824+
825+ if (XE_IOCTL_DBG(xe, !xe_device_uc_enabled(xe)))
826+ return -EOPNOTSUPP;
827+
828+ if (XE_IOCTL_DBG(xe, !q->vm->xef))
829+ return -EINVAL;
830+
831+ if (XE_IOCTL_DBG(xe, xe_exec_queue_is_parallel(q)))
832+ return -EINVAL;
833+
834+ if (XE_IOCTL_DBG(xe, xe_exec_queue_is_multi_queue(q)))
835+ return -EINVAL;
836+
837+ if (value & DRM_XE_MULTI_GROUP_CREATE) {
838+ if (XE_IOCTL_DBG(xe, value & ~(DRM_XE_MULTI_GROUP_CREATE |
839+ DRM_XE_MULTI_GROUP_KEEP_ACTIVE)))
840+ return -EINVAL;
841+
842+ /*
843+ * KEEP_ACTIVE is not supported in preempt fence mode as in that mode,
844+ * VM_DESTROY ioctl expects all exec queues of that VM are already killed.
845+ */
846+ if (XE_IOCTL_DBG(xe, (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE) &&
847+ xe_vm_in_preempt_fence_mode(q->vm)))
848+ return -EINVAL;
849+
850+ q->multi_queue.valid = true;
851+ q->multi_queue.is_primary = true;
852+ q->multi_queue.pos = 0;
853+ if (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE)
854+ q->multi_queue.keep_active = true;
855+
856+ return 0;
857+ }
858+
859+ /* While adding secondary queues, the upper 32 bits must be 0 */
860+ if (XE_IOCTL_DBG(xe, value & (~0ull << 32)))
861+ return -EINVAL;
862+
863+ return xe_exec_queue_group_validate(xe, q, value);
864+}
865+
866+static int exec_queue_set_multi_queue_priority(struct xe_device *xe, struct xe_exec_queue *q,
867+ u64 value)
868+{
869+ if (XE_IOCTL_DBG(xe, value > XE_MULTI_QUEUE_PRIORITY_HIGH))
870+ return -EINVAL;
871+
872+ /* For queue creation time (!q->xef) setting, just store the priority value */
873+ if (!q->xef) {
874+ q->multi_queue.priority = value;
875+ return 0;
876+ }
877+
878+ if (!xe_exec_queue_is_multi_queue(q))
879+ return -EINVAL;
880+
881+ return q->ops->set_multi_queue_priority(q, value);
882+}
883+
570884 typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
571885 struct xe_exec_queue *q,
572886 u64 value);
@@ -575,11 +889,76 @@ static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = { · 2 unmodified lines
575889 [DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY] = exec_queue_set_priority,
576890 [DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE] = exec_queue_set_timeslice,
577891 [DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE] = exec_queue_set_pxp_type,
892+ [DRM_XE_EXEC_QUEUE_SET_HANG_REPLAY_STATE] = exec_queue_set_hang_replay_state,
893+ [DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP] = exec_queue_set_multi_group,
894+ [DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY] =
895+ exec_queue_set_multi_queue_priority,
578896 };
579897
898+int xe_exec_queue_set_property_ioctl(struct drm_device *dev, void *data,
899+ struct drm_file *file)
900+{
901+ struct xe_device *xe = to_xe_device(dev);
902+ struct xe_file *xef = to_xe_file(file);
903+ struct drm_xe_exec_queue_set_property *args = data;
904+ struct xe_exec_queue *q;
905+ int ret;
906+ u32 idx;
907+
908+ if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
909+ return -EINVAL;
910+
911+ if (XE_IOCTL_DBG(xe, args->property !=
912+ DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY))
913+ return -EINVAL;
914+
915+ q = xe_exec_queue_lookup(xef, args->exec_queue_id);
916+ if (XE_IOCTL_DBG(xe, !q))
917+ return -ENOENT;
918+
919+ idx = array_index_nospec(args->property,
920+ ARRAY_SIZE(exec_queue_set_property_funcs));
921+ ret = exec_queue_set_property_funcs[idx](xe, q, args->value);
922+ if (XE_IOCTL_DBG(xe, ret))
923+ goto err_post_lookup;
924+
925+ xe_exec_queue_put(q);
926+ return 0;
927+
928+ err_post_lookup:
929+ xe_exec_queue_put(q);
930+ return ret;
931+}
932+
933+static int exec_queue_user_ext_check(struct xe_exec_queue *q, u64 properties)
934+{
935+ u64 secondary_queue_valid_props = BIT_ULL(DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP) |
936+ BIT_ULL(DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY);
937+
938+ /*
939+ * Only MULTI_QUEUE_PRIORITY property is valid for secondary queues of a
940+ * multi-queue group.
941+ */
942+ if (xe_exec_queue_is_multi_queue_secondary(q) &&
943+ properties & ~secondary_queue_valid_props)
944+ return -EINVAL;
945+
946+ return 0;
947+}
948+
949+static int exec_queue_user_ext_check_final(struct xe_exec_queue *q, u64 properties)
950+{
951+ /* MULTI_QUEUE_PRIORITY only applies to multi-queue group queues */
952+ if ((properties & BIT_ULL(DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY)) &&
953+ !(properties & BIT_ULL(DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP)))
954+ return -EINVAL;
955+
956+ return 0;
957+}
958+
580959 static int exec_queue_user_ext_set_property(struct xe_device *xe,
581960 struct xe_exec_queue *q,
582− u64 extension)
961+ u64 extension, u64 *properties)
583962 {
584963 u64 __user *address = u64_to_user_ptr(extension);
585964 struct drm_xe_ext_set_property ext;
@@ -595,27 +974,35 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe, · 9 unmodified lines
595974 XE_IOCTL_DBG(xe, ext.pad) ||
596975 XE_IOCTL_DBG(xe, ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY &&
597976 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE &&
598− ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE))
977+ ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE &&
978+ ext.property != DRM_XE_EXEC_QUEUE_SET_HANG_REPLAY_STATE &&
979+ ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP &&
980+ ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY))
599981 return -EINVAL;
600982
601983 idx = array_index_nospec(ext.property, ARRAY_SIZE(exec_queue_set_property_funcs));
602984 if (!exec_queue_set_property_funcs[idx])
603985 return -EINVAL;
604986
987+ *properties |= BIT_ULL(idx);
988+ err = exec_queue_user_ext_check(q, *properties);
989+ if (XE_IOCTL_DBG(xe, err))
990+ return err;
991+
605992 return exec_queue_set_property_funcs[idx](xe, q, ext.value);
606993 }
607994
608995 typedef int (*xe_exec_queue_user_extension_fn)(struct xe_device *xe,
609996 struct xe_exec_queue *q,
610− u64 extension);
997+ u64 extension, u64 *properties);
611998
612999 static const xe_exec_queue_user_extension_fn exec_queue_user_extension_funcs[] = {
6131000 [DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY] = exec_queue_user_ext_set_property,
6141001 };
6151002
6161003 #define MAX_USER_EXTENSIONS 16
617−static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
618− u64 extensions, int ext_number)
1004+static int __exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
1005+ u64 extensions, int ext_number, u64 *properties)
6191006 {
6201007 u64 __user *address = u64_to_user_ptr(extensions);
6211008 struct drm_xe_user_extension ext;
@@ -636,13 +1023,36 @@ static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue · 14 unmodified lines
6361023
6371024 idx = array_index_nospec(ext.name,
6381025 ARRAY_SIZE(exec_queue_user_extension_funcs));
639− err = exec_queue_user_extension_funcs[idx](xe, q, extensions);
1026+ err = exec_queue_user_extension_funcs[idx](xe, q, extensions, properties);
6401027 if (XE_IOCTL_DBG(xe, err))
6411028 return err;
6421029
6431030 if (ext.next_extension)
644− return exec_queue_user_extensions(xe, q, ext.next_extension,
645− ++ext_number);
1031+ return __exec_queue_user_extensions(xe, q, ext.next_extension,
1032+ ++ext_number, properties);
1033+
1034+ return 0;
1035+}
1036+
1037+static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
1038+ u64 extensions)
1039+{
1040+ u64 properties = 0;
1041+ int err;
1042+
1043+ err = __exec_queue_user_extensions(xe, q, extensions, 0, &properties);
1044+ if (XE_IOCTL_DBG(xe, err))
1045+ return err;
1046+
1047+ err = exec_queue_user_ext_check_final(q, properties);
1048+ if (XE_IOCTL_DBG(xe, err))
1049+ return err;
1050+
1051+ if (xe_exec_queue_is_multi_queue_primary(q)) {
1052+ err = xe_exec_queue_group_init(xe, q);
1053+ if (XE_IOCTL_DBG(xe, err))
1054+ return err;
1055+ }
6461056
6471057 return 0;
6481058 }
@@ -798,12 +1208,18 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data, · 149 unmodified lines
7981208 if (IS_ERR(q))
7991209 return PTR_ERR(q);
8001210
1211+ if (xe_exec_queue_is_multi_queue_secondary(q)) {
1212+ err = xe_exec_queue_group_add(xe, q);
1213+ if (XE_IOCTL_DBG(xe, err))
1214+ goto put_exec_queue;
1215+ }
1216+
8011217 if (xe_vm_in_preempt_fence_mode(vm)) {
8021218 q->lr.context = dma_fence_context_alloc(1);
8031219
8041220 err = xe_vm_add_compute_exec_queue(vm, q);
8051221 if (XE_IOCTL_DBG(xe, err))
806− goto put_exec_queue;
1222+ goto delete_queue_group;
8071223 }
8081224
8091225 if (q->vm && q->hwe->hw_engine_group) {
@@ -826,6 +1242,9 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data, · 16 unmodified lines
8261242
8271243 kill_exec_queue:
8281244 xe_exec_queue_kill(q);
1245+delete_queue_group:
1246+ if (xe_exec_queue_is_multi_queue_secondary(q))
1247+ xe_exec_queue_group_delete(xe, q);
8291248 put_exec_queue:
8301249 xe_exec_queue_put(q);
8311250 return err;
@@ -981,6 +1400,11 @@ void xe_exec_queue_kill(struct xe_exec_queue *q) · 149 unmodified lines
9811400
9821401 q->ops->kill(q);
9831402 xe_vm_remove_compute_exec_queue(q->vm, q);
1403+
1404+ if (!xe_exec_queue_is_multi_queue_primary(q) && q->multi_queue.keep_active) {
1405+ xe_exec_queue_group_kill_put(q->multi_queue.group);
1406+ q->multi_queue.keep_active = false;
1407+ }
9841408 }
9851409
9861410 int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
@@ -1007,7 +1431,10 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data, · 20 unmodified lines
10071431 if (q->vm && q->hwe->hw_engine_group)
10081432 xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q);
10091433
1010− xe_exec_queue_kill(q);
1434+ if (xe_exec_queue_is_multi_queue_primary(q))
1435+ xe_exec_queue_group_kill_put(q->multi_queue.group);
1436+ else
1437+ xe_exec_queue_kill(q);
10111438
10121439 trace_xe_exec_queue_close(q);
10131440 xe_exec_queue_put(q);
drivers/gpu/drm/xe/xe_exec_queue.h+68−0
@@ -66,6 +66,55 @@ static inline bool xe_exec_queue_uses_pxp(struct xe_exec_queue *q) · 65 unmodified lines
6666 return q->pxp.type;
6767 }
6868
69+/**
70+ * xe_exec_queue_is_multi_queue() - Whether an exec_queue is part of a queue group.
71+ * @q: The exec_queue
72+ *
73+ * Return: True if the exec_queue is part of a queue group, false otherwise.
74+ */
75+static inline bool xe_exec_queue_is_multi_queue(struct xe_exec_queue *q)
76+{
77+ return q->multi_queue.valid;
78+}
79+
80+/**
81+ * xe_exec_queue_is_multi_queue_primary() - Whether an exec_queue is primary queue
82+ * of a multi queue group.
83+ * @q: The exec_queue
84+ *
85+ * Return: True if @q is primary queue of a queue group, false otherwise.
86+ */
87+static inline bool xe_exec_queue_is_multi_queue_primary(struct xe_exec_queue *q)
88+{
89+ return q->multi_queue.is_primary;
90+}
91+
92+/**
93+ * xe_exec_queue_is_multi_queue_secondary() - Whether an exec_queue is secondary queue
94+ * of a multi queue group.
95+ * @q: The exec_queue
96+ *
97+ * Return: True if @q is secondary queue of a queue group, false otherwise.
98+ */
99+static inline bool xe_exec_queue_is_multi_queue_secondary(struct xe_exec_queue *q)
100+{
101+ return xe_exec_queue_is_multi_queue(q) && !xe_exec_queue_is_multi_queue_primary(q);
102+}
103+
104+/**
105+ * xe_exec_queue_multi_queue_primary() - Get multi queue group's primary queue
106+ * @q: The exec_queue
107+ *
108+ * If @q belongs to a multi queue group, then the primary queue of the group will
109+ * be returned. Otherwise, @q will be returned.
110+ */
111+static inline struct xe_exec_queue *xe_exec_queue_multi_queue_primary(struct xe_exec_queue *q)
112+{
113+ return xe_exec_queue_is_multi_queue(q) ? q->multi_queue.group->primary : q;
114+}
115+
116+void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group);
117+
69118 bool xe_exec_queue_is_lr(struct xe_exec_queue *q);
70119
71120 bool xe_exec_queue_is_idle(struct xe_exec_queue *q);
@@ -78,6 +127,8 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data, · 6 unmodified lines
78127 struct drm_file *file);
79128 int xe_exec_queue_get_property_ioctl(struct drm_device *dev, void *data,
80129 struct drm_file *file);
130+int xe_exec_queue_set_property_ioctl(struct drm_device *dev, void *data,
131+ struct drm_file *file);
81132 enum xe_exec_queue_priority xe_exec_queue_device_get_max_priority(struct xe_device *xe);
82133
83134 void xe_exec_queue_last_fence_put(struct xe_exec_queue *e, struct xe_vm *vm);
@@ -111,4 +162,21 @@ int xe_exec_queue_contexts_hwsp_rebase(struct xe_exec_queue *q, void *scratch); · 27 unmodified lines
111162
112163 struct xe_lrc *xe_exec_queue_lrc(struct xe_exec_queue *q);
113164
165+/**
166+ * xe_exec_queue_idle_skip_suspend() - Can exec queue skip suspend
167+ * @q: The exec_queue
168+ *
169+ * If an exec queue is not parallel and is idle, the suspend steps can be
170+ * skipped in the submission backend immediatley signaling the suspend fence.
171+ * Parallel queues cannot skip this step due to limitations in the submission
172+ * backend.
173+ *
174+ * Return: True if exec queue is idle and can skip suspend steps, False
175+ * otherwise
176+ */
177+static inline bool xe_exec_queue_idle_skip_suspend(struct xe_exec_queue *q)
178+{
179+ return !xe_exec_queue_is_parallel(q) && xe_exec_queue_is_idle(q);
180+}
181+
114182 #endif
drivers/gpu/drm/xe/xe_exec_queue_types.h+62−0
@@ -32,6 +32,44 @@ enum xe_exec_queue_priority { · 31 unmodified lines
3232 XE_EXEC_QUEUE_PRIORITY_COUNT
3333 };
3434
35+/**
36+ * enum xe_multi_queue_priority - Multi Queue priority values
37+ *
38+ * The priority values of the queues within the multi queue group.
39+ */
40+enum xe_multi_queue_priority {
41+ /** @XE_MULTI_QUEUE_PRIORITY_LOW: Priority low */
42+ XE_MULTI_QUEUE_PRIORITY_LOW = 0,
43+ /** @XE_MULTI_QUEUE_PRIORITY_NORMAL: Priority normal */
44+ XE_MULTI_QUEUE_PRIORITY_NORMAL,
45+ /** @XE_MULTI_QUEUE_PRIORITY_HIGH: Priority high */
46+ XE_MULTI_QUEUE_PRIORITY_HIGH,
47+};
48+
49+/**
50+ * struct xe_exec_queue_group - Execution multi queue group
51+ *
52+ * Contains multi queue group information.
53+ */
54+struct xe_exec_queue_group {
55+ /** @primary: Primary queue of this group */
56+ struct xe_exec_queue *primary;
57+ /** @cgp_bo: BO for the Context Group Page */
58+ struct xe_bo *cgp_bo;
59+ /** @xa: xarray to store LRCs */
60+ struct xarray xa;
61+ /** @list: List of all secondary queues in the group */
62+ struct list_head list;
63+ /** @list_lock: Secondary queue list lock */
64+ struct mutex list_lock;
65+ /** @kill_refcount: ref count to kill primary queue */
66+ struct kref kill_refcount;
67+ /** @sync_pending: CGP_SYNC_DONE g2h response pending */
68+ bool sync_pending;
69+ /** @banned: Group banned */
70+ bool banned;
71+};
72+
3573 /**
3674 * struct xe_exec_queue - Execution queue
3775 *
@@ -111,6 +149,24 @@ struct xe_exec_queue { · 73 unmodified lines
111149 struct xe_guc_exec_queue *guc;
112150 };
113151
152+ /** @multi_queue: Multi queue information */
153+ struct {
154+ /** @multi_queue.group: Queue group information */
155+ struct xe_exec_queue_group *group;
156+ /** @multi_queue.link: Link into group's secondary queues list */
157+ struct list_head link;
158+ /** @multi_queue.priority: Queue priority within the multi-queue group */
159+ enum xe_multi_queue_priority priority;
160+ /** @multi_queue.pos: Position of queue within the multi-queue group */
161+ u8 pos;
162+ /** @multi_queue.valid: Queue belongs to a multi queue group */
163+ u8 valid:1;
164+ /** @multi_queue.is_primary: Is primary queue (Q0) of the group */
165+ u8 is_primary:1;
166+ /** @multi_queue.keep_active: Keep the group active after primary is destroyed */
167+ u8 keep_active:1;
168+ } multi_queue;
169+
114170 /** @sched_props: scheduling properties */
115171 struct {
116172 /** @sched_props.timeslice_us: timeslice period in micro-seconds */
@@ -167,6 +223,9 @@ struct xe_exec_queue { · 50 unmodified lines
167223 /** @ufence_timeline_value: User fence timeline value */
168224 u64 ufence_timeline_value;
169225
226+ /** @replay_state: GPU hang replay state */
227+ void *replay_state;
228+
170229 /** @ops: submission backend exec queue operations */
171230 const struct xe_exec_queue_ops *ops;
172231
@@ -213,6 +272,9 @@ struct xe_exec_queue_ops { · 40 unmodified lines
213272 int (*set_timeslice)(struct xe_exec_queue *q, u32 timeslice_us);
214273 /** @set_preempt_timeout: Set preemption timeout for exec queue */
215274 int (*set_preempt_timeout)(struct xe_exec_queue *q, u32 preempt_timeout_us);
275+ /** @set_multi_queue_priority: Set multi queue priority */
276+ int (*set_multi_queue_priority)(struct xe_exec_queue *q,
277+ enum xe_multi_queue_priority priority);
216278 /**
217279 * @suspend: Suspend exec queue from executing, allowed to be called
218280 * multiple times in a row before resume with the caveat that
drivers/gpu/drm/xe/xe_execlist.c+1−1
@@ -269,7 +269,7 @@ struct xe_execlist_port *xe_execlist_port_create(struct xe_device *xe, · 268 unmodified lines
269269
270270 port->hwe = hwe;
271271
272− port->lrc = xe_lrc_create(hwe, NULL, SZ_16K, XE_IRQ_DEFAULT_MSIX, 0);
272+ port->lrc = xe_lrc_create(hwe, NULL, NULL, SZ_16K, XE_IRQ_DEFAULT_MSIX, 0);
273273 if (IS_ERR(port->lrc)) {
274274 err = PTR_ERR(port->lrc);
275275 goto err;
drivers/gpu/drm/xe/xe_force_wake.c+7−0
@@ -166,6 +166,13 @@ static int domain_sleep_wait(struct xe_gt *gt, · 165 unmodified lines
166166 * xe_force_wake_ref_has_domain() function. Caller must call
167167 * xe_force_wake_put() function to decrease incremented refcounts.
168168 *
169+ * When possible, scope-based forcewake (through CLASS(xe_force_wake, ...) or
170+ * xe_with_force_wake()) should be used instead of direct calls to this
171+ * function. Direct usage of get/put should only be used when the function
172+ * has goto-based flows that can interfere with scope-based cleanup, or when
173+ * the lifetime of the forcewake reference does not match a specific scope
174+ * (e.g., forcewake obtained in one function and released in a different one).
175+ *
169176 * Return: opaque reference to woken domains or zero if none of requested
170177 * domains were awake.
171178 */
drivers/gpu/drm/xe/xe_force_wake.h+40−0
@@ -61,4 +61,44 @@ xe_force_wake_ref_has_domain(unsigned int fw_ref, enum xe_force_wake_domains dom · 60 unmodified lines
6161 return fw_ref & domain;
6262 }
6363
64+struct xe_force_wake_ref {
65+ struct xe_force_wake *fw;
66+ unsigned int domains;
67+};
68+
69+static struct xe_force_wake_ref
70+xe_force_wake_constructor(struct xe_force_wake *fw, unsigned int domains)
71+{
72+ struct xe_force_wake_ref fw_ref = { .fw = fw };
73+
74+ fw_ref.domains = xe_force_wake_get(fw, domains);
75+
76+ return fw_ref;
77+}
78+
79+DEFINE_CLASS(xe_force_wake, struct xe_force_wake_ref,
80+ xe_force_wake_put(_T.fw, _T.domains),
81+ xe_force_wake_constructor(fw, domains),
82+ struct xe_force_wake *fw, unsigned int domains);
83+
84+/*
85+ * Scoped helper for the forcewake class, using the same trick as scoped_guard()
86+ * to bind the lifetime to the next statement/block.
87+ */
88+#define __xe_with_force_wake(ref, fw, domains, done) \
89+ for (CLASS(xe_force_wake, ref)(fw, domains), *(done) = NULL; \
90+ !(done); (done) = (void *)1)
91+
92+#define xe_with_force_wake(ref, fw, domains) \
93+ __xe_with_force_wake(ref, fw, domains, __UNIQUE_ID(done))
94+
95+/*
96+ * Used when xe_force_wake_constructor() has already been called by another
97+ * function and the current function is responsible for releasing the forcewake
98+ * reference in all possible cases and error paths.
99+ */
100+DEFINE_CLASS(xe_force_wake_release_only, struct xe_force_wake_ref,
101+ if (_T.fw) xe_force_wake_put(_T.fw, _T.domains), fw_ref,
102+ struct xe_force_wake_ref fw_ref);
103+
64104 #endif
drivers/gpu/drm/xe/xe_ggtt.c+1−2
@@ -396,9 +396,8 @@ static void ggtt_node_remove_work_func(struct work_struct *work) · 395 unmodified lines
396396 delayed_removal_work);
397397 struct xe_device *xe = tile_to_xe(node->ggtt->tile);
398398
399− xe_pm_runtime_get(xe);
399+ guard(xe_pm_runtime)(xe);
400400 ggtt_node_remove(node);
401− xe_pm_runtime_put(xe);
402401 }
403402
404403 /**
drivers/gpu/drm/xe/xe_gsc.c+6−15
@@ -352,7 +352,6 @@ static void gsc_work(struct work_struct *work) · 351 unmodified lines
352352 struct xe_gsc *gsc = container_of(work, typeof(*gsc), work);
353353 struct xe_gt *gt = gsc_to_gt(gsc);
354354 struct xe_device *xe = gt_to_xe(gt);
355− unsigned int fw_ref;
356355 u32 actions;
357356 int ret;
358357
@@ -361,13 +360,12 @@ static void gsc_work(struct work_struct *work) · 2 unmodified lines
361360 gsc->work_actions = 0;
362361 spin_unlock_irq(&gsc->lock);
363362
364− xe_pm_runtime_get(xe);
365− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
363+ guard(xe_pm_runtime)(xe);
364+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC);
366365
367366 if (actions & GSC_ACTION_ER_COMPLETE) {
368− ret = gsc_er_complete(gt);
369− if (ret)
370− goto out;
367+ if (gsc_er_complete(gt))
368+ return;
371369 }
372370
373371 if (actions & GSC_ACTION_FW_LOAD) {
@@ -380,10 +378,6 @@ static void gsc_work(struct work_struct *work) · 6 unmodified lines
380378
381379 if (actions & GSC_ACTION_SW_PROXY)
382380 xe_gsc_proxy_request_handler(gsc);
383−
384−out:
385− xe_force_wake_put(gt_to_fw(gt), fw_ref);
386− xe_pm_runtime_put(xe);
387381 }
388382
389383 void xe_gsc_hwe_irq_handler(struct xe_hw_engine *hwe, u16 intr_vec)
@@ -615,7 +609,6 @@ void xe_gsc_print_info(struct xe_gsc *gsc, struct drm_printer *p) · 225 unmodified lines
615609 {
616610 struct xe_gt *gt = gsc_to_gt(gsc);
617611 struct xe_mmio *mmio = &gt->mmio;
618− unsigned int fw_ref;
619612
620613 xe_uc_fw_print(&gsc->fw, p);
621614
@@ -624,8 +617,8 @@ void xe_gsc_print_info(struct xe_gsc *gsc, struct drm_printer *p) · 2 unmodified lines
624617 if (!xe_uc_fw_is_enabled(&gsc->fw))
625618 return;
626619
627− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
628− if (!fw_ref)
620+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC);
621+ if (!fw_ref.domains)
629622 return;
630623
631624 drm_printf(p, "\nHECI1 FWSTS: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
@@ -635,6 +628,4 @@ void xe_gsc_print_info(struct xe_gsc *gsc, struct drm_printer *p) · 3 unmodified lines
635628 xe_mmio_read32(mmio, HECI_FWSTS4(MTL_GSC_HECI1_BASE)),
636629 xe_mmio_read32(mmio, HECI_FWSTS5(MTL_GSC_HECI1_BASE)),
637630 xe_mmio_read32(mmio, HECI_FWSTS6(MTL_GSC_HECI1_BASE)));
638−
639− xe_force_wake_put(gt_to_fw(gt), fw_ref);
640631 }
drivers/gpu/drm/xe/xe_gsc_debugfs.c+1−2
@@ -37,9 +37,8 @@ static int gsc_info(struct seq_file *m, void *data) · 36 unmodified lines
3737 struct xe_device *xe = gsc_to_xe(gsc);
3838 struct drm_printer p = drm_seq_file_printer(m);
3939
40− xe_pm_runtime_get(xe);
40+ guard(xe_pm_runtime)(xe);
4141 xe_gsc_print_info(gsc, &p);
42− xe_pm_runtime_put(xe);
4342
4443 return 0;
4544 }
drivers/gpu/drm/xe/xe_gsc_proxy.c+7−10
@@ -440,22 +440,19 @@ static void xe_gsc_proxy_remove(void *arg) · 439 unmodified lines
440440 struct xe_gsc *gsc = arg;
441441 struct xe_gt *gt = gsc_to_gt(gsc);
442442 struct xe_device *xe = gt_to_xe(gt);
443− unsigned int fw_ref = 0;
444443
445444 if (!gsc->proxy.component_added)
446445 return;
447446
448447 /* disable HECI2 IRQs */
449− xe_pm_runtime_get(xe);
450− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
451− if (!fw_ref)
452− xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n");
448+ scoped_guard(xe_pm_runtime, xe) {
449+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC);
450+ if (!fw_ref.domains)
451+ xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n");
453452
454− /* try do disable irq even if forcewake failed */
455− gsc_proxy_irq_toggle(gsc, false);
456−
457− xe_force_wake_put(gt_to_fw(gt), fw_ref);
458− xe_pm_runtime_put(xe);
453+ /* try do disable irq even if forcewake failed */
454+ gsc_proxy_irq_toggle(gsc, false);
455+ }
459456
460457 xe_gsc_wait_for_worker_completion(gsc);
461458
drivers/gpu/drm/xe/xe_gt.c+87−87
@@ -103,14 +103,13 @@ void xe_gt_sanitize(struct xe_gt *gt) · 102 unmodified lines
103103
104104 static void xe_gt_enable_host_l2_vram(struct xe_gt *gt)
105105 {
106− unsigned int fw_ref;
107106 u32 reg;
108107
109108 if (!XE_GT_WA(gt, 16023588340))
110109 return;
111110
112− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
113− if (!fw_ref)
111+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
112+ if (!fw_ref.domains)
114113 return;
115114
116115 if (xe_gt_is_main_type(gt)) {
@@ -120,12 +119,10 @@ static void xe_gt_enable_host_l2_vram(struct xe_gt *gt) · 3 unmodified lines
120119 }
121120
122121 xe_gt_mcr_multicast_write(gt, XEHPC_L3CLOS_MASK(3), 0xF);
123− xe_force_wake_put(gt_to_fw(gt), fw_ref);
124122 }
125123
126124 static void xe_gt_disable_host_l2_vram(struct xe_gt *gt)
127125 {
128− unsigned int fw_ref;
129126 u32 reg;
130127
131128 if (!XE_GT_WA(gt, 16023588340))
@@ -134,15 +131,13 @@ static void xe_gt_disable_host_l2_vram(struct xe_gt *gt) · 2 unmodified lines
134131 if (xe_gt_is_media_type(gt))
135132 return;
136133
137− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
138− if (!fw_ref)
134+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
135+ if (!fw_ref.domains)
139136 return;
140137
141138 reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMREQSTRM_CTRL);
142139 reg &= ~CG_DIS_CNTLBUS;
143140 xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg);
144−
145− xe_force_wake_put(gt_to_fw(gt), fw_ref);
146141 }
147142
148143 static void gt_reset_worker(struct work_struct *w);
@@ -389,7 +384,6 @@ put_exec_queue: · 240 unmodified lines
389384
390385 int xe_gt_init_early(struct xe_gt *gt)
391386 {
392− unsigned int fw_ref;
393387 int err;
394388
395389 if (IS_SRIOV_PF(gt_to_xe(gt))) {
@@ -436,13 +430,12 @@ int xe_gt_init_early(struct xe_gt *gt) · 40 unmodified lines
436430 if (err)
437431 return err;
438432
439− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
440− if (!fw_ref)
433+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
434+ if (!fw_ref.domains)
441435 return -ETIMEDOUT;
442436
443437 xe_gt_mcr_init_early(gt);
444438 xe_pat_init(gt);
445− xe_force_wake_put(gt_to_fw(gt), fw_ref);
446439
447440 return 0;
448441 }
@@ -460,16 +453,15 @@ static void dump_pat_on_error(struct xe_gt *gt) · 11 unmodified lines
460453
461454 static int gt_init_with_gt_forcewake(struct xe_gt *gt)
462455 {
463− unsigned int fw_ref;
464456 int err;
465457
466− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
467− if (!fw_ref)
458+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
459+ if (!fw_ref.domains)
468460 return -ETIMEDOUT;
469461
470462 err = xe_uc_init(&gt->uc);
471463 if (err)
472− goto err_force_wake;
464+ return err;
473465
474466 xe_gt_topology_init(gt);
475467 xe_gt_mcr_init(gt);
@@ -478,7 +470,7 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt) · 2 unmodified lines
478470 if (xe_gt_is_main_type(gt)) {
479471 err = xe_ggtt_init(gt_to_tile(gt)->mem.ggtt);
480472 if (err)
481− goto err_force_wake;
473+ return err;
482474 if (IS_SRIOV_PF(gt_to_xe(gt)))
483475 xe_lmtt_init(&gt_to_tile(gt)->sriov.pf.lmtt);
484476 }
@@ -492,17 +484,17 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt) · 7 unmodified lines
492484 err = xe_hw_engines_init_early(gt);
493485 if (err) {
494486 dump_pat_on_error(gt);
495− goto err_force_wake;
487+ return err;
496488 }
497489
498490 err = xe_hw_engine_class_sysfs_init(gt);
499491 if (err)
500− goto err_force_wake;
492+ return err;
501493
502494 /* Initialize CCS mode sysfs after early initialization of HW engines */
503495 err = xe_gt_ccs_mode_sysfs_init(gt);
504496 if (err)
505− goto err_force_wake;
497+ return err;
506498
507499 /*
508500 * Stash hardware-reported version. Since this register does not exist
@@ -510,25 +502,16 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt) · 1 unmodified line
510502 */
511503 gt->info.gmdid = xe_mmio_read32(&gt->mmio, GMD_ID);
512504
513− xe_force_wake_put(gt_to_fw(gt), fw_ref);
514505 return 0;
515−
516−err_force_wake:
517− xe_force_wake_put(gt_to_fw(gt), fw_ref);
518−
519− return err;
520506 }
521507
522508 static int gt_init_with_all_forcewake(struct xe_gt *gt)
523509 {
524− unsigned int fw_ref;
525510 int err;
526511
527− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
528− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) {
529− err = -ETIMEDOUT;
530− goto err_force_wake;
531− }
512+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
513+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL))
514+ return -ETIMEDOUT;
532515
533516 xe_gt_mcr_set_implicit_defaults(gt);
534517 xe_wa_process_gt(gt);
@@ -537,20 +520,20 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt) · 2 unmodified lines
537520
538521 err = xe_gt_clock_init(gt);
539522 if (err)
540− goto err_force_wake;
523+ return err;
541524
542525 xe_mocs_init(gt);
543526 err = xe_execlist_init(gt);
544527 if (err)
545− goto err_force_wake;
528+ return err;
546529
547530 err = xe_hw_engines_init(gt);
548531 if (err)
549− goto err_force_wake;
532+ return err;
550533
551534 err = xe_uc_init_post_hwconfig(&gt->uc);
552535 if (err)
553− goto err_force_wake;
536+ return err;
554537
555538 if (xe_gt_is_main_type(gt)) {
556539 /*
@@ -561,10 +544,8 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt) · 4 unmodified lines
561544
562545 gt->usm.bb_pool = xe_sa_bo_manager_init(gt_to_tile(gt),
563546 IS_DGFX(xe) ? SZ_1M : SZ_512K, 16);
564− if (IS_ERR(gt->usm.bb_pool)) {
565− err = PTR_ERR(gt->usm.bb_pool);
566− goto err_force_wake;
567− }
547+ if (IS_ERR(gt->usm.bb_pool))
548+ return PTR_ERR(gt->usm.bb_pool);
568549 }
569550 }
570551
@@ -573,12 +554,12 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt) · 2 unmodified lines
573554
574555 err = xe_migrate_init(tile->migrate);
575556 if (err)
576− goto err_force_wake;
557+ return err;
577558 }
578559
579560 err = xe_uc_load_hw(&gt->uc);
580561 if (err)
581− goto err_force_wake;
562+ return err;
582563
583564 /* Configure default CCS mode of 1 engine with all resources */
584565 if (xe_gt_ccs_mode_enabled(gt)) {
@@ -592,14 +573,7 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt) · 7 unmodified lines
592573 if (IS_SRIOV_PF(gt_to_xe(gt)))
593574 xe_gt_sriov_pf_init_hw(gt);
594575
595− xe_force_wake_put(gt_to_fw(gt), fw_ref);
596−
597576 return 0;
598−
599−err_force_wake:
600− xe_force_wake_put(gt_to_fw(gt), fw_ref);
601−
602− return err;
603577 }
604578
605579 static void xe_gt_fini(void *arg)
@@ -902,56 +876,42 @@ void xe_gt_reset_async(struct xe_gt *gt) · 296 unmodified lines
902876
903877 void xe_gt_suspend_prepare(struct xe_gt *gt)
904878 {
905− unsigned int fw_ref;
906−
907− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
908−
879+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
909880 xe_uc_suspend_prepare(&gt->uc);
910−
911− xe_force_wake_put(gt_to_fw(gt), fw_ref);
912881 }
913882
914883 int xe_gt_suspend(struct xe_gt *gt)
915884 {
916− unsigned int fw_ref;
917885 int err;
918886
919887 xe_gt_dbg(gt, "suspending\n");
920888 xe_gt_sanitize(gt);
921889
922− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
923− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
924− goto err_msg;
890+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
891+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) {
892+ xe_gt_err(gt, "suspend failed (%pe)\n", ERR_PTR(-ETIMEDOUT));
893+ return -ETIMEDOUT;
894+ }
925895
926896 err = xe_uc_suspend(&gt->uc);
927− if (err)
928− goto err_force_wake;
897+ if (err) {
898+ xe_gt_err(gt, "suspend failed (%pe)\n", ERR_PTR(err));
899+ return err;
900+ }
929901
930902 xe_gt_idle_disable_pg(gt);
931903
932904 xe_gt_disable_host_l2_vram(gt);
933905
934− xe_force_wake_put(gt_to_fw(gt), fw_ref);
935906 xe_gt_dbg(gt, "suspended\n");
936907
937908 return 0;
938−
939−err_msg:
940− err = -ETIMEDOUT;
941−err_force_wake:
942− xe_force_wake_put(gt_to_fw(gt), fw_ref);
943− xe_gt_err(gt, "suspend failed (%pe)\n", ERR_PTR(err));
944−
945− return err;
946909 }
947910
948911 void xe_gt_shutdown(struct xe_gt *gt)
949912 {
950− unsigned int fw_ref;
951−
952− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
913+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
953914 do_gt_reset(gt);
954− xe_force_wake_put(gt_to_fw(gt), fw_ref);
955915 }
956916
957917 /**
@@ -976,32 +936,72 @@ int xe_gt_sanitize_freq(struct xe_gt *gt) · 18 unmodified lines
976936
977937 int xe_gt_resume(struct xe_gt *gt)
978938 {
979− unsigned int fw_ref;
980939 int err;
981940
982941 xe_gt_dbg(gt, "resuming\n");
983− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
984− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
985− goto err_msg;
942+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
943+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) {
944+ xe_gt_err(gt, "resume failed (%pe)\n", ERR_PTR(-ETIMEDOUT));
945+ return -ETIMEDOUT;
946+ }
986947
987948 err = do_gt_restart(gt);
988949 if (err)
989− goto err_force_wake;
950+ return err;
990951
991952 xe_gt_idle_enable_pg(gt);
992953
993− xe_force_wake_put(gt_to_fw(gt), fw_ref);
994954 xe_gt_dbg(gt, "resumed\n");
995955
996956 return 0;
957+}
997958
998−err_msg:
999− err = -ETIMEDOUT;
1000−err_force_wake:
1001− xe_force_wake_put(gt_to_fw(gt), fw_ref);
1002− xe_gt_err(gt, "resume failed (%pe)\n", ERR_PTR(err));
959+/**
960+ * xe_gt_runtime_suspend() - GT runtime suspend
961+ * @gt: the GT object
962+ *
963+ * Return: 0 on success, negative error code otherwise.
964+ */
965+int xe_gt_runtime_suspend(struct xe_gt *gt)
966+{
967+ xe_gt_dbg(gt, "runtime suspending\n");
1003968
1004− return err;
969+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
970+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) {
971+ xe_gt_err(gt, "runtime suspend failed (%pe)\n", ERR_PTR(-ETIMEDOUT));
972+ return -ETIMEDOUT;
973+ }
974+
975+ xe_uc_runtime_suspend(&gt->uc);
976+ xe_gt_disable_host_l2_vram(gt);
977+
978+ xe_gt_dbg(gt, "runtime suspended\n");
979+
980+ return 0;
981+}
982+
983+/**
984+ * xe_gt_runtime_resume() - GT runtime resume
985+ * @gt: the GT object
986+ *
987+ * Return: 0 on success, negative error code otherwise.
988+ */
989+int xe_gt_runtime_resume(struct xe_gt *gt)
990+{
991+ xe_gt_dbg(gt, "runtime resuming\n");
992+
993+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
994+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) {
995+ xe_gt_err(gt, "runtime resume failed (%pe)\n", ERR_PTR(-ETIMEDOUT));
996+ return -ETIMEDOUT;
997+ }
998+
999+ xe_gt_enable_host_l2_vram(gt);
1000+ xe_uc_runtime_resume(&gt->uc);
1001+
1002+ xe_gt_dbg(gt, "runtime resumed\n");
1003+
1004+ return 0;
10051005 }
10061006
10071007 struct xe_hw_engine *xe_gt_hw_engine(struct xe_gt *gt,
drivers/gpu/drm/xe/xe_gt.h+2−0
@@ -58,6 +58,8 @@ int xe_gt_suspend(struct xe_gt *gt); · 57 unmodified lines
5858 void xe_gt_shutdown(struct xe_gt *gt);
5959 int xe_gt_resume(struct xe_gt *gt);
6060 void xe_gt_reset_async(struct xe_gt *gt);
61+int xe_gt_runtime_resume(struct xe_gt *gt);
62+int xe_gt_runtime_suspend(struct xe_gt *gt);
6163 void xe_gt_sanitize(struct xe_gt *gt);
6264 int xe_gt_sanitize_freq(struct xe_gt *gt);
6365
drivers/gpu/drm/xe/xe_gt_debugfs.c+9−21
@@ -105,35 +105,24 @@ int xe_gt_debugfs_show_with_rpm(struct seq_file *m, void *data) · 104 unmodified lines
105105 struct drm_info_node *node = m->private;
106106 struct xe_gt *gt = node_to_gt(node);
107107 struct xe_device *xe = gt_to_xe(gt);
108− int ret;
109−
110− xe_pm_runtime_get(xe);
111− ret = xe_gt_debugfs_simple_show(m, data);
112− xe_pm_runtime_put(xe);
113108
114− return ret;
109+ guard(xe_pm_runtime)(xe);
110+ return xe_gt_debugfs_simple_show(m, data);
115111 }
116112
117113 static int hw_engines(struct xe_gt *gt, struct drm_printer *p)
118114 {
119115 struct xe_hw_engine *hwe;
120116 enum xe_hw_engine_id id;
121− unsigned int fw_ref;
122− int ret = 0;
123117
124− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
125− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) {
126− ret = -ETIMEDOUT;
127− goto fw_put;
128− }
118+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
119+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL))
120+ return -ETIMEDOUT;
129121
130122 for_each_hw_engine(hwe, gt, id)
131123 xe_hw_engine_print(hwe, p);
132124
133−fw_put:
134− xe_force_wake_put(gt_to_fw(gt), fw_ref);
135−
136− return ret;
125+ return 0;
137126 }
138127
139128 static int steering(struct xe_gt *gt, struct drm_printer *p)
@@ -220,6 +209,7 @@ static const struct drm_info_list vf_safe_debugfs_list[] = { · 80 unmodified lines
220209 { "default_lrc_vcs", .show = xe_gt_debugfs_show_with_rpm, .data = vcs_default_lrc },
221210 { "default_lrc_vecs", .show = xe_gt_debugfs_show_with_rpm, .data = vecs_default_lrc },
222211 { "hwconfig", .show = xe_gt_debugfs_show_with_rpm, .data = hwconfig },
212+ { "pat_sw_config", .show = xe_gt_debugfs_simple_show, .data = xe_pat_dump_sw_config },
223213 };
224214
225215 /* everything else should be added here */
@@ -269,9 +259,8 @@ static void force_reset(struct xe_gt *gt) · 43 unmodified lines
269259 {
270260 struct xe_device *xe = gt_to_xe(gt);
271261
272− xe_pm_runtime_get(xe);
262+ guard(xe_pm_runtime)(xe);
273263 xe_gt_reset_async(gt);
274− xe_pm_runtime_put(xe);
275264 }
276265
277266 static ssize_t force_reset_write(struct file *file,
@@ -297,9 +286,8 @@ static void force_reset_sync(struct xe_gt *gt) · 19 unmodified lines
297286 {
298287 struct xe_device *xe = gt_to_xe(gt);
299288
300− xe_pm_runtime_get(xe);
289+ guard(xe_pm_runtime)(xe);
301290 xe_gt_reset(gt);
302− xe_pm_runtime_put(xe);
303291 }
304292
305293 static ssize_t force_reset_sync_write(struct file *file,
drivers/gpu/drm/xe/xe_gt_freq.c+9−18
@@ -70,9 +70,8 @@ static ssize_t act_freq_show(struct kobject *kobj, · 69 unmodified lines
7070 struct xe_guc_pc *pc = dev_to_pc(dev);
7171 u32 freq;
7272
73− xe_pm_runtime_get(dev_to_xe(dev));
73+ guard(xe_pm_runtime)(dev_to_xe(dev));
7474 freq = xe_guc_pc_get_act_freq(pc);
75− xe_pm_runtime_put(dev_to_xe(dev));
7675
7776 return sysfs_emit(buf, "%d\n", freq);
7877 }
@@ -86,9 +85,8 @@ static ssize_t cur_freq_show(struct kobject *kobj, · 7 unmodified lines
8685 u32 freq;
8786 ssize_t ret;
8887
89− xe_pm_runtime_get(dev_to_xe(dev));
88+ guard(xe_pm_runtime)(dev_to_xe(dev));
9089 ret = xe_guc_pc_get_cur_freq(pc, &freq);
91− xe_pm_runtime_put(dev_to_xe(dev));
9290 if (ret)
9391 return ret;
9492
@@ -113,9 +111,8 @@ static ssize_t rpe_freq_show(struct kobject *kobj, · 18 unmodified lines
113111 struct xe_guc_pc *pc = dev_to_pc(dev);
114112 u32 freq;
115113
116− xe_pm_runtime_get(dev_to_xe(dev));
114+ guard(xe_pm_runtime)(dev_to_xe(dev));
117115 freq = xe_guc_pc_get_rpe_freq(pc);
118− xe_pm_runtime_put(dev_to_xe(dev));
119116
120117 return sysfs_emit(buf, "%d\n", freq);
121118 }
@@ -128,9 +125,8 @@ static ssize_t rpa_freq_show(struct kobject *kobj, · 6 unmodified lines
128125 struct xe_guc_pc *pc = dev_to_pc(dev);
129126 u32 freq;
130127
131− xe_pm_runtime_get(dev_to_xe(dev));
128+ guard(xe_pm_runtime)(dev_to_xe(dev));
132129 freq = xe_guc_pc_get_rpa_freq(pc);
133− xe_pm_runtime_put(dev_to_xe(dev));
134130
135131 return sysfs_emit(buf, "%d\n", freq);
136132 }
@@ -154,9 +150,8 @@ static ssize_t min_freq_show(struct kobject *kobj, · 17 unmodified lines
154150 u32 freq;
155151 ssize_t ret;
156152
157− xe_pm_runtime_get(dev_to_xe(dev));
153+ guard(xe_pm_runtime)(dev_to_xe(dev));
158154 ret = xe_guc_pc_get_min_freq(pc, &freq);
159− xe_pm_runtime_put(dev_to_xe(dev));
160155 if (ret)
161156 return ret;
162157
@@ -175,9 +170,8 @@ static ssize_t min_freq_store(struct kobject *kobj, · 12 unmodified lines
175170 if (ret)
176171 return ret;
177172
178− xe_pm_runtime_get(dev_to_xe(dev));
173+ guard(xe_pm_runtime)(dev_to_xe(dev));
179174 ret = xe_guc_pc_set_min_freq(pc, freq);
180− xe_pm_runtime_put(dev_to_xe(dev));
181175 if (ret)
182176 return ret;
183177
@@ -193,9 +187,8 @@ static ssize_t max_freq_show(struct kobject *kobj, · 9 unmodified lines
193187 u32 freq;
194188 ssize_t ret;
195189
196− xe_pm_runtime_get(dev_to_xe(dev));
190+ guard(xe_pm_runtime)(dev_to_xe(dev));
197191 ret = xe_guc_pc_get_max_freq(pc, &freq);
198− xe_pm_runtime_put(dev_to_xe(dev));
199192 if (ret)
200193 return ret;
201194
@@ -214,9 +207,8 @@ static ssize_t max_freq_store(struct kobject *kobj, · 12 unmodified lines
214207 if (ret)
215208 return ret;
216209
217− xe_pm_runtime_get(dev_to_xe(dev));
210+ guard(xe_pm_runtime)(dev_to_xe(dev));
218211 ret = xe_guc_pc_set_max_freq(pc, freq);
219− xe_pm_runtime_put(dev_to_xe(dev));
220212 if (ret)
221213 return ret;
222214
@@ -243,9 +235,8 @@ static ssize_t power_profile_store(struct kobject *kobj, · 20 unmodified lines
243235 struct xe_guc_pc *pc = dev_to_pc(dev);
244236 int err;
245237
246− xe_pm_runtime_get(dev_to_xe(dev));
238+ guard(xe_pm_runtime)(dev_to_xe(dev));
247239 err = xe_guc_pc_set_power_profile(pc, buff);
248− xe_pm_runtime_put(dev_to_xe(dev));
249240
250241 return err ?: count;
251242 }
drivers/gpu/drm/xe/xe_gt_idle.c+12−29
@@ -105,7 +105,6 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt) · 104 unmodified lines
105105 struct xe_gt_idle *gtidle = &gt->gtidle;
106106 struct xe_mmio *mmio = &gt->mmio;
107107 u32 vcs_mask, vecs_mask;
108− unsigned int fw_ref;
109108 int i, j;
110109
111110 if (IS_SRIOV_VF(xe))
@@ -137,7 +136,7 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt) · 25 unmodified lines
137136 }
138137 }
139138
140− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
139+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
141140 if (xe->info.skip_guc_pc) {
142141 /*
143142 * GuC sets the hysteresis value when GuC PC is enabled
@@ -154,13 +153,11 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt) · 10 unmodified lines
154153 VDN_MFXVDENC_POWERGATE_ENABLE(2));
155154
156155 xe_mmio_write32(mmio, POWERGATE_ENABLE, gtidle->powergate_enable);
157− xe_force_wake_put(gt_to_fw(gt), fw_ref);
158156 }
159157
160158 void xe_gt_idle_disable_pg(struct xe_gt *gt)
161159 {
162160 struct xe_gt_idle *gtidle = &gt->gtidle;
163− unsigned int fw_ref;
164161
165162 if (IS_SRIOV_VF(gt_to_xe(gt)))
166163 return;
@@ -168,9 +165,8 @@ void xe_gt_idle_disable_pg(struct xe_gt *gt) · 1 unmodified line
168165 xe_device_assert_mem_access(gt_to_xe(gt));
169166 gtidle->powergate_enable = 0;
170167
171− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
168+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
172169 xe_mmio_write32(&gt->mmio, POWERGATE_ENABLE, gtidle->powergate_enable);
173− xe_force_wake_put(gt_to_fw(gt), fw_ref);
174170 }
175171
176172 /**
@@ -189,7 +185,6 @@ int xe_gt_idle_pg_print(struct xe_gt *gt, struct drm_printer *p) · 12 unmodified lines
189185 enum xe_gt_idle_state state;
190186 u32 pg_enabled, pg_status = 0;
191187 u32 vcs_mask, vecs_mask;
192− unsigned int fw_ref;
193188 int n;
194189 /*
195190 * Media Slices
@@ -226,14 +221,12 @@ int xe_gt_idle_pg_print(struct xe_gt *gt, struct drm_printer *p) · 30 unmodified lines
226221
227222 /* Do not wake the GT to read powergating status */
228223 if (state != GT_IDLE_C6) {
229− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
230− if (!fw_ref)
224+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
225+ if (!fw_ref.domains)
231226 return -ETIMEDOUT;
232227
233228 pg_enabled = xe_mmio_read32(&gt->mmio, POWERGATE_ENABLE);
234229 pg_status = xe_mmio_read32(&gt->mmio, POWERGATE_DOMAIN_STATUS);
235−
236− xe_force_wake_put(gt_to_fw(gt), fw_ref);
237230 }
238231
239232 if (gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK) {
@@ -271,13 +264,9 @@ static ssize_t name_show(struct kobject *kobj, · 31 unmodified lines
271264 struct device *dev = kobj_to_dev(kobj);
272265 struct xe_gt_idle *gtidle = dev_to_gtidle(dev);
273266 struct xe_guc_pc *pc = gtidle_to_pc(gtidle);
274− ssize_t ret;
275−
276− xe_pm_runtime_get(pc_to_xe(pc));
277− ret = sysfs_emit(buff, "%s\n", gtidle->name);
278− xe_pm_runtime_put(pc_to_xe(pc));
279267
280− return ret;
268+ guard(xe_pm_runtime)(pc_to_xe(pc));
269+ return sysfs_emit(buff, "%s\n", gtidle->name);
281270 }
282271 static struct kobj_attribute name_attr = __ATTR_RO(name);
283272
@@ -289,9 +278,8 @@ static ssize_t idle_status_show(struct kobject *kobj, · 5 unmodified lines
289278 struct xe_guc_pc *pc = gtidle_to_pc(gtidle);
290279 enum xe_gt_idle_state state;
291280
292− xe_pm_runtime_get(pc_to_xe(pc));
293− state = gtidle->idle_status(pc);
294− xe_pm_runtime_put(pc_to_xe(pc));
281+ scoped_guard(xe_pm_runtime, pc_to_xe(pc))
282+ state = gtidle->idle_status(pc);
295283
296284 return sysfs_emit(buff, "%s\n", gt_idle_state_to_string(state));
297285 }
@@ -319,9 +307,8 @@ static ssize_t idle_residency_ms_show(struct kobject *kobj, · 21 unmodified lines
319307 struct xe_guc_pc *pc = gtidle_to_pc(gtidle);
320308 u64 residency;
321309
322− xe_pm_runtime_get(pc_to_xe(pc));
323− residency = xe_gt_idle_residency_msec(gtidle);
324− xe_pm_runtime_put(pc_to_xe(pc));
310+ scoped_guard(xe_pm_runtime, pc_to_xe(pc))
311+ residency = xe_gt_idle_residency_msec(gtidle);
325312
326313 return sysfs_emit(buff, "%llu\n", residency);
327314 }
@@ -404,21 +391,17 @@ void xe_gt_idle_enable_c6(struct xe_gt *gt) · 76 unmodified lines
404391
405392 int xe_gt_idle_disable_c6(struct xe_gt *gt)
406393 {
407− unsigned int fw_ref;
408−
409394 xe_device_assert_mem_access(gt_to_xe(gt));
410395
411396 if (IS_SRIOV_VF(gt_to_xe(gt)))
412397 return 0;
413398
414− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
415− if (!fw_ref)
399+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
400+ if (!fw_ref.domains)
416401 return -ETIMEDOUT;
417402
418403 xe_mmio_write32(&gt->mmio, RC_CONTROL, 0);
419404 xe_mmio_write32(&gt->mmio, RC_STATE, 0);
420405
421− xe_force_wake_put(gt_to_fw(gt), fw_ref);
422−
423406 return 0;
424407 }
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c+12−7
@@ -269,7 +269,8 @@ static u32 encode_config_ggtt(u32 *cfg, const struct xe_gt_sriov_config *config, · 268 unmodified lines
269269 }
270270
271271 /* Return: number of configuration dwords written */
272−static u32 encode_config(u32 *cfg, const struct xe_gt_sriov_config *config, bool details)
272+static u32 encode_config(struct xe_gt *gt, u32 *cfg, const struct xe_gt_sriov_config *config,
273+ bool details)
273274 {
274275 u32 n = 0;
275276
@@ -303,9 +304,11 @@ static u32 encode_config(u32 *cfg, const struct xe_gt_sriov_config *config, bool · 27 unmodified lines
303304 cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_PREEMPT_TIMEOUT);
304305 cfg[n++] = config->preempt_timeout;
305306
306−#define encode_threshold_config(TAG, ...) ({ \
307− cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_THRESHOLD_##TAG); \
308− cfg[n++] = config->thresholds[MAKE_XE_GUC_KLV_THRESHOLD_INDEX(TAG)]; \
307+#define encode_threshold_config(TAG, NAME, VER...) ({ \
308+ if (IF_ARGS(GUC_FIRMWARE_VER_AT_LEAST(&gt->uc.guc, VER), true, VER)) { \
309+ cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_THRESHOLD_##TAG); \
310+ cfg[n++] = config->thresholds[MAKE_XE_GUC_KLV_THRESHOLD_INDEX(TAG)]; \
311+ } \
309312 });
310313
311314 MAKE_XE_GUC_KLV_THRESHOLDS_SET(encode_threshold_config);
@@ -328,7 +331,7 @@ static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid) · 16 unmodified lines
328331 return -ENOBUFS;
329332
330333 cfg = xe_guc_buf_cpu_ptr(buf);
331− num_dwords = encode_config(cfg, config, true);
334+ num_dwords = encode_config(gt, cfg, config, true);
332335 xe_gt_assert(gt, num_dwords <= max_cfg_dwords);
333336
334337 if (xe_gt_is_media_type(gt)) {
@@ -2518,7 +2521,7 @@ ssize_t xe_gt_sriov_pf_config_save(struct xe_gt *gt, unsigned int vfid, void *bu · 2183 unmodified lines
25182521 ret = -ENOBUFS;
25192522 } else {
25202523 config = pf_pick_vf_config(gt, vfid);
2521− ret = encode_config(buf, config, false) * sizeof(u32);
2524+ ret = encode_config(gt, buf, config, false) * sizeof(u32);
25222525 }
25232526 }
25242527 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));
@@ -2551,11 +2554,13 @@ static int pf_restore_vf_config_klv(struct xe_gt *gt, unsigned int vfid, · 26 unmodified lines
25512554 return pf_provision_preempt_timeout(gt, vfid, value[0]);
25522555
25532556 /* auto-generate case statements */
2554−#define define_threshold_key_to_provision_case(TAG, ...) \
2557+#define define_threshold_key_to_provision_case(TAG, NAME, VER...) \
25552558 case MAKE_GUC_KLV_VF_CFG_THRESHOLD_KEY(TAG): \
25562559 BUILD_BUG_ON(MAKE_GUC_KLV_VF_CFG_THRESHOLD_LEN(TAG) != 1u); \
25572560 if (len != MAKE_GUC_KLV_VF_CFG_THRESHOLD_LEN(TAG)) \
25582561 return -EBADMSG; \
2562+ if (IF_ARGS(!GUC_FIRMWARE_VER_AT_LEAST(&gt->uc.guc, VER), false, VER)) \
2563+ return -EKEYREJECTED; \
25592564 return pf_provision_threshold(gt, vfid, \
25602565 MAKE_XE_GUC_KLV_THRESHOLD_INDEX(TAG), \
25612566 value[0]);
drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c+10−11
@@ -21,6 +21,7 @@ · 20 unmodified lines
2121 #include "xe_gt_sriov_pf_monitor.h"
2222 #include "xe_gt_sriov_pf_policy.h"
2323 #include "xe_gt_sriov_pf_service.h"
24+#include "xe_guc.h"
2425 #include "xe_pm.h"
2526 #include "xe_sriov_pf.h"
2627 #include "xe_sriov_pf_provision.h"
@@ -123,11 +124,10 @@ static int POLICY##_set(void *data, u64 val) \ · 96 unmodified lines
123124 if (val > (TYPE)~0ull) \
124125 return -EOVERFLOW; \
125126 \
126− xe_pm_runtime_get(xe); \
127+ guard(xe_pm_runtime)(xe); \
127128 err = xe_gt_sriov_pf_policy_set_##POLICY(gt, val); \
128129 if (!err) \
129130 xe_sriov_pf_provision_set_custom_mode(xe); \
130− xe_pm_runtime_put(xe); \
131131 \
132132 return err; \
133133 } \
@@ -189,12 +189,11 @@ static int CONFIG##_set(void *data, u64 val) \ · 55 unmodified lines
189189 if (val > (TYPE)~0ull) \
190190 return -EOVERFLOW; \
191191 \
192− xe_pm_runtime_get(xe); \
192+ guard(xe_pm_runtime)(xe); \
193193 err = xe_sriov_pf_wait_ready(xe) ?: \
194194 xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val); \
195195 if (!err) \
196196 xe_sriov_pf_provision_set_custom_mode(xe); \
197− xe_pm_runtime_put(xe); \
198197 \
199198 return err; \
200199 } \
@@ -249,11 +248,10 @@ static int set_threshold(void *data, u64 val, enum xe_guc_klv_threshold_index in · 48 unmodified lines
249248 if (val > (u32)~0ull)
250249 return -EOVERFLOW;
251250
252− xe_pm_runtime_get(xe);
251+ guard(xe_pm_runtime)(xe);
253252 err = xe_gt_sriov_pf_config_set_threshold(gt, vfid, index, val);
254253 if (!err)
255254 xe_sriov_pf_provision_set_custom_mode(xe);
256− xe_pm_runtime_put(xe);
257255
258256 return err;
259257 }
@@ -304,9 +302,11 @@ static void pf_add_config_attrs(struct xe_gt *gt, struct dentry *parent, unsigne · 44 unmodified lines
304302 &sched_priority_fops);
305303
306304 /* register all threshold attributes */
307−#define register_threshold_attribute(TAG, NAME, ...) \
308− debugfs_create_file_unsafe("threshold_" #NAME, 0644, parent, parent, \
309− &NAME##_fops);
305+#define register_threshold_attribute(TAG, NAME, VER...) ({ \
306+ if (IF_ARGS(GUC_FIRMWARE_VER_AT_LEAST(&gt->uc.guc, VER), true, VER)) \
307+ debugfs_create_file_unsafe("threshold_" #NAME, 0644, parent, parent, \
308+ &NAME##_fops); \
309+});
310310 MAKE_XE_GUC_KLV_THRESHOLDS_SET(register_threshold_attribute)
311311 #undef register_threshold_attribute
312312 }
@@ -358,9 +358,8 @@ static ssize_t control_write(struct file *file, const char __user *buf, size_t c · 45 unmodified lines
358358 xe_gt_assert(gt, sizeof(cmd) > strlen(control_cmds[n].cmd));
359359
360360 if (sysfs_streq(cmd, control_cmds[n].cmd)) {
361− xe_pm_runtime_get(xe);
361+ guard(xe_pm_runtime)(xe);
362362 ret = control_cmds[n].fn ? (*control_cmds[n].fn)(gt, vfid) : 0;
363− xe_pm_runtime_put(xe);
364363 break;
365364 }
366365 }
drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c+1−1
@@ -1026,7 +1026,7 @@ static void action_ring_cleanup(void *arg) · 1025 unmodified lines
10261026
10271027 static void pf_gt_migration_check_support(struct xe_gt *gt)
10281028 {
1029− if (GUC_FIRMWARE_VER(&gt->uc.guc) < MAKE_GUC_VER(70, 54, 0))
1029+ if (!GUC_FIRMWARE_VER_AT_LEAST(&gt->uc.guc, 70, 54))
10301030 xe_sriov_pf_migration_disable(gt_to_xe(gt), "requires GuC version >= 70.54.0");
10311031 }
10321032
drivers/gpu/drm/xe/xe_gt_sriov_vf.c+126−44
@@ -5,6 +5,7 @@ · 4 unmodified lines
55
66 #include <linux/bitfield.h>
77 #include <linux/bsearch.h>
8+#include <linux/delay.h>
89
910 #include <drm/drm_managed.h>
1011 #include <drm/drm_print.h>
@@ -41,6 +42,37 @@ · 30 unmodified lines
4142
4243 #define make_u64_from_u32(hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo)))
4344
45+#ifdef CONFIG_DRM_XE_DEBUG
46+enum VF_MIGRATION_WAIT_POINTS {
47+ VF_MIGRATION_WAIT_RESFIX_START = BIT(0),
48+ VF_MIGRATION_WAIT_FIXUPS = BIT(1),
49+ VF_MIGRATION_WAIT_RESTART_JOBS = BIT(2),
50+ VF_MIGRATION_WAIT_RESFIX_DONE = BIT(3),
51+};
52+
53+#define VF_MIGRATION_WAIT_DELAY_IN_MS 1000
54+static void vf_post_migration_inject_wait(struct xe_gt *gt,
55+ enum VF_MIGRATION_WAIT_POINTS wait)
56+{
57+ while (gt->sriov.vf.migration.debug.resfix_stoppers & wait) {
58+ xe_gt_dbg(gt,
59+ "*TESTING* injecting %u ms delay due to resfix_stoppers=%#x, to continue clear %#x\n",
60+ VF_MIGRATION_WAIT_DELAY_IN_MS,
61+ gt->sriov.vf.migration.debug.resfix_stoppers, wait);
62+
63+ msleep(VF_MIGRATION_WAIT_DELAY_IN_MS);
64+ }
65+}
66+
67+#define VF_MIGRATION_INJECT_WAIT(gt, _POS) ({ \
68+ struct xe_gt *__gt = (gt); \
69+ vf_post_migration_inject_wait(__gt, VF_MIGRATION_WAIT_##_POS); \
70+ })
71+
72+#else
73+#define VF_MIGRATION_INJECT_WAIT(_gt, ...) typecheck(struct xe_gt *, (_gt))
74+#endif
75+
4476 static int guc_action_vf_reset(struct xe_guc *guc)
4577 {
4678 u32 request[GUC_HXG_REQUEST_MSG_MIN_LEN] = {
@@ -299,12 +331,13 @@ void xe_gt_sriov_vf_guc_versions(struct xe_gt *gt, · 252 unmodified lines
299331 *found = gt->sriov.vf.guc_version;
300332 }
301333
302−static int guc_action_vf_notify_resfix_done(struct xe_guc *guc)
334+static int guc_action_vf_resfix_start(struct xe_guc *guc, u16 marker)
303335 {
304336 u32 request[GUC_HXG_REQUEST_MSG_MIN_LEN] = {
305337 FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
306338 FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) |
307− FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_ACTION_VF2GUC_NOTIFY_RESFIX_DONE),
339+ FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_ACTION_VF2GUC_RESFIX_START) |
340+ FIELD_PREP(VF2GUC_RESFIX_START_REQUEST_MSG_0_MARKER, marker),
308341 };
309342 int ret;
310343
@@ -313,28 +346,43 @@ static int guc_action_vf_notify_resfix_done(struct xe_guc *guc) · 2 unmodified lines
313346 return ret > 0 ? -EPROTO : ret;
314347 }
315348
316−/**
317− * vf_notify_resfix_done - Notify GuC about resource fixups apply completed.
318− * @gt: the &xe_gt struct instance linked to target GuC
319− *
320− * Returns: 0 if the operation completed successfully, or a negative error
321− * code otherwise.
322− */
323−static int vf_notify_resfix_done(struct xe_gt *gt)
349+static int vf_resfix_start(struct xe_gt *gt, u16 marker)
324350 {
325351 struct xe_guc *guc = &gt->uc.guc;
326− int err;
327352
328353 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt)));
329354
330− err = guc_action_vf_notify_resfix_done(guc);
331− if (unlikely(err))
332− xe_gt_sriov_err(gt, "Failed to notify GuC about resource fixup done (%pe)\n",
333− ERR_PTR(err));
334− else
335− xe_gt_sriov_dbg_verbose(gt, "sent GuC resource fixup done\n");
355+ VF_MIGRATION_INJECT_WAIT(gt, RESFIX_START);
336356
337− return err;
357+ xe_gt_sriov_dbg_verbose(gt, "Sending resfix start marker %u\n", marker);
358+
359+ return guc_action_vf_resfix_start(guc, marker);
360+}
361+
362+static int guc_action_vf_resfix_done(struct xe_guc *guc, u16 marker)
363+{
364+ u32 request[GUC_HXG_REQUEST_MSG_MIN_LEN] = {
365+ FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
366+ FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) |
367+ FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_ACTION_VF2GUC_RESFIX_DONE) |
368+ FIELD_PREP(VF2GUC_RESFIX_DONE_REQUEST_MSG_0_MARKER, marker),
369+ };
370+ int ret;
371+
372+ ret = xe_guc_mmio_send(guc, request, ARRAY_SIZE(request));
373+
374+ return ret > 0 ? -EPROTO : ret;
375+}
376+
377+static int vf_resfix_done(struct xe_gt *gt, u16 marker)
378+{
379+ struct xe_guc *guc = &gt->uc.guc;
380+
381+ xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt)));
382+
383+ xe_gt_sriov_dbg_verbose(gt, "Sending resfix done marker %u\n", marker);
384+
385+ return guc_action_vf_resfix_done(guc, marker);
338386 }
339387
340388 static int guc_action_query_single_klv(struct xe_guc *guc, u32 key,
@@ -1123,12 +1171,8 @@ static bool vf_post_migration_shutdown(struct xe_gt *gt) · 782 unmodified lines
11231171 return true;
11241172 }
11251173
1126− spin_lock_irq(&gt->sriov.vf.migration.lock);
1127− gt->sriov.vf.migration.recovery_queued = false;
1128− spin_unlock_irq(&gt->sriov.vf.migration.lock);
1129−
11301174 xe_guc_ct_flush_and_stop(&gt->uc.guc.ct);
1131− xe_guc_submit_pause(&gt->uc.guc);
1175+ xe_guc_submit_pause_vf(&gt->uc.guc);
11321176 xe_tlb_inval_reset(&gt->tlb_inval);
11331177
11341178 return false;
@@ -1144,6 +1188,8 @@ static int vf_post_migration_fixups(struct xe_gt *gt) · 9 unmodified lines
11441188 void *buf = gt->sriov.vf.migration.scratch;
11451189 int err;
11461190
1191+ VF_MIGRATION_INJECT_WAIT(gt, FIXUPS);
1192+
11471193 /* xe_gt_sriov_vf_query_config will fixup the GGTT addresses */
11481194 err = xe_gt_sriov_vf_query_config(gt);
11491195 if (err)
@@ -1162,13 +1208,22 @@ static int vf_post_migration_fixups(struct xe_gt *gt) · 12 unmodified lines
11621208
11631209 static void vf_post_migration_rearm(struct xe_gt *gt)
11641210 {
1211+ VF_MIGRATION_INJECT_WAIT(gt, RESTART_JOBS);
1212+
1213+ /*
1214+ * Make sure interrupts on the new HW are properly set. The GuC IRQ
1215+ * must be working at this point, since the recovery did started,
1216+ * but the rest was not enabled using the procedure from spec.
1217+ */
1218+ xe_irq_resume(gt_to_xe(gt));
1219+
11651220 xe_guc_ct_restart(&gt->uc.guc.ct);
1166− xe_guc_submit_unpause_prepare(&gt->uc.guc);
1221+ xe_guc_submit_unpause_prepare_vf(&gt->uc.guc);
11671222 }
11681223
11691224 static void vf_post_migration_kickstart(struct xe_gt *gt)
11701225 {
1171− xe_guc_submit_unpause(&gt->uc.guc);
1226+ xe_guc_submit_unpause_vf(&gt->uc.guc);
11721227 }
11731228
11741229 static void vf_post_migration_abort(struct xe_gt *gt)
@@ -1183,37 +1238,49 @@ static void vf_post_migration_abort(struct xe_gt *gt) · 8 unmodified lines
11831238 xe_guc_submit_pause_abort(&gt->uc.guc);
11841239 }
11851240
1186−static int vf_post_migration_notify_resfix_done(struct xe_gt *gt)
1241+static int vf_post_migration_resfix_done(struct xe_gt *gt, u16 marker)
11871242 {
1188− bool skip_resfix = false;
1243+ VF_MIGRATION_INJECT_WAIT(gt, RESFIX_DONE);
11891244
11901245 spin_lock_irq(&gt->sriov.vf.migration.lock);
1191− if (gt->sriov.vf.migration.recovery_queued) {
1192− skip_resfix = true;
1193− xe_gt_sriov_dbg(gt, "another recovery imminent, resfix skipped\n");
1194− } else {
1246+ if (gt->sriov.vf.migration.recovery_queued)
1247+ xe_gt_sriov_dbg(gt, "another recovery imminent\n");
1248+ else
11951249 WRITE_ONCE(gt->sriov.vf.migration.recovery_inprogress, false);
1196− }
11971250 spin_unlock_irq(&gt->sriov.vf.migration.lock);
11981251
1199− if (skip_resfix)
1200− return -EAGAIN;
1252+ return vf_resfix_done(gt, marker);
1253+}
12011254
1202− /*
1203− * Make sure interrupts on the new HW are properly set. The GuC IRQ
1204− * must be working at this point, since the recovery did started,
1205− * but the rest was not enabled using the procedure from spec.
1206− */
1207− xe_irq_resume(gt_to_xe(gt));
1255+static int vf_post_migration_resfix_start(struct xe_gt *gt, u16 marker)
1256+{
1257+ int err;
1258+
1259+ err = vf_resfix_start(gt, marker);
12081260
1209− return vf_notify_resfix_done(gt);
1261+ guard(spinlock_irq) (&gt->sriov.vf.migration.lock);
1262+ gt->sriov.vf.migration.recovery_queued = false;
1263+
1264+ return err;
1265+}
1266+
1267+static u16 vf_post_migration_next_resfix_marker(struct xe_gt *gt)
1268+{
1269+ xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt)));
1270+
1271+ BUILD_BUG_ON(1 + ((typeof(gt->sriov.vf.migration.resfix_marker))~0) >
1272+ FIELD_MAX(VF2GUC_RESFIX_START_REQUEST_MSG_0_MARKER));
1273+
1274+ /* add 1 to avoid zero-marker */
1275+ return 1 + gt->sriov.vf.migration.resfix_marker++;
12101276 }
12111277
12121278 static void vf_post_migration_recovery(struct xe_gt *gt)
12131279 {
12141280 struct xe_device *xe = gt_to_xe(gt);
1215− int err;
1281+ u16 marker;
12161282 bool retry;
1283+ int err;
12171284
12181285 xe_gt_sriov_dbg(gt, "migration recovery in progress\n");
12191286
@@ -1227,15 +1294,30 @@ static void vf_post_migration_recovery(struct xe_gt *gt) · 7 unmodified lines
12271294 goto fail;
12281295 }
12291296
1297+ marker = vf_post_migration_next_resfix_marker(gt);
1298+
1299+ err = vf_post_migration_resfix_start(gt, marker);
1300+ if (unlikely(err)) {
1301+ xe_gt_sriov_err(gt, "Recovery failed at GuC RESFIX_START step (%pe)\n",
1302+ ERR_PTR(err));
1303+ goto fail;
1304+ }
1305+
12301306 err = vf_post_migration_fixups(gt);
12311307 if (err)
12321308 goto fail;
12331309
12341310 vf_post_migration_rearm(gt);
12351311
1236− err = vf_post_migration_notify_resfix_done(gt);
1237− if (err && err != -EAGAIN)
1312+ err = vf_post_migration_resfix_done(gt, marker);
1313+ if (err) {
1314+ if (err == -EREMCHG)
1315+ goto queue;
1316+
1317+ xe_gt_sriov_err(gt, "Recovery failed at GuC RESFIX_DONE step (%pe)\n",
1318+ ERR_PTR(err));
12381319 goto fail;
1320+ }
12391321
12401322 vf_post_migration_kickstart(gt);
12411323
drivers/gpu/drm/xe/xe_gt_sriov_vf_debugfs.c+12−0
@@ -69,4 +69,16 @@ void xe_gt_sriov_vf_debugfs_register(struct xe_gt *gt, struct dentry *root) · 68 unmodified lines
6969 vfdentry->d_inode->i_private = gt;
7070
7171 drm_debugfs_create_files(vf_info, ARRAY_SIZE(vf_info), vfdentry, minor);
72+
73+ /*
74+ * /sys/kernel/debug/dri/BDF/
75+ * ├── tile0
76+ * ├── gt0
77+ * ├── vf
78+ * ├── resfix_stoppers
79+ */
80+ if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) {
81+ debugfs_create_x8("resfix_stoppers", 0600, vfdentry,
82+ &gt->sriov.vf.migration.debug.resfix_stoppers);
83+ }
7284 }
drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h+13−0
@@ -52,6 +52,19 @@ struct xe_gt_sriov_vf_migration { · 51 unmodified lines
5252 wait_queue_head_t wq;
5353 /** @scratch: Scratch memory for VF recovery */
5454 void *scratch;
55+ /** @debug: Debug hooks for delaying migration */
56+ struct {
57+ /**
58+ * @debug.resfix_stoppers: Stop and wait at different stages
59+ * during post migration recovery
60+ */
61+ u8 resfix_stoppers;
62+ } debug;
63+ /**
64+ * @resfix_marker: Marker sent on start and on end of post-migration
65+ * steps.
66+ */
67+ u8 resfix_marker;
5568 /** @recovery_teardown: VF post migration recovery is being torn down */
5669 bool recovery_teardown;
5770 /** @recovery_queued: VF post migration recovery in queued */
drivers/gpu/drm/xe/xe_gt_stats.c+10−0
@@ -66,6 +66,16 @@ static const char *const stat_description[__XE_GT_STATS_NUM_IDS] = { · 65 unmodified lines
6666 DEF_STAT_STR(SVM_4K_BIND_US, "svm_4K_bind_us"),
6767 DEF_STAT_STR(SVM_64K_BIND_US, "svm_64K_bind_us"),
6868 DEF_STAT_STR(SVM_2M_BIND_US, "svm_2M_bind_us"),
69+ DEF_STAT_STR(HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_COUNT,
70+ "hw_engine_group_suspend_lr_queue_count"),
71+ DEF_STAT_STR(HW_ENGINE_GROUP_SKIP_LR_QUEUE_COUNT,
72+ "hw_engine_group_skip_lr_queue_count"),
73+ DEF_STAT_STR(HW_ENGINE_GROUP_WAIT_DMA_QUEUE_COUNT,
74+ "hw_engine_group_wait_dma_queue_count"),
75+ DEF_STAT_STR(HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_US,
76+ "hw_engine_group_suspend_lr_queue_us"),
77+ DEF_STAT_STR(HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US,
78+ "hw_engine_group_wait_dma_queue_us"),
6979 };
7080
7181 /**
drivers/gpu/drm/xe/xe_gt_stats.h+32−0
@@ -6,6 +6,8 @@ · 5 unmodified lines
66 #ifndef _XE_GT_STATS_H_
77 #define _XE_GT_STATS_H_
88
9+#include <linux/ktime.h>
10+
911 #include "xe_gt_stats_types.h"
1012
1113 struct xe_gt;
@@ -23,4 +25,34 @@ xe_gt_stats_incr(struct xe_gt *gt, const enum xe_gt_stats_id id, · 11 unmodified lines
2325 }
2426
2527 #endif
28+
29+/**
30+ * xe_gt_stats_ktime_us_delta() - Get delta in microseconds between now and a
31+ * start time
32+ * @start: Start time
33+ *
34+ * Helper for GT stats to get delta in microseconds between now and a start
35+ * time, compiles out if GT stats are disabled.
36+ *
37+ * Return: Delta in microseconds between now and a start time
38+ */
39+static inline s64 xe_gt_stats_ktime_us_delta(ktime_t start)
40+{
41+ return IS_ENABLED(CONFIG_DEBUG_FS) ?
42+ ktime_us_delta(ktime_get(), start) : 0;
43+}
44+
45+/**
46+ * xe_gt_stats_ktime_get() - Get current ktime
47+ *
48+ * Helper for GT stats to get current ktime, compiles out if GT stats are
49+ * disabled.
50+ *
51+ * Return: Get current ktime
52+ */
53+static inline ktime_t xe_gt_stats_ktime_get(void)
54+{
55+ return IS_ENABLED(CONFIG_DEBUG_FS) ? ktime_get() : 0;
56+}
57+
2658 #endif
drivers/gpu/drm/xe/xe_gt_stats_types.h+5−0
@@ -44,6 +44,11 @@ enum xe_gt_stats_id { · 43 unmodified lines
4444 XE_GT_STATS_ID_SVM_4K_BIND_US,
4545 XE_GT_STATS_ID_SVM_64K_BIND_US,
4646 XE_GT_STATS_ID_SVM_2M_BIND_US,
47+ XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_COUNT,
48+ XE_GT_STATS_ID_HW_ENGINE_GROUP_SKIP_LR_QUEUE_COUNT,
49+ XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_COUNT,
50+ XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_US,
51+ XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US,
4752 /* must be the last entry */
4853 __XE_GT_STATS_NUM_IDS,
4954 };
drivers/gpu/drm/xe/xe_gt_throttle.c+3−6
@@ -85,7 +85,7 @@ u32 xe_gt_throttle_get_limit_reasons(struct xe_gt *gt) · 84 unmodified lines
8585 {
8686 struct xe_device *xe = gt_to_xe(gt);
8787 struct xe_reg reg;
88− u32 val, mask;
88+ u32 mask;
8989
9090 if (xe_gt_is_media_type(gt))
9191 reg = MTL_MEDIA_PERF_LIMIT_REASONS;
@@ -97,11 +97,8 @@ u32 xe_gt_throttle_get_limit_reasons(struct xe_gt *gt) · 5 unmodified lines
9797 else
9898 mask = GT0_PERF_LIMIT_REASONS_MASK;
9999
100− xe_pm_runtime_get(xe);
101− val = xe_mmio_read32(&gt->mmio, reg) & mask;
102− xe_pm_runtime_put(xe);
103−
104− return val;
100+ guard(xe_pm_runtime)(xe);
101+ return xe_mmio_read32(&gt->mmio, reg) & mask;
105102 }
106103
107104 static bool is_throttled_by(struct xe_gt *gt, u32 mask)
drivers/gpu/drm/xe/xe_gt_types.h+5−0
@@ -140,6 +140,11 @@ struct xe_gt { · 139 unmodified lines
140140 u64 engine_mask;
141141 /** @info.gmdid: raw GMD_ID value from hardware */
142142 u32 gmdid;
143+ /**
144+ * @multi_queue_engine_class_mask: Bitmask of engine classes with
145+ * multi queue support enabled.
146+ */
147+ u16 multi_queue_engine_class_mask;
143148 /** @info.id: Unique ID of this GT within the PCI Device */
144149 u8 id;
145150 /** @info.has_indirect_ring_state: GT has indirect ring state support */
drivers/gpu/drm/xe/xe_guc.c+60−20
@@ -104,7 +104,7 @@ static u32 guc_ctl_log_params_flags(struct xe_guc *guc) · 103 unmodified lines
104104 u32 offset = guc_bo_ggtt_addr(guc, guc->log.bo) >> PAGE_SHIFT;
105105 u32 flags;
106106
107− #if (((CRASH_BUFFER_SIZE) % SZ_1M) == 0)
107+ #if (((XE_GUC_LOG_CRASH_DUMP_BUFFER_SIZE) % SZ_1M) == 0)
108108 #define LOG_UNIT SZ_1M
109109 #define LOG_FLAG GUC_LOG_LOG_ALLOC_UNITS
110110 #else
@@ -112,7 +112,7 @@ static u32 guc_ctl_log_params_flags(struct xe_guc *guc) · 1 unmodified line
112112 #define LOG_FLAG 0
113113 #endif
114114
115− #if (((CAPTURE_BUFFER_SIZE) % SZ_1M) == 0)
115+ #if (((XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE) % SZ_1M) == 0)
116116 #define CAPTURE_UNIT SZ_1M
117117 #define CAPTURE_FLAG GUC_LOG_CAPTURE_ALLOC_UNITS
118118 #else
@@ -120,20 +120,21 @@ static u32 guc_ctl_log_params_flags(struct xe_guc *guc) · 1 unmodified line
120120 #define CAPTURE_FLAG 0
121121 #endif
122122
123− BUILD_BUG_ON(!CRASH_BUFFER_SIZE);
124− BUILD_BUG_ON(!IS_ALIGNED(CRASH_BUFFER_SIZE, LOG_UNIT));
125− BUILD_BUG_ON(!DEBUG_BUFFER_SIZE);
126− BUILD_BUG_ON(!IS_ALIGNED(DEBUG_BUFFER_SIZE, LOG_UNIT));
127− BUILD_BUG_ON(!CAPTURE_BUFFER_SIZE);
128− BUILD_BUG_ON(!IS_ALIGNED(CAPTURE_BUFFER_SIZE, CAPTURE_UNIT));
123+ BUILD_BUG_ON(!XE_GUC_LOG_CRASH_DUMP_BUFFER_SIZE);
124+ BUILD_BUG_ON(!IS_ALIGNED(XE_GUC_LOG_CRASH_DUMP_BUFFER_SIZE, LOG_UNIT));
125+ BUILD_BUG_ON(!XE_GUC_LOG_EVENT_DATA_BUFFER_SIZE);
126+ BUILD_BUG_ON(!IS_ALIGNED(XE_GUC_LOG_EVENT_DATA_BUFFER_SIZE, LOG_UNIT));
127+ BUILD_BUG_ON(!XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE);
128+ BUILD_BUG_ON(!IS_ALIGNED(XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE, CAPTURE_UNIT));
129129
130130 flags = GUC_LOG_VALID |
131131 GUC_LOG_NOTIFY_ON_HALF_FULL |
132132 CAPTURE_FLAG |
133133 LOG_FLAG |
134− FIELD_PREP(GUC_LOG_CRASH, CRASH_BUFFER_SIZE / LOG_UNIT - 1) |
135− FIELD_PREP(GUC_LOG_DEBUG, DEBUG_BUFFER_SIZE / LOG_UNIT - 1) |
136− FIELD_PREP(GUC_LOG_CAPTURE, CAPTURE_BUFFER_SIZE / CAPTURE_UNIT - 1) |
134+ FIELD_PREP(GUC_LOG_CRASH_DUMP, XE_GUC_LOG_CRASH_DUMP_BUFFER_SIZE / LOG_UNIT - 1) |
135+ FIELD_PREP(GUC_LOG_EVENT_DATA, XE_GUC_LOG_EVENT_DATA_BUFFER_SIZE / LOG_UNIT - 1) |
136+ FIELD_PREP(GUC_LOG_STATE_CAPTURE, XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE /
137+ CAPTURE_UNIT - 1) |
137138 FIELD_PREP(GUC_LOG_BUF_ADDR, offset);
138139
139140 #undef LOG_UNIT
@@ -660,11 +661,9 @@ static void guc_fini_hw(void *arg) · 520 unmodified lines
660661 {
661662 struct xe_guc *guc = arg;
662663 struct xe_gt *gt = guc_to_gt(guc);
663− unsigned int fw_ref;
664664
665− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
666− xe_uc_sanitize_reset(&guc_to_gt(guc)->uc);
667− xe_force_wake_put(gt_to_fw(gt), fw_ref);
665+ xe_with_force_wake(fw_ref, gt_to_fw(gt), XE_FORCEWAKE_ALL)
666+ xe_uc_sanitize_reset(&guc_to_gt(guc)->uc);
668667
669668 guc_g2g_fini(guc);
670669 }
@@ -768,6 +767,10 @@ int xe_guc_init(struct xe_guc *guc) · 97 unmodified lines
768767 if (!xe_uc_fw_is_enabled(&guc->fw))
769768 return 0;
770769
770+ /* Disable page reclaim if GuC FW does not support */
771+ if (GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 14, 0))
772+ xe->info.has_page_reclaim_hw_assist = false;
773+
771774 if (IS_SRIOV_VF(xe)) {
772775 ret = xe_guc_ct_init(&guc->ct);
773776 if (ret)
@@ -1485,6 +1488,12 @@ timeout: · 711 unmodified lines
14851488 u32 hint = FIELD_GET(GUC_HXG_FAILURE_MSG_0_HINT, header);
14861489 u32 error = FIELD_GET(GUC_HXG_FAILURE_MSG_0_ERROR, header);
14871490
1491+ if (unlikely(error == XE_GUC_RESPONSE_VF_MIGRATED)) {
1492+ xe_gt_dbg(gt, "GuC mmio request %#x rejected due to MIGRATION (hint %#x)\n",
1493+ request[0], hint);
1494+ return -EREMCHG;
1495+ }
1496+
14881497 xe_gt_err(gt, "GuC mmio request %#x: failure %#x hint %#x\n",
14891498 request[0], error, hint);
14901499 return -ENXIO;
@@ -1618,18 +1627,51 @@ int xe_guc_start(struct xe_guc *guc) · 127 unmodified lines
16181627 return xe_guc_submit_start(guc);
16191628 }
16201629
1630+/**
1631+ * xe_guc_runtime_suspend() - GuC runtime suspend
1632+ * @guc: The GuC object
1633+ *
1634+ * Stop further runs of submission tasks on given GuC and runtime suspend
1635+ * GuC CT.
1636+ */
1637+void xe_guc_runtime_suspend(struct xe_guc *guc)
1638+{
1639+ xe_guc_submit_pause(guc);
1640+ xe_guc_submit_disable(guc);
1641+ xe_guc_ct_runtime_suspend(&guc->ct);
1642+}
1643+
1644+/**
1645+ * xe_guc_runtime_resume() - GuC runtime resume
1646+ * @guc: The GuC object
1647+ *
1648+ * Runtime resume GuC CT and allow further runs of submission tasks on
1649+ * given GuC.
1650+ */
1651+void xe_guc_runtime_resume(struct xe_guc *guc)
1652+{
1653+ /*
1654+ * Runtime PM flows are not applicable for VFs, so it's safe to
1655+ * directly enable IRQ.
1656+ */
1657+ guc_enable_irq(guc);
1658+
1659+ xe_guc_ct_runtime_resume(&guc->ct);
1660+ xe_guc_submit_enable(guc);
1661+ xe_guc_submit_unpause(guc);
1662+}
1663+
16211664 void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p)
16221665 {
16231666 struct xe_gt *gt = guc_to_gt(guc);
1624− unsigned int fw_ref;
16251667 u32 status;
16261668 int i;
16271669
16281670 xe_uc_fw_print(&guc->fw, p);
16291671
16301672 if (!IS_SRIOV_VF(gt_to_xe(gt))) {
1631− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
1632− if (!fw_ref)
1673+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
1674+ if (!fw_ref.domains)
16331675 return;
16341676
16351677 status = xe_mmio_read32(&gt->mmio, GUC_STATUS);
@@ -1649,8 +1691,6 @@ void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p) · 13 unmodified lines
16491691 drm_printf(p, "\t%2d: \t0x%x\n",
16501692 i, xe_mmio_read32(&gt->mmio, SOFT_SCRATCH(i)));
16511693 }
1652−
1653− xe_force_wake_put(gt_to_fw(gt), fw_ref);
16541694 }
16551695
16561696 drm_puts(p, "\n");
drivers/gpu/drm/xe/xe_guc.h+23−0
@@ -18,10 +18,16 @@ · 17 unmodified lines
1818 */
1919 #define MAKE_GUC_VER(maj, min, pat) (((maj) << 16) | ((min) << 8) | (pat))
2020 #define MAKE_GUC_VER_STRUCT(ver) MAKE_GUC_VER((ver).major, (ver).minor, (ver).patch)
21+#define MAKE_GUC_VER_ARGS(ver...) \
22+ (BUILD_BUG_ON_ZERO(COUNT_ARGS(ver) < 2 || COUNT_ARGS(ver) > 3) + \
23+ MAKE_GUC_VER(PICK_ARG1(ver), PICK_ARG2(ver), IF_ARGS(PICK_ARG3(ver), 0, PICK_ARG3(ver))))
24+
2125 #define GUC_SUBMIT_VER(guc) \
2226 MAKE_GUC_VER_STRUCT((guc)->fw.versions.found[XE_UC_FW_VER_COMPATIBILITY])
2327 #define GUC_FIRMWARE_VER(guc) \
2428 MAKE_GUC_VER_STRUCT((guc)->fw.versions.found[XE_UC_FW_VER_RELEASE])
29+#define GUC_FIRMWARE_VER_AT_LEAST(guc, ver...) \
30+ xe_guc_fw_version_at_least((guc), MAKE_GUC_VER_ARGS(ver))
2531
2632 struct drm_printer;
2733
@@ -35,6 +41,8 @@ int xe_guc_upload(struct xe_guc *guc); · 7 unmodified lines
3541 int xe_guc_min_load_for_hwconfig(struct xe_guc *guc);
3642 int xe_guc_enable_communication(struct xe_guc *guc);
3743 int xe_guc_opt_in_features_enable(struct xe_guc *guc);
44+void xe_guc_runtime_suspend(struct xe_guc *guc);
45+void xe_guc_runtime_resume(struct xe_guc *guc);
3846 int xe_guc_suspend(struct xe_guc *guc);
3947 void xe_guc_notify(struct xe_guc *guc);
4048 int xe_guc_auth_huc(struct xe_guc *guc, u32 rsa_addr);
@@ -94,4 +102,19 @@ static inline struct drm_device *guc_to_drm(struct xe_guc *guc) · 53 unmodified lines
94102 return &guc_to_xe(guc)->drm;
95103 }
96104
105+/**
106+ * xe_guc_fw_version_at_least() - Check if GuC is at least of given version.
107+ * @guc: the &xe_guc
108+ * @ver: the version to check
109+ *
110+ * The @ver should be prepared using MAKE_GUC_VER(major, minor, patch).
111+ *
112+ * Return: true if loaded GuC firmware is at least of given version,
113+ * false otherwise.
114+ */
115+static inline bool xe_guc_fw_version_at_least(const struct xe_guc *guc, u32 ver)
116+{
117+ return GUC_FIRMWARE_VER(guc) >= ver;
118+}
119+
97120 #endif
drivers/gpu/drm/xe/xe_guc_ads.c+3−3
@@ -317,7 +317,7 @@ static void guc_waklv_init(struct xe_guc_ads *ads) · 316 unmodified lines
317317 offset = guc_ads_waklv_offset(ads);
318318 remain = guc_ads_waklv_size(ads);
319319
320− if (XE_GT_WA(gt, 14019882105) || XE_GT_WA(gt, 16021333562))
320+ if (XE_GT_WA(gt, 16021333562))
321321 guc_waklv_enable(ads, NULL, 0, &offset, &remain,
322322 GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED);
323323 if (XE_GT_WA(gt, 18024947630))
@@ -347,10 +347,10 @@ static void guc_waklv_init(struct xe_guc_ads *ads) · 23 unmodified lines
347347 guc_waklv_enable(ads, NULL, 0, &offset, &remain,
348348 GUC_WORKAROUND_KLV_ID_BACK_TO_BACK_RCS_ENGINE_RESET);
349349
350− if (GUC_FIRMWARE_VER(&gt->uc.guc) >= MAKE_GUC_VER(70, 44, 0) && XE_GT_WA(gt, 16026508708))
350+ if (GUC_FIRMWARE_VER_AT_LEAST(&gt->uc.guc, 70, 44) && XE_GT_WA(gt, 16026508708))
351351 guc_waklv_enable(ads, NULL, 0, &offset, &remain,
352352 GUC_WA_KLV_RESET_BB_STACK_PTR_ON_VF_SWITCH);
353− if (GUC_FIRMWARE_VER(&gt->uc.guc) >= MAKE_GUC_VER(70, 47, 0) && XE_GT_WA(gt, 16026007364)) {
353+ if (GUC_FIRMWARE_VER_AT_LEAST(&gt->uc.guc, 70, 47) && XE_GT_WA(gt, 16026007364)) {
354354 u32 data[] = {
355355 0x0,
356356 0xF,
drivers/gpu/drm/xe/xe_guc_buf.c+1−1
@@ -30,7 +30,7 @@ static int guc_buf_cache_init(struct xe_guc_buf_cache *cache, u32 size) · 29 unmodified lines
3030 struct xe_gt *gt = cache_to_gt(cache);
3131 struct xe_sa_manager *sam;
3232
33− sam = __xe_sa_bo_manager_init(gt_to_tile(gt), size, 0, sizeof(u32));
33+ sam = __xe_sa_bo_manager_init(gt_to_tile(gt), size, 0, sizeof(u32), 0);
3434 if (IS_ERR(sam))
3535 return PTR_ERR(sam);
3636 cache->sam = sam;
drivers/gpu/drm/xe/xe_guc_capture.c+8−8
@@ -843,7 +843,7 @@ static void check_guc_capture_size(struct xe_guc *guc) · 842 unmodified lines
843843 {
844844 int capture_size = guc_capture_output_size_est(guc);
845845 int spare_size = capture_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER;
846− u32 buffer_size = xe_guc_log_section_size_capture(&guc->log);
846+ u32 buffer_size = XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE;
847847
848848 /*
849849 * NOTE: capture_size is much smaller than the capture region
@@ -949,7 +949,7 @@ guc_capture_init_node(struct xe_guc *guc, struct __guc_capture_parsed_output *no · 99 unmodified lines
949949 * ADS module also calls separately for PF vs VF.
950950 *
951951 * --> alloc B: GuC output capture buf (registered via guc_init_params(log_param))
952− * Size = #define CAPTURE_BUFFER_SIZE (warns if on too-small)
952+ * Size = XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE (warns if on too-small)
953953 * Note2: 'x 3' to hold multiple capture groups
954954 *
955955 * GUC Runtime notify capture:
@@ -1367,7 +1367,7 @@ static int __guc_capture_flushlog_complete(struct xe_guc *guc) · 411 unmodified lines
13671367 {
13681368 u32 action[] = {
13691369 XE_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE,
1370− GUC_LOG_BUFFER_CAPTURE
1370+ GUC_LOG_TYPE_STATE_CAPTURE
13711371 };
13721372
13731373 return xe_guc_ct_send_g2h_handler(&guc->ct, action, ARRAY_SIZE(action));
@@ -1384,8 +1384,8 @@ static void __guc_capture_process_output(struct xe_guc *guc) · 10 unmodified lines
13841384 u32 log_buf_state_offset;
13851385 u32 src_data_offset;
13861386
1387− log_buf_state_offset = sizeof(struct guc_log_buffer_state) * GUC_LOG_BUFFER_CAPTURE;
1388− src_data_offset = xe_guc_get_log_buffer_offset(&guc->log, GUC_LOG_BUFFER_CAPTURE);
1387+ log_buf_state_offset = sizeof(struct guc_log_buffer_state) * GUC_LOG_TYPE_STATE_CAPTURE;
1388+ src_data_offset = XE_GUC_LOG_STATE_CAPTURE_OFFSET;
13891389
13901390 /*
13911391 * Make a copy of the state structure, inside GuC log buffer
@@ -1395,15 +1395,15 @@ static void __guc_capture_process_output(struct xe_guc *guc) · 3 unmodified lines
13951395 xe_map_memcpy_from(guc_to_xe(guc), &log_buf_state_local, &guc->log.bo->vmap,
13961396 log_buf_state_offset, sizeof(struct guc_log_buffer_state));
13971397
1398− buffer_size = xe_guc_get_log_buffer_size(&guc->log, GUC_LOG_BUFFER_CAPTURE);
1398+ buffer_size = XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE;
13991399 read_offset = log_buf_state_local.read_ptr;
14001400 write_offset = log_buf_state_local.sampled_write_ptr;
14011401 full_count = FIELD_GET(GUC_LOG_BUFFER_STATE_BUFFER_FULL_CNT, log_buf_state_local.flags);
14021402
14031403 /* Bookkeeping stuff */
14041404 tmp = FIELD_GET(GUC_LOG_BUFFER_STATE_FLUSH_TO_FILE, log_buf_state_local.flags);
1405− guc->log.stats[GUC_LOG_BUFFER_CAPTURE].flush += tmp;
1406− new_overflow = xe_guc_check_log_buf_overflow(&guc->log, GUC_LOG_BUFFER_CAPTURE,
1405+ guc->log.stats[GUC_LOG_TYPE_STATE_CAPTURE].flush += tmp;
1406+ new_overflow = xe_guc_check_log_buf_overflow(&guc->log, GUC_LOG_TYPE_STATE_CAPTURE,
14071407 full_count);
14081408
14091409 /* Now copy the actual logs. */
drivers/gpu/drm/xe/xe_guc_ct.c+170−103
@@ -42,6 +42,21 @@ static void ct_exit_safe_mode(struct xe_guc_ct *ct); · 41 unmodified lines
4242 static void guc_ct_change_state(struct xe_guc_ct *ct,
4343 enum xe_guc_ct_state state);
4444
45+static struct xe_guc *ct_to_guc(struct xe_guc_ct *ct)
46+{
47+ return container_of(ct, struct xe_guc, ct);
48+}
49+
50+static struct xe_gt *ct_to_gt(struct xe_guc_ct *ct)
51+{
52+ return container_of(ct, struct xe_gt, uc.guc.ct);
53+}
54+
55+static struct xe_device *ct_to_xe(struct xe_guc_ct *ct)
56+{
57+ return gt_to_xe(ct_to_gt(ct));
58+}
59+
4560 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
4661 enum {
4762 /* Internal states, not error conditions */
@@ -68,14 +83,101 @@ enum { · 20 unmodified lines
6883 static void ct_dead_worker_func(struct work_struct *w);
6984 static void ct_dead_capture(struct xe_guc_ct *ct, struct guc_ctb *ctb, u32 reason_code);
7085
71−#define CT_DEAD(ct, ctb, reason_code) ct_dead_capture((ct), (ctb), CT_DEAD_##reason_code)
86+static void ct_dead_fini(struct xe_guc_ct *ct)
87+{
88+ cancel_work_sync(&ct->dead.worker);
89+}
90+
91+static void ct_dead_init(struct xe_guc_ct *ct)
92+{
93+ spin_lock_init(&ct->dead.lock);
94+ INIT_WORK(&ct->dead.worker, ct_dead_worker_func);
95+
96+#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC)
97+ stack_depot_init();
98+#endif
99+}
100+
101+static void fast_req_stack_save(struct xe_guc_ct *ct, unsigned int slot)
102+{
103+#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC)
104+ unsigned long entries[SZ_32];
105+ unsigned int n;
106+
107+ n = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
108+ /* May be called under spinlock, so avoid sleeping */
109+ ct->fast_req[slot].stack = stack_depot_save(entries, n, GFP_NOWAIT);
110+#endif
111+}
112+
113+static void fast_req_dump(struct xe_guc_ct *ct, u16 fence, unsigned int slot)
114+{
115+ struct xe_gt *gt = ct_to_gt(ct);
116+#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC)
117+ char *buf __cleanup(kfree) = kmalloc(SZ_4K, GFP_NOWAIT);
118+
119+ if (buf && stack_depot_snprint(ct->fast_req[slot].stack, buf, SZ_4K, 0))
120+ xe_gt_err(gt, "Fence 0x%x was used by action %#04x sent at:\n%s\n",
121+ fence, ct->fast_req[slot].action, buf);
122+ else
123+ xe_gt_err(gt, "Fence 0x%x was used by action %#04x [failed to retrieve stack]\n",
124+ fence, ct->fast_req[slot].action);
125+#else
126+ xe_gt_err(gt, "Fence 0x%x was used by action %#04x\n",
127+ fence, ct->fast_req[slot].action);
128+#endif
129+}
130+
131+static void fast_req_report(struct xe_guc_ct *ct, u16 fence)
132+{
133+ u16 fence_min = U16_MAX, fence_max = 0;
134+ struct xe_gt *gt = ct_to_gt(ct);
135+ unsigned int n;
136+
137+ lockdep_assert_held(&ct->lock);
138+
139+ for (n = 0; n < ARRAY_SIZE(ct->fast_req); n++) {
140+ if (ct->fast_req[n].fence < fence_min)
141+ fence_min = ct->fast_req[n].fence;
142+ if (ct->fast_req[n].fence > fence_max)
143+ fence_max = ct->fast_req[n].fence;
144+
145+ if (ct->fast_req[n].fence != fence)
146+ continue;
147+
148+ return fast_req_dump(ct, fence, n);
149+ }
150+
151+ xe_gt_warn(gt, "Fence 0x%x not found - tracking buffer wrapped? [range = 0x%x -> 0x%x, next = 0x%X]\n",
152+ fence, fence_min, fence_max, ct->fence_seqno);
153+}
154+
155+static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action)
156+{
157+ unsigned int slot = fence % ARRAY_SIZE(ct->fast_req);
158+
159+ fast_req_stack_save(ct, slot);
160+ ct->fast_req[slot].fence = fence;
161+ ct->fast_req[slot].action = action;
162+}
163+
164+#define CT_DEAD(ct, ctb, reason_code) ct_dead_capture((ct), (ctb), CT_DEAD_##reason_code)
165+
72166 #else
167+
168+static void ct_dead_fini(struct xe_guc_ct *ct) { }
169+static void ct_dead_init(struct xe_guc_ct *ct) { }
170+
171+static void fast_req_report(struct xe_guc_ct *ct, u16 fence) { }
172+static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action) { }
173+
73174 #define CT_DEAD(ct, ctb, reason) \
74175 do { \
75176 struct guc_ctb *_ctb = (ctb); \
76177 if (_ctb) \
77178 _ctb->info.broken = true; \
78179 } while (0)
180+
79181 #endif
80182
81183 /* Used when a CT send wants to block and / or receive data */
@@ -112,24 +214,6 @@ static bool g2h_fence_needs_alloc(struct g2h_fence *g2h_fence) · 30 unmodified lines
112214 return g2h_fence->seqno == ~0x0;
113215 }
114216
115−static struct xe_guc *
116−ct_to_guc(struct xe_guc_ct *ct)
117−{
118− return container_of(ct, struct xe_guc, ct);
119−}
120−
121−static struct xe_gt *
122−ct_to_gt(struct xe_guc_ct *ct)
123−{
124− return container_of(ct, struct xe_gt, uc.guc.ct);
125−}
126−
127−static struct xe_device *
128−ct_to_xe(struct xe_guc_ct *ct)
129−{
130− return gt_to_xe(ct_to_gt(ct));
131−}
132−
133217 /**
134218 * DOC: GuC CTB Blob
135219 *
@@ -169,8 +253,11 @@ ct_to_xe(struct xe_guc_ct *ct) · 33 unmodified lines
169253 #define CTB_DESC_SIZE ALIGN(sizeof(struct guc_ct_buffer_desc), SZ_2K)
170254 #define CTB_H2G_BUFFER_OFFSET (CTB_DESC_SIZE * 2)
171255 #define CTB_H2G_BUFFER_SIZE (SZ_4K)
256+#define CTB_H2G_BUFFER_DWORDS (CTB_H2G_BUFFER_SIZE / sizeof(u32))
172257 #define CTB_G2H_BUFFER_SIZE (SZ_128K)
258+#define CTB_G2H_BUFFER_DWORDS (CTB_G2H_BUFFER_SIZE / sizeof(u32))
173259 #define G2H_ROOM_BUFFER_SIZE (CTB_G2H_BUFFER_SIZE / 2)
260+#define G2H_ROOM_BUFFER_DWORDS (CTB_G2H_BUFFER_DWORDS / 2)
174261
175262 /**
176263 * xe_guc_ct_queue_proc_time_jiffies - Return maximum time to process a full
@@ -199,9 +286,7 @@ static void guc_ct_fini(struct drm_device *drm, void *arg) · 22 unmodified lines
199286 {
200287 struct xe_guc_ct *ct = arg;
201288
202−#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
203− cancel_work_sync(&ct->dead.worker);
204−#endif
289+ ct_dead_fini(ct);
205290 ct_exit_safe_mode(ct);
206291 destroy_workqueue(ct->g2h_wq);
207292 xa_destroy(&ct->fence_lookup);
@@ -239,13 +324,8 @@ int xe_guc_ct_init_noalloc(struct xe_guc_ct *ct) · 31 unmodified lines
239324 xa_init(&ct->fence_lookup);
240325 INIT_WORK(&ct->g2h_worker, g2h_worker_func);
241326 INIT_DELAYED_WORK(&ct->safe_mode_worker, safe_mode_worker_func);
242−#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
243− spin_lock_init(&ct->dead.lock);
244− INIT_WORK(&ct->dead.worker, ct_dead_worker_func);
245−#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC)
246− stack_depot_init();
247−#endif
248−#endif
327+
328+ ct_dead_init(ct);
249329 init_waitqueue_head(&ct->wq);
250330 init_waitqueue_head(&ct->g2h_fence_wq);
251331
@@ -326,7 +406,7 @@ int xe_guc_ct_init_post_hwconfig(struct xe_guc_ct *ct) · 74 unmodified lines
326406 static void guc_ct_ctb_h2g_init(struct xe_device *xe, struct guc_ctb *h2g,
327407 struct iosys_map *map)
328408 {
329− h2g->info.size = CTB_H2G_BUFFER_SIZE / sizeof(u32);
409+ h2g->info.size = CTB_H2G_BUFFER_DWORDS;
330410 h2g->info.resv_space = 0;
331411 h2g->info.tail = 0;
332412 h2g->info.head = 0;
@@ -344,8 +424,8 @@ static void guc_ct_ctb_h2g_init(struct xe_device *xe, struct guc_ctb *h2g, · 11 unmodified lines
344424 static void guc_ct_ctb_g2h_init(struct xe_device *xe, struct guc_ctb *g2h,
345425 struct iosys_map *map)
346426 {
347− g2h->info.size = CTB_G2H_BUFFER_SIZE / sizeof(u32);
348− g2h->info.resv_space = G2H_ROOM_BUFFER_SIZE / sizeof(u32);
427+ g2h->info.size = CTB_G2H_BUFFER_DWORDS;
428+ g2h->info.resv_space = G2H_ROOM_BUFFER_DWORDS;
349429 g2h->info.head = 0;
350430 g2h->info.tail = 0;
351431 g2h->info.space = CIRC_SPACE(g2h->info.tail, g2h->info.head,
@@ -640,6 +720,39 @@ void xe_guc_ct_stop(struct xe_guc_ct *ct) · 288 unmodified lines
640720 stop_g2h_handler(ct);
641721 }
642722
723+/**
724+ * xe_guc_ct_runtime_suspend() - GuC CT runtime suspend
725+ * @ct: the &xe_guc_ct
726+ *
727+ * Set GuC CT to disabled state.
728+ */
729+void xe_guc_ct_runtime_suspend(struct xe_guc_ct *ct)
730+{
731+ struct guc_ctb *g2h = &ct->ctbs.g2h;
732+ u32 credits = CIRC_SPACE(0, 0, CTB_G2H_BUFFER_DWORDS) - G2H_ROOM_BUFFER_DWORDS;
733+
734+ /* We should be back to guc_ct_ctb_g2h_init() values */
735+ xe_gt_assert(ct_to_gt(ct), g2h->info.space == credits);
736+
737+ /*
738+ * Since we're already in runtime suspend path, we shouldn't have pending
739+ * messages. But if there happen to be any, we'd probably want them to be
740+ * thrown as errors for further investigation.
741+ */
742+ xe_guc_ct_disable(ct);
743+}
744+
745+/**
746+ * xe_guc_ct_runtime_resume() - GuC CT runtime resume
747+ * @ct: the &xe_guc_ct
748+ *
749+ * Restart GuC CT and set it to enabled state.
750+ */
751+void xe_guc_ct_runtime_resume(struct xe_guc_ct *ct)
752+{
753+ xe_guc_ct_restart(ct);
754+}
755+
643756 static bool h2g_has_room(struct xe_guc_ct *ct, u32 cmd_len)
644757 {
645758 struct guc_ctb *h2g = &ct->ctbs.h2g;
@@ -747,28 +860,6 @@ static void g2h_release_space(struct xe_guc_ct *ct, u32 g2h_len) · 101 unmodified lines
747860 spin_unlock_irq(&ct->fast_lock);
748861 }
749862
750−#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
751−static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action)
752−{
753− unsigned int slot = fence % ARRAY_SIZE(ct->fast_req);
754−#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC)
755− unsigned long entries[SZ_32];
756− unsigned int n;
757−
758− n = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
759−
760− /* May be called under spinlock, so avoid sleeping */
761− ct->fast_req[slot].stack = stack_depot_save(entries, n, GFP_NOWAIT);
762−#endif
763− ct->fast_req[slot].fence = fence;
764− ct->fast_req[slot].action = action;
765−}
766−#else
767−static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action)
768−{
769−}
770−#endif
771−
772863 /*
773864 * The CT protocol accepts a 16 bits fence. This field is fully owned by the
774865 * driver, the GuC will just copy it to the reply message. Since we need to
@@ -1310,10 +1401,12 @@ static int parse_g2h_event(struct xe_guc_ct *ct, u32 *msg, u32 len) · 535 unmodified lines
13101401 lockdep_assert_held(&ct->lock);
13111402
13121403 switch (action) {
1404+ case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE:
13131405 case XE_GUC_ACTION_SCHED_CONTEXT_MODE_DONE:
13141406 case XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
13151407 case XE_GUC_ACTION_SCHED_ENGINE_MODE_DONE:
13161408 case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
1409+ case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
13171410 g2h_release_space(ct, len);
13181411 }
13191412
@@ -1338,55 +1431,6 @@ static int guc_crash_process_msg(struct xe_guc_ct *ct, u32 action) · 18 unmodified lines
13381431 return 0;
13391432 }
13401433
1341−#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
1342−static void fast_req_report(struct xe_guc_ct *ct, u16 fence)
1343−{
1344− u16 fence_min = U16_MAX, fence_max = 0;
1345− struct xe_gt *gt = ct_to_gt(ct);
1346− bool found = false;
1347− unsigned int n;
1348−#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC)
1349− char *buf;
1350−#endif
1351−
1352− lockdep_assert_held(&ct->lock);
1353−
1354− for (n = 0; n < ARRAY_SIZE(ct->fast_req); n++) {
1355− if (ct->fast_req[n].fence < fence_min)
1356− fence_min = ct->fast_req[n].fence;
1357− if (ct->fast_req[n].fence > fence_max)
1358− fence_max = ct->fast_req[n].fence;
1359−
1360− if (ct->fast_req[n].fence != fence)
1361− continue;
1362− found = true;
1363−
1364−#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC)
1365− buf = kmalloc(SZ_4K, GFP_NOWAIT);
1366− if (buf && stack_depot_snprint(ct->fast_req[n].stack, buf, SZ_4K, 0))
1367− xe_gt_err(gt, "Fence 0x%x was used by action %#04x sent at:\n%s",
1368− fence, ct->fast_req[n].action, buf);
1369− else
1370− xe_gt_err(gt, "Fence 0x%x was used by action %#04x [failed to retrieve stack]\n",
1371− fence, ct->fast_req[n].action);
1372− kfree(buf);
1373−#else
1374− xe_gt_err(gt, "Fence 0x%x was used by action %#04x\n",
1375− fence, ct->fast_req[n].action);
1376−#endif
1377− break;
1378− }
1379−
1380− if (!found)
1381− xe_gt_warn(gt, "Fence 0x%x not found - tracking buffer wrapped? [range = 0x%x -> 0x%x, next = 0x%X]\n",
1382− fence, fence_min, fence_max, ct->fence_seqno);
1383−}
1384−#else
1385−static void fast_req_report(struct xe_guc_ct *ct, u16 fence)
1386−{
1387−}
1388−#endif
1389−
13901434 static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len)
13911435 {
13921436 struct xe_gt *gt = ct_to_gt(ct);
@@ -1549,6 +1593,15 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len) · 156 unmodified lines
15491593 ret = xe_guc_pagefault_handler(guc, payload, adj_len);
15501594 break;
15511595 case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
1596+ case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
1597+ /*
1598+ * Page reclamation is an extension of TLB invalidation. Both
1599+ * operations share the same seqno and fence. When either
1600+ * action completes, we need to signal the corresponding
1601+ * fence. Since the handling logic (lookup fence by seqno,
1602+ * fence signalling) is identical, we use the same handler
1603+ * for both G2H events.
1604+ */
15521605 ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len);
15531606 break;
15541607 case XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF:
@@ -1572,6 +1625,13 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len) · 17 unmodified lines
15721625 ret = xe_guc_g2g_test_notification(guc, payload, adj_len);
15731626 break;
15741627 #endif
1628+ case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE:
1629+ ret = xe_guc_exec_queue_cgp_sync_done_handler(guc, payload, adj_len);
1630+ break;
1631+ case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CGP_CONTEXT_ERROR:
1632+ ret = xe_guc_exec_queue_cgp_context_error_handler(guc, payload,
1633+ adj_len);
1634+ break;
15751635 default:
15761636 xe_gt_err(gt, "unexpected G2H action 0x%04x\n", action);
15771637 }
@@ -1714,6 +1774,7 @@ static int g2h_read(struct xe_guc_ct *ct, u32 *msg, bool fast_path) · 136 unmodified lines
17141774 switch (action) {
17151775 case XE_GUC_ACTION_REPORT_PAGE_FAULT_REQ_DESC:
17161776 case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
1777+ case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
17171778 break; /* Process these in fast-path */
17181779 default:
17191780 return 0;
@@ -1750,6 +1811,12 @@ static void g2h_fast_path(struct xe_guc_ct *ct, u32 *msg, u32 len) · 30 unmodified lines
17501811 ret = xe_guc_pagefault_handler(guc, payload, adj_len);
17511812 break;
17521813 case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
1814+ case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
1815+ /*
1816+ * Seqno and fence handling of page reclamation and TLB
1817+ * invalidation is identical, so we can use the same handler
1818+ * for both actions.
1819+ */
17531820 __g2h_release_space(ct, len);
17541821 ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len);
17551822 break;
drivers/gpu/drm/xe/xe_guc_ct.h+2−0
@@ -17,6 +17,8 @@ int xe_guc_ct_init_post_hwconfig(struct xe_guc_ct *ct); · 16 unmodified lines
1717 int xe_guc_ct_enable(struct xe_guc_ct *ct);
1818 int xe_guc_ct_restart(struct xe_guc_ct *ct);
1919 void xe_guc_ct_disable(struct xe_guc_ct *ct);
20+void xe_guc_ct_runtime_resume(struct xe_guc_ct *ct);
21+void xe_guc_ct_runtime_suspend(struct xe_guc_ct *ct);
2022 void xe_guc_ct_stop(struct xe_guc_ct *ct);
2123 void xe_guc_ct_flush_and_stop(struct xe_guc_ct *ct);
2224 void xe_guc_ct_fast_path(struct xe_guc_ct *ct);
drivers/gpu/drm/xe/xe_guc_debugfs.c+9−6
@@ -70,13 +70,9 @@ static int guc_debugfs_show(struct seq_file *m, void *data) · 69 unmodified lines
7070 struct xe_gt *gt = grandparent->d_inode->i_private;
7171 struct xe_device *xe = gt_to_xe(gt);
7272 int (*print)(struct xe_guc *, struct drm_printer *) = node->info_ent->data;
73− int ret;
7473
75− xe_pm_runtime_get(xe);
76− ret = print(&gt->uc.guc, &p);
77− xe_pm_runtime_put(xe);
78−
79− return ret;
74+ guard(xe_pm_runtime)(xe);
75+ return print(&gt->uc.guc, &p);
8076 }
8177
8278 static int guc_log(struct xe_guc *guc, struct drm_printer *p)
@@ -85,6 +81,12 @@ static int guc_log(struct xe_guc *guc, struct drm_printer *p) · 2 unmodified lines
8581 return 0;
8682 }
8783
84+static int guc_log_lfd(struct xe_guc *guc, struct drm_printer *p)
85+{
86+ xe_guc_log_print_lfd(&guc->log, p);
87+ return 0;
88+}
89+
8890 static int guc_log_dmesg(struct xe_guc *guc, struct drm_printer *p)
8991 {
9092 xe_guc_log_print_dmesg(&guc->log);
@@ -121,6 +123,7 @@ static const struct drm_info_list slpc_debugfs_list[] = { · 30 unmodified lines
121123 /* everything else should be added here */
122124 static const struct drm_info_list pf_only_debugfs_list[] = {
123125 { "guc_log", .show = guc_debugfs_show, .data = guc_log },
126+ { "guc_log_lfd", .show = guc_debugfs_show, .data = guc_log_lfd },
124127 { "guc_log_dmesg", .show = guc_debugfs_show, .data = guc_log_dmesg },
125128 };
126129
drivers/gpu/drm/xe/xe_guc_fwif.h+7−3
@@ -16,6 +16,8 @@ · 15 unmodified lines
1616 #define G2H_LEN_DW_DEREGISTER_CONTEXT 3
1717 #define G2H_LEN_DW_TLB_INVALIDATE 3
1818 #define G2H_LEN_DW_G2G_NOTIFY_MIN 3
19+#define G2H_LEN_DW_MULTI_QUEUE_CONTEXT 3
20+#define G2H_LEN_DW_PAGE_RECLAMATION 3
1921
2022 #define GUC_ID_MAX 65535
2123 #define GUC_ID_UNKNOWN 0xffffffff
@@ -62,6 +64,8 @@ struct guc_ctxt_registration_info { · 40 unmodified lines
6264 u32 wq_base_lo;
6365 u32 wq_base_hi;
6466 u32 wq_size;
67+ u32 cgp_lo;
68+ u32 cgp_hi;
6569 u32 hwlrca_lo;
6670 u32 hwlrca_hi;
6771 };
@@ -91,9 +95,9 @@ struct guc_update_exec_queue_policy { · 23 unmodified lines
9195 #define GUC_LOG_NOTIFY_ON_HALF_FULL BIT(1)
9296 #define GUC_LOG_CAPTURE_ALLOC_UNITS BIT(2)
9397 #define GUC_LOG_LOG_ALLOC_UNITS BIT(3)
94−#define GUC_LOG_CRASH REG_GENMASK(5, 4)
95−#define GUC_LOG_DEBUG REG_GENMASK(9, 6)
96−#define GUC_LOG_CAPTURE REG_GENMASK(11, 10)
98+#define GUC_LOG_CRASH_DUMP REG_GENMASK(5, 4)
99+#define GUC_LOG_EVENT_DATA REG_GENMASK(9, 6)
100+#define GUC_LOG_STATE_CAPTURE REG_GENMASK(11, 10)
97101 #define GUC_LOG_BUF_ADDR REG_GENMASK(31, 12)
98102
99103 #define GUC_CTL_WA 1
drivers/gpu/drm/xe/xe_guc_klv_thresholds_set_types.h+6−0
@@ -24,6 +24,11 @@ · 23 unmodified lines
2424 * ABI and the associated &NAME, that may be used in code or debugfs/sysfs::
2525 *
2626 * define(TAG, NAME)
27+ *
28+ * If required, KLVs can be labeled with GuC firmware version that added them::
29+ *
30+ * define(TAG, NAME, MAJOR, MINOR)
31+ * define(TAG, NAME, MAJOR, MINOR, PATCH)
2732 */
2833 #define MAKE_XE_GUC_KLV_THRESHOLDS_SET(define) \
2934 define(CAT_ERR, cat_error_count) \
@@ -32,6 +37,7 @@ · 2 unmodified lines
3237 define(H2G_STORM, guc_time_us) \
3338 define(IRQ_STORM, irq_time_us) \
3439 define(DOORBELL_STORM, doorbell_time_us) \
40+ define(MULTI_LRC_COUNT, multi_lrc_count, 70, 53)\
3541 /* end */
3642
3743 /**
drivers/gpu/drm/xe/xe_guc_log.c+406−101
@@ -7,8 +7,10 @@ · 6 unmodified lines
77
88 #include <linux/fault-inject.h>
99
10+#include <linux/utsname.h>
1011 #include <drm/drm_managed.h>
1112
13+#include "abi/guc_lfd_abi.h"
1214 #include "regs/xe_guc_regs.h"
1315 #include "xe_bo.h"
1416 #include "xe_devcoredump.h"
@@ -19,6 +21,77 @@ · 4 unmodified lines
1921 #include "xe_mmio.h"
2022 #include "xe_module.h"
2123
24+#define GUC_LOG_CHUNK_SIZE SZ_2M
25+
26+/* Magic keys define */
27+#define GUC_LFD_DRIVER_KEY_STREAMING 0x8086AAAA474C5346
28+#define GUC_LFD_LOG_BUFFER_MARKER_2 0xDEADFEED
29+#define GUC_LFD_CRASH_DUMP_BUFFER_MARKER_2 0x8086DEAD
30+#define GUC_LFD_STATE_CAPTURE_BUFFER_MARKER_2 0xBEEFFEED
31+#define GUC_LFD_LOG_BUFFER_MARKER_1V2 0xCABBA9E6
32+#define GUC_LFD_STATE_CAPTURE_BUFFER_MARKER_1V2 0xCABBA9F7
33+#define GUC_LFD_DATA_HEADER_MAGIC 0x8086
34+
35+/* LFD supported LIC type range */
36+#define GUC_LIC_TYPE_FIRST GUC_LIC_TYPE_GUC_SW_VERSION
37+#define GUC_LIC_TYPE_LAST GUC_LIC_TYPE_BUILD_PLATFORM_ID
38+#define GUC_LFD_TYPE_FW_RANGE_FIRST GUC_LFD_TYPE_FW_VERSION
39+#define GUC_LFD_TYPE_FW_RANGE_LAST GUC_LFD_TYPE_BUILD_PLATFORM_ID
40+
41+#define GUC_LOG_BUFFER_STATE_HEADER_LENGTH 4096
42+#define GUC_LOG_BUFFER_INIT_CONFIG 3
43+
44+struct guc_log_buffer_entry_list {
45+ u32 offset;
46+ u32 rd_ptr;
47+ u32 wr_ptr;
48+ u32 wrap_offset;
49+ u32 buf_size;
50+};
51+
52+struct guc_lic_save {
53+ u32 version;
54+ /*
55+ * Array of init config KLV values.
56+ * Range from GUC_LOG_LIC_TYPE_FIRST to GUC_LOG_LIC_TYPE_LAST
57+ */
58+ u32 values[GUC_LIC_TYPE_LAST - GUC_LIC_TYPE_FIRST + 1];
59+ struct guc_log_buffer_entry_list entry[GUC_LOG_BUFFER_INIT_CONFIG];
60+};
61+
62+static struct guc_log_buffer_entry_markers {
63+ u32 key[2];
64+} const entry_markers[GUC_LOG_BUFFER_INIT_CONFIG + 1] = {
65+ {{
66+ GUC_LFD_LOG_BUFFER_MARKER_1V2,
67+ GUC_LFD_LOG_BUFFER_MARKER_2
68+ }},
69+ {{
70+ GUC_LFD_LOG_BUFFER_MARKER_1V2,
71+ GUC_LFD_CRASH_DUMP_BUFFER_MARKER_2
72+ }},
73+ {{
74+ GUC_LFD_STATE_CAPTURE_BUFFER_MARKER_1V2,
75+ GUC_LFD_STATE_CAPTURE_BUFFER_MARKER_2
76+ }},
77+ {{
78+ GUC_LIC_MAGIC,
79+ (FIELD_PREP_CONST(GUC_LIC_VERSION_MASK_MAJOR, GUC_LIC_VERSION_MAJOR) |
80+ FIELD_PREP_CONST(GUC_LIC_VERSION_MASK_MINOR, GUC_LIC_VERSION_MINOR))
81+ }}
82+};
83+
84+static struct guc_log_lic_lfd_map {
85+ u32 lic;
86+ u32 lfd;
87+} const lic_lfd_type_map[] = {
88+ {GUC_LIC_TYPE_GUC_SW_VERSION, GUC_LFD_TYPE_FW_VERSION},
89+ {GUC_LIC_TYPE_GUC_DEVICE_ID, GUC_LFD_TYPE_GUC_DEVICE_ID},
90+ {GUC_LIC_TYPE_TSC_FREQUENCY, GUC_LFD_TYPE_TSC_FREQUENCY},
91+ {GUC_LIC_TYPE_GMD_ID, GUC_LFD_TYPE_GMD_ID},
92+ {GUC_LIC_TYPE_BUILD_PLATFORM_ID, GUC_LFD_TYPE_BUILD_PLATFORM_ID}
93+};
94+
2295 static struct xe_guc *
2396 log_to_guc(struct xe_guc_log *log)
2497 {
@@ -37,33 +110,6 @@ log_to_xe(struct xe_guc_log *log) · 12 unmodified lines
37110 return gt_to_xe(log_to_gt(log));
38111 }
39112
40−static size_t guc_log_size(void)
41−{
42− /*
43− * GuC Log buffer Layout
44− *
45− * +===============================+ 00B
46− * | Crash dump state header |
47− * +-------------------------------+ 32B
48− * | Debug state header |
49− * +-------------------------------+ 64B
50− * | Capture state header |
51− * +-------------------------------+ 96B
52− * | |
53− * +===============================+ PAGE_SIZE (4KB)
54− * | Crash Dump logs |
55− * +===============================+ + CRASH_SIZE
56− * | Debug logs |
57− * +===============================+ + DEBUG_SIZE
58− * | Capture logs |
59− * +===============================+ + CAPTURE_SIZE
60− */
61− return PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE +
62− CAPTURE_BUFFER_SIZE;
63−}
64−
65−#define GUC_LOG_CHUNK_SIZE SZ_2M
66−
67113 static struct xe_guc_log_snapshot *xe_guc_log_snapshot_alloc(struct xe_guc_log *log, bool atomic)
68114 {
69115 struct xe_guc_log_snapshot *snapshot;
@@ -145,7 +191,6 @@ struct xe_guc_log_snapshot *xe_guc_log_snapshot_capture(struct xe_guc_log *log, · 75 unmodified lines
145191 struct xe_device *xe = log_to_xe(log);
146192 struct xe_guc *guc = log_to_guc(log);
147193 struct xe_gt *gt = log_to_gt(log);
148− unsigned int fw_ref;
149194 size_t remain;
150195 int i;
151196
@@ -165,13 +210,12 @@ struct xe_guc_log_snapshot *xe_guc_log_snapshot_capture(struct xe_guc_log *log, · 13 unmodified lines
165210 remain -= size;
166211 }
167212
168− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
169− if (!fw_ref) {
213+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
214+ if (!fw_ref.domains)
170215 snapshot->stamp = ~0ULL;
171− } else {
216+ else
172217 snapshot->stamp = xe_mmio_read64_2x32(&gt->mmio, GUC_PMTIMESTAMP_LO);
173− xe_force_wake_put(gt_to_fw(gt), fw_ref);
174− }
218+
175219 snapshot->ktime = ktime_get_boottime_ns();
176220 snapshot->level = log->level;
177221 snapshot->ver_found = guc->fw.versions.found[XE_UC_FW_VER_RELEASE];
@@ -216,6 +260,318 @@ void xe_guc_log_snapshot_print(struct xe_guc_log_snapshot *snapshot, struct drm_ · 38 unmodified lines
216260 }
217261 }
218262
263+static inline void lfd_output_binary(struct drm_printer *p, char *buf, int buf_size)
264+{
265+ seq_write(p->arg, buf, buf_size);
266+}
267+
268+static inline int xe_guc_log_add_lfd_header(struct guc_lfd_data *lfd)
269+{
270+ lfd->header = FIELD_PREP_CONST(GUC_LFD_DATA_HEADER_MASK_MAGIC, GUC_LFD_DATA_HEADER_MAGIC);
271+ return offsetof(struct guc_lfd_data, data);
272+}
273+
274+static int xe_guc_log_add_typed_payload(struct drm_printer *p, u32 type,
275+ u32 data_len, void *data)
276+{
277+ struct guc_lfd_data lfd;
278+ int len;
279+
280+ len = xe_guc_log_add_lfd_header(&lfd);
281+ lfd.header |= FIELD_PREP(GUC_LFD_DATA_HEADER_MASK_TYPE, type);
282+ /* make length DW aligned */
283+ lfd.data_count = DIV_ROUND_UP(data_len, sizeof(u32));
284+ lfd_output_binary(p, (char *)&lfd, len);
285+
286+ lfd_output_binary(p, data, data_len);
287+ len += lfd.data_count * sizeof(u32);
288+
289+ return len;
290+}
291+
292+static inline int lic_type_to_index(u32 lic_type)
293+{
294+ XE_WARN_ON(lic_type < GUC_LIC_TYPE_FIRST || lic_type > GUC_LIC_TYPE_LAST);
295+
296+ return lic_type - GUC_LIC_TYPE_FIRST;
297+}
298+
299+static inline int lfd_type_to_index(u32 lfd_type)
300+{
301+ int i, lic_type = 0;
302+
303+ XE_WARN_ON(lfd_type < GUC_LFD_TYPE_FW_RANGE_FIRST || lfd_type > GUC_LFD_TYPE_FW_RANGE_LAST);
304+
305+ for (i = 0; i < ARRAY_SIZE(lic_lfd_type_map); i++)
306+ if (lic_lfd_type_map[i].lfd == lfd_type)
307+ lic_type = lic_lfd_type_map[i].lic;
308+
309+ /* If not found, lic_type_to_index will warning invalid type */
310+ return lic_type_to_index(lic_type);
311+}
312+
313+static int xe_guc_log_add_klv(struct drm_printer *p, u32 lfd_type,
314+ struct guc_lic_save *config)
315+{
316+ int klv_index = lfd_type_to_index(lfd_type);
317+
318+ return xe_guc_log_add_typed_payload(p, lfd_type, sizeof(u32), &config->values[klv_index]);
319+}
320+
321+static int xe_guc_log_add_os_id(struct drm_printer *p, u32 id)
322+{
323+ struct guc_lfd_data_os_info os_id;
324+ struct guc_lfd_data lfd;
325+ int len, info_len, section_len;
326+ char *version;
327+ u32 blank = 0;
328+
329+ len = xe_guc_log_add_lfd_header(&lfd);
330+ lfd.header |= FIELD_PREP(GUC_LFD_DATA_HEADER_MASK_TYPE, GUC_LFD_TYPE_OS_ID);
331+
332+ os_id.os_id = id;
333+ section_len = offsetof(struct guc_lfd_data_os_info, build_version);
334+
335+ version = init_utsname()->release;
336+ info_len = strlen(version);
337+
338+ /* make length DW aligned */
339+ lfd.data_count = DIV_ROUND_UP(section_len + info_len, sizeof(u32));
340+ lfd_output_binary(p, (char *)&lfd, len);
341+ lfd_output_binary(p, (char *)&os_id, section_len);
342+ lfd_output_binary(p, version, info_len);
343+
344+ /* Padding with 0 */
345+ section_len = lfd.data_count * sizeof(u32) - section_len - info_len;
346+ if (section_len)
347+ lfd_output_binary(p, (char *)&blank, section_len);
348+
349+ len += lfd.data_count * sizeof(u32);
350+ return len;
351+}
352+
353+static void xe_guc_log_loop_log_init(struct guc_lic *init, struct guc_lic_save *config)
354+{
355+ struct guc_klv_generic_dw_t *p = (void *)init->data;
356+ int i;
357+
358+ for (i = 0; i < init->data_count;) {
359+ int klv_len = FIELD_GET(GUC_KLV_0_LEN, p->kl) + 1;
360+ int key = FIELD_GET(GUC_KLV_0_KEY, p->kl);
361+
362+ if (key < GUC_LIC_TYPE_FIRST || key > GUC_LIC_TYPE_LAST) {
363+ XE_WARN_ON(key < GUC_LIC_TYPE_FIRST || key > GUC_LIC_TYPE_LAST);
364+ break;
365+ }
366+ config->values[lic_type_to_index(key)] = p->value;
367+ i += klv_len + 1; /* Whole KLV structure length in dwords */
368+ p = (void *)((u32 *)p + klv_len);
369+ }
370+}
371+
372+static int find_marker(u32 mark0, u32 mark1)
373+{
374+ int i;
375+
376+ for (i = 0; i < ARRAY_SIZE(entry_markers); i++)
377+ if (mark0 == entry_markers[i].key[0] && mark1 == entry_markers[i].key[1])
378+ return i;
379+
380+ return ARRAY_SIZE(entry_markers);
381+}
382+
383+static void xe_guc_log_load_lic(void *guc_log, struct guc_lic_save *config)
384+{
385+ u32 offset = GUC_LOG_BUFFER_STATE_HEADER_LENGTH;
386+ struct guc_log_buffer_state *p = guc_log;
387+
388+ config->version = p->version;
389+ while (p->marker[0]) {
390+ int index;
391+
392+ index = find_marker(p->marker[0], p->marker[1]);
393+
394+ if (index < ARRAY_SIZE(entry_markers)) {
395+ if (index == GUC_LOG_BUFFER_INIT_CONFIG) {
396+ /* Load log init config */
397+ xe_guc_log_loop_log_init((void *)p, config);
398+
399+ /* LIC structure is the last */
400+ return;
401+ }
402+ config->entry[index].offset = offset;
403+ config->entry[index].rd_ptr = p->read_ptr;
404+ config->entry[index].wr_ptr = p->write_ptr;
405+ config->entry[index].wrap_offset = p->wrap_offset;
406+ config->entry[index].buf_size = p->size;
407+ }
408+ offset += p->size;
409+ p++;
410+ }
411+}
412+
413+static int
414+xe_guc_log_output_lfd_init(struct drm_printer *p, struct xe_guc_log_snapshot *snapshot,
415+ struct guc_lic_save *config)
416+{
417+ int type, len;
418+ size_t size = 0;
419+
420+ /* FW required types */
421+ for (type = GUC_LFD_TYPE_FW_RANGE_FIRST; type <= GUC_LFD_TYPE_FW_RANGE_LAST; type++)
422+ size += xe_guc_log_add_klv(p, type, config);
423+
424+ /* KMD required type(s) */
425+ len = xe_guc_log_add_os_id(p, GUC_LFD_OS_TYPE_OSID_LIN);
426+ size += len;
427+
428+ return size;
429+}
430+
431+static void
432+xe_guc_log_print_chunks(struct drm_printer *p, struct xe_guc_log_snapshot *snapshot,
433+ u32 from, u32 to)
434+{
435+ int chunk_from = from % GUC_LOG_CHUNK_SIZE;
436+ int chunk_id = from / GUC_LOG_CHUNK_SIZE;
437+ int to_chunk_id = to / GUC_LOG_CHUNK_SIZE;
438+ int chunk_to = to % GUC_LOG_CHUNK_SIZE;
439+ int pos = from;
440+
441+ do {
442+ size_t size = (to_chunk_id == chunk_id ? chunk_to : GUC_LOG_CHUNK_SIZE) -
443+ chunk_from;
444+
445+ lfd_output_binary(p, snapshot->copy[chunk_id] + chunk_from, size);
446+ pos += size;
447+ chunk_id++;
448+ chunk_from = 0;
449+ } while (pos < to);
450+}
451+
452+static inline int
453+xe_guc_log_add_log_event(struct drm_printer *p, struct xe_guc_log_snapshot *snapshot,
454+ struct guc_lic_save *config)
455+{
456+ size_t size;
457+ u32 data_len, section_len;
458+ struct guc_lfd_data lfd;
459+ struct guc_log_buffer_entry_list *entry;
460+ struct guc_lfd_data_log_events_buf events_buf;
461+
462+ entry = &config->entry[GUC_LOG_TYPE_EVENT_DATA];
463+
464+ /* Skip empty log */
465+ if (entry->rd_ptr == entry->wr_ptr)
466+ return 0;
467+
468+ size = xe_guc_log_add_lfd_header(&lfd);
469+ lfd.header |= FIELD_PREP(GUC_LFD_DATA_HEADER_MASK_TYPE, GUC_LFD_TYPE_LOG_EVENTS_BUFFER);
470+ events_buf.log_events_format_version = config->version;
471+
472+ /* Adjust to log_format_buf */
473+ section_len = offsetof(struct guc_lfd_data_log_events_buf, log_event);
474+ data_len = section_len;
475+
476+ /* Calculate data length */
477+ data_len += entry->rd_ptr < entry->wr_ptr ? (entry->wr_ptr - entry->rd_ptr) :
478+ (entry->wr_ptr + entry->wrap_offset - entry->rd_ptr);
479+ /* make length u32 aligned */
480+ lfd.data_count = DIV_ROUND_UP(data_len, sizeof(u32));
481+
482+ /* Output GUC_LFD_TYPE_LOG_EVENTS_BUFFER header */
483+ lfd_output_binary(p, (char *)&lfd, size);
484+ lfd_output_binary(p, (char *)&events_buf, section_len);
485+
486+ /* Output data from guc log chunks directly */
487+ if (entry->rd_ptr < entry->wr_ptr) {
488+ xe_guc_log_print_chunks(p, snapshot, entry->offset + entry->rd_ptr,
489+ entry->offset + entry->wr_ptr);
490+ } else {
491+ /* 1st, print from rd to wrap offset */
492+ xe_guc_log_print_chunks(p, snapshot, entry->offset + entry->rd_ptr,
493+ entry->offset + entry->wrap_offset);
494+
495+ /* 2nd, print from buf start to wr */
496+ xe_guc_log_print_chunks(p, snapshot, entry->offset, entry->offset + entry->wr_ptr);
497+ }
498+ return size;
499+}
500+
501+static int
502+xe_guc_log_add_crash_dump(struct drm_printer *p, struct xe_guc_log_snapshot *snapshot,
503+ struct guc_lic_save *config)
504+{
505+ struct guc_log_buffer_entry_list *entry;
506+ int chunk_from, chunk_id;
507+ int from, to, i;
508+ size_t size = 0;
509+ u32 *buf32;
510+
511+ entry = &config->entry[GUC_LOG_TYPE_CRASH_DUMP];
512+
513+ /* Skip zero sized crash dump */
514+ if (!entry->buf_size)
515+ return 0;
516+
517+ /* Check if crash dump section are all zero */
518+ from = entry->offset;
519+ to = entry->offset + entry->buf_size;
520+ chunk_from = from % GUC_LOG_CHUNK_SIZE;
521+ chunk_id = from / GUC_LOG_CHUNK_SIZE;
522+ buf32 = snapshot->copy[chunk_id] + chunk_from;
523+
524+ for (i = 0; i < entry->buf_size / sizeof(u32); i++)
525+ if (buf32[i])
526+ break;
527+
528+ /* Buffer has non-zero data? */
529+ if (i < entry->buf_size / sizeof(u32)) {
530+ struct guc_lfd_data lfd;
531+
532+ size = xe_guc_log_add_lfd_header(&lfd);
533+ lfd.header |= FIELD_PREP(GUC_LFD_DATA_HEADER_MASK_TYPE, GUC_LFD_TYPE_FW_CRASH_DUMP);
534+ /* Calculate data length */
535+ lfd.data_count = DIV_ROUND_UP(entry->buf_size, sizeof(u32));
536+ /* Output GUC_LFD_TYPE_FW_CRASH_DUMP header */
537+ lfd_output_binary(p, (char *)&lfd, size);
538+
539+ /* rd/wr ptr is not used for crash dump */
540+ xe_guc_log_print_chunks(p, snapshot, from, to);
541+ }
542+ return size;
543+}
544+
545+static void
546+xe_guc_log_snapshot_print_lfd(struct xe_guc_log_snapshot *snapshot, struct drm_printer *p)
547+{
548+ struct guc_lfd_file_header header;
549+ struct guc_lic_save config;
550+ size_t size;
551+
552+ if (!snapshot || !snapshot->size)
553+ return;
554+
555+ header.magic = GUC_LFD_DRIVER_KEY_STREAMING;
556+ header.version = FIELD_PREP_CONST(GUC_LFD_FILE_HEADER_VERSION_MASK_MINOR,
557+ GUC_LFD_FORMAT_VERSION_MINOR) |
558+ FIELD_PREP_CONST(GUC_LFD_FILE_HEADER_VERSION_MASK_MAJOR,
559+ GUC_LFD_FORMAT_VERSION_MAJOR);
560+
561+ /* Output LFD file header */
562+ lfd_output_binary(p, (char *)&header,
563+ offsetof(struct guc_lfd_file_header, stream));
564+
565+ /* Output LFD stream */
566+ xe_guc_log_load_lic(snapshot->copy[0], &config);
567+ size = xe_guc_log_output_lfd_init(p, snapshot, &config);
568+ if (!size)
569+ return;
570+
571+ xe_guc_log_add_log_event(p, snapshot, &config);
572+ xe_guc_log_add_crash_dump(p, snapshot, &config);
573+}
574+
219575 /**
220576 * xe_guc_log_print_dmesg - dump a copy of the GuC log to dmesg
221577 * @log: GuC log structure
@@ -251,13 +607,27 @@ void xe_guc_log_print(struct xe_guc_log *log, struct drm_printer *p) · 29 unmodified lines
251607 xe_guc_log_snapshot_free(snapshot);
252608 }
253609
610+/**
611+ * xe_guc_log_print_lfd - dump a copy of the GuC log in LFD format
612+ * @log: GuC log structure
613+ * @p: the printer object to output to
614+ */
615+void xe_guc_log_print_lfd(struct xe_guc_log *log, struct drm_printer *p)
616+{
617+ struct xe_guc_log_snapshot *snapshot;
618+
619+ snapshot = xe_guc_log_snapshot_capture(log, false);
620+ xe_guc_log_snapshot_print_lfd(snapshot, p);
621+ xe_guc_log_snapshot_free(snapshot);
622+}
623+
254624 int xe_guc_log_init(struct xe_guc_log *log)
255625 {
256626 struct xe_device *xe = log_to_xe(log);
257627 struct xe_tile *tile = gt_to_tile(log_to_gt(log));
258628 struct xe_bo *bo;
259629
260− bo = xe_managed_bo_create_pin_map(xe, tile, guc_log_size(),
630+ bo = xe_managed_bo_create_pin_map(xe, tile, GUC_LOG_SIZE,
261631 XE_BO_FLAG_SYSTEM |
262632 XE_BO_FLAG_GGTT |
263633 XE_BO_FLAG_GGTT_INVALIDATE |
@@ -265,7 +635,7 @@ int xe_guc_log_init(struct xe_guc_log *log) · 1 unmodified line
265635 if (IS_ERR(bo))
266636 return PTR_ERR(bo);
267637
268− xe_map_memset(xe, &bo->vmap, 0, 0, guc_log_size());
638+ xe_map_memset(xe, &bo->vmap, 0, 0, xe_bo_size(bo));
269639 log->bo = bo;
270640 log->level = xe_modparam.guc_log_level;
271641
@@ -274,71 +644,6 @@ int xe_guc_log_init(struct xe_guc_log *log) · 2 unmodified lines
274644
275645 ALLOW_ERROR_INJECTION(xe_guc_log_init, ERRNO); /* See xe_pci_probe() */
276646
277−static u32 xe_guc_log_section_size_crash(struct xe_guc_log *log)
278−{
279− return CRASH_BUFFER_SIZE;
280−}
281−
282−static u32 xe_guc_log_section_size_debug(struct xe_guc_log *log)
283−{
284− return DEBUG_BUFFER_SIZE;
285−}
286−
287−/**
288− * xe_guc_log_section_size_capture - Get capture buffer size within log sections.
289− * @log: The log object.
290− *
291− * This function will return the capture buffer size within log sections.
292− *
293− * Return: capture buffer size.
294− */
295−u32 xe_guc_log_section_size_capture(struct xe_guc_log *log)
296−{
297− return CAPTURE_BUFFER_SIZE;
298−}
299−
300−/**
301− * xe_guc_get_log_buffer_size - Get log buffer size for a type.
302− * @log: The log object.
303− * @type: The log buffer type
304− *
305− * Return: buffer size.
306− */
307−u32 xe_guc_get_log_buffer_size(struct xe_guc_log *log, enum guc_log_buffer_type type)
308−{
309− switch (type) {
310− case GUC_LOG_BUFFER_CRASH_DUMP:
311− return xe_guc_log_section_size_crash(log);
312− case GUC_LOG_BUFFER_DEBUG:
313− return xe_guc_log_section_size_debug(log);
314− case GUC_LOG_BUFFER_CAPTURE:
315− return xe_guc_log_section_size_capture(log);
316− }
317− return 0;
318−}
319−
320−/**
321− * xe_guc_get_log_buffer_offset - Get offset in log buffer for a type.
322− * @log: The log object.
323− * @type: The log buffer type
324− *
325− * This function will return the offset in the log buffer for a type.
326− * Return: buffer offset.
327− */
328−u32 xe_guc_get_log_buffer_offset(struct xe_guc_log *log, enum guc_log_buffer_type type)
329−{
330− enum guc_log_buffer_type i;
331− u32 offset = PAGE_SIZE;/* for the log_buffer_states */
332−
333− for (i = GUC_LOG_BUFFER_CRASH_DUMP; i < GUC_LOG_BUFFER_TYPE_MAX; ++i) {
334− if (i == type)
335− break;
336− offset += xe_guc_get_log_buffer_size(log, i);
337− }
338−
339− return offset;
340−}
341−
342647 /**
343648 * xe_guc_check_log_buf_overflow - Check if log buffer overflowed
344649 * @log: The log object.
@@ -352,7 +657,7 @@ u32 xe_guc_get_log_buffer_offset(struct xe_guc_log *log, enum guc_log_buffer_typ · 7 unmodified lines
352657 *
353658 * Return: True if overflowed.
354659 */
355−bool xe_guc_check_log_buf_overflow(struct xe_guc_log *log, enum guc_log_buffer_type type,
660+bool xe_guc_check_log_buf_overflow(struct xe_guc_log *log, enum guc_log_type type,
356661 unsigned int full_cnt)
357662 {
358663 unsigned int prev_full_cnt = log->stats[type].sampled_overflow;
drivers/gpu/drm/xe/xe_guc_log.h+20−10
@@ -13,14 +13,26 @@ struct drm_printer; · 12 unmodified lines
1313 struct xe_device;
1414
1515 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC)
16−#define CRASH_BUFFER_SIZE SZ_1M
17−#define DEBUG_BUFFER_SIZE SZ_8M
18−#define CAPTURE_BUFFER_SIZE SZ_2M
16+#define XE_GUC_LOG_EVENT_DATA_BUFFER_SIZE SZ_8M
17+#define XE_GUC_LOG_CRASH_DUMP_BUFFER_SIZE SZ_1M
18+#define XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE SZ_2M
1919 #else
20−#define CRASH_BUFFER_SIZE SZ_16K
21−#define DEBUG_BUFFER_SIZE SZ_64K
22−#define CAPTURE_BUFFER_SIZE SZ_1M
20+#define XE_GUC_LOG_EVENT_DATA_BUFFER_SIZE SZ_64K
21+#define XE_GUC_LOG_CRASH_DUMP_BUFFER_SIZE SZ_16K
22+#define XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE SZ_1M
2323 #endif
24+
25+#define GUC_LOG_SIZE (SZ_4K + \
26+ XE_GUC_LOG_EVENT_DATA_BUFFER_SIZE + \
27+ XE_GUC_LOG_CRASH_DUMP_BUFFER_SIZE + \
28+ XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE)
29+
30+#define XE_GUC_LOG_EVENT_DATA_OFFSET SZ_4K
31+#define XE_GUC_LOG_CRASH_DUMP_OFFSET (XE_GUC_LOG_EVENT_DATA_OFFSET + \
32+ XE_GUC_LOG_EVENT_DATA_BUFFER_SIZE)
33+#define XE_GUC_LOG_STATE_CAPTURE_OFFSET (XE_GUC_LOG_CRASH_DUMP_OFFSET + \
34+ XE_GUC_LOG_CRASH_DUMP_BUFFER_SIZE)
35+
2436 /*
2537 * While we're using plain log level in i915, GuC controls are much more...
2638 * "elaborate"? We have a couple of bits for verbosity, separate bit for actual
@@ -40,6 +52,7 @@ struct xe_device; · 13 unmodified lines
4052
4153 int xe_guc_log_init(struct xe_guc_log *log);
4254 void xe_guc_log_print(struct xe_guc_log *log, struct drm_printer *p);
55+void xe_guc_log_print_lfd(struct xe_guc_log *log, struct drm_printer *p);
4356 void xe_guc_log_print_dmesg(struct xe_guc_log *log);
4457 struct xe_guc_log_snapshot *xe_guc_log_snapshot_capture(struct xe_guc_log *log, bool atomic);
4558 void xe_guc_log_snapshot_print(struct xe_guc_log_snapshot *snapshot, struct drm_printer *p);
@@ -51,11 +64,8 @@ xe_guc_log_get_level(struct xe_guc_log *log) · 5 unmodified lines
5164 return log->level;
5265 }
5366
54−u32 xe_guc_log_section_size_capture(struct xe_guc_log *log);
55−u32 xe_guc_get_log_buffer_size(struct xe_guc_log *log, enum guc_log_buffer_type type);
56−u32 xe_guc_get_log_buffer_offset(struct xe_guc_log *log, enum guc_log_buffer_type type);
5767 bool xe_guc_check_log_buf_overflow(struct xe_guc_log *log,
58− enum guc_log_buffer_type type,
68+ enum guc_log_type type,
5969 unsigned int full_cnt);
6070
6171 #endif
drivers/gpu/drm/xe/xe_guc_pc.c+19−47
@@ -76,7 +76,7 @@ · 75 unmodified lines
7676 * exposes a programming interface to the host for the control of SLPC.
7777 *
7878 * Frequency management:
79− * =====================
79+ * ---------------------
8080 *
8181 * Xe driver enables SLPC with all of its defaults features and frequency
8282 * selection, which varies per platform.
@@ -87,7 +87,7 @@ · 4 unmodified lines
8787 * for any workload.
8888 *
8989 * Render-C States:
90− * ================
90+ * ----------------
9191 *
9292 * Render-C states is also a GuC PC feature that is now enabled in Xe for
9393 * all platforms.
@@ -499,21 +499,17 @@ u32 xe_guc_pc_get_cur_freq_fw(struct xe_guc_pc *pc) · 405 unmodified lines
499499 int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq)
500500 {
501501 struct xe_gt *gt = pc_to_gt(pc);
502− unsigned int fw_ref;
503502
504503 /*
505504 * GuC SLPC plays with cur freq request when GuCRC is enabled
506505 * Block RC6 for a more reliable read.
507506 */
508− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
509− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) {
510− xe_force_wake_put(gt_to_fw(gt), fw_ref);
507+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
508+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT))
511509 return -ETIMEDOUT;
512− }
513510
514511 *freq = get_cur_freq(gt);
515512
516− xe_force_wake_put(gt_to_fw(gt), fw_ref);
517513 return 0;
518514 }
519515
@@ -1087,13 +1083,8 @@ int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc) · 567 unmodified lines
10871083 */
10881084 int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mode)
10891085 {
1090− int ret;
1091−
1092− xe_pm_runtime_get(pc_to_xe(pc));
1093− ret = pc_action_set_param(pc, SLPC_PARAM_PWRGATE_RC_MODE, mode);
1094− xe_pm_runtime_put(pc_to_xe(pc));
1095−
1096− return ret;
1086+ guard(xe_pm_runtime)(pc_to_xe(pc));
1087+ return pc_action_set_param(pc, SLPC_PARAM_PWRGATE_RC_MODE, mode);
10971088 }
10981089
10991090 /**
@@ -1104,13 +1095,8 @@ int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mod · 4 unmodified lines
11041095 */
11051096 int xe_guc_pc_unset_gucrc_mode(struct xe_guc_pc *pc)
11061097 {
1107− int ret;
1108−
1109− xe_pm_runtime_get(pc_to_xe(pc));
1110− ret = pc_action_unset_param(pc, SLPC_PARAM_PWRGATE_RC_MODE);
1111− xe_pm_runtime_put(pc_to_xe(pc));
1112−
1113− return ret;
1098+ guard(xe_pm_runtime)(pc_to_xe(pc));
1099+ return pc_action_unset_param(pc, SLPC_PARAM_PWRGATE_RC_MODE);
11141100 }
11151101
11161102 static void pc_init_pcode_freq(struct xe_guc_pc *pc)
@@ -1198,7 +1184,7 @@ int xe_guc_pc_set_power_profile(struct xe_guc_pc *pc, const char *buf) · 81 unmodified lines
11981184 return -EINVAL;
11991185
12001186 guard(mutex)(&pc->freq_lock);
1201− xe_pm_runtime_get_noresume(pc_to_xe(pc));
1187+ guard(xe_pm_runtime_noresume)(pc_to_xe(pc));
12021188
12031189 ret = pc_action_set_param(pc,
12041190 SLPC_PARAM_POWER_PROFILE,
@@ -1209,8 +1195,6 @@ int xe_guc_pc_set_power_profile(struct xe_guc_pc *pc, const char *buf) · 4 unmodified lines
12091195 else
12101196 pc->power_profile = val;
12111197
1212− xe_pm_runtime_put(pc_to_xe(pc));
1213−
12141198 return ret;
12151199 }
12161200
@@ -1223,17 +1207,14 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) · 6 unmodified lines
12231207 struct xe_device *xe = pc_to_xe(pc);
12241208 struct xe_gt *gt = pc_to_gt(pc);
12251209 u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data));
1226− unsigned int fw_ref;
12271210 ktime_t earlier;
12281211 int ret;
12291212
12301213 xe_gt_assert(gt, xe_device_uc_enabled(xe));
12311214
1232− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
1233− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) {
1234− xe_force_wake_put(gt_to_fw(gt), fw_ref);
1215+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
1216+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT))
12351217 return -ETIMEDOUT;
1236− }
12371218
12381219 if (xe->info.skip_guc_pc) {
12391220 if (xe->info.platform != XE_PVC)
@@ -1241,9 +1222,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) · 1 unmodified line
12411222
12421223 /* Request max possible since dynamic freq mgmt is not enabled */
12431224 pc_set_cur_freq(pc, UINT_MAX);
1244−
1245− ret = 0;
1246− goto out;
1225+ return 0;
12471226 }
12481227
12491228 xe_map_memset(xe, &pc->bo->vmap, 0, 0, size);
@@ -1252,7 +1231,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) · 2 unmodified lines
12521231 earlier = ktime_get();
12531232 ret = pc_action_reset(pc);
12541233 if (ret)
1255− goto out;
1234+ return ret;
12561235
12571236 if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING,
12581237 SLPC_RESET_TIMEOUT_MS)) {
@@ -1263,8 +1242,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) · 4 unmodified lines
12631242 if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING,
12641243 SLPC_RESET_EXTENDED_TIMEOUT_MS)) {
12651244 xe_gt_err(gt, "GuC PC Start failed: Dynamic GT frequency control and GT sleep states are now disabled.\n");
1266− ret = -EIO;
1267− goto out;
1245+ return -EIO;
12681246 }
12691247
12701248 xe_gt_warn(gt, "GuC PC excessive start time: %lldms",
@@ -1273,21 +1251,20 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) · 2 unmodified lines
12731251
12741252 ret = pc_init_freqs(pc);
12751253 if (ret)
1276− goto out;
1254+ return ret;
12771255
12781256 ret = pc_set_mert_freq_cap(pc);
12791257 if (ret)
1280− goto out;
1258+ return ret;
12811259
12821260 if (xe->info.platform == XE_PVC) {
12831261 xe_guc_pc_gucrc_disable(pc);
1284− ret = 0;
1285− goto out;
1262+ return 0;
12861263 }
12871264
12881265 ret = pc_action_setup_gucrc(pc, GUCRC_FIRMWARE_CONTROL);
12891266 if (ret)
1290− goto out;
1267+ return ret;
12911268
12921269 /* Enable SLPC Optimized Strategy for compute */
12931270 ret = pc_action_set_strategy(pc, SLPC_OPTIMIZED_STRATEGY_COMPUTE);
@@ -1297,8 +1274,6 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) · 3 unmodified lines
12971274 if (unlikely(ret))
12981275 xe_gt_err(gt, "Failed to set SLPC power profile: %pe\n", ERR_PTR(ret));
12991276
1300−out:
1301− xe_force_wake_put(gt_to_fw(gt), fw_ref);
13021277 return ret;
13031278 }
13041279
@@ -1330,19 +1305,16 @@ static void xe_guc_pc_fini_hw(void *arg) · 25 unmodified lines
13301305 {
13311306 struct xe_guc_pc *pc = arg;
13321307 struct xe_device *xe = pc_to_xe(pc);
1333− unsigned int fw_ref;
13341308
13351309 if (xe_device_wedged(xe))
13361310 return;
13371311
1338− fw_ref = xe_force_wake_get(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL);
1312+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL);
13391313 xe_guc_pc_gucrc_disable(pc);
13401314 XE_WARN_ON(xe_guc_pc_stop(pc));
13411315
13421316 /* Bind requested freq to mert_freq_cap before unload */
13431317 pc_set_cur_freq(pc, min(pc_max_freq_cap(pc), xe_guc_pc_get_rpe_freq(pc)));
1344−
1345− xe_force_wake_put(gt_to_fw(pc_to_gt(pc)), fw_ref);
13461318 }
13471319
13481320 /**
drivers/gpu/drm/xe/xe_guc_submit.c+637−68
@@ -19,6 +19,7 @@ · 18 unmodified lines
1919 #include "abi/guc_klvs_abi.h"
2020 #include "regs/xe_lrc_layout.h"
2121 #include "xe_assert.h"
22+#include "xe_bo.h"
2223 #include "xe_devcoredump.h"
2324 #include "xe_device.h"
2425 #include "xe_exec_queue.h"
@@ -47,6 +48,8 @@ · 22 unmodified lines
4748 #include "xe_uc_fw.h"
4849 #include "xe_vm.h"
4950
51+#define XE_GUC_EXEC_QUEUE_CGP_CONTEXT_ERROR_LEN 6
52+
5053 static struct xe_guc *
5154 exec_queue_to_guc(struct xe_exec_queue *q)
5255 {
@@ -72,6 +75,7 @@ exec_queue_to_guc(struct xe_exec_queue *q) · 19 unmodified lines
7275 #define EXEC_QUEUE_STATE_EXTRA_REF (1 << 11)
7376 #define EXEC_QUEUE_STATE_PENDING_RESUME (1 << 12)
7477 #define EXEC_QUEUE_STATE_PENDING_TDR_EXIT (1 << 13)
78+#define EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND (1 << 14)
7579
7680 static bool exec_queue_registered(struct xe_exec_queue *q)
7781 {
@@ -263,6 +267,21 @@ static void clear_exec_queue_pending_tdr_exit(struct xe_exec_queue *q) · 185 unmodified lines
263267 atomic_and(~EXEC_QUEUE_STATE_PENDING_TDR_EXIT, &q->guc->state);
264268 }
265269
270+static bool exec_queue_idle_skip_suspend(struct xe_exec_queue *q)
271+{
272+ return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND;
273+}
274+
275+static void set_exec_queue_idle_skip_suspend(struct xe_exec_queue *q)
276+{
277+ atomic_or(EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND, &q->guc->state);
278+}
279+
280+static void clear_exec_queue_idle_skip_suspend(struct xe_exec_queue *q)
281+{
282+ atomic_and(~EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND, &q->guc->state);
283+}
284+
266285 static bool exec_queue_killed_or_banned_or_wedged(struct xe_exec_queue *q)
267286 {
268287 return (atomic_read(&q->guc->state) &
@@ -541,7 +560,8 @@ static void init_policies(struct xe_guc *guc, struct xe_exec_queue *q) · 272 unmodified lines
541560 u32 slpc_exec_queue_freq_req = 0;
542561 u32 preempt_timeout_us = q->sched_props.preempt_timeout_us;
543562
544− xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
563+ xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q) &&
564+ !xe_exec_queue_is_multi_queue_secondary(q));
545565
546566 if (q->flags & EXEC_QUEUE_FLAG_LOW_LATENCY)
547567 slpc_exec_queue_freq_req |= SLPC_CTX_FREQ_REQ_IS_COMPUTE;
@@ -561,6 +581,8 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue · 13 unmodified lines
561581 {
562582 struct exec_queue_policy policy;
563583
584+ xe_assert(guc_to_xe(guc), !xe_exec_queue_is_multi_queue_secondary(q));
585+
564586 __guc_exec_queue_policy_start_klv(&policy, q->guc->id);
565587 __guc_exec_queue_policy_add_preemption_timeout(&policy, 1);
566588
@@ -568,6 +590,89 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue · 1 unmodified line
568590 __guc_exec_queue_policy_action_size(&policy), 0, 0);
569591 }
570592
593+static bool vf_recovery(struct xe_guc *guc)
594+{
595+ return xe_gt_recovery_pending(guc_to_gt(guc));
596+}
597+
598+static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
599+{
600+ struct xe_guc *guc = exec_queue_to_guc(q);
601+ struct xe_device *xe = guc_to_xe(guc);
602+
603+ /** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
604+ wake_up_all(&xe->ufence_wq);
605+
606+ if (xe_exec_queue_is_lr(q))
607+ queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
608+ else
609+ xe_sched_tdr_queue_imm(&q->guc->sched);
610+}
611+
612+static void xe_guc_exec_queue_group_trigger_cleanup(struct xe_exec_queue *q)
613+{
614+ struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
615+ struct xe_exec_queue_group *group = q->multi_queue.group;
616+ struct xe_exec_queue *eq;
617+
618+ xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)),
619+ xe_exec_queue_is_multi_queue(q));
620+
621+ /* Group banned, skip timeout check in TDR */
622+ WRITE_ONCE(group->banned, true);
623+ xe_guc_exec_queue_trigger_cleanup(primary);
624+
625+ mutex_lock(&group->list_lock);
626+ list_for_each_entry(eq, &group->list, multi_queue.link)
627+ xe_guc_exec_queue_trigger_cleanup(eq);
628+ mutex_unlock(&group->list_lock);
629+}
630+
631+static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
632+{
633+ if (xe_exec_queue_is_multi_queue(q)) {
634+ struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
635+ struct xe_exec_queue_group *group = q->multi_queue.group;
636+ struct xe_exec_queue *eq;
637+
638+ /* Group banned, skip timeout check in TDR */
639+ WRITE_ONCE(group->banned, true);
640+
641+ set_exec_queue_reset(primary);
642+ if (!exec_queue_banned(primary) && !exec_queue_check_timeout(primary))
643+ xe_guc_exec_queue_trigger_cleanup(primary);
644+
645+ mutex_lock(&group->list_lock);
646+ list_for_each_entry(eq, &group->list, multi_queue.link) {
647+ set_exec_queue_reset(eq);
648+ if (!exec_queue_banned(eq) && !exec_queue_check_timeout(eq))
649+ xe_guc_exec_queue_trigger_cleanup(eq);
650+ }
651+ mutex_unlock(&group->list_lock);
652+ } else {
653+ set_exec_queue_reset(q);
654+ if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
655+ xe_guc_exec_queue_trigger_cleanup(q);
656+ }
657+}
658+
659+static void set_exec_queue_group_banned(struct xe_exec_queue *q)
660+{
661+ struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
662+ struct xe_exec_queue_group *group = q->multi_queue.group;
663+ struct xe_exec_queue *eq;
664+
665+ /* Ban all queues of the multi-queue group */
666+ xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)),
667+ xe_exec_queue_is_multi_queue(q));
668+ set_exec_queue_banned(primary);
669+
670+ mutex_lock(&group->list_lock);
671+ list_for_each_entry(eq, &group->list, multi_queue.link)
672+ set_exec_queue_banned(eq);
673+ mutex_unlock(&group->list_lock);
674+}
675+
571676 #define parallel_read(xe_, map_, field_) \
572677 xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
573678 field_)
@@ -575,6 +680,181 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue · 1 unmodified line
575680 xe_map_wr_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
576681 field_, val_)
577682
683+/**
684+ * DOC: Multi Queue Group GuC interface
685+ *
686+ * The multi queue group coordination between KMD and GuC is through a software
687+ * construct called Context Group Page (CGP). The CGP is a KMD managed 4KB page
688+ * allocated in the global GTT.
689+ *
690+ * CGP format:
691+ *
692+ * +-----------+---------------------------+---------------------------------------------+
693+ * | DWORD | Name | Description |
694+ * +-----------+---------------------------+---------------------------------------------+
695+ * | 0 | Version | Bits [15:8]=Major ver, [7:0]=Minor ver |
696+ * +-----------+---------------------------+---------------------------------------------+
697+ * | 1..15 | RESERVED | MBZ |
698+ * +-----------+---------------------------+---------------------------------------------+
699+ * | 16 | KMD_QUEUE_UPDATE_MASK_DW0 | KMD queue mask for queues 31..0 |
700+ * +-----------+---------------------------+---------------------------------------------+
701+ * | 17 | KMD_QUEUE_UPDATE_MASK_DW1 | KMD queue mask for queues 63..32 |
702+ * +-----------+---------------------------+---------------------------------------------+
703+ * | 18..31 | RESERVED | MBZ |
704+ * +-----------+---------------------------+---------------------------------------------+
705+ * | 32 | Q0CD_DW0 | Queue 0 context LRC descriptor lower DWORD |
706+ * +-----------+---------------------------+---------------------------------------------+
707+ * | 33 | Q0ContextIndex | Context ID for Queue 0 |
708+ * +-----------+---------------------------+---------------------------------------------+
709+ * | 34 | Q1CD_DW0 | Queue 1 context LRC descriptor lower DWORD |
710+ * +-----------+---------------------------+---------------------------------------------+
711+ * | 35 | Q1ContextIndex | Context ID for Queue 1 |
712+ * +-----------+---------------------------+---------------------------------------------+
713+ * | ... |... | ... |
714+ * +-----------+---------------------------+---------------------------------------------+
715+ * | 158 | Q63CD_DW0 | Queue 63 context LRC descriptor lower DWORD |
716+ * +-----------+---------------------------+---------------------------------------------+
717+ * | 159 | Q63ContextIndex | Context ID for Queue 63 |
718+ * +-----------+---------------------------+---------------------------------------------+
719+ * | 160..1024 | RESERVED | MBZ |
720+ * +-----------+---------------------------+---------------------------------------------+
721+ *
722+ * While registering Q0 with GuC, CGP is updated with Q0 entry and GuC is notified
723+ * through XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE H2G message which specifies
724+ * the CGP address. When the secondary queues are added to the group, the CGP is
725+ * updated with entry for that queue and GuC is notified through the H2G interface
726+ * XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC. GuC responds to these H2G messages
727+ * with a XE_GUC_ACTION_NOTIFY_MULTIQ_CONTEXT_CGP_SYNC_DONE G2H message. GuC also
728+ * sends a XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CGP_CONTEXT_ERROR notification for any
729+ * error in the CGP. Only one of these CGP update messages can be outstanding
730+ * (waiting for GuC response) at any time. The bits in KMD_QUEUE_UPDATE_MASK_DW*
731+ * fields indicate which queue entry is being updated in the CGP.
732+ *
733+ * The primary queue (Q0) represents the multi queue group context in GuC and
734+ * submission on any queue of the group must be through Q0 GuC interface only.
735+ *
736+ * As it is not required to register secondary queues with GuC, the secondary queue
737+ * context ids in the CGP are populated with Q0 context id.
738+ */
739+
740+#define CGP_VERSION_MAJOR_SHIFT 8
741+
742+static void xe_guc_exec_queue_group_cgp_update(struct xe_device *xe,
743+ struct xe_exec_queue *q)
744+{
745+ struct xe_exec_queue_group *group = q->multi_queue.group;
746+ u32 guc_id = group->primary->guc->id;
747+
748+ /* Currently implementing CGP version 1.0 */
749+ xe_map_wr(xe, &group->cgp_bo->vmap, 0, u32,
750+ 1 << CGP_VERSION_MAJOR_SHIFT);
751+
752+ xe_map_wr(xe, &group->cgp_bo->vmap,
753+ (32 + q->multi_queue.pos * 2) * sizeof(u32),
754+ u32, lower_32_bits(xe_lrc_descriptor(q->lrc[0])));
755+
756+ xe_map_wr(xe, &group->cgp_bo->vmap,
757+ (33 + q->multi_queue.pos * 2) * sizeof(u32),
758+ u32, guc_id);
759+
760+ if (q->multi_queue.pos / 32) {
761+ xe_map_wr(xe, &group->cgp_bo->vmap, 17 * sizeof(u32),
762+ u32, BIT(q->multi_queue.pos % 32));
763+ xe_map_wr(xe, &group->cgp_bo->vmap, 16 * sizeof(u32), u32, 0);
764+ } else {
765+ xe_map_wr(xe, &group->cgp_bo->vmap, 16 * sizeof(u32),
766+ u32, BIT(q->multi_queue.pos));
767+ xe_map_wr(xe, &group->cgp_bo->vmap, 17 * sizeof(u32), u32, 0);
768+ }
769+}
770+
771+static void xe_guc_exec_queue_group_cgp_sync(struct xe_guc *guc,
772+ struct xe_exec_queue *q,
773+ const u32 *action, u32 len)
774+{
775+ struct xe_exec_queue_group *group = q->multi_queue.group;
776+ struct xe_device *xe = guc_to_xe(guc);
777+ long ret;
778+
779+ /*
780+ * As all queues of a multi queue group use single drm scheduler
781+ * submit workqueue, CGP synchronization with GuC are serialized.
782+ * Hence, no locking is required here.
783+ * Wait for any pending CGP_SYNC_DONE response before updating the
784+ * CGP page and sending CGP_SYNC message.
785+ *
786+ * FIXME: Support VF migration
787+ */
788+ ret = wait_event_timeout(guc->ct.wq,
789+ !READ_ONCE(group->sync_pending) ||
790+ xe_guc_read_stopped(guc), HZ);
791+ if (!ret || xe_guc_read_stopped(guc)) {
792+ /* CGP_SYNC failed. Reset gt, cleanup the group */
793+ xe_gt_warn(guc_to_gt(guc), "Wait for CGP_SYNC_DONE response failed!\n");
794+ set_exec_queue_group_banned(q);
795+ xe_gt_reset_async(q->gt);
796+ xe_guc_exec_queue_group_trigger_cleanup(q);
797+ return;
798+ }
799+
800+ xe_lrc_set_multi_queue_priority(q->lrc[0], q->multi_queue.priority);
801+ xe_guc_exec_queue_group_cgp_update(xe, q);
802+
803+ WRITE_ONCE(group->sync_pending, true);
804+ xe_guc_ct_send(&guc->ct, action, len, G2H_LEN_DW_MULTI_QUEUE_CONTEXT, 1);
805+}
806+
807+static void __register_exec_queue_group(struct xe_guc *guc,
808+ struct xe_exec_queue *q,
809+ struct guc_ctxt_registration_info *info)
810+{
811+#define MAX_MULTI_QUEUE_REG_SIZE (8)
812+ u32 action[MAX_MULTI_QUEUE_REG_SIZE];
813+ int len = 0;
814+
815+ action[len++] = XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE;
816+ action[len++] = info->flags;
817+ action[len++] = info->context_idx;
818+ action[len++] = info->engine_class;
819+ action[len++] = info->engine_submit_mask;
820+ action[len++] = 0; /* Reserved */
821+ action[len++] = info->cgp_lo;
822+ action[len++] = info->cgp_hi;
823+
824+ xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_REG_SIZE);
825+#undef MAX_MULTI_QUEUE_REG_SIZE
826+
827+ /*
828+ * The above XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE do expect a
829+ * XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE response
830+ * from guc.
831+ */
832+ xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
833+}
834+
835+static void xe_guc_exec_queue_group_add(struct xe_guc *guc,
836+ struct xe_exec_queue *q)
837+{
838+#define MAX_MULTI_QUEUE_CGP_SYNC_SIZE (2)
839+ u32 action[MAX_MULTI_QUEUE_CGP_SYNC_SIZE];
840+ int len = 0;
841+
842+ xe_gt_assert(guc_to_gt(guc), xe_exec_queue_is_multi_queue_secondary(q));
843+
844+ action[len++] = XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC;
845+ action[len++] = q->multi_queue.group->primary->guc->id;
846+
847+ xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_CGP_SYNC_SIZE);
848+#undef MAX_MULTI_QUEUE_CGP_SYNC_SIZE
849+
850+ /*
851+ * The above XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC do expect a
852+ * XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE response
853+ * from guc.
854+ */
855+ xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
856+}
857+
578858 static void __register_mlrc_exec_queue(struct xe_guc *guc,
579859 struct xe_exec_queue *q,
580860 struct guc_ctxt_registration_info *info)
@@ -670,6 +950,13 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type) · 89 unmodified lines
670950 info.flags = CONTEXT_REGISTRATION_FLAG_KMD |
671951 FIELD_PREP(CONTEXT_REGISTRATION_FLAG_TYPE, ctx_type);
672952
953+ if (xe_exec_queue_is_multi_queue(q)) {
954+ struct xe_exec_queue_group *group = q->multi_queue.group;
955+
956+ info.cgp_lo = xe_bo_ggtt_addr(group->cgp_bo);
957+ info.cgp_hi = 0;
958+ }
959+
673960 if (xe_exec_queue_is_parallel(q)) {
674961 u64 ggtt_addr = xe_lrc_parallel_ggtt_addr(lrc);
675962 struct iosys_map map = xe_lrc_parallel_map(lrc);
@@ -700,11 +987,18 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type) · 24 unmodified lines
700987
701988 set_exec_queue_registered(q);
702989 trace_xe_exec_queue_register(q);
703− if (xe_exec_queue_is_parallel(q))
990+ if (xe_exec_queue_is_multi_queue_primary(q))
991+ __register_exec_queue_group(guc, q, &info);
992+ else if (xe_exec_queue_is_parallel(q))
704993 __register_mlrc_exec_queue(guc, q, &info);
705− else
994+ else if (!xe_exec_queue_is_multi_queue_secondary(q))
706995 __register_exec_queue(guc, &info);
707− init_policies(guc, q);
996+
997+ if (!xe_exec_queue_is_multi_queue_secondary(q))
998+ init_policies(guc, q);
999+
1000+ if (xe_exec_queue_is_multi_queue_secondary(q))
1001+ xe_guc_exec_queue_group_add(guc, q);
7081002 }
7091003
7101004 static u32 wq_space_until_wrap(struct xe_exec_queue *q)
@@ -712,11 +1006,6 @@ static u32 wq_space_until_wrap(struct xe_exec_queue *q) · 1 unmodified line
7121006 return (WQ_SIZE - q->guc->wqi_tail);
7131007 }
7141008
715−static bool vf_recovery(struct xe_guc *guc)
716−{
717− return xe_gt_recovery_pending(guc_to_gt(guc));
718−}
719−
7201009 static inline void relaxed_ms_sleep(unsigned int delay_ms)
7211010 {
7221011 unsigned long min_us, max_us;
@@ -845,7 +1134,7 @@ static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job) · 122 unmodified lines
8451134 if (!job->restore_replay || job->last_replay) {
8461135 if (xe_exec_queue_is_parallel(q))
8471136 wq_item_append(q);
848− else
1137+ else if (!exec_queue_idle_skip_suspend(q))
8491138 xe_lrc_set_ring_tail(lrc, lrc->ring.tail);
8501139 job->last_replay = false;
8511140 }
@@ -853,6 +1142,12 @@ static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job) · 1 unmodified line
8531142 if (exec_queue_suspended(q) && !xe_exec_queue_is_parallel(q))
8541143 return;
8551144
1145+ /*
1146+ * All queues in a multi-queue group will use the primary queue
1147+ * of the group to interface with GuC.
1148+ */
1149+ q = xe_exec_queue_multi_queue_primary(q);
1150+
8561151 if (!exec_queue_enabled(q) && !exec_queue_suspended(q)) {
8571152 action[len++] = XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET;
8581153 action[len++] = q->guc->id;
@@ -899,6 +1194,18 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job) · 40 unmodified lines
8991194 trace_xe_sched_job_run(job);
9001195
9011196 if (!killed_or_banned_or_wedged && !xe_sched_job_is_error(job)) {
1197+ if (xe_exec_queue_is_multi_queue_secondary(q)) {
1198+ struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
1199+
1200+ if (exec_queue_killed_or_banned_or_wedged(primary)) {
1201+ killed_or_banned_or_wedged = true;
1202+ goto run_job_out;
1203+ }
1204+
1205+ if (!exec_queue_registered(primary))
1206+ register_exec_queue(primary, GUC_CONTEXT_NORMAL);
1207+ }
1208+
9021209 if (!exec_queue_registered(q))
9031210 register_exec_queue(q, GUC_CONTEXT_NORMAL);
9041211 if (!job->restore_replay)
@@ -907,6 +1214,7 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job) · 2 unmodified lines
9071214 job->restore_replay = false;
9081215 }
9091216
1217+run_job_out:
9101218 /*
9111219 * We don't care about job-fence ordering in LR VMs because these fences
9121220 * are never exported; they are used solely to keep jobs on the pending
@@ -932,6 +1240,11 @@ int xe_guc_read_stopped(struct xe_guc *guc) · 19 unmodified lines
9321240 return atomic_read(&guc->submission_state.stopped);
9331241 }
9341242
1243+static void handle_multi_queue_secondary_sched_done(struct xe_guc *guc,
1244+ struct xe_exec_queue *q,
1245+ u32 runnable_state);
1246+static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q);
1247+
9351248 #define MAKE_SCHED_CONTEXT_ACTION(q, enable_disable) \
9361249 u32 action[] = { \
9371250 XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET, \
@@ -945,7 +1258,9 @@ static void disable_scheduling_deregister(struct xe_guc *guc, · 7 unmodified lines
9451258 MAKE_SCHED_CONTEXT_ACTION(q, DISABLE);
9461259 int ret;
9471260
948− set_min_preemption_timeout(guc, q);
1261+ if (!xe_exec_queue_is_multi_queue_secondary(q))
1262+ set_min_preemption_timeout(guc, q);
1263+
9491264 smp_rmb();
9501265 ret = wait_event_timeout(guc->ct.wq,
9511266 (!exec_queue_pending_enable(q) &&
@@ -973,23 +1288,12 @@ static void disable_scheduling_deregister(struct xe_guc *guc, · 21 unmodified lines
9731288 * Reserve space for both G2H here as the 2nd G2H is sent from a G2H
9741289 * handler and we are not allowed to reserved G2H space in handlers.
9751290 */
976− xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
977− G2H_LEN_DW_SCHED_CONTEXT_MODE_SET +
978− G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
979−}
980−
981−static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
982−{
983− struct xe_guc *guc = exec_queue_to_guc(q);
984− struct xe_device *xe = guc_to_xe(guc);
985−
986− /** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
987− wake_up_all(&xe->ufence_wq);
988−
989− if (xe_exec_queue_is_lr(q))
990− queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
1291+ if (xe_exec_queue_is_multi_queue_secondary(q))
1292+ handle_multi_queue_secondary_sched_done(guc, q, 0);
9911293 else
992− xe_sched_tdr_queue_imm(&q->guc->sched);
1294+ xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
1295+ G2H_LEN_DW_SCHED_CONTEXT_MODE_SET +
1296+ G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
9931297 }
9941298
9951299 /**
@@ -1181,8 +1485,11 @@ static void enable_scheduling(struct xe_exec_queue *q) · 185 unmodified lines
11811485 set_exec_queue_enabled(q);
11821486 trace_xe_exec_queue_scheduling_enable(q);
11831487
1184− xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
1185− G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
1488+ if (xe_exec_queue_is_multi_queue_secondary(q))
1489+ handle_multi_queue_secondary_sched_done(guc, q, 1);
1490+ else
1491+ xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
1492+ G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
11861493
11871494 ret = wait_event_timeout(guc->ct.wq,
11881495 !exec_queue_pending_enable(q) ||
@@ -1206,14 +1513,17 @@ static void disable_scheduling(struct xe_exec_queue *q, bool immediate) · 17 unmodified lines
12061513 xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
12071514 xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q));
12081515
1209− if (immediate)
1516+ if (immediate && !xe_exec_queue_is_multi_queue_secondary(q))
12101517 set_min_preemption_timeout(guc, q);
12111518 clear_exec_queue_enabled(q);
12121519 set_exec_queue_pending_disable(q);
12131520 trace_xe_exec_queue_scheduling_disable(q);
12141521
1215− xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
1216− G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
1522+ if (xe_exec_queue_is_multi_queue_secondary(q))
1523+ handle_multi_queue_secondary_sched_done(guc, q, 0);
1524+ else
1525+ xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
1526+ G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
12171527 }
12181528
12191529 static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
@@ -1231,8 +1541,11 @@ static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q) · 11 unmodified lines
12311541 set_exec_queue_destroyed(q);
12321542 trace_xe_exec_queue_deregister(q);
12331543
1234− xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
1235− G2H_LEN_DW_DEREGISTER_CONTEXT, 1);
1544+ if (xe_exec_queue_is_multi_queue_secondary(q))
1545+ handle_deregister_done(guc, q);
1546+ else
1547+ xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
1548+ G2H_LEN_DW_DEREGISTER_CONTEXT, 1);
12361549 }
12371550
12381551 static enum drm_gpu_sched_stat
@@ -1245,7 +1558,6 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) · 6 unmodified lines
12451558 struct xe_guc *guc = exec_queue_to_guc(q);
12461559 const char *process_name = "no process";
12471560 struct xe_device *xe = guc_to_xe(guc);
1248− unsigned int fw_ref;
12491561 int err = -ETIME;
12501562 pid_t pid = -1;
12511563 int i = 0;
@@ -1271,6 +1583,19 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) · 19 unmodified lines
12711583 exec_queue_killed_or_banned_or_wedged(q) ||
12721584 exec_queue_destroyed(q);
12731585
1586+ /* Skip timeout check if multi-queue group is banned */
1587+ if (xe_exec_queue_is_multi_queue(q) &&
1588+ READ_ONCE(q->multi_queue.group->banned))
1589+ skip_timeout_check = true;
1590+
1591+ /*
1592+ * FIXME: In multi-queue scenario, the TDR must ensure that the whole
1593+ * multi-queue group is off the HW before signaling the fences to avoid
1594+ * possible memory corruptions. This means disabling scheduling on the
1595+ * primary queue before or during the secondary queue's TDR. Need to
1596+ * implement this in least obtrusive way.
1597+ */
1598+
12741599 /*
12751600 * If devcoredump not captured and GuC capture for the job is not ready
12761601 * do manual capture first and decide later if we need to use it
@@ -1278,13 +1603,11 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) · 1 unmodified line
12781603 if (!exec_queue_killed(q) && !xe->devcoredump.captured &&
12791604 !xe_guc_capture_get_matching_and_lock(q)) {
12801605 /* take force wake before engine register manual capture */
1281− fw_ref = xe_force_wake_get(gt_to_fw(q->gt), XE_FORCEWAKE_ALL);
1282− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
1606+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(q->gt), XE_FORCEWAKE_ALL);
1607+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL))
12831608 xe_gt_info(q->gt, "failed to get forcewake for coredump capture\n");
12841609
12851610 xe_engine_snapshot_capture_for_queue(q);
1286−
1287− xe_force_wake_put(gt_to_fw(q->gt), fw_ref);
12881611 }
12891612
12901613 /*
@@ -1425,7 +1748,10 @@ trigger_reset: · 134 unmodified lines
14251748 xe_sched_add_pending_job(sched, job);
14261749 xe_sched_submission_start(sched);
14271750
1428− xe_guc_exec_queue_trigger_cleanup(q);
1751+ if (xe_exec_queue_is_multi_queue(q))
1752+ xe_guc_exec_queue_group_trigger_cleanup(q);
1753+ else
1754+ xe_guc_exec_queue_trigger_cleanup(q);
14291755
14301756 /* Mark all outstanding jobs as bad, thus completing them */
14311757 spin_lock(&sched->base.job_list_lock);
@@ -1475,17 +1801,23 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w) · 43 unmodified lines
14751801 struct xe_exec_queue *q = ge->q;
14761802 struct xe_guc *guc = exec_queue_to_guc(q);
14771803
1478− xe_pm_runtime_get(guc_to_xe(guc));
1804+ guard(xe_pm_runtime)(guc_to_xe(guc));
14791805 trace_xe_exec_queue_destroy(q);
14801806
1807+ if (xe_exec_queue_is_multi_queue_secondary(q)) {
1808+ struct xe_exec_queue_group *group = q->multi_queue.group;
1809+
1810+ mutex_lock(&group->list_lock);
1811+ list_del(&q->multi_queue.link);
1812+ mutex_unlock(&group->list_lock);
1813+ }
1814+
14811815 if (xe_exec_queue_is_lr(q))
14821816 cancel_work_sync(&ge->lr_tdr);
14831817 /* Confirm no work left behind accessing device structures */
14841818 cancel_delayed_work_sync(&ge->sched.base.work_tdr);
14851819
14861820 xe_exec_queue_fini(q);
1487−
1488− xe_pm_runtime_put(guc_to_xe(guc));
14891821 }
14901822
14911823 static void guc_exec_queue_destroy_async(struct xe_exec_queue *q)
@@ -1590,9 +1922,10 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg) · 98 unmodified lines
15901922 {
15911923 struct xe_exec_queue *q = msg->private_data;
15921924 struct xe_guc *guc = exec_queue_to_guc(q);
1925+ bool idle_skip_suspend = xe_exec_queue_idle_skip_suspend(q);
15931926
1594− if (guc_exec_queue_allowed_to_change_state(q) && !exec_queue_suspended(q) &&
1595− exec_queue_enabled(q)) {
1927+ if (!idle_skip_suspend && guc_exec_queue_allowed_to_change_state(q) &&
1928+ !exec_queue_suspended(q) && exec_queue_enabled(q)) {
15961929 wait_event(guc->ct.wq, vf_recovery(guc) ||
15971930 ((q->guc->resume_time != RESUME_PENDING ||
15981931 xe_guc_read_stopped(guc)) && !exec_queue_pending_disable(q)));
@@ -1611,11 +1944,33 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg) · 12 unmodified lines
16111944 disable_scheduling(q, false);
16121945 }
16131946 } else if (q->guc->suspend_pending) {
1947+ if (idle_skip_suspend)
1948+ set_exec_queue_idle_skip_suspend(q);
16141949 set_exec_queue_suspended(q);
16151950 suspend_fence_signal(q);
16161951 }
16171952 }
16181953
1954+static void sched_context(struct xe_exec_queue *q)
1955+{
1956+ struct xe_guc *guc = exec_queue_to_guc(q);
1957+ struct xe_lrc *lrc = q->lrc[0];
1958+ u32 action[] = {
1959+ XE_GUC_ACTION_SCHED_CONTEXT,
1960+ q->guc->id,
1961+ };
1962+
1963+ xe_gt_assert(guc_to_gt(guc), !xe_exec_queue_is_parallel(q));
1964+ xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q));
1965+ xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
1966+ xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q));
1967+
1968+ trace_xe_exec_queue_submit(q);
1969+
1970+ xe_lrc_set_ring_tail(lrc, lrc->ring.tail);
1971+ xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0);
1972+}
1973+
16191974 static void __guc_exec_queue_process_msg_resume(struct xe_sched_msg *msg)
16201975 {
16211976 struct xe_exec_queue *q = msg->private_data;
@@ -1623,19 +1978,53 @@ static void __guc_exec_queue_process_msg_resume(struct xe_sched_msg *msg) · 1 unmodified line
16231978 if (guc_exec_queue_allowed_to_change_state(q)) {
16241979 clear_exec_queue_suspended(q);
16251980 if (!exec_queue_enabled(q)) {
1981+ if (exec_queue_idle_skip_suspend(q)) {
1982+ struct xe_lrc *lrc = q->lrc[0];
1983+
1984+ clear_exec_queue_idle_skip_suspend(q);
1985+ xe_lrc_set_ring_tail(lrc, lrc->ring.tail);
1986+ }
16261987 q->guc->resume_time = RESUME_PENDING;
16271988 set_exec_queue_pending_resume(q);
16281989 enable_scheduling(q);
1990+ } else if (exec_queue_idle_skip_suspend(q)) {
1991+ clear_exec_queue_idle_skip_suspend(q);
1992+ sched_context(q);
16291993 }
16301994 } else {
16311995 clear_exec_queue_suspended(q);
1996+ clear_exec_queue_idle_skip_suspend(q);
1997+ }
1998+}
1999+
2000+static void __guc_exec_queue_process_msg_set_multi_queue_priority(struct xe_sched_msg *msg)
2001+{
2002+ struct xe_exec_queue *q = msg->private_data;
2003+
2004+ if (guc_exec_queue_allowed_to_change_state(q)) {
2005+#define MAX_MULTI_QUEUE_CGP_SYNC_SIZE (2)
2006+ struct xe_guc *guc = exec_queue_to_guc(q);
2007+ struct xe_exec_queue_group *group = q->multi_queue.group;
2008+ u32 action[MAX_MULTI_QUEUE_CGP_SYNC_SIZE];
2009+ int len = 0;
2010+
2011+ action[len++] = XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC;
2012+ action[len++] = group->primary->guc->id;
2013+
2014+ xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_CGP_SYNC_SIZE);
2015+#undef MAX_MULTI_QUEUE_CGP_SYNC_SIZE
2016+
2017+ xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
16322018 }
2019+
2020+ kfree(msg);
16332021 }
16342022
1635−#define CLEANUP 1 /* Non-zero values to catch uninitialized msg */
1636−#define SET_SCHED_PROPS 2
1637−#define SUSPEND 3
1638−#define RESUME 4
2023+#define CLEANUP 1 /* Non-zero values to catch uninitialized msg */
2024+#define SET_SCHED_PROPS 2
2025+#define SUSPEND 3
2026+#define RESUME 4
2027+#define SET_MULTI_QUEUE_PRIORITY 5
16392028 #define OPCODE_MASK 0xf
16402029 #define MSG_LOCKED BIT(8)
16412030 #define MSG_HEAD BIT(9)
@@ -1659,6 +2048,9 @@ static void guc_exec_queue_process_msg(struct xe_sched_msg *msg) · 17 unmodified lines
16592048 case RESUME:
16602049 __guc_exec_queue_process_msg_resume(msg);
16612050 break;
2051+ case SET_MULTI_QUEUE_PRIORITY:
2052+ __guc_exec_queue_process_msg_set_multi_queue_priority(msg);
2053+ break;
16622054 default:
16632055 XE_WARN_ON("Unknown message type");
16642056 }
@@ -1680,6 +2072,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) · 15 unmodified lines
16802072 {
16812073 struct xe_gpu_scheduler *sched;
16822074 struct xe_guc *guc = exec_queue_to_guc(q);
2075+ struct workqueue_struct *submit_wq = NULL;
16832076 struct xe_guc_exec_queue *ge;
16842077 long timeout;
16852078 int err, i;
@@ -1700,8 +2093,20 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) · 14 unmodified lines
17002093
17012094 timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT :
17022095 msecs_to_jiffies(q->sched_props.job_timeout_ms);
2096+
2097+ /*
2098+ * Use primary queue's submit_wq for all secondary queues of a
2099+ * multi queue group. This serialization avoids any locking around
2100+ * CGP synchronization with GuC.
2101+ */
2102+ if (xe_exec_queue_is_multi_queue_secondary(q)) {
2103+ struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
2104+
2105+ submit_wq = primary->guc->sched.base.submit_wq;
2106+ }
2107+
17032108 err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops,
1704− NULL, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64,
2109+ submit_wq, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64,
17052110 timeout, guc_to_gt(guc)->ordered_wq, NULL,
17062111 q->name, gt_to_xe(q->gt)->drm.dev);
17072112 if (err)
@@ -1730,7 +2135,23 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) · 22 unmodified lines
17302135
17312136 xe_exec_queue_assign_name(q, q->guc->id);
17322137
1733− trace_xe_exec_queue_create(q);
2138+ /*
2139+ * Maintain secondary queues of the multi queue group in a list
2140+ * for handling dependencies across the queues in the group.
2141+ */
2142+ if (xe_exec_queue_is_multi_queue_secondary(q)) {
2143+ struct xe_exec_queue_group *group = q->multi_queue.group;
2144+
2145+ INIT_LIST_HEAD(&q->multi_queue.link);
2146+ mutex_lock(&group->list_lock);
2147+ list_add_tail(&q->multi_queue.link, &group->list);
2148+ mutex_unlock(&group->list_lock);
2149+ }
2150+
2151+ if (xe_exec_queue_is_multi_queue(q))
2152+ trace_xe_exec_queue_create_multi_queue(q);
2153+ else
2154+ trace_xe_exec_queue_create(q);
17342155
17352156 return 0;
17362157
@@ -1862,6 +2283,27 @@ static int guc_exec_queue_set_preempt_timeout(struct xe_exec_queue *q, · 125 unmodified lines
18622283 return 0;
18632284 }
18642285
2286+static int guc_exec_queue_set_multi_queue_priority(struct xe_exec_queue *q,
2287+ enum xe_multi_queue_priority priority)
2288+{
2289+ struct xe_sched_msg *msg;
2290+
2291+ xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)), xe_exec_queue_is_multi_queue(q));
2292+
2293+ if (q->multi_queue.priority == priority ||
2294+ exec_queue_killed_or_banned_or_wedged(q))
2295+ return 0;
2296+
2297+ msg = kmalloc(sizeof(*msg), GFP_KERNEL);
2298+ if (!msg)
2299+ return -ENOMEM;
2300+
2301+ q->multi_queue.priority = priority;
2302+ guc_exec_queue_add_msg(q, msg, SET_MULTI_QUEUE_PRIORITY);
2303+
2304+ return 0;
2305+}
2306+
18652307 static int guc_exec_queue_suspend(struct xe_exec_queue *q)
18662308 {
18672309 struct xe_gpu_scheduler *sched = &q->guc->sched;
@@ -1936,6 +2378,10 @@ static void guc_exec_queue_resume(struct xe_exec_queue *q) · 68 unmodified lines
19362378
19372379 static bool guc_exec_queue_reset_status(struct xe_exec_queue *q)
19382380 {
2381+ if (xe_exec_queue_is_multi_queue_secondary(q) &&
2382+ guc_exec_queue_reset_status(xe_exec_queue_multi_queue_primary(q)))
2383+ return true;
2384+
19392385 return exec_queue_reset(q) || exec_queue_killed_or_banned_or_wedged(q);
19402386 }
19412387
@@ -1953,6 +2399,7 @@ static const struct xe_exec_queue_ops guc_exec_queue_ops = { · 11 unmodified lines
19532399 .set_priority = guc_exec_queue_set_priority,
19542400 .set_timeslice = guc_exec_queue_set_timeslice,
19552401 .set_preempt_timeout = guc_exec_queue_set_preempt_timeout,
2402+ .set_multi_queue_priority = guc_exec_queue_set_multi_queue_priority,
19562403 .suspend = guc_exec_queue_suspend,
19572404 .suspend_wait = guc_exec_queue_suspend_wait,
19582405 .resume = guc_exec_queue_resume,
@@ -2202,6 +2649,22 @@ void xe_guc_submit_pause(struct xe_guc *guc) · 243 unmodified lines
22022649 struct xe_exec_queue *q;
22032650 unsigned long index;
22042651
2652+ mutex_lock(&guc->submission_state.lock);
2653+ xa_for_each(&guc->submission_state.exec_queue_lookup, index, q)
2654+ xe_sched_submission_stop(&q->guc->sched);
2655+ mutex_unlock(&guc->submission_state.lock);
2656+}
2657+
2658+/**
2659+ * xe_guc_submit_pause_vf - Stop further runs of submission tasks for VF.
2660+ * @guc: the &xe_guc struct instance whose scheduler is to be disabled
2661+ */
2662+void xe_guc_submit_pause_vf(struct xe_guc *guc)
2663+{
2664+ struct xe_exec_queue *q;
2665+ unsigned long index;
2666+
2667+ xe_gt_assert(guc_to_gt(guc), IS_SRIOV_VF(guc_to_xe(guc)));
22052668 xe_gt_assert(guc_to_gt(guc), vf_recovery(guc));
22062669
22072670 mutex_lock(&guc->submission_state.lock);
@@ -2293,14 +2756,15 @@ static void guc_exec_queue_unpause_prepare(struct xe_guc *guc, · 85 unmodified lines
22932756 }
22942757
22952758 /**
2296− * xe_guc_submit_unpause_prepare - Prepare unpause submission tasks on given GuC.
2759+ * xe_guc_submit_unpause_prepare_vf - Prepare unpause submission tasks for VF.
22972760 * @guc: the &xe_guc struct instance whose scheduler is to be prepared for unpause
22982761 */
2299−void xe_guc_submit_unpause_prepare(struct xe_guc *guc)
2762+void xe_guc_submit_unpause_prepare_vf(struct xe_guc *guc)
23002763 {
23012764 struct xe_exec_queue *q;
23022765 unsigned long index;
23032766
2767+ xe_gt_assert(guc_to_gt(guc), IS_SRIOV_VF(guc_to_xe(guc)));
23042768 xe_gt_assert(guc_to_gt(guc), vf_recovery(guc));
23052769
23062770 mutex_lock(&guc->submission_state.lock);
@@ -2376,6 +2840,23 @@ void xe_guc_submit_unpause(struct xe_guc *guc) · 69 unmodified lines
23762840 struct xe_exec_queue *q;
23772841 unsigned long index;
23782842
2843+ mutex_lock(&guc->submission_state.lock);
2844+ xa_for_each(&guc->submission_state.exec_queue_lookup, index, q)
2845+ xe_sched_submission_start(&q->guc->sched);
2846+ mutex_unlock(&guc->submission_state.lock);
2847+}
2848+
2849+/**
2850+ * xe_guc_submit_unpause_vf - Allow further runs of submission tasks for VF.
2851+ * @guc: the &xe_guc struct instance whose scheduler is to be enabled
2852+ */
2853+void xe_guc_submit_unpause_vf(struct xe_guc *guc)
2854+{
2855+ struct xe_exec_queue *q;
2856+ unsigned long index;
2857+
2858+ xe_gt_assert(guc_to_gt(guc), IS_SRIOV_VF(guc_to_xe(guc)));
2859+
23792860 mutex_lock(&guc->submission_state.lock);
23802861 xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) {
23812862 /*
@@ -2452,7 +2933,11 @@ static void deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q) · 70 unmodified lines
24522933
24532934 trace_xe_exec_queue_deregister(q);
24542935
2455− xe_guc_ct_send_g2h_handler(&guc->ct, action, ARRAY_SIZE(action));
2936+ if (xe_exec_queue_is_multi_queue_secondary(q))
2937+ handle_deregister_done(guc, q);
2938+ else
2939+ xe_guc_ct_send_g2h_handler(&guc->ct, action,
2940+ ARRAY_SIZE(action));
24562941 }
24572942
24582943 static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
@@ -2502,6 +2987,16 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q, · 43 unmodified lines
25022987 }
25032988 }
25042989
2990+static void handle_multi_queue_secondary_sched_done(struct xe_guc *guc,
2991+ struct xe_exec_queue *q,
2992+ u32 runnable_state)
2993+{
2994+ /* Take CT lock here as handle_sched_done() do send a h2g message */
2995+ mutex_lock(&guc->ct.lock);
2996+ handle_sched_done(guc, q, runnable_state);
2997+ mutex_unlock(&guc->ct.lock);
2998+}
2999+
25053000 int xe_guc_sched_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
25063001 {
25073002 struct xe_exec_queue *q;
@@ -2585,8 +3080,9 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len) · 77 unmodified lines
25853080 if (unlikely(!q))
25863081 return -EPROTO;
25873082
2588− xe_gt_info(gt, "Engine reset: engine_class=%s, logical_mask: 0x%x, guc_id=%d",
2589− xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id);
3083+ xe_gt_info(gt, "Engine reset: engine_class=%s, logical_mask: 0x%x, guc_id=%d, state=0x%0x",
3084+ xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id,
3085+ atomic_read(&q->guc->state));
25903086
25913087 trace_xe_exec_queue_reset(q);
25923088
@@ -2596,9 +3092,7 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len) · 3 unmodified lines
25963092 * jobs by setting timeout of the job to the minimum value kicking
25973093 * guc_exec_queue_timedout_job.
25983094 */
2599− set_exec_queue_reset(q);
2600− if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
2601− xe_guc_exec_queue_trigger_cleanup(q);
3095+ xe_guc_exec_queue_reset_trigger_cleanup(q);
26023096
26033097 return 0;
26043098 }
@@ -2666,20 +3160,18 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg, · 61 unmodified lines
26663160 * See bspec 54047 and 72187 for details.
26673161 */
26683162 if (type != XE_GUC_CAT_ERR_TYPE_INVALID)
2669− xe_gt_dbg(gt,
2670− "Engine memory CAT error [%u]: class=%s, logical_mask: 0x%x, guc_id=%d",
2671− type, xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id);
3163+ xe_gt_info(gt,
3164+ "Engine memory CAT error [%u]: class=%s, logical_mask: 0x%x, guc_id=%d",
3165+ type, xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id);
26723166 else
2673− xe_gt_dbg(gt,
2674− "Engine memory CAT error: class=%s, logical_mask: 0x%x, guc_id=%d",
2675− xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id);
3167+ xe_gt_info(gt,
3168+ "Engine memory CAT error: class=%s, logical_mask: 0x%x, guc_id=%d",
3169+ xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id);
26763170
26773171 trace_xe_exec_queue_memory_cat_error(q);
26783172
26793173 /* Treat the same as engine reset */
2680− set_exec_queue_reset(q);
2681− if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
2682− xe_guc_exec_queue_trigger_cleanup(q);
3174+ xe_guc_exec_queue_reset_trigger_cleanup(q);
26833175
26843176 return 0;
26853177 }
@@ -2706,6 +3198,73 @@ int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 le · 20 unmodified lines
27063198 return 0;
27073199 }
27083200
3201+int xe_guc_exec_queue_cgp_context_error_handler(struct xe_guc *guc, u32 *msg,
3202+ u32 len)
3203+{
3204+ struct xe_gt *gt = guc_to_gt(guc);
3205+ struct xe_device *xe = guc_to_xe(guc);
3206+ struct xe_exec_queue *q;
3207+ u32 guc_id = msg[2];
3208+
3209+ if (unlikely(len != XE_GUC_EXEC_QUEUE_CGP_CONTEXT_ERROR_LEN)) {
3210+ drm_err(&xe->drm, "Invalid length %u", len);
3211+ return -EPROTO;
3212+ }
3213+
3214+ q = g2h_exec_queue_lookup(guc, guc_id);
3215+ if (unlikely(!q))
3216+ return -EPROTO;
3217+
3218+ xe_gt_dbg(gt,
3219+ "CGP context error: [%s] err=0x%x, q0_id=0x%x LRCA=0x%x guc_id=0x%x",
3220+ msg[0] & 1 ? "uc" : "kmd", msg[1], msg[2], msg[3], msg[4]);
3221+
3222+ trace_xe_exec_queue_cgp_context_error(q);
3223+
3224+ /* Treat the same as engine reset */
3225+ xe_guc_exec_queue_reset_trigger_cleanup(q);
3226+
3227+ return 0;
3228+}
3229+
3230+/**
3231+ * xe_guc_exec_queue_cgp_sync_done_handler - CGP synchronization done handler
3232+ * @guc: guc
3233+ * @msg: message indicating CGP sync done
3234+ * @len: length of message
3235+ *
3236+ * Set multi queue group's sync_pending flag to false and wakeup anyone waiting
3237+ * for CGP synchronization to complete.
3238+ *
3239+ * Return: 0 on success, -EPROTO for malformed messages.
3240+ */
3241+int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
3242+{
3243+ struct xe_device *xe = guc_to_xe(guc);
3244+ struct xe_exec_queue *q;
3245+ u32 guc_id = msg[0];
3246+
3247+ if (unlikely(len < 1)) {
3248+ drm_err(&xe->drm, "Invalid CGP_SYNC_DONE length %u", len);
3249+ return -EPROTO;
3250+ }
3251+
3252+ q = g2h_exec_queue_lookup(guc, guc_id);
3253+ if (unlikely(!q))
3254+ return -EPROTO;
3255+
3256+ if (!xe_exec_queue_is_multi_queue_primary(q)) {
3257+ drm_err(&xe->drm, "Unexpected CGP_SYNC_DONE response");
3258+ return -EPROTO;
3259+ }
3260+
3261+ /* Wakeup the serialized cgp update wait */
3262+ WRITE_ONCE(q->multi_queue.group->sync_pending, false);
3263+ xe_guc_ct_wake_waiters(&guc->ct);
3264+
3265+ return 0;
3266+}
3267+
27093268 static void
27103269 guc_exec_queue_wq_snapshot_capture(struct xe_exec_queue *q,
27113270 struct xe_guc_submit_exec_queue_snapshot *snapshot)
@@ -2805,6 +3364,11 @@ xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q) · 93 unmodified lines
28053364 if (snapshot->parallel_execution)
28063365 guc_exec_queue_wq_snapshot_capture(q, snapshot);
28073366
3367+ if (xe_exec_queue_is_multi_queue(q)) {
3368+ snapshot->multi_queue.valid = true;
3369+ snapshot->multi_queue.primary = xe_exec_queue_multi_queue_primary(q)->guc->id;
3370+ snapshot->multi_queue.pos = q->multi_queue.pos;
3371+ }
28083372 spin_lock(&sched->base.job_list_lock);
28093373 snapshot->pending_list_size = list_count_nodes(&sched->base.pending_list);
28103374 snapshot->pending_list = kmalloc_array(snapshot->pending_list_size,
@@ -2887,6 +3451,11 @@ xe_guc_exec_queue_snapshot_print(struct xe_guc_submit_exec_queue_snapshot *snaps · 76 unmodified lines
28873451 if (snapshot->parallel_execution)
28883452 guc_exec_queue_wq_snapshot_print(snapshot, p);
28893453
3454+ if (snapshot->multi_queue.valid) {
3455+ drm_printf(p, "\tMulti queue primary GuC ID: %d\n", snapshot->multi_queue.primary);
3456+ drm_printf(p, "\tMulti queue position: %d\n", snapshot->multi_queue.pos);
3457+ }
3458+
28903459 for (i = 0; snapshot->pending_list && i < snapshot->pending_list_size;
28913460 i++)
28923461 drm_printf(p, "\tJob: seqno=%d, fence=%d, finished=%d\n",
drivers/gpu/drm/xe/xe_guc_submit.h+7−2
@@ -21,9 +21,11 @@ void xe_guc_submit_reset_wait(struct xe_guc *guc); · 20 unmodified lines
2121 void xe_guc_submit_stop(struct xe_guc *guc);
2222 int xe_guc_submit_start(struct xe_guc *guc);
2323 void xe_guc_submit_pause(struct xe_guc *guc);
24−void xe_guc_submit_unpause(struct xe_guc *guc);
25−void xe_guc_submit_unpause_prepare(struct xe_guc *guc);
2624 void xe_guc_submit_pause_abort(struct xe_guc *guc);
25+void xe_guc_submit_pause_vf(struct xe_guc *guc);
26+void xe_guc_submit_unpause(struct xe_guc *guc);
27+void xe_guc_submit_unpause_vf(struct xe_guc *guc);
28+void xe_guc_submit_unpause_prepare_vf(struct xe_guc *guc);
2729 void xe_guc_submit_wedge(struct xe_guc *guc);
2830
2931 int xe_guc_read_stopped(struct xe_guc *guc);
@@ -34,6 +36,9 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg, · 4 unmodified lines
3436 u32 len);
3537 int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 len);
3638 int xe_guc_error_capture_handler(struct xe_guc *guc, u32 *msg, u32 len);
39+int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
40+int xe_guc_exec_queue_cgp_context_error_handler(struct xe_guc *guc, u32 *msg,
41+ u32 len);
3742
3843 struct xe_guc_submit_exec_queue_snapshot *
3944 xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q);
drivers/gpu/drm/xe/xe_guc_submit_types.h+13−0
@@ -135,6 +135,19 @@ struct xe_guc_submit_exec_queue_snapshot { · 134 unmodified lines
135135 u32 wq[WQ_SIZE / sizeof(u32)];
136136 } parallel;
137137
138+ /** @multi_queue: snapshot of the multi queue information */
139+ struct {
140+ /**
141+ * @multi_queue.primary: GuC id of the primary exec queue
142+ * of the multi queue group.
143+ */
144+ u32 primary;
145+ /** @multi_queue.pos: Position of the exec queue within the multi queue group */
146+ u8 pos;
147+ /** @valid: The exec queue is part of a multi queue group */
148+ bool valid;
149+ } multi_queue;
150+
138151 /** @pending_list_size: Size of the pending list snapshot array */
139152 int pending_list_size;
140153 /** @pending_list: snapshot of the pending list info */
drivers/gpu/drm/xe/xe_guc_tlb_inval.c+31−10
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313 #include "xe_guc_tlb_inval.h"
1414 #include "xe_force_wake.h"
1515 #include "xe_mmio.h"
16+#include "xe_sa.h"
1617 #include "xe_tlb_inval.h"
1718
1819 #include "regs/xe_guc_regs.h"
@@ -34,9 +35,12 @@ static int send_tlb_inval(struct xe_guc *guc, const u32 *action, int len) · 15 unmodified lines
3435 G2H_LEN_DW_TLB_INVALIDATE, 1);
3536 }
3637
37−#define MAKE_INVAL_OP(type) ((type << XE_GUC_TLB_INVAL_TYPE_SHIFT) | \
38+#define MAKE_INVAL_OP_FLUSH(type, flush_cache) ((type << XE_GUC_TLB_INVAL_TYPE_SHIFT) | \
3839 XE_GUC_TLB_INVAL_MODE_HEAVY << XE_GUC_TLB_INVAL_MODE_SHIFT | \
39− XE_GUC_TLB_INVAL_FLUSH_CACHE)
40+ (flush_cache ? \
41+ XE_GUC_TLB_INVAL_FLUSH_CACHE : 0))
42+
43+#define MAKE_INVAL_OP(type) MAKE_INVAL_OP_FLUSH(type, true)
4044
4145 static int send_tlb_inval_all(struct xe_tlb_inval *tlb_inval, u32 seqno)
4246 {
@@ -71,12 +75,11 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno) · 28 unmodified lines
7175 return send_tlb_inval(guc, action, ARRAY_SIZE(action));
7276 } else if (xe_device_uc_enabled(xe) && !xe_device_wedged(xe)) {
7377 struct xe_mmio *mmio = &gt->mmio;
74− unsigned int fw_ref;
7578
7679 if (IS_SRIOV_VF(xe))
7780 return -ECANCELED;
7881
79− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
82+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
8083 if (xe->info.platform == XE_PVC || GRAPHICS_VER(xe) >= 20) {
8184 xe_mmio_write32(mmio, PVC_GUC_TLB_INV_DESC1,
8285 PVC_GUC_TLB_INV_DESC1_INVALIDATE);
@@ -86,12 +89,25 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno) · 3 unmodified lines
8689 xe_mmio_write32(mmio, GUC_TLB_INV_CR,
8790 GUC_TLB_INV_CR_INVALIDATE);
8891 }
89− xe_force_wake_put(gt_to_fw(gt), fw_ref);
9092 }
9193
9294 return -ECANCELED;
9395 }
9496
97+static int send_page_reclaim(struct xe_guc *guc, u32 seqno,
98+ u64 gpu_addr)
99+{
100+ u32 action[] = {
101+ XE_GUC_ACTION_PAGE_RECLAMATION,
102+ seqno,
103+ lower_32_bits(gpu_addr),
104+ upper_32_bits(gpu_addr),
105+ };
106+
107+ return xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
108+ G2H_LEN_DW_PAGE_RECLAMATION, 1);
109+}
110+
95111 /*
96112 * Ensure that roundup_pow_of_two(length) doesn't overflow.
97113 * Note that roundup_pow_of_two() operates on unsigned long,
@@ -100,20 +116,21 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno) · 2 unmodified lines
100116 #define MAX_RANGE_TLB_INVALIDATION_LENGTH (rounddown_pow_of_two(ULONG_MAX))
101117
102118 static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
103− u64 start, u64 end, u32 asid)
119+ u64 start, u64 end, u32 asid,
120+ struct drm_suballoc *prl_sa)
104121 {
105122 #define MAX_TLB_INVALIDATION_LEN 7
106123 struct xe_guc *guc = tlb_inval->private;
107124 struct xe_gt *gt = guc_to_gt(guc);
108125 u32 action[MAX_TLB_INVALIDATION_LEN];
109126 u64 length = end - start;
110− int len = 0;
127+ int len = 0, err;
111128
112129 if (guc_to_xe(guc)->info.force_execlist)
113130 return -ECANCELED;
114131
115132 action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
116− action[len++] = seqno;
133+ action[len++] = !prl_sa ? seqno : TLB_INVALIDATION_SEQNO_INVALID;
117134 if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
118135 length > MAX_RANGE_TLB_INVALIDATION_LENGTH) {
119136 action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL);
@@ -154,7 +171,8 @@ static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno, · 34 unmodified lines
154171 ilog2(SZ_2M) + 1)));
155172 xe_gt_assert(gt, IS_ALIGNED(start, length));
156173
157− action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_PAGE_SELECTIVE);
174+ /* Flush on NULL case, Media is not required to modify flush due to no PPC so NOP */
175+ action[len++] = MAKE_INVAL_OP_FLUSH(XE_GUC_TLB_INVAL_PAGE_SELECTIVE, !prl_sa);
158176 action[len++] = asid;
159177 action[len++] = lower_32_bits(start);
160178 action[len++] = upper_32_bits(start);
@@ -163,7 +181,10 @@ static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno, · 2 unmodified lines
163181
164182 xe_gt_assert(gt, len <= MAX_TLB_INVALIDATION_LEN);
165183
166− return send_tlb_inval(guc, action, len);
184+ err = send_tlb_inval(guc, action, len);
185+ if (!err && prl_sa)
186+ err = send_page_reclaim(guc, seqno, xe_sa_bo_gpu_addr(prl_sa));
187+ return err;
167188 }
168189
169190 static bool tlb_inval_initialized(struct xe_tlb_inval *tlb_inval)
drivers/gpu/drm/xe/xe_huc.c+2−5
@@ -300,19 +300,16 @@ void xe_huc_sanitize(struct xe_huc *huc) · 299 unmodified lines
300300 void xe_huc_print_info(struct xe_huc *huc, struct drm_printer *p)
301301 {
302302 struct xe_gt *gt = huc_to_gt(huc);
303− unsigned int fw_ref;
304303
305304 xe_uc_fw_print(&huc->fw, p);
306305
307306 if (!xe_uc_fw_is_enabled(&huc->fw))
308307 return;
309308
310− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
311− if (!fw_ref)
309+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
310+ if (!fw_ref.domains)
312311 return;
313312
314313 drm_printf(p, "\nHuC status: 0x%08x\n",
315314 xe_mmio_read32(&gt->mmio, HUC_KERNEL_LOAD_INFO));
316−
317− xe_force_wake_put(gt_to_fw(gt), fw_ref);
318315 }
drivers/gpu/drm/xe/xe_huc_debugfs.c+1−2
@@ -37,9 +37,8 @@ static int huc_info(struct seq_file *m, void *data) · 36 unmodified lines
3737 struct xe_device *xe = huc_to_xe(huc);
3838 struct drm_printer p = drm_seq_file_printer(m);
3939
40− xe_pm_runtime_get(xe);
40+ guard(xe_pm_runtime)(xe);
4141 xe_huc_print_info(huc, &p);
42− xe_pm_runtime_put(xe);
4342
4443 return 0;
4544 }
drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c+6−10
@@ -43,16 +43,14 @@ static ssize_t xe_hw_engine_class_sysfs_attr_show(struct kobject *kobj, · 42 unmodified lines
4343 {
4444 struct xe_device *xe = kobj_to_xe(kobj);
4545 struct kobj_attribute *kattr;
46− ssize_t ret = -EIO;
4746
4847 kattr = container_of(attr, struct kobj_attribute, attr);
4948 if (kattr->show) {
50− xe_pm_runtime_get(xe);
51− ret = kattr->show(kobj, kattr, buf);
52− xe_pm_runtime_put(xe);
49+ guard(xe_pm_runtime)(xe);
50+ return kattr->show(kobj, kattr, buf);
5351 }
5452
55− return ret;
53+ return -EIO;
5654 }
5755
5856 static ssize_t xe_hw_engine_class_sysfs_attr_store(struct kobject *kobj,
@@ -62,16 +60,14 @@ static ssize_t xe_hw_engine_class_sysfs_attr_store(struct kobject *kobj, · 3 unmodified lines
6260 {
6361 struct xe_device *xe = kobj_to_xe(kobj);
6462 struct kobj_attribute *kattr;
65− ssize_t ret = -EIO;
6663
6764 kattr = container_of(attr, struct kobj_attribute, attr);
6865 if (kattr->store) {
69− xe_pm_runtime_get(xe);
70− ret = kattr->store(kobj, kattr, buf, count);
71− xe_pm_runtime_put(xe);
66+ guard(xe_pm_runtime)(xe);
67+ return kattr->store(kobj, kattr, buf, count);
7268 }
7369
74− return ret;
70+ return -EIO;
7571 }
7672
7773 static const struct sysfs_ops xe_hw_engine_class_sysfs_ops = {
drivers/gpu/drm/xe/xe_hw_engine_group.c+71−8
@@ -9,7 +9,9 @@ · 8 unmodified lines
99 #include "xe_device.h"
1010 #include "xe_exec_queue.h"
1111 #include "xe_gt.h"
12+#include "xe_gt_stats.h"
1213 #include "xe_hw_engine_group.h"
14+#include "xe_sync.h"
1315 #include "xe_vm.h"
1416
1517 static void
@@ -20,7 +22,8 @@ hw_engine_group_resume_lr_jobs_func(struct work_struct *w) · 4 unmodified lines
2022 int err;
2123 enum xe_hw_engine_group_execution_mode previous_mode;
2224
23− err = xe_hw_engine_group_get_mode(group, EXEC_MODE_LR, &previous_mode);
25+ err = xe_hw_engine_group_get_mode(group, EXEC_MODE_LR, &previous_mode,
26+ NULL, 0);
2427 if (err)
2528 return;
2629
@@ -188,23 +191,39 @@ void xe_hw_engine_group_resume_faulting_lr_jobs(struct xe_hw_engine_group *group · 161 unmodified lines
188191 /**
189192 * xe_hw_engine_group_suspend_faulting_lr_jobs() - Suspend the faulting LR jobs of this group
190193 * @group: The hw engine group
194+ * @has_deps: dma-fence job triggering suspend has dependencies
191195 *
192196 * Return: 0 on success, negative error code on error.
193197 */
194−static int xe_hw_engine_group_suspend_faulting_lr_jobs(struct xe_hw_engine_group *group)
198+static int xe_hw_engine_group_suspend_faulting_lr_jobs(struct xe_hw_engine_group *group,
199+ bool has_deps)
195200 {
196201 int err;
197202 struct xe_exec_queue *q;
203+ struct xe_gt *gt = NULL;
198204 bool need_resume = false;
205+ ktime_t start = xe_gt_stats_ktime_get();
199206
200207 lockdep_assert_held_write(&group->mode_sem);
201208
202209 list_for_each_entry(q, &group->exec_queue_list, hw_engine_group_link) {
210+ bool idle_skip_suspend;
211+
203212 if (!xe_vm_in_fault_mode(q->vm))
204213 continue;
205214
206− need_resume = true;
215+ idle_skip_suspend = xe_exec_queue_idle_skip_suspend(q);
216+ if (!idle_skip_suspend && has_deps)
217+ return -EAGAIN;
218+
219+ xe_gt_stats_incr(q->gt, XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_COUNT, 1);
220+ if (idle_skip_suspend)
221+ xe_gt_stats_incr(q->gt,
222+ XE_GT_STATS_ID_HW_ENGINE_GROUP_SKIP_LR_QUEUE_COUNT, 1);
223+
224+ need_resume |= !idle_skip_suspend;
207225 q->ops->suspend(q);
226+ gt = q->gt;
208227 }
209228
210229 list_for_each_entry(q, &group->exec_queue_list, hw_engine_group_link) {
@@ -216,6 +235,12 @@ static int xe_hw_engine_group_suspend_faulting_lr_jobs(struct xe_hw_engine_group · 5 unmodified lines
216235 return err;
217236 }
218237
238+ if (gt) {
239+ xe_gt_stats_incr(gt,
240+ XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_US,
241+ xe_gt_stats_ktime_us_delta(start));
242+ }
243+
219244 if (need_resume)
220245 xe_hw_engine_group_resume_faulting_lr_jobs(group);
221246
@@ -236,7 +261,9 @@ static int xe_hw_engine_group_wait_for_dma_fence_jobs(struct xe_hw_engine_group · 14 unmodified lines
236261 {
237262 long timeout;
238263 struct xe_exec_queue *q;
264+ struct xe_gt *gt = NULL;
239265 struct dma_fence *fence;
266+ ktime_t start = xe_gt_stats_ktime_get();
240267
241268 lockdep_assert_held_write(&group->mode_sem);
242269
@@ -244,18 +271,26 @@ static int xe_hw_engine_group_wait_for_dma_fence_jobs(struct xe_hw_engine_group · 1 unmodified line
244271 if (xe_vm_in_lr_mode(q->vm))
245272 continue;
246273
274+ xe_gt_stats_incr(q->gt, XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_COUNT, 1);
247275 fence = xe_exec_queue_last_fence_get_for_resume(q, q->vm);
248276 timeout = dma_fence_wait(fence, false);
249277 dma_fence_put(fence);
278+ gt = q->gt;
250279
251280 if (timeout < 0)
252281 return -ETIME;
253282 }
254283
284+ if (gt) {
285+ xe_gt_stats_incr(gt,
286+ XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US,
287+ xe_gt_stats_ktime_us_delta(start));
288+ }
289+
255290 return 0;
256291 }
257292
258−static int switch_mode(struct xe_hw_engine_group *group)
293+static int switch_mode(struct xe_hw_engine_group *group, bool has_deps)
259294 {
260295 int err = 0;
261296 enum xe_hw_engine_group_execution_mode new_mode;
@@ -265,7 +300,8 @@ static int switch_mode(struct xe_hw_engine_group *group) · 3 unmodified lines
265300 switch (group->cur_mode) {
266301 case EXEC_MODE_LR:
267302 new_mode = EXEC_MODE_DMA_FENCE;
268− err = xe_hw_engine_group_suspend_faulting_lr_jobs(group);
303+ err = xe_hw_engine_group_suspend_faulting_lr_jobs(group,
304+ has_deps);
269305 break;
270306 case EXEC_MODE_DMA_FENCE:
271307 new_mode = EXEC_MODE_LR;
@@ -281,19 +317,36 @@ static int switch_mode(struct xe_hw_engine_group *group) · 9 unmodified lines
281317 return 0;
282318 }
283319
320+static int wait_syncs(struct xe_sync_entry *syncs, int num_syncs)
321+{
322+ int err, i;
323+
324+ for (i = 0; i < num_syncs; ++i) {
325+ err = xe_sync_entry_wait(syncs + i);
326+ if (err)
327+ return err;
328+ }
329+
330+ return 0;
331+}
332+
284333 /**
285334 * xe_hw_engine_group_get_mode() - Get the group to execute in the new mode
286335 * @group: The hw engine group
287336 * @new_mode: The new execution mode
288337 * @previous_mode: Pointer to the previous mode provided for use by caller
338+ * @syncs: Syncs from exec IOCTL
339+ * @num_syncs: Number of syncs from exec IOCTL
289340 *
290341 * Return: 0 if successful, -EINTR if locking failed.
291342 */
292343 int xe_hw_engine_group_get_mode(struct xe_hw_engine_group *group,
293344 enum xe_hw_engine_group_execution_mode new_mode,
294− enum xe_hw_engine_group_execution_mode *previous_mode)
345+ enum xe_hw_engine_group_execution_mode *previous_mode,
346+ struct xe_sync_entry *syncs, int num_syncs)
295347 __acquires(&group->mode_sem)
296348 {
349+ bool has_deps = !!num_syncs;
297350 int err = down_read_interruptible(&group->mode_sem);
298351
299352 if (err)
@@ -303,15 +356,25 @@ __acquires(&group->mode_sem) · 3 unmodified lines
303356
304357 if (new_mode != group->cur_mode) {
305358 up_read(&group->mode_sem);
359+retry:
306360 err = down_write_killable(&group->mode_sem);
307361 if (err)
308362 return err;
309363
310364 if (new_mode != group->cur_mode) {
311− err = switch_mode(group);
365+ err = switch_mode(group, has_deps);
312366 if (err) {
313367 up_write(&group->mode_sem);
314− return err;
368+
369+ if (err != -EAGAIN)
370+ return err;
371+
372+ err = wait_syncs(syncs, num_syncs);
373+ if (err)
374+ return err;
375+
376+ has_deps = false;
377+ goto retry;
315378 }
316379 }
317380 downgrade_write(&group->mode_sem);
drivers/gpu/drm/xe/xe_hw_engine_group.h+3−1
@@ -11,6 +11,7 @@ · 10 unmodified lines
1111 struct drm_device;
1212 struct xe_exec_queue;
1313 struct xe_gt;
14+struct xe_sync_entry;
1415
1516 int xe_hw_engine_setup_groups(struct xe_gt *gt);
1617
@@ -19,7 +20,8 @@ void xe_hw_engine_group_del_exec_queue(struct xe_hw_engine_group *group, struct · 2 unmodified lines
1920
2021 int xe_hw_engine_group_get_mode(struct xe_hw_engine_group *group,
2122 enum xe_hw_engine_group_execution_mode new_mode,
22− enum xe_hw_engine_group_execution_mode *previous_mode);
23+ enum xe_hw_engine_group_execution_mode *previous_mode,
24+ struct xe_sync_entry *syncs, int num_syncs);
2325 void xe_hw_engine_group_put(struct xe_hw_engine_group *group);
2426
2527 enum xe_hw_engine_group_execution_mode
drivers/gpu/drm/xe/xe_hwmon.c+14−38
@@ -502,7 +502,7 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at · 501 unmodified lines
502502
503503 int ret = 0;
504504
505− xe_pm_runtime_get(hwmon->xe);
505+ guard(xe_pm_runtime)(hwmon->xe);
506506
507507 mutex_lock(&hwmon->hwmon_lock);
508508
@@ -521,8 +521,6 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at · 12 unmodified lines
521521
522522 mutex_unlock(&hwmon->hwmon_lock);
523523
524− xe_pm_runtime_put(hwmon->xe);
525−
526524 x = REG_FIELD_GET(PWR_LIM_TIME_X, reg_val);
527525 y = REG_FIELD_GET(PWR_LIM_TIME_Y, reg_val);
528526
@@ -604,7 +602,7 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a · 75 unmodified lines
604602 rxy = REG_FIELD_PREP(PWR_LIM_TIME_X, x) |
605603 REG_FIELD_PREP(PWR_LIM_TIME_Y, y);
606604
607− xe_pm_runtime_get(hwmon->xe);
605+ guard(xe_pm_runtime)(hwmon->xe);
608606
609607 mutex_lock(&hwmon->hwmon_lock);
610608
@@ -616,8 +614,6 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a · 5 unmodified lines
616614
617615 mutex_unlock(&hwmon->hwmon_lock);
618616
619− xe_pm_runtime_put(hwmon->xe);
620−
621617 return count;
622618 }
623619
@@ -1124,37 +1120,25 @@ xe_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, · 500 unmodified lines
11241120 int channel, long *val)
11251121 {
11261122 struct xe_hwmon *hwmon = dev_get_drvdata(dev);
1127− int ret;
11281123
1129− xe_pm_runtime_get(hwmon->xe);
1124+ guard(xe_pm_runtime)(hwmon->xe);
11301125
11311126 switch (type) {
11321127 case hwmon_temp:
1133− ret = xe_hwmon_temp_read(hwmon, attr, channel, val);
1134− break;
1128+ return xe_hwmon_temp_read(hwmon, attr, channel, val);
11351129 case hwmon_power:
1136− ret = xe_hwmon_power_read(hwmon, attr, channel, val);
1137− break;
1130+ return xe_hwmon_power_read(hwmon, attr, channel, val);
11381131 case hwmon_curr:
1139− ret = xe_hwmon_curr_read(hwmon, attr, channel, val);
1140− break;
1132+ return xe_hwmon_curr_read(hwmon, attr, channel, val);
11411133 case hwmon_in:
1142− ret = xe_hwmon_in_read(hwmon, attr, channel, val);
1143− break;
1134+ return xe_hwmon_in_read(hwmon, attr, channel, val);
11441135 case hwmon_energy:
1145− ret = xe_hwmon_energy_read(hwmon, attr, channel, val);
1146− break;
1136+ return xe_hwmon_energy_read(hwmon, attr, channel, val);
11471137 case hwmon_fan:
1148− ret = xe_hwmon_fan_read(hwmon, attr, channel, val);
1149− break;
1138+ return xe_hwmon_fan_read(hwmon, attr, channel, val);
11501139 default:
1151− ret = -EOPNOTSUPP;
1152− break;
1140+ return -EOPNOTSUPP;
11531141 }
1154−
1155− xe_pm_runtime_put(hwmon->xe);
1156−
1157− return ret;
11581142 }
11591143
11601144 static int
@@ -1162,25 +1146,17 @@ xe_hwmon_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, · 1 unmodified line
11621146 int channel, long val)
11631147 {
11641148 struct xe_hwmon *hwmon = dev_get_drvdata(dev);
1165− int ret;
11661149
1167− xe_pm_runtime_get(hwmon->xe);
1150+ guard(xe_pm_runtime)(hwmon->xe);
11681151
11691152 switch (type) {
11701153 case hwmon_power:
1171− ret = xe_hwmon_power_write(hwmon, attr, channel, val);
1172− break;
1154+ return xe_hwmon_power_write(hwmon, attr, channel, val);
11731155 case hwmon_curr:
1174− ret = xe_hwmon_curr_write(hwmon, attr, channel, val);
1175− break;
1156+ return xe_hwmon_curr_write(hwmon, attr, channel, val);
11761157 default:
1177− ret = -EOPNOTSUPP;
1178− break;
1158+ return -EOPNOTSUPP;
11791159 }
1180−
1181− xe_pm_runtime_put(hwmon->xe);
1182−
1183− return ret;
11841160 }
11851161
11861162 static int xe_hwmon_read_label(struct device *dev,
drivers/gpu/drm/xe/xe_i2c.c+1−1
@@ -319,7 +319,7 @@ int xe_i2c_probe(struct xe_device *xe) · 318 unmodified lines
319319 struct xe_i2c *i2c;
320320 int ret;
321321
322− if (xe->info.platform != XE_BATTLEMAGE)
322+ if (!xe->info.has_i2c)
323323 return 0;
324324
325325 if (IS_SRIOV_VF(xe))
drivers/gpu/drm/xe/xe_irq.c+2−0
@@ -21,6 +21,7 @@ · 20 unmodified lines
2121 #include "xe_hw_error.h"
2222 #include "xe_i2c.h"
2323 #include "xe_memirq.h"
24+#include "xe_mert.h"
2425 #include "xe_mmio.h"
2526 #include "xe_pxp.h"
2627 #include "xe_sriov.h"
@@ -525,6 +526,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg) · 498 unmodified lines
525526 xe_heci_csc_irq_handler(xe, master_ctl);
526527 xe_display_irq_handler(xe, master_ctl);
527528 xe_i2c_irq_handler(xe, master_ctl);
529+ xe_mert_irq_handler(xe, master_ctl);
528530 gu_misc_iir = gu_misc_irq_ack(xe, master_ctl);
529531 }
530532 }
drivers/gpu/drm/xe/xe_lmtt.c+22−3
@@ -8,15 +8,18 @@ · 7 unmodified lines
88 #include <drm/drm_managed.h>
99
1010 #include "regs/xe_gt_regs.h"
11+#include "regs/xe_mert_regs.h"
1112
1213 #include "xe_assert.h"
1314 #include "xe_bo.h"
1415 #include "xe_tlb_inval.h"
1516 #include "xe_lmtt.h"
1617 #include "xe_map.h"
18+#include "xe_mert.h"
1719 #include "xe_mmio.h"
1820 #include "xe_res_cursor.h"
1921 #include "xe_sriov.h"
22+#include "xe_tile.h"
2023 #include "xe_tile_sriov_printk.h"
2124
2225 /**
@@ -196,16 +199,22 @@ static void lmtt_setup_dir_ptr(struct xe_lmtt *lmtt) · 173 unmodified lines
196199 struct xe_device *xe = tile_to_xe(tile);
197200 dma_addr_t offset = xe_bo_main_addr(lmtt->pd->bo, XE_PAGE_SIZE);
198201 struct xe_gt *gt;
202+ u32 config;
199203 u8 id;
200204
201205 lmtt_debug(lmtt, "DIR offset %pad\n", &offset);
202206 lmtt_assert(lmtt, xe_bo_is_vram(lmtt->pd->bo));
203207 lmtt_assert(lmtt, IS_ALIGNED(offset, SZ_64K));
204208
209+ config = LMEM_EN | REG_FIELD_PREP(LMTT_DIR_PTR, offset / SZ_64K);
210+
205211 for_each_gt_on_tile(gt, tile, id)
206212 xe_mmio_write32(&gt->mmio,
207213 GRAPHICS_VER(xe) >= 20 ? XE2_LMEM_CFG : LMEM_CFG,
208− LMEM_EN | REG_FIELD_PREP(LMTT_DIR_PTR, offset / SZ_64K));
214+ config);
215+
216+ if (xe_device_has_mert(xe) && xe_tile_is_root(tile))
217+ xe_mmio_write32(&tile->mmio, MERT_LMEM_CFG, config);
209218 }
210219
211220 /**
@@ -262,19 +271,29 @@ static int lmtt_invalidate_hw(struct xe_lmtt *lmtt) · 50 unmodified lines
262271 * @lmtt: the &xe_lmtt to invalidate
263272 *
264273 * Send requests to all GuCs on this tile to invalidate all TLBs.
274+ * If the platform has a standalone MERT, also invalidate MERT's TLB.
265275 *
266276 * This function should be called only when running as a PF driver.
267277 */
268278 void xe_lmtt_invalidate_hw(struct xe_lmtt *lmtt)
269279 {
280+ struct xe_tile *tile = lmtt_to_tile(lmtt);
281+ struct xe_device *xe = lmtt_to_xe(lmtt);
270282 int err;
271283
272− lmtt_assert(lmtt, IS_SRIOV_PF(lmtt_to_xe(lmtt)));
284+ lmtt_assert(lmtt, IS_SRIOV_PF(xe));
273285
274286 err = lmtt_invalidate_hw(lmtt);
275287 if (err)
276− xe_tile_sriov_err(lmtt_to_tile(lmtt), "LMTT invalidation failed (%pe)",
288+ xe_tile_sriov_err(tile, "LMTT invalidation failed (%pe)",
277289 ERR_PTR(err));
290+
291+ if (xe_device_has_mert(xe) && xe_tile_is_root(tile)) {
292+ err = xe_mert_invalidate_lmtt(tile);
293+ if (err)
294+ xe_tile_sriov_err(tile, "MERT LMTT invalidation failed (%pe)",
295+ ERR_PTR(err));
296+ }
278297 }
279298
280299 static void lmtt_write_pte(struct xe_lmtt *lmtt, struct xe_lmtt_pt *pt,
drivers/gpu/drm/xe/xe_lrc.c+63−10
@@ -44,6 +44,11 @@ · 43 unmodified lines
4444 #define LRC_INDIRECT_CTX_BO_SIZE SZ_4K
4545 #define LRC_INDIRECT_RING_STATE_SIZE SZ_4K
4646
47+#define LRC_PRIORITY GENMASK_ULL(10, 9)
48+#define LRC_PRIORITY_LOW 0
49+#define LRC_PRIORITY_NORMAL 1
50+#define LRC_PRIORITY_HIGH 2
51+
4752 /*
4853 * Layout of the LRC and associated data allocated as
4954 * lrc->bo:
@@ -91,13 +96,19 @@ gt_engine_needs_indirect_ctx(struct xe_gt *gt, enum xe_engine_class class) · 41 unmodified lines
9196 return false;
9297 }
9398
94−size_t xe_gt_lrc_size(struct xe_gt *gt, enum xe_engine_class class)
99+/**
100+ * xe_gt_lrc_hang_replay_size() - Hang replay size
101+ * @gt: The GT
102+ * @class: Hardware engine class
103+ *
104+ * Determine size of GPU hang replay state for a GT and hardware engine class.
105+ *
106+ * Return: Size of GPU hang replay size
107+ */
108+size_t xe_gt_lrc_hang_replay_size(struct xe_gt *gt, enum xe_engine_class class)
95109 {
96110 struct xe_device *xe = gt_to_xe(gt);
97− size_t size;
98−
99− /* Per-process HW status page (PPHWSP) */
100− size = LRC_PPHWSP_SIZE;
111+ size_t size = 0;
101112
102113 /* Engine context image */
103114 switch (class) {
@@ -123,11 +134,18 @@ size_t xe_gt_lrc_size(struct xe_gt *gt, enum xe_engine_class class) · 19 unmodified lines
123134 size += 1 * SZ_4K;
124135 }
125136
137+ return size;
138+}
139+
140+size_t xe_gt_lrc_size(struct xe_gt *gt, enum xe_engine_class class)
141+{
142+ size_t size = xe_gt_lrc_hang_replay_size(gt, class);
143+
126144 /* Add indirect ring state page */
127145 if (xe_gt_has_indirect_ring_state(gt))
128146 size += LRC_INDIRECT_RING_STATE_SIZE;
129147
130− return size;
148+ return size + LRC_PPHWSP_SIZE;
131149 }
132150
133151 /*
@@ -1386,8 +1404,33 @@ setup_indirect_ctx(struct xe_lrc *lrc, struct xe_hw_engine *hwe) · 1252 unmodified lines
13861404 return 0;
13871405 }
13881406
1407+static u8 xe_multi_queue_prio_to_lrc(struct xe_lrc *lrc, enum xe_multi_queue_priority priority)
1408+{
1409+ struct xe_device *xe = gt_to_xe(lrc->gt);
1410+
1411+ xe_assert(xe, (priority >= XE_MULTI_QUEUE_PRIORITY_LOW &&
1412+ priority <= XE_MULTI_QUEUE_PRIORITY_HIGH));
1413+
1414+ /* xe_multi_queue_priority is directly mapped to LRC priority values */
1415+ return priority;
1416+}
1417+
1418+/**
1419+ * xe_lrc_set_multi_queue_priority() - Set multi queue priority in LRC
1420+ * @lrc: Logical Ring Context
1421+ * @priority: Multi queue priority of the exec queue
1422+ *
1423+ * Convert @priority to LRC multi queue priority and update the @lrc descriptor
1424+ */
1425+void xe_lrc_set_multi_queue_priority(struct xe_lrc *lrc, enum xe_multi_queue_priority priority)
1426+{
1427+ lrc->desc &= ~LRC_PRIORITY;
1428+ lrc->desc |= FIELD_PREP(LRC_PRIORITY, xe_multi_queue_prio_to_lrc(lrc, priority));
1429+}
1430+
13891431 static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
1390− struct xe_vm *vm, u32 ring_size, u16 msix_vec,
1432+ struct xe_vm *vm, void *replay_state, u32 ring_size,
1433+ u16 msix_vec,
13911434 u32 init_flags)
13921435 {
13931436 struct xe_gt *gt = hwe->gt;
@@ -1402,6 +1445,7 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, · 8 unmodified lines
14021445
14031446 kref_init(&lrc->refcount);
14041447 lrc->gt = gt;
1448+ lrc->replay_size = xe_gt_lrc_hang_replay_size(gt, hwe->class);
14051449 lrc->size = lrc_size;
14061450 lrc->flags = 0;
14071451 lrc->ring.size = ring_size;
@@ -1438,11 +1482,14 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, · 30 unmodified lines
14381482 * scratch.
14391483 */
14401484 map = __xe_lrc_pphwsp_map(lrc);
1441− if (gt->default_lrc[hwe->class]) {
1485+ if (gt->default_lrc[hwe->class] || replay_state) {
14421486 xe_map_memset(xe, &map, 0, 0, LRC_PPHWSP_SIZE); /* PPHWSP */
14431487 xe_map_memcpy_to(xe, &map, LRC_PPHWSP_SIZE,
14441488 gt->default_lrc[hwe->class] + LRC_PPHWSP_SIZE,
14451489 lrc_size - LRC_PPHWSP_SIZE);
1490+ if (replay_state)
1491+ xe_map_memcpy_to(xe, &map, LRC_PPHWSP_SIZE,
1492+ replay_state, lrc->replay_size);
14461493 } else {
14471494 void *init_data = empty_lrc_data(hwe);
14481495
@@ -1550,6 +1597,7 @@ err_lrc_finish: · 101 unmodified lines
15501597 * xe_lrc_create - Create a LRC
15511598 * @hwe: Hardware Engine
15521599 * @vm: The VM (address space)
1600+ * @replay_state: GPU hang replay state
15531601 * @ring_size: LRC ring size
15541602 * @msix_vec: MSI-X interrupt vector (for platforms that support it)
15551603 * @flags: LRC initialization flags
@@ -1560,7 +1608,7 @@ err_lrc_finish: · 4 unmodified lines
15601608 * upon failure.
15611609 */
15621610 struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm,
1563− u32 ring_size, u16 msix_vec, u32 flags)
1611+ void *replay_state, u32 ring_size, u16 msix_vec, u32 flags)
15641612 {
15651613 struct xe_lrc *lrc;
15661614 int err;
@@ -1569,7 +1617,7 @@ struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm, · 2 unmodified lines
15691617 if (!lrc)
15701618 return ERR_PTR(-ENOMEM);
15711619
1572− err = xe_lrc_init(lrc, hwe, vm, ring_size, msix_vec, flags);
1620+ err = xe_lrc_init(lrc, hwe, vm, replay_state, ring_size, msix_vec, flags);
15731621 if (err) {
15741622 kfree(lrc);
15751623 return ERR_PTR(err);
@@ -2235,6 +2283,8 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc) · 659 unmodified lines
22352283 snapshot->lrc_bo = xe_bo_get(lrc->bo);
22362284 snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc);
22372285 snapshot->lrc_size = lrc->size;
2286+ snapshot->replay_offset = 0;
2287+ snapshot->replay_size = lrc->replay_size;
22382288 snapshot->lrc_snapshot = NULL;
22392289 snapshot->ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(lrc));
22402290 snapshot->ctx_job_timestamp = xe_lrc_ctx_job_timestamp(lrc);
@@ -2305,6 +2355,9 @@ void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer · 64 unmodified lines
23052355 }
23062356
23072357 drm_printf(p, "\n\t[HWCTX].length: 0x%lx\n", snapshot->lrc_size - LRC_PPHWSP_SIZE);
2358+ drm_printf(p, "\n\t[HWCTX].replay_offset: 0x%lx\n", snapshot->replay_offset);
2359+ drm_printf(p, "\n\t[HWCTX].replay_length: 0x%lx\n", snapshot->replay_size);
2360+
23082361 drm_puts(p, "\t[HWCTX].data: ");
23092362 for (; i < snapshot->lrc_size; i += sizeof(u32)) {
23102363 u32 *val = snapshot->lrc_snapshot + i;
drivers/gpu/drm/xe/xe_lrc.h+6−1
@@ -13,6 +13,7 @@ struct drm_printer; · 12 unmodified lines
1313 struct xe_bb;
1414 struct xe_device;
1515 struct xe_exec_queue;
16+enum xe_multi_queue_priority;
1617 enum xe_engine_class;
1718 struct xe_gt;
1819 struct xe_hw_engine;
@@ -23,6 +24,7 @@ struct xe_lrc_snapshot { · 4 unmodified lines
2324 struct xe_bo *lrc_bo;
2425 void *lrc_snapshot;
2526 unsigned long lrc_size, lrc_offset;
27+ unsigned long replay_size, replay_offset;
2628
2729 u32 context_desc;
2830 u32 ring_addr;
@@ -49,7 +51,7 @@ struct xe_lrc_snapshot { · 20 unmodified lines
4951 #define XE_LRC_CREATE_USER_CTX BIT(2)
5052
5153 struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm,
52− u32 ring_size, u16 msix_vec, u32 flags);
54+ void *replay_state, u32 ring_size, u16 msix_vec, u32 flags);
5355 void xe_lrc_destroy(struct kref *ref);
5456
5557 /**
@@ -86,6 +88,7 @@ static inline size_t xe_lrc_ring_size(void) · 30 unmodified lines
8688 return SZ_16K;
8789 }
8890
91+size_t xe_gt_lrc_hang_replay_size(struct xe_gt *gt, enum xe_engine_class class);
8992 size_t xe_gt_lrc_size(struct xe_gt *gt, enum xe_engine_class class);
9093 u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc);
9194 u32 xe_lrc_regs_offset(struct xe_lrc *lrc);
@@ -133,6 +136,8 @@ void xe_lrc_dump_default(struct drm_printer *p, · 41 unmodified lines
133136
134137 u32 *xe_lrc_emit_hwe_state_instructions(struct xe_exec_queue *q, u32 *cs);
135138
139+void xe_lrc_set_multi_queue_priority(struct xe_lrc *lrc, enum xe_multi_queue_priority priority);
140+
136141 struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc);
137142 void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot);
138143 void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer *p);
drivers/gpu/drm/xe/xe_lrc_types.h+3−0
@@ -25,6 +25,9 @@ struct xe_lrc { · 24 unmodified lines
2525 /** @size: size of the lrc and optional indirect ring state */
2626 u32 size;
2727
28+ /** @replay_size: Size LRC needed for replaying a hang */
29+ u32 replay_size;
30+
2831 /** @gt: gt which this LRC belongs to */
2932 struct xe_gt *gt;
3033
drivers/gpu/drm/xe/xe_mert.c+82−0
@@ -0,0 +1,82 @@
1+// SPDX-License-Identifier: MIT
2+/*
3+ * Copyright(c) 2025, Intel Corporation. All rights reserved.
4+ */
5+
6+#include "regs/xe_irq_regs.h"
7+#include "regs/xe_mert_regs.h"
8+
9+#include "xe_device.h"
10+#include "xe_mert.h"
11+#include "xe_mmio.h"
12+#include "xe_tile.h"
13+
14+/**
15+ * xe_mert_invalidate_lmtt - Invalidate MERT LMTT
16+ * @tile: the &xe_tile
17+ *
18+ * Trigger invalidation of the MERT LMTT and wait for completion.
19+ *
20+ * Return: 0 on success or -ETIMEDOUT in case of a timeout.
21+ */
22+int xe_mert_invalidate_lmtt(struct xe_tile *tile)
23+{
24+ struct xe_device *xe = tile_to_xe(tile);
25+ struct xe_mert *mert = &tile->mert;
26+ const long timeout = HZ / 4;
27+ unsigned long flags;
28+
29+ xe_assert(xe, xe_device_has_mert(xe));
30+ xe_assert(xe, xe_tile_is_root(tile));
31+
32+ spin_lock_irqsave(&mert->lock, flags);
33+ if (!mert->tlb_inv_triggered) {
34+ mert->tlb_inv_triggered = true;
35+ reinit_completion(&mert->tlb_inv_done);
36+ xe_mmio_write32(&tile->mmio, MERT_TLB_INV_DESC_A, MERT_TLB_INV_DESC_A_VALID);
37+ }
38+ spin_unlock_irqrestore(&mert->lock, flags);
39+
40+ if (!wait_for_completion_timeout(&mert->tlb_inv_done, timeout))
41+ return -ETIMEDOUT;
42+
43+ return 0;
44+}
45+
46+/**
47+ * xe_mert_irq_handler - Handler for MERT interrupts
48+ * @xe: the &xe_device
49+ * @master_ctl: interrupt register
50+ *
51+ * Handle interrupts generated by MERT.
52+ */
53+void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl)
54+{
55+ struct xe_tile *tile = xe_device_get_root_tile(xe);
56+ unsigned long flags;
57+ u32 reg_val;
58+ u8 err;
59+
60+ if (!(master_ctl & SOC_H2DMEMINT_IRQ))
61+ return;
62+
63+ reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT);
64+ xe_mmio_write32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT, 0);
65+
66+ err = FIELD_GET(MERT_TLB_CT_ERROR_MASK, reg_val);
67+ if (err == MERT_TLB_CT_LMTT_FAULT)
68+ drm_dbg(&xe->drm, "MERT catastrophic error: LMTT fault (VF%u)\n",
69+ FIELD_GET(MERT_TLB_CT_VFID_MASK, reg_val));
70+ else if (err)
71+ drm_dbg(&xe->drm, "MERT catastrophic error: Unexpected fault (0x%x)\n", err);
72+
73+ spin_lock_irqsave(&tile->mert.lock, flags);
74+ if (tile->mert.tlb_inv_triggered) {
75+ reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_INV_DESC_A);
76+ if (!(reg_val & MERT_TLB_INV_DESC_A_VALID)) {
77+ tile->mert.tlb_inv_triggered = false;
78+ complete_all(&tile->mert.tlb_inv_done);
79+ }
80+ }
81+ spin_unlock_irqrestore(&tile->mert.lock, flags);
82+}
drivers/gpu/drm/xe/xe_mert.h+32−0
@@ -0,0 +1,32 @@
1+/* SPDX-License-Identifier: MIT */
2+/*
3+ * Copyright(c) 2025, Intel Corporation. All rights reserved.
4+ */
5+
6+#ifndef __XE_MERT_H__
7+#define __XE_MERT_H__
8+
9+#include <linux/completion.h>
10+#include <linux/spinlock.h>
11+#include <linux/types.h>
12+
13+struct xe_device;
14+struct xe_tile;
15+
16+struct xe_mert {
17+ /** @lock: protects the TLB invalidation status */
18+ spinlock_t lock;
19+ /** @tlb_inv_triggered: indicates if TLB invalidation was triggered */
20+ bool tlb_inv_triggered;
21+ /** @mert.tlb_inv_done: completion of TLB invalidation */
22+ struct completion tlb_inv_done;
23+};
24+
25+#ifdef CONFIG_PCI_IOV
26+int xe_mert_invalidate_lmtt(struct xe_tile *tile);
27+void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl);
28+#else
29+static inline void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl) { }
30+#endif
31+
32+#endif /* __XE_MERT_H__ */
drivers/gpu/drm/xe/xe_migrate.c+54−3
@@ -34,6 +34,7 @@ · 33 unmodified lines
3434 #include "xe_res_cursor.h"
3535 #include "xe_sa.h"
3636 #include "xe_sched_job.h"
37+#include "xe_sriov_vf_ccs.h"
3738 #include "xe_sync.h"
3839 #include "xe_trace_bo.h"
3940 #include "xe_validation.h"
@@ -1103,12 +1104,16 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, · 1063 unmodified lines
11031104 u32 batch_size, batch_size_allocated;
11041105 struct xe_device *xe = gt_to_xe(gt);
11051106 struct xe_res_cursor src_it, ccs_it;
1107+ struct xe_sriov_vf_ccs_ctx *ctx;
1108+ struct xe_sa_manager *bb_pool;
11061109 u64 size = xe_bo_size(src_bo);
11071110 struct xe_bb *bb = NULL;
11081111 u64 src_L0, src_L0_ofs;
11091112 u32 src_L0_pt;
11101113 int err;
11111114
1115+ ctx = &xe->sriov.vf.ccs.contexts[read_write];
1116+
11121117 xe_res_first_sg(xe_bo_sg(src_bo), 0, size, &src_it);
11131118
11141119 xe_res_first_sg(xe_bo_sg(src_bo), xe_bo_ccs_pages_start(src_bo),
@@ -1141,11 +1146,15 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, · 26 unmodified lines
11411146 size -= src_L0;
11421147 }
11431148
1149+ bb_pool = ctx->mem.ccs_bb_pool;
1150+ guard(mutex) (xe_sa_bo_swap_guard(bb_pool));
1151+ xe_sa_bo_swap_shadow(bb_pool);
1152+
11441153 bb = xe_bb_ccs_new(gt, batch_size, read_write);
11451154 if (IS_ERR(bb)) {
11461155 drm_err(&xe->drm, "BB allocation failed.\n");
11471156 err = PTR_ERR(bb);
1148− goto err_ret;
1157+ return err;
11491158 }
11501159
11511160 batch_size_allocated = batch_size;
@@ -1194,10 +1203,52 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, · 42 unmodified lines
11941203 xe_assert(xe, (batch_size_allocated == bb->len));
11951204 src_bo->bb_ccs[read_write] = bb;
11961205
1206+ xe_sriov_vf_ccs_rw_update_bb_addr(ctx);
1207+ xe_sa_bo_sync_shadow(bb->bo);
11971208 return 0;
1209+}
11981210
1199−err_ret:
1200− return err;
1211+/**
1212+ * xe_migrate_ccs_rw_copy_clear() - Clear the CCS read/write batch buffer
1213+ * content.
1214+ * @src_bo: The buffer object @src is currently bound to.
1215+ * @read_write : Creates BB commands for CCS read/write.
1216+ *
1217+ * Directly clearing the BB lacks atomicity and can lead to undefined
1218+ * behavior if the vCPU is halted mid-operation during the clearing
1219+ * process. To avoid this issue, we use a shadow buffer object approach.
1220+ *
1221+ * First swap the SA BO address with the shadow BO, perform the clearing
1222+ * operation on the BB, update the shadow BO in the ring buffer, then
1223+ * sync the shadow and the actual buffer to maintain consistency.
1224+ *
1225+ * Returns: None.
1226+ */
1227+void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo,
1228+ enum xe_sriov_vf_ccs_rw_ctxs read_write)
1229+{
1230+ struct xe_bb *bb = src_bo->bb_ccs[read_write];
1231+ struct xe_device *xe = xe_bo_device(src_bo);
1232+ struct xe_sriov_vf_ccs_ctx *ctx;
1233+ struct xe_sa_manager *bb_pool;
1234+ u32 *cs;
1235+
1236+ xe_assert(xe, IS_SRIOV_VF(xe));
1237+
1238+ ctx = &xe->sriov.vf.ccs.contexts[read_write];
1239+ bb_pool = ctx->mem.ccs_bb_pool;
1240+
1241+ guard(mutex) (xe_sa_bo_swap_guard(bb_pool));
1242+ xe_sa_bo_swap_shadow(bb_pool);
1243+
1244+ cs = xe_sa_bo_cpu_addr(bb->bo);
1245+ memset(cs, MI_NOOP, bb->len * sizeof(u32));
1246+ xe_sriov_vf_ccs_rw_update_bb_addr(ctx);
1247+
1248+ xe_sa_bo_sync_shadow(bb->bo);
1249+
1250+ xe_bb_free(bb, NULL);
1251+ src_bo->bb_ccs[read_write] = NULL;
12011252 }
12021253
12031254 /**
drivers/gpu/drm/xe/xe_migrate.h+3−0
@@ -134,6 +134,9 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, · 133 unmodified lines
134134 struct xe_bo *src_bo,
135135 enum xe_sriov_vf_ccs_rw_ctxs read_write);
136136
137+void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo,
138+ enum xe_sriov_vf_ccs_rw_ctxs read_write);
139+
137140 struct xe_lrc *xe_migrate_lrc(struct xe_migrate *migrate);
138141 struct xe_exec_queue *xe_migrate_exec_queue(struct xe_migrate *migrate);
139142 struct dma_fence *xe_migrate_vram_copy_chunk(struct xe_bo *vram_bo, u64 vram_offset,
drivers/gpu/drm/xe/xe_mocs.c+6−12
@@ -811,26 +811,20 @@ int xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p) · 810 unmodified lines
811811 struct xe_device *xe = gt_to_xe(gt);
812812 enum xe_force_wake_domains domain;
813813 struct xe_mocs_info table;
814− unsigned int fw_ref, flags;
815− int err = 0;
814+ unsigned int flags;
816815
817816 flags = get_mocs_settings(xe, &table);
818817
819818 domain = flags & HAS_LNCF_MOCS ? XE_FORCEWAKE_ALL : XE_FW_GT;
820− xe_pm_runtime_get_noresume(xe);
821− fw_ref = xe_force_wake_get(gt_to_fw(gt), domain);
822819
823− if (!xe_force_wake_ref_has_domain(fw_ref, domain)) {
824− err = -ETIMEDOUT;
825− goto err_fw;
826− }
820+ guard(xe_pm_runtime_noresume)(xe);
821+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), domain);
822+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, domain))
823+ return -ETIMEDOUT;
827824
828825 table.ops->dump(&table, flags, gt, p);
829826
830−err_fw:
831− xe_force_wake_put(gt_to_fw(gt), fw_ref);
832− xe_pm_runtime_put(xe);
833− return err;
827+ return 0;
834828 }
835829
836830 #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
drivers/gpu/drm/xe/xe_nvm.c+23−11
@@ -10,6 +10,7 @@ · 9 unmodified lines
1010 #include "xe_device_types.h"
1111 #include "xe_mmio.h"
1212 #include "xe_nvm.h"
13+#include "xe_pcode_api.h"
1314 #include "regs/xe_gsc_regs.h"
1415 #include "xe_sriov.h"
1516
@@ -45,39 +46,50 @@ static bool xe_nvm_non_posted_erase(struct xe_device *xe) · 29 unmodified lines
4546 {
4647 struct xe_mmio *mmio = xe_root_tile_mmio(xe);
4748
48− if (xe->info.platform != XE_BATTLEMAGE)
49+ switch (xe->info.platform) {
50+ case XE_CRESCENTISLAND:
51+ case XE_BATTLEMAGE:
52+ return !(xe_mmio_read32(mmio, XE_REG(GEN12_CNTL_PROTECTED_NVM_REG)) &
53+ NVM_NON_POSTED_ERASE_CHICKEN_BIT);
54+ default:
4955 return false;
50− return !(xe_mmio_read32(mmio, XE_REG(GEN12_CNTL_PROTECTED_NVM_REG)) &
51− NVM_NON_POSTED_ERASE_CHICKEN_BIT);
56+ }
5257 }
5358
5459 static bool xe_nvm_writable_override(struct xe_device *xe)
5560 {
5661 struct xe_mmio *mmio = xe_root_tile_mmio(xe);
5762 bool writable_override;
58− resource_size_t base;
63+ struct xe_reg reg;
64+ u32 test_bit;
5965
6066 switch (xe->info.platform) {
67+ case XE_CRESCENTISLAND:
68+ reg = PCODE_SCRATCH(0);
69+ test_bit = FDO_MODE;
70+ break;
6171 case XE_BATTLEMAGE:
62− base = DG2_GSC_HECI2_BASE;
72+ reg = HECI_FWSTS2(DG2_GSC_HECI2_BASE);
73+ test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE;
6374 break;
6475 case XE_PVC:
65− base = PVC_GSC_HECI2_BASE;
76+ reg = HECI_FWSTS2(PVC_GSC_HECI2_BASE);
77+ test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE;
6678 break;
6779 case XE_DG2:
68− base = DG2_GSC_HECI2_BASE;
80+ reg = HECI_FWSTS2(DG2_GSC_HECI2_BASE);
81+ test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE;
6982 break;
7083 case XE_DG1:
71− base = DG1_GSC_HECI2_BASE;
84+ reg = HECI_FWSTS2(DG1_GSC_HECI2_BASE);
85+ test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE;
7286 break;
7387 default:
7488 drm_err(&xe->drm, "Unknown platform\n");
7589 return true;
7690 }
7791
78− writable_override =
79− !(xe_mmio_read32(mmio, HECI_FWSTS2(base)) &
80− HECI_FW_STATUS_2_NVM_ACCESS_MODE);
92+ writable_override = !(xe_mmio_read32(mmio, reg) & test_bit);
8193 if (writable_override)
8294 drm_info(&xe->drm, "NVM access overridden by jumper\n");
8395 return writable_override;
drivers/gpu/drm/xe/xe_oa.c+65−29
@@ -1941,6 +1941,7 @@ static bool oa_unit_supports_oa_format(struct xe_oa_open_param *param, int type) · 1940 unmodified lines
19411941 type == DRM_XE_OA_FMT_TYPE_OAC || type == DRM_XE_OA_FMT_TYPE_PEC;
19421942 case DRM_XE_OA_UNIT_TYPE_OAM:
19431943 case DRM_XE_OA_UNIT_TYPE_OAM_SAG:
1944+ case DRM_XE_OA_UNIT_TYPE_MERT:
19441945 return type == DRM_XE_OA_FMT_TYPE_OAM || type == DRM_XE_OA_FMT_TYPE_OAM_MPEC;
19451946 default:
19461947 return false;
@@ -1966,10 +1967,6 @@ static int xe_oa_assign_hwe(struct xe_oa *oa, struct xe_oa_open_param *param) · 19 unmodified lines
19661967 enum xe_hw_engine_id id;
19671968 int ret = 0;
19681969
1969− /* If not provided, OA unit defaults to OA unit 0 as per uapi */
1970− if (!param->oa_unit)
1971− param->oa_unit = &xe_root_mmio_gt(oa->xe)->oa.oa_unit[0];
1972−
19731970 /* When we have an exec_q, get hwe from the exec_q */
19741971 if (param->exec_q) {
19751972 param->hwe = xe_gt_hw_engine(param->exec_q->gt, param->exec_q->class,
@@ -2035,7 +2032,15 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f · 59 unmodified lines
20352032 if (ret)
20362033 return ret;
20372034
2035+ /* If not provided, OA unit defaults to OA unit 0 as per uapi */
2036+ if (!param.oa_unit)
2037+ param.oa_unit = &xe_root_mmio_gt(oa->xe)->oa.oa_unit[0];
2038+
20382039 if (param.exec_queue_id > 0) {
2040+ /* An exec_queue is only needed for OAR/OAC functionality on OAG */
2041+ if (XE_IOCTL_DBG(oa->xe, param.oa_unit->type != DRM_XE_OA_UNIT_TYPE_OAG))
2042+ return -EINVAL;
2043+
20392044 param.exec_q = xe_exec_queue_lookup(xef, param.exec_queue_id);
20402045 if (XE_IOCTL_DBG(oa->xe, !param.exec_q))
20412046 return -ENOENT;
@@ -2224,6 +2229,8 @@ static const struct xe_mmio_range xe2_oa_mux_regs[] = { · 182 unmodified lines
22242229 { .start = 0xE18C, .end = 0xE18C }, /* SAMPLER_MODE */
22252230 { .start = 0xE590, .end = 0xE590 }, /* TDL_LSC_LAT_MEASURE_TDL_GFX */
22262231 { .start = 0x13000, .end = 0x137FC }, /* PES_0_PESL0 - PES_63_UPPER_PESL3 */
2232+ { .start = 0x145194, .end = 0x145194 }, /* SYS_MEM_LAT_MEASURE */
2233+ { .start = 0x145340, .end = 0x14537C }, /* MERTSS_PES_0 - MERTSS_PES_7 */
22272234 {},
22282235 };
22292236
@@ -2515,7 +2522,12 @@ int xe_oa_register(struct xe_device *xe) · 285 unmodified lines
25152522 static u32 num_oa_units_per_gt(struct xe_gt *gt)
25162523 {
25172524 if (xe_gt_is_main_type(gt) || GRAPHICS_VER(gt_to_xe(gt)) < 20)
2518− return 1;
2525+ /*
2526+ * Mert OA unit belongs to the SoC, not a gt, so should be accessed using
2527+ * xe_root_tile_mmio(). However, for all known platforms this is the same as
2528+ * accessing via xe_root_mmio_gt()->mmio.
2529+ */
2530+ return xe_device_has_mert(gt_to_xe(gt)) ? 2 : 1;
25192531 else if (!IS_DGFX(gt_to_xe(gt)))
25202532 return XE_OAM_UNIT_SCMI_0 + 1; /* SAG + SCMI_0 */
25212533 else
@@ -2570,40 +2582,57 @@ static u32 __hwe_oa_unit(struct xe_hw_engine *hwe) · 48 unmodified lines
25702582 static struct xe_oa_regs __oam_regs(u32 base)
25712583 {
25722584 return (struct xe_oa_regs) {
2573− base,
2574− OAM_HEAD_POINTER(base),
2575− OAM_TAIL_POINTER(base),
2576− OAM_BUFFER(base),
2577− OAM_CONTEXT_CONTROL(base),
2578− OAM_CONTROL(base),
2579− OAM_DEBUG(base),
2580− OAM_STATUS(base),
2581− OAM_CONTROL_COUNTER_SEL_MASK,
2585+ .base = base,
2586+ .oa_head_ptr = OAM_HEAD_POINTER(base),
2587+ .oa_tail_ptr = OAM_TAIL_POINTER(base),
2588+ .oa_buffer = OAM_BUFFER(base),
2589+ .oa_ctx_ctrl = OAM_CONTEXT_CONTROL(base),
2590+ .oa_ctrl = OAM_CONTROL(base),
2591+ .oa_debug = OAM_DEBUG(base),
2592+ .oa_status = OAM_STATUS(base),
2593+ .oa_mmio_trg = OAM_MMIO_TRG(base),
2594+ .oa_ctrl_counter_select_mask = OAM_CONTROL_COUNTER_SEL_MASK,
25822595 };
25832596 }
25842597
25852598 static struct xe_oa_regs __oag_regs(void)
25862599 {
25872600 return (struct xe_oa_regs) {
2588− 0,
2589− OAG_OAHEADPTR,
2590− OAG_OATAILPTR,
2591− OAG_OABUFFER,
2592− OAG_OAGLBCTXCTRL,
2593− OAG_OACONTROL,
2594− OAG_OA_DEBUG,
2595− OAG_OASTATUS,
2596− OAG_OACONTROL_OA_COUNTER_SEL_MASK,
2601+ .base = 0,
2602+ .oa_head_ptr = OAG_OAHEADPTR,
2603+ .oa_tail_ptr = OAG_OATAILPTR,
2604+ .oa_buffer = OAG_OABUFFER,
2605+ .oa_ctx_ctrl = OAG_OAGLBCTXCTRL,
2606+ .oa_ctrl = OAG_OACONTROL,
2607+ .oa_debug = OAG_OA_DEBUG,
2608+ .oa_status = OAG_OASTATUS,
2609+ .oa_mmio_trg = OAG_MMIOTRIGGER,
2610+ .oa_ctrl_counter_select_mask = OAG_OACONTROL_OA_COUNTER_SEL_MASK,
2611+ };
2612+}
2613+
2614+static struct xe_oa_regs __oamert_regs(void)
2615+{
2616+ return (struct xe_oa_regs) {
2617+ .base = 0,
2618+ .oa_head_ptr = OAMERT_HEAD_POINTER,
2619+ .oa_tail_ptr = OAMERT_TAIL_POINTER,
2620+ .oa_buffer = OAMERT_BUFFER,
2621+ .oa_ctx_ctrl = OAMERT_CONTEXT_CONTROL,
2622+ .oa_ctrl = OAMERT_CONTROL,
2623+ .oa_debug = OAMERT_DEBUG,
2624+ .oa_status = OAMERT_STATUS,
2625+ .oa_mmio_trg = OAMERT_MMIO_TRG,
2626+ .oa_ctrl_counter_select_mask = OAM_CONTROL_COUNTER_SEL_MASK,
25972627 };
25982628 }
25992629
26002630 static void __xe_oa_init_oa_units(struct xe_gt *gt)
26012631 {
2602− /* Actual address is MEDIA_GT_GSI_OFFSET + oam_base_addr[i] */
26032632 const u32 oam_base_addr[] = {
2604− [XE_OAM_UNIT_SAG] = 0x13000,
2605− [XE_OAM_UNIT_SCMI_0] = 0x14000,
2606− [XE_OAM_UNIT_SCMI_1] = 0x14800,
2633+ [XE_OAM_UNIT_SAG] = XE_OAM_SAG_BASE,
2634+ [XE_OAM_UNIT_SCMI_0] = XE_OAM_SCMI_0_BASE,
2635+ [XE_OAM_UNIT_SCMI_1] = XE_OAM_SCMI_1_BASE,
26072636 };
26082637 int i, num_units = gt->oa.num_oa_units;
26092638
@@ -2611,8 +2640,15 @@ static void __xe_oa_init_oa_units(struct xe_gt *gt) · 1 unmodified line
26112640 struct xe_oa_unit *u = &gt->oa.oa_unit[i];
26122641
26132642 if (xe_gt_is_main_type(gt)) {
2614− u->regs = __oag_regs();
2615− u->type = DRM_XE_OA_UNIT_TYPE_OAG;
2643+ if (!i) {
2644+ u->regs = __oag_regs();
2645+ u->type = DRM_XE_OA_UNIT_TYPE_OAG;
2646+ } else {
2647+ xe_gt_assert(gt, xe_device_has_mert(gt_to_xe(gt)));
2648+ xe_gt_assert(gt, gt == xe_root_mmio_gt(gt_to_xe(gt)));
2649+ u->regs = __oamert_regs();
2650+ u->type = DRM_XE_OA_UNIT_TYPE_MERT;
2651+ }
26162652 } else {
26172653 xe_gt_assert(gt, GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270);
26182654 u->regs = __oam_regs(oam_base_addr[i]);
drivers/gpu/drm/xe/xe_oa_types.h+1−0
@@ -87,6 +87,7 @@ struct xe_oa_regs { · 86 unmodified lines
8787 struct xe_reg oa_ctrl;
8888 struct xe_reg oa_debug;
8989 struct xe_reg oa_status;
90+ struct xe_reg oa_mmio_trg;
9091 u32 oa_ctrl_counter_select_mask;
9192 };
9293
drivers/gpu/drm/xe/xe_page_reclaim.c+136−0
@@ -0,0 +1,136 @@
1+// SPDX-License-Identifier: MIT
2+/*
3+ * Copyright © 2025 Intel Corporation
4+ */
5+
6+#include <linux/bitfield.h>
7+#include <linux/kref.h>
8+#include <linux/mm.h>
9+#include <linux/slab.h>
10+
11+#include "xe_page_reclaim.h"
12+
13+#include "regs/xe_gt_regs.h"
14+#include "xe_assert.h"
15+#include "xe_macros.h"
16+#include "xe_mmio.h"
17+#include "xe_pat.h"
18+#include "xe_sa.h"
19+#include "xe_tlb_inval_types.h"
20+#include "xe_vm.h"
21+
22+/**
23+ * xe_page_reclaim_skip() - Decide whether PRL should be skipped for a VMA
24+ * @tile: Tile owning the VMA
25+ * @vma: VMA under consideration
26+ *
27+ * PPC flushing may be handled by HW for specific PAT encodings.
28+ * Skip PPC flushing/Page Reclaim for scenarios below due to redundant
29+ * flushes.
30+ * - pat_index is transient display (1)
31+ *
32+ * Return: true when page reclamation is unnecessary, false otherwise.
33+ */
34+bool xe_page_reclaim_skip(struct xe_tile *tile, struct xe_vma *vma)
35+{
36+ u8 l3_policy;
37+
38+ l3_policy = xe_pat_index_get_l3_policy(tile->xe, vma->attr.pat_index);
39+
40+ /*
41+ * - l3_policy: 0=WB, 1=XD ("WB - Transient Display"), 3=UC
42+ * Transient display flushes is taken care by HW, l3_policy = 1.
43+ *
44+ * HW will sequence these transient flushes at various sync points so
45+ * any event of page reclamation will hit these sync points before
46+ * page reclamation could execute.
47+ */
48+ return (l3_policy == XE_L3_POLICY_XD);
49+}
50+
51+/**
52+ * xe_page_reclaim_create_prl_bo() - Back a PRL with a suballocated GGTT BO
53+ * @tlb_inval: TLB invalidation frontend associated with the request
54+ * @prl: page reclaim list data that bo will copy from
55+ * @fence: tlb invalidation fence that page reclaim action is paired to
56+ *
57+ * Suballocates a 4K BO out of the tile reclaim pool, copies the PRL CPU
58+ * copy into the BO and queues the buffer for release when @fence signals.
59+ *
60+ * Return: struct drm_suballoc pointer on success or ERR_PTR on failure.
61+ */
62+struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inval,
63+ struct xe_page_reclaim_list *prl,
64+ struct xe_tlb_inval_fence *fence)
65+{
66+ struct xe_gt *gt = container_of(tlb_inval, struct xe_gt, tlb_inval);
67+ struct xe_tile *tile = gt_to_tile(gt);
68+ /* (+1) for NULL page_reclaim_entry to indicate end of list */
69+ int prl_size = min(prl->num_entries + 1, XE_PAGE_RECLAIM_MAX_ENTRIES) *
70+ sizeof(struct xe_guc_page_reclaim_entry);
71+ struct drm_suballoc *prl_sa;
72+
73+ /* Maximum size of PRL is 1 4K-page */
74+ prl_sa = __xe_sa_bo_new(tile->mem.reclaim_pool,
75+ prl_size, GFP_ATOMIC);
76+ if (IS_ERR(prl_sa))
77+ return prl_sa;
78+
79+ memcpy(xe_sa_bo_cpu_addr(prl_sa), prl->entries,
80+ prl_size);
81+ xe_sa_bo_flush_write(prl_sa);
82+ /* Queue up sa_bo_free on tlb invalidation fence signal */
83+ xe_sa_bo_free(prl_sa, &fence->base);
84+
85+ return prl_sa;
86+}
87+
88+/**
89+ * xe_page_reclaim_list_invalidate() - Mark a PRL as invalid
90+ * @prl: Page reclaim list to reset
91+ *
92+ * Clears the entries pointer and marks the list as invalid so
93+ * future use knows PRL is unusable. It is expected that the entries
94+ * have already been released.
95+ */
96+void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl)
97+{
98+ xe_page_reclaim_entries_put(prl->entries);
99+ prl->entries = NULL;
100+ prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
101+}
102+
103+/**
104+ * xe_page_reclaim_list_init() - Initialize a page reclaim list
105+ * @prl: Page reclaim list to initialize
106+ *
107+ * NULLs both values in list to prepare on initalization.
108+ */
109+void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl)
110+{
111+ // xe_page_reclaim_list_invalidate(prl);
112+ prl->entries = NULL;
113+ prl->num_entries = 0;
114+}
115+
116+/**
117+ * xe_page_reclaim_list_alloc_entries() - Allocate page reclaim list entries
118+ * @prl: Page reclaim list to allocate entries for
119+ *
120+ * Allocate one 4K page for the PRL entries, otherwise assign prl->entries to NULL.
121+ */
122+int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl)
123+{
124+ struct page *page;
125+
126+ if (XE_WARN_ON(prl->entries))
127+ return 0;
128+
129+ page = alloc_page(GFP_KERNEL | __GFP_ZERO);
130+ if (page) {
131+ prl->entries = page_address(page);
132+ prl->num_entries = 0;
133+ }
134+
135+ return page ? 0 : -ENOMEM;
136+}
drivers/gpu/drm/xe/xe_page_reclaim.h+105−0
@@ -0,0 +1,105 @@
1+/* SPDX-License-Identifier: MIT */
2+/*
3+ * Copyright © 2025 Intel Corporation
4+ */
5+
6+#ifndef _XE_PAGE_RECLAIM_H_
7+#define _XE_PAGE_RECLAIM_H_
8+
9+#include <linux/kref.h>
10+#include <linux/mm.h>
11+#include <linux/slab.h>
12+#include <linux/types.h>
13+#include <linux/workqueue.h>
14+#include <linux/bits.h>
15+
16+#define XE_PAGE_RECLAIM_MAX_ENTRIES 512
17+#define XE_PAGE_RECLAIM_LIST_MAX_SIZE SZ_4K
18+
19+struct xe_tlb_inval;
20+struct xe_tlb_inval_fence;
21+struct xe_tile;
22+struct xe_vma;
23+
24+struct xe_guc_page_reclaim_entry {
25+ u64 qw;
26+/* valid reclaim entry bit */
27+#define XE_PAGE_RECLAIM_VALID BIT_ULL(0)
28+/*
29+ * offset order of page size to be reclaimed
30+ * page_size = 1 << (XE_PTE_SHIFT + reclamation_size)
31+ */
32+#define XE_PAGE_RECLAIM_SIZE GENMASK_ULL(6, 1)
33+#define XE_PAGE_RECLAIM_RSVD_0 GENMASK_ULL(11, 7)
34+/* lower 20 bits of the physical address */
35+#define XE_PAGE_RECLAIM_ADDR_LO GENMASK_ULL(31, 12)
36+/* upper 20 bits of the physical address */
37+#define XE_PAGE_RECLAIM_ADDR_HI GENMASK_ULL(51, 32)
38+#define XE_PAGE_RECLAIM_RSVD_1 GENMASK_ULL(63, 52)
39+} __packed;
40+
41+struct xe_page_reclaim_list {
42+ /** @entries: array of page reclaim entries, page allocated */
43+ struct xe_guc_page_reclaim_entry *entries;
44+ /** @num_entries: number of entries */
45+ int num_entries;
46+#define XE_PAGE_RECLAIM_INVALID_LIST -1
47+};
48+
49+/**
50+ * xe_page_reclaim_list_is_new() - Check if PRL is new allocation
51+ * @prl: Pointer to page reclaim list
52+ *
53+ * PRL indicates it hasn't been allocated through both values being NULL
54+ */
55+static inline bool xe_page_reclaim_list_is_new(struct xe_page_reclaim_list *prl)
56+{
57+ return !prl->entries && prl->num_entries == 0;
58+}
59+
60+/**
61+ * xe_page_reclaim_list_valid() - Check if the page reclaim list is valid
62+ * @prl: Pointer to page reclaim list
63+ *
64+ * PRL uses the XE_PAGE_RECLAIM_INVALID_LIST to indicate that a PRL
65+ * is unusable.
66+ */
67+static inline bool xe_page_reclaim_list_valid(struct xe_page_reclaim_list *prl)
68+{
69+ return !xe_page_reclaim_list_is_new(prl) &&
70+ prl->num_entries != XE_PAGE_RECLAIM_INVALID_LIST;
71+}
72+
73+bool xe_page_reclaim_skip(struct xe_tile *tile, struct xe_vma *vma);
74+struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inval,
75+ struct xe_page_reclaim_list *prl,
76+ struct xe_tlb_inval_fence *fence);
77+void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl);
78+void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl);
79+int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl);
80+/**
81+ * xe_page_reclaim_entries_get() - Increment the reference count of page reclaim entries.
82+ * @entries: Pointer to the array of page reclaim entries.
83+ *
84+ * This function increments the reference count of the backing page.
85+ */
86+static inline void xe_page_reclaim_entries_get(struct xe_guc_page_reclaim_entry *entries)
87+{
88+ if (entries)
89+ get_page(virt_to_page(entries));
90+}
91+
92+/**
93+ * xe_page_reclaim_entries_put() - Decrement the reference count of page reclaim entries.
94+ * @entries: Pointer to the array of page reclaim entries.
95+ *
96+ * This function decrements the reference count of the backing page
97+ * and frees it if the count reaches zero.
98+ */
99+static inline void xe_page_reclaim_entries_put(struct xe_guc_page_reclaim_entry *entries)
100+{
101+ if (entries)
102+ put_page(virt_to_page(entries));
103+}
104+
105+#endif /* _XE_PAGE_RECLAIM_H_ */
drivers/gpu/drm/xe/xe_pagefault.c+18−18
@@ -223,22 +223,22 @@ static bool xe_pagefault_queue_pop(struct xe_pagefault_queue *pf_queue, · 222 unmodified lines
223223
224224 static void xe_pagefault_print(struct xe_pagefault *pf)
225225 {
226− xe_gt_dbg(pf->gt, "\n\tASID: %d\n"
227− "\tFaulted Address: 0x%08x%08x\n"
228− "\tFaultType: %d\n"
229− "\tAccessType: %d\n"
230− "\tFaultLevel: %d\n"
231− "\tEngineClass: %d %s\n"
232− "\tEngineInstance: %d\n",
233− pf->consumer.asid,
234− upper_32_bits(pf->consumer.page_addr),
235− lower_32_bits(pf->consumer.page_addr),
236− pf->consumer.fault_type,
237− pf->consumer.access_type,
238− pf->consumer.fault_level,
239− pf->consumer.engine_class,
240− xe_hw_engine_class_to_str(pf->consumer.engine_class),
241− pf->consumer.engine_instance);
226+ xe_gt_info(pf->gt, "\n\tASID: %d\n"
227+ "\tFaulted Address: 0x%08x%08x\n"
228+ "\tFaultType: %d\n"
229+ "\tAccessType: %d\n"
230+ "\tFaultLevel: %d\n"
231+ "\tEngineClass: %d %s\n"
232+ "\tEngineInstance: %d\n",
233+ pf->consumer.asid,
234+ upper_32_bits(pf->consumer.page_addr),
235+ lower_32_bits(pf->consumer.page_addr),
236+ pf->consumer.fault_type,
237+ pf->consumer.access_type,
238+ pf->consumer.fault_level,
239+ pf->consumer.engine_class,
240+ xe_hw_engine_class_to_str(pf->consumer.engine_class),
241+ pf->consumer.engine_instance);
242242 }
243243
244244 static void xe_pagefault_queue_work(struct work_struct *w)
@@ -260,8 +260,8 @@ static void xe_pagefault_queue_work(struct work_struct *w) · 15 unmodified lines
260260 err = xe_pagefault_service(&pf);
261261 if (err) {
262262 xe_pagefault_print(&pf);
263− xe_gt_dbg(pf.gt, "Fault response: Unsuccessful %pe\n",
264− ERR_PTR(err));
263+ xe_gt_info(pf.gt, "Fault response: Unsuccessful %pe\n",
264+ ERR_PTR(err));
265265 }
266266
267267 pf.producer.ops->ack_fault(&pf, err);
drivers/gpu/drm/xe/xe_pat.c+152−68
@@ -9,6 +9,7 @@ · 8 unmodified lines
99
1010 #include <generated/xe_wa_oob.h>
1111
12+#include "regs/xe_gt_regs.h"
1213 #include "regs/xe_reg_defs.h"
1314 #include "xe_assert.h"
1415 #include "xe_device.h"
@@ -50,8 +51,37 @@ · 35 unmodified lines
5051 #define XELP_PAT_WC REG_FIELD_PREP(XELP_MEM_TYPE_MASK, 1)
5152 #define XELP_PAT_UC REG_FIELD_PREP(XELP_MEM_TYPE_MASK, 0)
5253
54+#define PAT_LABEL_LEN 20
55+
5356 static const char *XELP_MEM_TYPE_STR_MAP[] = { "UC", "WC", "WT", "WB" };
5457
58+static void xe_pat_index_label(char *label, size_t len, int index)
59+{
60+ snprintf(label, len, "PAT[%2d] ", index);
61+}
62+
63+static void xelp_pat_entry_dump(struct drm_printer *p, int index, u32 pat)
64+{
65+ u8 mem_type = REG_FIELD_GET(XELP_MEM_TYPE_MASK, pat);
66+
67+ drm_printf(p, "PAT[%2d] = %s (%#8x)\n", index,
68+ XELP_MEM_TYPE_STR_MAP[mem_type], pat);
69+}
70+
71+static void xehpc_pat_entry_dump(struct drm_printer *p, int index, u32 pat)
72+{
73+ drm_printf(p, "PAT[%2d] = [ %u, %u ] (%#8x)\n", index,
74+ REG_FIELD_GET(XELP_MEM_TYPE_MASK, pat),
75+ REG_FIELD_GET(XEHPC_CLOS_LEVEL_MASK, pat), pat);
76+}
77+
78+static void xelpg_pat_entry_dump(struct drm_printer *p, int index, u32 pat)
79+{
80+ drm_printf(p, "PAT[%2d] = [ %u, %u ] (%#8x)\n", index,
81+ REG_FIELD_GET(XELPG_L4_POLICY_MASK, pat),
82+ REG_FIELD_GET(XELPG_INDEX_COH_MODE_MASK, pat), pat);
83+}
84+
5585 struct xe_pat_ops {
5686 void (*program_graphics)(struct xe_gt *gt, const struct xe_pat_table_entry table[],
5787 int n_entries);
@@ -196,6 +226,19 @@ u16 xe_pat_index_get_coh_mode(struct xe_device *xe, u16 pat_index) · 138 unmodified lines
196226 return xe->pat.table[pat_index].coh_mode;
197227 }
198228
229+bool xe_pat_index_get_comp_en(struct xe_device *xe, u16 pat_index)
230+{
231+ WARN_ON(pat_index >= xe->pat.n_entries);
232+ return !!(xe->pat.table[pat_index].value & XE2_COMP_EN);
233+}
234+
235+u16 xe_pat_index_get_l3_policy(struct xe_device *xe, u16 pat_index)
236+{
237+ WARN_ON(pat_index >= xe->pat.n_entries);
238+
239+ return REG_FIELD_GET(XE2_L3_POLICY, xe->pat.table[pat_index].value);
240+}
241+
199242 static void program_pat(struct xe_gt *gt, const struct xe_pat_table_entry table[],
200243 int n_entries)
201244 {
@@ -233,24 +276,20 @@ static void program_pat_mcr(struct xe_gt *gt, const struct xe_pat_table_entry ta · 31 unmodified lines
233276 static int xelp_dump(struct xe_gt *gt, struct drm_printer *p)
234277 {
235278 struct xe_device *xe = gt_to_xe(gt);
236− unsigned int fw_ref;
237279 int i;
238280
239− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
240− if (!fw_ref)
281+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
282+ if (!fw_ref.domains)
241283 return -ETIMEDOUT;
242284
243285 drm_printf(p, "PAT table:\n");
244286
245287 for (i = 0; i < xe->pat.n_entries; i++) {
246288 u32 pat = xe_mmio_read32(&gt->mmio, XE_REG(_PAT_INDEX(i)));
247− u8 mem_type = REG_FIELD_GET(XELP_MEM_TYPE_MASK, pat);
248289
249− drm_printf(p, "PAT[%2d] = %s (%#8x)\n", i,
250− XELP_MEM_TYPE_STR_MAP[mem_type], pat);
290+ xelp_pat_entry_dump(p, i, pat);
251291 }
252292
253− xe_force_wake_put(gt_to_fw(gt), fw_ref);
254293 return 0;
255294 }
256295
@@ -262,26 +301,20 @@ static const struct xe_pat_ops xelp_pat_ops = { · 5 unmodified lines
262301 static int xehp_dump(struct xe_gt *gt, struct drm_printer *p)
263302 {
264303 struct xe_device *xe = gt_to_xe(gt);
265− unsigned int fw_ref;
266304 int i;
267305
268− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
269− if (!fw_ref)
306+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
307+ if (!fw_ref.domains)
270308 return -ETIMEDOUT;
271309
272310 drm_printf(p, "PAT table:\n");
273311
274312 for (i = 0; i < xe->pat.n_entries; i++) {
275313 u32 pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i)));
276− u8 mem_type;
277−
278− mem_type = REG_FIELD_GET(XELP_MEM_TYPE_MASK, pat);
279314
280− drm_printf(p, "PAT[%2d] = %s (%#8x)\n", i,
281− XELP_MEM_TYPE_STR_MAP[mem_type], pat);
315+ xelp_pat_entry_dump(p, i, pat);
282316 }
283317
284− xe_force_wake_put(gt_to_fw(gt), fw_ref);
285318 return 0;
286319 }
287320
@@ -293,11 +326,10 @@ static const struct xe_pat_ops xehp_pat_ops = { · 5 unmodified lines
293326 static int xehpc_dump(struct xe_gt *gt, struct drm_printer *p)
294327 {
295328 struct xe_device *xe = gt_to_xe(gt);
296− unsigned int fw_ref;
297329 int i;
298330
299− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
300− if (!fw_ref)
331+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
332+ if (!fw_ref.domains)
301333 return -ETIMEDOUT;
302334
303335 drm_printf(p, "PAT table:\n");
@@ -305,12 +337,9 @@ static int xehpc_dump(struct xe_gt *gt, struct drm_printer *p) · 1 unmodified line
305337 for (i = 0; i < xe->pat.n_entries; i++) {
306338 u32 pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i)));
307339
308− drm_printf(p, "PAT[%2d] = [ %u, %u ] (%#8x)\n", i,
309− REG_FIELD_GET(XELP_MEM_TYPE_MASK, pat),
310− REG_FIELD_GET(XEHPC_CLOS_LEVEL_MASK, pat), pat);
340+ xehpc_pat_entry_dump(p, i, pat);
311341 }
312342
313− xe_force_wake_put(gt_to_fw(gt), fw_ref);
314343 return 0;
315344 }
316345
@@ -322,11 +351,10 @@ static const struct xe_pat_ops xehpc_pat_ops = { · 5 unmodified lines
322351 static int xelpg_dump(struct xe_gt *gt, struct drm_printer *p)
323352 {
324353 struct xe_device *xe = gt_to_xe(gt);
325− unsigned int fw_ref;
326354 int i;
327355
328− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
329− if (!fw_ref)
356+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
357+ if (!fw_ref.domains)
330358 return -ETIMEDOUT;
331359
332360 drm_printf(p, "PAT table:\n");
@@ -339,12 +367,9 @@ static int xelpg_dump(struct xe_gt *gt, struct drm_printer *p) · 6 unmodified lines
339367 else
340368 pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i)));
341369
342− drm_printf(p, "PAT[%2d] = [ %u, %u ] (%#8x)\n", i,
343− REG_FIELD_GET(XELPG_L4_POLICY_MASK, pat),
344− REG_FIELD_GET(XELPG_INDEX_COH_MODE_MASK, pat), pat);
370+ xelpg_pat_entry_dump(p, i, pat);
345371 }
346372
347− xe_force_wake_put(gt_to_fw(gt), fw_ref);
348373 return 0;
349374 }
350375
@@ -358,15 +383,38 @@ static const struct xe_pat_ops xelpg_pat_ops = { · 7 unmodified lines
358383 .dump = xelpg_dump,
359384 };
360385
386+static void xe2_pat_entry_dump(struct drm_printer *p, const char *label, u32 pat, bool rsvd)
387+{
388+ drm_printf(p, "%s= [ %u, %u, %u, %u, %u, %u ] (%#8x)%s\n", label,
389+ !!(pat & XE2_NO_PROMOTE),
390+ !!(pat & XE2_COMP_EN),
391+ REG_FIELD_GET(XE2_L3_CLOS, pat),
392+ REG_FIELD_GET(XE2_L3_POLICY, pat),
393+ REG_FIELD_GET(XE2_L4_POLICY, pat),
394+ REG_FIELD_GET(XE2_COH_MODE, pat),
395+ pat, rsvd ? " *" : "");
396+}
397+
398+static void xe3p_xpc_pat_entry_dump(struct drm_printer *p, const char *label, u32 pat, bool rsvd)
399+{
400+ drm_printf(p, "%s= [ %u, %u, %u, %u, %u ] (%#8x)%s\n", label,
401+ !!(pat & XE2_NO_PROMOTE),
402+ REG_FIELD_GET(XE2_L3_CLOS, pat),
403+ REG_FIELD_GET(XE2_L3_POLICY, pat),
404+ REG_FIELD_GET(XE2_L4_POLICY, pat),
405+ REG_FIELD_GET(XE2_COH_MODE, pat),
406+ pat, rsvd ? " *" : "");
407+}
408+
361409 static int xe2_dump(struct xe_gt *gt, struct drm_printer *p)
362410 {
363411 struct xe_device *xe = gt_to_xe(gt);
364− unsigned int fw_ref;
365412 u32 pat;
366413 int i;
414+ char label[PAT_LABEL_LEN];
367415
368− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
369− if (!fw_ref)
416+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
417+ if (!fw_ref.domains)
370418 return -ETIMEDOUT;
371419
372420 drm_printf(p, "PAT table: (* = reserved entry)\n");
@@ -377,14 +425,8 @@ static int xe2_dump(struct xe_gt *gt, struct drm_printer *p) · 4 unmodified lines
377425 else
378426 pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i)));
379427
380− drm_printf(p, "PAT[%2d] = [ %u, %u, %u, %u, %u, %u ] (%#8x)%s\n", i,
381− !!(pat & XE2_NO_PROMOTE),
382− !!(pat & XE2_COMP_EN),
383− REG_FIELD_GET(XE2_L3_CLOS, pat),
384− REG_FIELD_GET(XE2_L3_POLICY, pat),
385− REG_FIELD_GET(XE2_L4_POLICY, pat),
386− REG_FIELD_GET(XE2_COH_MODE, pat),
387− pat, xe->pat.table[i].valid ? "" : " *");
428+ xe_pat_index_label(label, sizeof(label), i);
429+ xe2_pat_entry_dump(p, label, pat, !xe->pat.table[i].valid);
388430 }
389431
390432 /*
@@ -397,16 +439,8 @@ static int xe2_dump(struct xe_gt *gt, struct drm_printer *p) · 6 unmodified lines
397439 pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_PTA));
398440
399441 drm_printf(p, "Page Table Access:\n");
400− drm_printf(p, "PTA_MODE= [ %u, %u, %u, %u, %u, %u ] (%#8x)\n",
401− !!(pat & XE2_NO_PROMOTE),
402− !!(pat & XE2_COMP_EN),
403− REG_FIELD_GET(XE2_L3_CLOS, pat),
404− REG_FIELD_GET(XE2_L3_POLICY, pat),
405− REG_FIELD_GET(XE2_L4_POLICY, pat),
406− REG_FIELD_GET(XE2_COH_MODE, pat),
407− pat);
442+ xe2_pat_entry_dump(p, "PTA_MODE", pat, false);
408443
409− xe_force_wake_put(gt_to_fw(gt), fw_ref);
410444 return 0;
411445 }
412446
@@ -419,12 +453,12 @@ static const struct xe_pat_ops xe2_pat_ops = { · 6 unmodified lines
419453 static int xe3p_xpc_dump(struct xe_gt *gt, struct drm_printer *p)
420454 {
421455 struct xe_device *xe = gt_to_xe(gt);
422− unsigned int fw_ref;
423456 u32 pat;
424457 int i;
458+ char label[PAT_LABEL_LEN];
425459
426− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
427− if (!fw_ref)
460+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
461+ if (!fw_ref.domains)
428462 return -ETIMEDOUT;
429463
430464 drm_printf(p, "PAT table: (* = reserved entry)\n");
@@ -432,13 +466,8 @@ static int xe3p_xpc_dump(struct xe_gt *gt, struct drm_printer *p) · 1 unmodified line
432466 for (i = 0; i < xe->pat.n_entries; i++) {
433467 pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i)));
434468
435− drm_printf(p, "PAT[%2d] = [ %u, %u, %u, %u, %u ] (%#8x)%s\n", i,
436− !!(pat & XE2_NO_PROMOTE),
437− REG_FIELD_GET(XE2_L3_CLOS, pat),
438− REG_FIELD_GET(XE2_L3_POLICY, pat),
439− REG_FIELD_GET(XE2_L4_POLICY, pat),
440− REG_FIELD_GET(XE2_COH_MODE, pat),
441− pat, xe->pat.table[i].valid ? "" : " *");
469+ xe_pat_index_label(label, sizeof(label), i);
470+ xe3p_xpc_pat_entry_dump(p, label, pat, !xe->pat.table[i].valid);
442471 }
443472
444473 /*
@@ -448,15 +477,8 @@ static int xe3p_xpc_dump(struct xe_gt *gt, struct drm_printer *p) · 3 unmodified lines
448477 pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_PTA));
449478
450479 drm_printf(p, "Page Table Access:\n");
451− drm_printf(p, "PTA_MODE= [ %u, %u, %u, %u, %u ] (%#8x)\n",
452− !!(pat & XE2_NO_PROMOTE),
453− REG_FIELD_GET(XE2_L3_CLOS, pat),
454− REG_FIELD_GET(XE2_L3_POLICY, pat),
455− REG_FIELD_GET(XE2_L4_POLICY, pat),
456− REG_FIELD_GET(XE2_COH_MODE, pat),
457− pat);
480+ xe3p_xpc_pat_entry_dump(p, "PTA_MODE", pat, false);
458481
459− xe_force_wake_put(gt_to_fw(gt), fw_ref);
460482 return 0;
461483 }
462484
@@ -578,3 +600,65 @@ int xe_pat_dump(struct xe_gt *gt, struct drm_printer *p) · 115 unmodified lines
578600
579601 return xe->pat.ops->dump(gt, p);
580602 }
603+
604+/**
605+ * xe_pat_dump_sw_config() - Dump the software-configured GT PAT table into a drm printer.
606+ * @gt: the &xe_gt
607+ * @p: the &drm_printer
608+ *
609+ * Return: 0 on success or a negative error code on failure.
610+ */
611+int xe_pat_dump_sw_config(struct xe_gt *gt, struct drm_printer *p)
612+{
613+ struct xe_device *xe = gt_to_xe(gt);
614+ char label[PAT_LABEL_LEN];
615+
616+ if (!xe->pat.table || !xe->pat.n_entries)
617+ return -EOPNOTSUPP;
618+
619+ drm_printf(p, "PAT table:%s\n", GRAPHICS_VER(xe) >= 20 ? " (* = reserved entry)" : "");
620+ for (u32 i = 0; i < xe->pat.n_entries; i++) {
621+ u32 pat = xe->pat.table[i].value;
622+
623+ if (GRAPHICS_VERx100(xe) == 3511) {
624+ xe_pat_index_label(label, sizeof(label), i);
625+ xe3p_xpc_pat_entry_dump(p, label, pat, !xe->pat.table[i].valid);
626+ } else if (GRAPHICS_VER(xe) == 30 || GRAPHICS_VER(xe) == 20) {
627+ xe_pat_index_label(label, sizeof(label), i);
628+ xe2_pat_entry_dump(p, label, pat, !xe->pat.table[i].valid);
629+ } else if (xe->info.platform == XE_METEORLAKE) {
630+ xelpg_pat_entry_dump(p, i, pat);
631+ } else if (xe->info.platform == XE_PVC) {
632+ xehpc_pat_entry_dump(p, i, pat);
633+ } else if (xe->info.platform == XE_DG2 || GRAPHICS_VERx100(xe) <= 1210) {
634+ xelp_pat_entry_dump(p, i, pat);
635+ } else {
636+ return -EOPNOTSUPP;
637+ }
638+ }
639+
640+ if (xe->pat.pat_pta) {
641+ u32 pat = xe->pat.pat_pta->value;
642+
643+ drm_printf(p, "Page Table Access:\n");
644+ xe2_pat_entry_dump(p, "PTA_MODE", pat, false);
645+ }
646+
647+ if (xe->pat.pat_ats) {
648+ u32 pat = xe->pat.pat_ats->value;
649+
650+ drm_printf(p, "PCIe ATS/PASID:\n");
651+ xe2_pat_entry_dump(p, "PAT_ATS ", pat, false);
652+ }
653+
654+ drm_printf(p, "Cache Level:\n");
655+ drm_printf(p, "IDX[XE_CACHE_NONE] = %d\n", xe->pat.idx[XE_CACHE_NONE]);
656+ drm_printf(p, "IDX[XE_CACHE_WT] = %d\n", xe->pat.idx[XE_CACHE_WT]);
657+ drm_printf(p, "IDX[XE_CACHE_WB] = %d\n", xe->pat.idx[XE_CACHE_WB]);
658+ if (GRAPHICS_VER(xe) >= 20) {
659+ drm_printf(p, "IDX[XE_CACHE_NONE_COMPRESSION] = %d\n",
660+ xe->pat.idx[XE_CACHE_NONE_COMPRESSION]);
661+ }
662+
663+ return 0;
664+}
drivers/gpu/drm/xe/xe_pat.h+21−0
@@ -49,6 +49,7 @@ void xe_pat_init_early(struct xe_device *xe); · 48 unmodified lines
4949 void xe_pat_init(struct xe_gt *gt);
5050
5151 int xe_pat_dump(struct xe_gt *gt, struct drm_printer *p);
52+int xe_pat_dump_sw_config(struct xe_gt *gt, struct drm_printer *p);
5253
5354 /**
5455 * xe_pat_index_get_coh_mode - Extract the coherency mode for the given
@@ -58,4 +59,24 @@ int xe_pat_dump(struct xe_gt *gt, struct drm_printer *p); · 3 unmodified lines
5859 */
5960 u16 xe_pat_index_get_coh_mode(struct xe_device *xe, u16 pat_index);
6061
62+/**
63+ * xe_pat_index_get_comp_en - Extract the compression enable flag for
64+ * the given pat_index.
65+ * @xe: xe device
66+ * @pat_index: The pat_index to query
67+ *
68+ * Return: true if compression is enabled for this pat_index, false otherwise.
69+ */
70+bool xe_pat_index_get_comp_en(struct xe_device *xe, u16 pat_index);
71+
72+#define XE_L3_POLICY_WB 0 /* Write-back */
73+#define XE_L3_POLICY_XD 1 /* WB - Transient Display */
74+#define XE_L3_POLICY_UC 3 /* Uncached */
75+/**
76+ * xe_pat_index_get_l3_policy - Extract the L3 policy for the given pat_index.
77+ * @xe: xe device
78+ * @pat_index: The pat_index to query
79+ */
80+u16 xe_pat_index_get_l3_policy(struct xe_device *xe, u16 pat_index);
81+
6182 #endif
drivers/gpu/drm/xe/xe_pci.c+29−0
@@ -108,6 +108,7 @@ static const struct xe_graphics_desc graphics_xe2 = { · 107 unmodified lines
108108
109109 static const struct xe_graphics_desc graphics_xe3p_xpc = {
110110 XE2_GFX_FEATURES,
111+ .has_indirect_ring_state = 1,
111112 .hw_engine_mask =
112113 GENMASK(XE_HW_ENGINE_BCS8, XE_HW_ENGINE_BCS1) |
113114 GENMASK(XE_HW_ENGINE_CCS3, XE_HW_ENGINE_CCS0),
@@ -168,6 +169,7 @@ static const struct xe_device_desc tgl_desc = { · 54 unmodified lines
168169 .pre_gmdid_media_ip = &media_ip_xem,
169170 PLATFORM(TIGERLAKE),
170171 .dma_mask_size = 39,
172+ .has_cached_pt = true,
171173 .has_display = true,
172174 .has_llc = true,
173175 .has_sriov = true,
@@ -182,6 +184,7 @@ static const struct xe_device_desc rkl_desc = { · 8 unmodified lines
182184 .pre_gmdid_media_ip = &media_ip_xem,
183185 PLATFORM(ROCKETLAKE),
184186 .dma_mask_size = 39,
187+ .has_cached_pt = true,
185188 .has_display = true,
186189 .has_llc = true,
187190 .max_gt_per_tile = 1,
@@ -197,6 +200,7 @@ static const struct xe_device_desc adl_s_desc = { · 9 unmodified lines
197200 .pre_gmdid_media_ip = &media_ip_xem,
198201 PLATFORM(ALDERLAKE_S),
199202 .dma_mask_size = 39,
203+ .has_cached_pt = true,
200204 .has_display = true,
201205 .has_llc = true,
202206 .has_sriov = true,
@@ -217,6 +221,7 @@ static const struct xe_device_desc adl_p_desc = { · 14 unmodified lines
217221 .pre_gmdid_media_ip = &media_ip_xem,
218222 PLATFORM(ALDERLAKE_P),
219223 .dma_mask_size = 39,
224+ .has_cached_pt = true,
220225 .has_display = true,
221226 .has_llc = true,
222227 .has_sriov = true,
@@ -235,6 +240,7 @@ static const struct xe_device_desc adl_n_desc = { · 12 unmodified lines
235240 .pre_gmdid_media_ip = &media_ip_xem,
236241 PLATFORM(ALDERLAKE_N),
237242 .dma_mask_size = 39,
243+ .has_cached_pt = true,
238244 .has_display = true,
239245 .has_llc = true,
240246 .has_sriov = true,
@@ -361,7 +367,9 @@ static const struct xe_device_desc bmg_desc = { · 120 unmodified lines
361367 .has_mbx_power_limits = true,
362368 .has_gsc_nvm = 1,
363369 .has_heci_cscfi = 1,
370+ .has_i2c = true,
364371 .has_late_bind = true,
372+ .has_pre_prod_wa = 1,
365373 .has_sriov = true,
366374 .has_mem_copy_instr = true,
367375 .max_gt_per_tile = 2,
@@ -381,6 +389,7 @@ static const struct xe_device_desc ptl_desc = { · 13 unmodified lines
381389 .has_flat_ccs = 1,
382390 .has_sriov = true,
383391 .has_mem_copy_instr = true,
392+ .has_pre_prod_wa = 1,
384393 .max_gt_per_tile = 2,
385394 .needs_scratch = true,
386395 .needs_shared_vf_gt_wq = true,
@@ -394,6 +403,7 @@ static const struct xe_device_desc nvls_desc = { · 7 unmodified lines
394403 .has_display = true,
395404 .has_flat_ccs = 1,
396405 .has_mem_copy_instr = true,
406+ .has_pre_prod_wa = 1,
397407 .max_gt_per_tile = 2,
398408 .require_force_probe = true,
399409 .va_bits = 48,
@@ -406,7 +416,11 @@ static const struct xe_device_desc cri_desc = { · 6 unmodified lines
406416 .dma_mask_size = 52,
407417 .has_display = false,
408418 .has_flat_ccs = false,
419+ .has_gsc_nvm = 1,
420+ .has_i2c = true,
409421 .has_mbx_power_limits = true,
422+ .has_mert = true,
423+ .has_pre_prod_wa = 1,
410424 .has_sriov = true,
411425 .max_gt_per_tile = 2,
412426 .require_force_probe = true,
@@ -663,6 +677,7 @@ static int xe_info_init_early(struct xe_device *xe, · 250 unmodified lines
663677 xe->info.vram_flags = desc->vram_flags;
664678
665679 xe->info.is_dgfx = desc->is_dgfx;
680+ xe->info.has_cached_pt = desc->has_cached_pt;
666681 xe->info.has_fan_control = desc->has_fan_control;
667682 /* runtime fusing may force flat_ccs to disabled later */
668683 xe->info.has_flat_ccs = desc->has_flat_ccs;
@@ -670,8 +685,12 @@ static int xe_info_init_early(struct xe_device *xe, · 1 unmodified line
670685 xe->info.has_gsc_nvm = desc->has_gsc_nvm;
671686 xe->info.has_heci_gscfi = desc->has_heci_gscfi;
672687 xe->info.has_heci_cscfi = desc->has_heci_cscfi;
688+ xe->info.has_i2c = desc->has_i2c;
673689 xe->info.has_late_bind = desc->has_late_bind;
674690 xe->info.has_llc = desc->has_llc;
691+ xe->info.has_mert = desc->has_mert;
692+ xe->info.has_page_reclaim_hw_assist = desc->has_page_reclaim_hw_assist;
693+ xe->info.has_pre_prod_wa = desc->has_pre_prod_wa;
675694 xe->info.has_pxp = desc->has_pxp;
676695 xe->info.has_sriov = xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev)) &&
677696 desc->has_sriov;
@@ -755,6 +774,7 @@ static struct xe_gt *alloc_primary_gt(struct xe_tile *tile, · 77 unmodified lines
755774 gt->info.type = XE_GT_TYPE_MAIN;
756775 gt->info.id = tile->id * xe->info.max_gt_per_tile;
757776 gt->info.has_indirect_ring_state = graphics_desc->has_indirect_ring_state;
777+ gt->info.multi_queue_engine_class_mask = graphics_desc->multi_queue_engine_class_mask;
758778 gt->info.engine_mask = graphics_desc->hw_engine_mask;
759779
760780 /*
@@ -1153,6 +1173,15 @@ static int xe_pci_runtime_suspend(struct device *dev) · 392 unmodified lines
11531173 struct xe_device *xe = pdev_to_xe_device(pdev);
11541174 int err;
11551175
1176+ /*
1177+ * We hold an additional reference to the runtime PM to keep PF in D0
1178+ * during VFs lifetime, as our VFs do not implement the PM capability.
1179+ * This means we should never be runtime suspending as long as VFs are
1180+ * enabled.
1181+ */
1182+ xe_assert(xe, !IS_SRIOV_VF(xe));
1183+ xe_assert(xe, !pci_num_vf(pdev));
1184+
11561185 err = xe_pm_runtime_suspend(xe);
11571186 if (err)
11581187 return err;
drivers/gpu/drm/xe/xe_pci_sriov.c+3−7
@@ -219,7 +219,6 @@ static int pf_disable_vfs(struct xe_device *xe) · 218 unmodified lines
219219 int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
220220 {
221221 struct xe_device *xe = pdev_to_xe_device(pdev);
222− int ret;
223222
224223 if (!IS_SRIOV_PF(xe))
225224 return -ENODEV;
@@ -233,14 +232,11 @@ int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) · 7 unmodified lines
233232 if (num_vfs && pci_num_vf(pdev))
234233 return -EBUSY;
235234
236− xe_pm_runtime_get(xe);
235+ guard(xe_pm_runtime)(xe);
237236 if (num_vfs > 0)
238− ret = pf_enable_vfs(xe, num_vfs);
237+ return pf_enable_vfs(xe, num_vfs);
239238 else
240− ret = pf_disable_vfs(xe);
241− xe_pm_runtime_put(xe);
242−
243− return ret;
239+ return pf_disable_vfs(xe);
244240 }
245241
246242 /**
drivers/gpu/drm/xe/xe_pci_types.h+6−0
@@ -37,16 +37,21 @@ struct xe_device_desc { · 36 unmodified lines
3737 u8 require_force_probe:1;
3838 u8 is_dgfx:1;
3939
40+ u8 has_cached_pt:1;
4041 u8 has_display:1;
4142 u8 has_fan_control:1;
4243 u8 has_flat_ccs:1;
4344 u8 has_gsc_nvm:1;
4445 u8 has_heci_gscfi:1;
4546 u8 has_heci_cscfi:1;
47+ u8 has_i2c:1;
4648 u8 has_late_bind:1;
4749 u8 has_llc:1;
4850 u8 has_mbx_power_limits:1;
4951 u8 has_mem_copy_instr:1;
52+ u8 has_mert:1;
53+ u8 has_pre_prod_wa:1;
54+ u8 has_page_reclaim_hw_assist:1;
5055 u8 has_pxp:1;
5156 u8 has_sriov:1;
5257 u8 needs_scratch:1;
@@ -58,6 +63,7 @@ struct xe_device_desc { · 5 unmodified lines
5863
5964 struct xe_graphics_desc {
6065 u64 hw_engine_mask; /* hardware engines provided by graphics IP */
66+ u16 multi_queue_engine_class_mask; /* bitmask of engine classes which support multi queue */
6167
6268 u8 has_asid:1;
6369 u8 has_atomic_enable_pte_bit:1;
drivers/gpu/drm/xe/xe_pcode_api.h+2−0
@@ -77,11 +77,13 @@ · 76 unmodified lines
7777
7878 #define PCODE_SCRATCH(x) XE_REG(0x138320 + ((x) * 4))
7979 /* PCODE_SCRATCH0 */
80+#define BREADCRUMB_VERSION REG_GENMASK(31, 29)
8081 #define AUXINFO_REG_OFFSET REG_GENMASK(17, 15)
8182 #define OVERFLOW_REG_OFFSET REG_GENMASK(14, 12)
8283 #define HISTORY_TRACKING REG_BIT(11)
8384 #define OVERFLOW_SUPPORT REG_BIT(10)
8485 #define AUXINFO_SUPPORT REG_BIT(9)
86+#define FDO_MODE REG_BIT(4)
8587 #define BOOT_STATUS REG_GENMASK(3, 1)
8688 #define CRITICAL_FAILURE 4
8789 #define NON_CRITICAL_FAILURE 7
drivers/gpu/drm/xe/xe_pm.c+5−5
@@ -591,7 +591,7 @@ int xe_pm_runtime_suspend(struct xe_device *xe) · 590 unmodified lines
591591 }
592592
593593 for_each_gt(gt, xe, id) {
594− err = xe_gt_suspend(gt);
594+ err = xe->d3cold.allowed ? xe_gt_suspend(gt) : xe_gt_runtime_suspend(gt);
595595 if (err)
596596 goto out_resume;
597597 }
@@ -633,10 +633,10 @@ int xe_pm_runtime_resume(struct xe_device *xe) · 35 unmodified lines
633633
634634 xe_rpm_lockmap_acquire(xe);
635635
636− for_each_gt(gt, xe, id)
637− xe_gt_idle_disable_c6(gt);
638−
639636 if (xe->d3cold.allowed) {
637+ for_each_gt(gt, xe, id)
638+ xe_gt_idle_disable_c6(gt);
639+
640640 err = xe_pcode_ready(xe, true);
641641 if (err)
642642 goto out;
@@ -657,7 +657,7 @@ int xe_pm_runtime_resume(struct xe_device *xe) · 14 unmodified lines
657657 xe_irq_resume(xe);
658658
659659 for_each_gt(gt, xe, id)
660− xe_gt_resume(gt);
660+ xe->d3cold.allowed ? xe_gt_resume(gt) : xe_gt_runtime_resume(gt);
661661
662662 xe_display_pm_runtime_resume(xe);
663663
drivers/gpu/drm/xe/xe_pmu.c+1−1
@@ -425,7 +425,7 @@ static ssize_t event_attr_show(struct device *dev, · 424 unmodified lines
425425 struct perf_pmu_events_attr *pmu_attr =
426426 container_of(attr, struct perf_pmu_events_attr, attr);
427427
428− return sprintf(buf, "event=%#04llx\n", pmu_attr->id);
428+ return sysfs_emit(buf, "event=%#04llx\n", pmu_attr->id);
429429 }
430430
431431 #define XE_EVENT_ATTR(name_, v_, id_) \
drivers/gpu/drm/xe/xe_pt.c+134−1
@@ -12,6 +12,7 @@ · 11 unmodified lines
1212 #include "xe_exec_queue.h"
1313 #include "xe_gt.h"
1414 #include "xe_migrate.h"
15+#include "xe_page_reclaim.h"
1516 #include "xe_pt_types.h"
1617 #include "xe_pt_walk.h"
1718 #include "xe_res_cursor.h"
@@ -1535,6 +1536,9 @@ struct xe_pt_stage_unbind_walk { · 1517 unmodified lines
15351536 /** @modified_end: Walk range start, modified like @modified_start. */
15361537 u64 modified_end;
15371538
1539+ /** @prl: Backing pointer to page reclaim list in pt_update_ops */
1540+ struct xe_page_reclaim_list *prl;
1541+
15381542 /* Output */
15391543 /* @wupd: Structure to track the page-table updates we're building */
15401544 struct xe_walk_update wupd;
@@ -1572,6 +1576,68 @@ static bool xe_pt_check_kill(u64 addr, u64 next, unsigned int level, · 31 unmodified lines
15721576 return false;
15731577 }
15741578
1579+/* Huge 2MB leaf lives directly in a level-1 table and has no children */
1580+static bool is_2m_pte(struct xe_pt *pte)
1581+{
1582+ return pte->level == 1 && !pte->base.children;
1583+}
1584+
1585+/* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */
1586+#define COMPUTE_RECLAIM_ADDRESS_MASK(page_size) \
1587+({ \
1588+ BUILD_BUG_ON(!__builtin_constant_p(page_size)); \
1589+ ilog2(page_size) - XE_PTE_SHIFT; \
1590+})
1591+
1592+static int generate_reclaim_entry(struct xe_tile *tile,
1593+ struct xe_page_reclaim_list *prl,
1594+ u64 pte, struct xe_pt *xe_child)
1595+{
1596+ struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries;
1597+ u64 phys_page = (pte & XE_PTE_ADDR_MASK) >> XE_PTE_SHIFT;
1598+ int num_entries = prl->num_entries;
1599+ u32 reclamation_size;
1600+
1601+ xe_tile_assert(tile, xe_child->level <= MAX_HUGEPTE_LEVEL);
1602+ xe_tile_assert(tile, reclaim_entries);
1603+ xe_tile_assert(tile, num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1);
1604+
1605+ if (!xe_page_reclaim_list_valid(prl))
1606+ return -EINVAL;
1607+
1608+ /**
1609+ * reclamation_size indicates the size of the page to be
1610+ * invalidated and flushed from non-coherent cache.
1611+ * Page size is computed as 2^(reclamation_size + XE_PTE_SHIFT) bytes.
1612+ * Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim
1613+ */
1614+ if (xe_child->level == 0 && !(pte & XE_PTE_PS64)) {
1615+ reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K); /* reclamation_size = 0 */
1616+ } else if (xe_child->level == 0) {
1617+ reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */
1618+ } else if (is_2m_pte(xe_child)) {
1619+ reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M); /* reclamation_size = 9 */
1620+ } else {
1621+ xe_page_reclaim_list_invalidate(prl);
1622+ vm_dbg(&tile_to_xe(tile)->drm,
1623+ "PRL invalidate: unsupported PTE level=%u pte=%#llx\n",
1624+ xe_child->level, pte);
1625+ return -EINVAL;
1626+ }
1627+
1628+ reclaim_entries[num_entries].qw =
1629+ FIELD_PREP(XE_PAGE_RECLAIM_VALID, 1) |
1630+ FIELD_PREP(XE_PAGE_RECLAIM_SIZE, reclamation_size) |
1631+ FIELD_PREP(XE_PAGE_RECLAIM_ADDR_LO, phys_page) |
1632+ FIELD_PREP(XE_PAGE_RECLAIM_ADDR_HI, phys_page >> 20);
1633+ prl->num_entries++;
1634+ vm_dbg(&tile_to_xe(tile)->drm,
1635+ "PRL add entry: level=%u pte=%#llx reclamation_size=%u prl_idx=%d\n",
1636+ xe_child->level, pte, reclamation_size, num_entries);
1637+
1638+ return 0;
1639+}
1640+
15751641 static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
15761642 unsigned int level, u64 addr, u64 next,
15771643 struct xe_ptw **child,
@@ -1579,11 +1645,48 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset, · 1 unmodified line
15791645 struct xe_pt_walk *walk)
15801646 {
15811647 struct xe_pt *xe_child = container_of(*child, typeof(*xe_child), base);
1648+ struct xe_pt_stage_unbind_walk *xe_walk =
1649+ container_of(walk, typeof(*xe_walk), base);
1650+ struct xe_device *xe = tile_to_xe(xe_walk->tile);
15821651
15831652 XE_WARN_ON(!*child);
15841653 XE_WARN_ON(!level);
1654+ /* Check for leaf node */
1655+ if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) &&
1656+ !xe_child->base.children) {
1657+ struct iosys_map *leaf_map = &xe_child->bo->vmap;
1658+ pgoff_t first = xe_pt_offset(addr, 0, walk);
1659+ pgoff_t count = xe_pt_num_entries(addr, next, 0, walk);
1660+
1661+ for (pgoff_t i = 0; i < count; i++) {
1662+ u64 pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64);
1663+ int ret;
1664+
1665+ /* Account for NULL terminated entry on end (-1) */
1666+ if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) {
1667+ ret = generate_reclaim_entry(xe_walk->tile, xe_walk->prl,
1668+ pte, xe_child);
1669+ if (ret)
1670+ break;
1671+ } else {
1672+ /* overflow, mark as invalid */
1673+ xe_page_reclaim_list_invalidate(xe_walk->prl);
1674+ vm_dbg(&xe->drm,
1675+ "PRL invalidate: overflow while adding pte=%#llx",
1676+ pte);
1677+ break;
1678+ }
1679+ }
1680+ }
15851681
1586− xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk);
1682+ /* If aborting page walk early, invalidate PRL since PTE may be dropped from this abort */
1683+ if (xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk) &&
1684+ xe_walk->prl && level > 1 && xe_child->base.children && xe_child->num_live != 0) {
1685+ xe_page_reclaim_list_invalidate(xe_walk->prl);
1686+ vm_dbg(&xe->drm,
1687+ "PRL invalidate: kill at level=%u addr=%#llx next=%#llx num_live=%u\n",
1688+ level, addr, next, xe_child->num_live);
1689+ }
15871690
15881691 return 0;
15891692 }
@@ -1654,6 +1757,8 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile, · 64 unmodified lines
16541757 {
16551758 u64 start = range ? xe_svm_range_start(range) : xe_vma_start(vma);
16561759 u64 end = range ? xe_svm_range_end(range) : xe_vma_end(vma);
1760+ struct xe_vm_pgtable_update_op *pt_update_op =
1761+ container_of(entries, struct xe_vm_pgtable_update_op, entries[0]);
16571762 struct xe_pt_stage_unbind_walk xe_walk = {
16581763 .base = {
16591764 .ops = &xe_pt_stage_unbind_ops,
@@ -1665,6 +1770,7 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile, · 5 unmodified lines
16651770 .modified_start = start,
16661771 .modified_end = end,
16671772 .wupd.entries = entries,
1773+ .prl = pt_update_op->prl,
16681774 };
16691775 struct xe_pt *pt = vm->pt_root[tile->id];
16701776
@@ -1897,6 +2003,7 @@ static int unbind_op_prepare(struct xe_tile *tile, · 226 unmodified lines
18972003 struct xe_vm_pgtable_update_ops *pt_update_ops,
18982004 struct xe_vma *vma)
18992005 {
2006+ struct xe_device *xe = tile_to_xe(tile);
19002007 u32 current_op = pt_update_ops->current_op;
19012008 struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
19022009 int err;
@@ -1914,6 +2021,17 @@ static int unbind_op_prepare(struct xe_tile *tile, · 11 unmodified lines
19142021 pt_op->vma = vma;
19152022 pt_op->bind = false;
19162023 pt_op->rebind = false;
2024+ /*
2025+ * Maintain one PRL located in pt_update_ops that all others in unbind op reference.
2026+ * Ensure that PRL is allocated only once, and if invalidated, remains an invalidated PRL.
2027+ */
2028+ if (xe->info.has_page_reclaim_hw_assist &&
2029+ xe_page_reclaim_list_is_new(&pt_update_ops->prl))
2030+ xe_page_reclaim_list_alloc_entries(&pt_update_ops->prl);
2031+
2032+ /* Page reclaim may not be needed due to other features, so skip the corresponding VMA */
2033+ pt_op->prl = (xe_page_reclaim_list_valid(&pt_update_ops->prl) &&
2034+ !xe_page_reclaim_skip(tile, vma)) ? &pt_update_ops->prl : NULL;
19172035
19182036 err = vma_reserve_fences(tile_to_xe(tile), vma);
19192037 if (err)
@@ -1979,6 +2097,7 @@ static int unbind_range_prepare(struct xe_vm *vm, · 59 unmodified lines
19792097 pt_op->vma = XE_INVALID_VMA;
19802098 pt_op->bind = false;
19812099 pt_op->rebind = false;
2100+ pt_op->prl = NULL;
19822101
19832102 pt_op->num_entries = xe_pt_stage_unbind(tile, vm, NULL, range,
19842103 pt_op->entries);
@@ -2096,6 +2215,7 @@ xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops) · 111 unmodified lines
20962215 init_llist_head(&pt_update_ops->deferred);
20972216 pt_update_ops->start = ~0x0ull;
20982217 pt_update_ops->last = 0x0ull;
2218+ xe_page_reclaim_list_init(&pt_update_ops->prl);
20992219 }
21002220
21012221 /**
@@ -2393,6 +2513,17 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops) · 291 unmodified lines
23932513 goto kill_vm_tile1;
23942514 }
23952515 update.ijob = ijob;
2516+ /*
2517+ * Only add page reclaim for the primary GT. Media GT does not have
2518+ * any PPC to flush, so enabling the PPC flush bit for media is
2519+ * effectively a NOP and provides no performance benefit nor
2520+ * interfere with primary GT.
2521+ */
2522+ if (xe_page_reclaim_list_valid(&pt_update_ops->prl)) {
2523+ xe_tlb_inval_job_add_page_reclaim(ijob, &pt_update_ops->prl);
2524+ /* Release ref from alloc, job will now handle it */
2525+ xe_page_reclaim_list_invalidate(&pt_update_ops->prl);
2526+ }
23962527
23972528 if (tile->media_gt) {
23982529 dep_scheduler = to_dep_scheduler(q, tile->media_gt);
@@ -2518,6 +2649,8 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops) · 119 unmodified lines
25182649 &vops->pt_update_ops[tile->id];
25192650 int i;
25202651
2652+ xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
2653+
25212654 lockdep_assert_held(&vops->vm->lock);
25222655 xe_vm_assert_held(vops->vm);
25232656
drivers/gpu/drm/xe/xe_pt_types.h+5−0
@@ -8,6 +8,7 @@ · 7 unmodified lines
88
99 #include <linux/types.h>
1010
11+#include "xe_page_reclaim.h"
1112 #include "xe_pt_walk.h"
1213
1314 struct xe_bo;
@@ -79,6 +80,8 @@ struct xe_vm_pgtable_update_op { · 65 unmodified lines
7980 struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
8081 /** @vma: VMA for operation, operation not valid if NULL */
8182 struct xe_vma *vma;
83+ /** @prl: Backing pointer to page reclaim list of pt_update_ops */
84+ struct xe_page_reclaim_list *prl;
8285 /** @num_entries: number of entries for this update operation */
8386 u32 num_entries;
8487 /** @bind: is a bind */
@@ -95,6 +98,8 @@ struct xe_vm_pgtable_update_ops { · 10 unmodified lines
9598 struct llist_head deferred;
9699 /** @q: exec queue for PT operations */
97100 struct xe_exec_queue *q;
101+ /** @prl: embedded page reclaim list */
102+ struct xe_page_reclaim_list prl;
98103 /** @start: start address of ops */
99104 u64 start;
100105 /** @last: last address of ops */
drivers/gpu/drm/xe/xe_pxp.c+18−37
@@ -58,10 +58,9 @@ bool xe_pxp_is_enabled(const struct xe_pxp *pxp) · 57 unmodified lines
5858 static bool pxp_prerequisites_done(const struct xe_pxp *pxp)
5959 {
6060 struct xe_gt *gt = pxp->gt;
61− unsigned int fw_ref;
6261 bool ready;
6362
64− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
63+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
6564
6665 /*
6766 * If force_wake fails we could falsely report the prerequisites as not
@@ -71,14 +70,12 @@ static bool pxp_prerequisites_done(const struct xe_pxp *pxp) · 3 unmodified lines
7170 * PXP. Therefore, we can just log the force_wake error and not escalate
7271 * it.
7372 */
74− XE_WARN_ON(!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL));
73+ XE_WARN_ON(!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL));
7574
7675 /* PXP requires both HuC authentication via GSC and GSC proxy initialized */
7776 ready = xe_huc_is_authenticated(&gt->uc.huc, XE_HUC_AUTH_VIA_GSC) &&
7877 xe_gsc_proxy_init_done(&gt->uc.gsc);
7978
80− xe_force_wake_put(gt_to_fw(gt), fw_ref);
81−
8279 return ready;
8380 }
8481
@@ -104,13 +101,12 @@ int xe_pxp_get_readiness_status(struct xe_pxp *pxp) · 19 unmodified lines
104101 xe_uc_fw_status_to_error(pxp->gt->uc.gsc.fw.status))
105102 return -EIO;
106103
107− xe_pm_runtime_get(pxp->xe);
104+ guard(xe_pm_runtime)(pxp->xe);
108105
109106 /* PXP requires both HuC loaded and GSC proxy initialized */
110107 if (pxp_prerequisites_done(pxp))
111108 ret = 1;
112109
113− xe_pm_runtime_put(pxp->xe);
114110 return ret;
115111 }
116112
@@ -135,35 +131,28 @@ static void pxp_invalidate_queues(struct xe_pxp *pxp); · 18 unmodified lines
135131 static int pxp_terminate_hw(struct xe_pxp *pxp)
136132 {
137133 struct xe_gt *gt = pxp->gt;
138− unsigned int fw_ref;
139134 int ret = 0;
140135
141136 drm_dbg(&pxp->xe->drm, "Terminating PXP\n");
142137
143− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
144− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) {
145− ret = -EIO;
146− goto out;
147− }
138+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
139+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT))
140+ return -EIO;
148141
149142 /* terminate the hw session */
150143 ret = xe_pxp_submit_session_termination(pxp, ARB_SESSION);
151144 if (ret)
152− goto out;
145+ return ret;
153146
154147 ret = pxp_wait_for_session_state(pxp, ARB_SESSION, false);
155148 if (ret)
156− goto out;
149+ return ret;
157150
158151 /* Trigger full HW cleanup */
159152 xe_mmio_write32(&gt->mmio, KCR_GLOBAL_TERMINATE, 1);
160153
161154 /* now we can tell the GSC to clean up its own state */
162− ret = xe_pxp_submit_session_invalidation(&pxp->gsc_res, ARB_SESSION);
163−
164−out:
165− xe_force_wake_put(gt_to_fw(gt), fw_ref);
166− return ret;
155+ return xe_pxp_submit_session_invalidation(&pxp->gsc_res, ARB_SESSION);
167156 }
168157
169158 static void mark_termination_in_progress(struct xe_pxp *pxp)
@@ -326,14 +315,12 @@ static int kcr_pxp_set_status(const struct xe_pxp *pxp, bool enable) · 156 unmodified lines
326315 {
327316 u32 val = enable ? _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES) :
328317 _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES);
329− unsigned int fw_ref;
330318
331− fw_ref = xe_force_wake_get(gt_to_fw(pxp->gt), XE_FW_GT);
332− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT))
319+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(pxp->gt), XE_FW_GT);
320+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT))
333321 return -EIO;
334322
335323 xe_mmio_write32(&pxp->gt->mmio, KCR_INIT, val);
336− xe_force_wake_put(gt_to_fw(pxp->gt), fw_ref);
337324
338325 return 0;
339326 }
@@ -453,34 +440,28 @@ out: · 113 unmodified lines
453440 static int __pxp_start_arb_session(struct xe_pxp *pxp)
454441 {
455442 int ret;
456− unsigned int fw_ref;
457443
458− fw_ref = xe_force_wake_get(gt_to_fw(pxp->gt), XE_FW_GT);
459− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT))
444+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(pxp->gt), XE_FW_GT);
445+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT))
460446 return -EIO;
461447
462− if (pxp_session_is_in_play(pxp, ARB_SESSION)) {
463− ret = -EEXIST;
464− goto out_force_wake;
465− }
448+ if (pxp_session_is_in_play(pxp, ARB_SESSION))
449+ return -EEXIST;
466450
467451 ret = xe_pxp_submit_session_init(&pxp->gsc_res, ARB_SESSION);
468452 if (ret) {
469453 drm_err(&pxp->xe->drm, "Failed to init PXP arb session: %pe\n", ERR_PTR(ret));
470− goto out_force_wake;
454+ return ret;
471455 }
472456
473457 ret = pxp_wait_for_session_state(pxp, ARB_SESSION, true);
474458 if (ret) {
475459 drm_err(&pxp->xe->drm, "PXP ARB session failed to go in play%pe\n", ERR_PTR(ret));
476− goto out_force_wake;
460+ return ret;
477461 }
478462
479463 drm_dbg(&pxp->xe->drm, "PXP ARB session is active\n");
480−
481−out_force_wake:
482− xe_force_wake_put(gt_to_fw(pxp->gt), fw_ref);
483− return ret;
464+ return 0;
484465 }
485466
486467 /**
drivers/gpu/drm/xe/xe_query.c+12−11
@@ -122,7 +122,6 @@ query_engine_cycles(struct xe_device *xe, · 121 unmodified lines
122122 __ktime_func_t cpu_clock;
123123 struct xe_hw_engine *hwe;
124124 struct xe_gt *gt;
125− unsigned int fw_ref;
126125
127126 if (IS_SRIOV_VF(xe))
128127 return -EOPNOTSUPP;
@@ -158,16 +157,13 @@ query_engine_cycles(struct xe_device *xe, · 29 unmodified lines
158157 if (!hwe)
159158 return -EINVAL;
160159
161− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
162− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) {
163− xe_force_wake_put(gt_to_fw(gt), fw_ref);
164− return -EIO;
165− }
166−
167− hwe_read_timestamp(hwe, &resp.engine_cycles, &resp.cpu_timestamp,
168− &resp.cpu_delta, cpu_clock);
160+ xe_with_force_wake(fw_ref, gt_to_fw(gt), XE_FORCEWAKE_ALL) {
161+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL))
162+ return -EIO;
169163
170− xe_force_wake_put(gt_to_fw(gt), fw_ref);
164+ hwe_read_timestamp(hwe, &resp.engine_cycles, &resp.cpu_timestamp,
165+ &resp.cpu_delta, cpu_clock);
166+ }
171167
172168 if (GRAPHICS_VER(xe) >= 20)
173169 resp.width = 64;
@@ -342,6 +338,9 @@ static int query_config(struct xe_device *xe, struct drm_xe_device_query *query) · 168 unmodified lines
342338 if (xe->info.has_usm && IS_ENABLED(CONFIG_DRM_XE_GPUSVM))
343339 config->info[DRM_XE_QUERY_CONFIG_FLAGS] |=
344340 DRM_XE_QUERY_CONFIG_FLAG_HAS_CPU_ADDR_MIRROR;
341+ if (GRAPHICS_VER(xe) >= 20)
342+ config->info[DRM_XE_QUERY_CONFIG_FLAGS] |=
343+ DRM_XE_QUERY_CONFIG_FLAG_HAS_NO_COMPRESSION_HINT;
345344 config->info[DRM_XE_QUERY_CONFIG_FLAGS] |=
346345 DRM_XE_QUERY_CONFIG_FLAG_HAS_LOW_LATENCY;
347346 config->info[DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT] =
@@ -686,7 +685,9 @@ static int query_oa_units(struct xe_device *xe, · 338 unmodified lines
686685 du->capabilities = DRM_XE_OA_CAPS_BASE | DRM_XE_OA_CAPS_SYNCS |
687686 DRM_XE_OA_CAPS_OA_BUFFER_SIZE |
688687 DRM_XE_OA_CAPS_WAIT_NUM_REPORTS |
689− DRM_XE_OA_CAPS_OAM;
688+ DRM_XE_OA_CAPS_OAM |
689+ DRM_XE_OA_CAPS_OA_UNIT_GT_ID;
690+ du->gt_id = u->gt->info.id;
690691 j = 0;
691692 for_each_hw_engine(hwe, gt, hwe_id) {
692693 if (!xe_hw_engine_is_reserved(hwe) &&
drivers/gpu/drm/xe/xe_reg_sr.c+5−12
@@ -168,7 +168,6 @@ void xe_reg_sr_apply_mmio(struct xe_reg_sr *sr, struct xe_gt *gt) · 167 unmodified lines
168168 {
169169 struct xe_reg_sr_entry *entry;
170170 unsigned long reg;
171− unsigned int fw_ref;
172171
173172 if (xa_empty(&sr->xa))
174173 return;
@@ -178,20 +177,14 @@ void xe_reg_sr_apply_mmio(struct xe_reg_sr *sr, struct xe_gt *gt) · 3 unmodified lines
178177
179178 xe_gt_dbg(gt, "Applying %s save-restore MMIOs\n", sr->name);
180179
181− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
182− if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
183− goto err_force_wake;
180+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
181+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) {
182+ xe_gt_err(gt, "Failed to apply, err=-ETIMEDOUT\n");
183+ return;
184+ }
184185
185186 xa_for_each(&sr->xa, reg, entry)
186187 apply_one_mmio(gt, entry);
187−
188− xe_force_wake_put(gt_to_fw(gt), fw_ref);
189−
190− return;
191−
192−err_force_wake:
193− xe_force_wake_put(gt_to_fw(gt), fw_ref);
194− xe_gt_err(gt, "Failed to apply, err=-ETIMEDOUT\n");
195188 }
196189
197190 /**
drivers/gpu/drm/xe/xe_reg_whitelist.c+59−22
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #include "regs/xe_gt_regs.h"
1010 #include "regs/xe_oa_regs.h"
1111 #include "regs/xe_regs.h"
12+#include "xe_device.h"
1213 #include "xe_gt_types.h"
1314 #include "xe_gt_printk.h"
1415 #include "xe_platform_types.h"
@@ -26,6 +27,13 @@ static bool match_not_render(const struct xe_device *xe, · 11 unmodified lines
2627 return hwe->class != XE_ENGINE_CLASS_RENDER;
2728 }
2829
30+static bool match_has_mert(const struct xe_device *xe,
31+ const struct xe_gt *gt,
32+ const struct xe_hw_engine *hwe)
33+{
34+ return xe_device_has_mert((struct xe_device *)xe);
35+}
36+
2937 static const struct xe_rtp_entry_sr register_whitelist[] = {
3038 { XE_RTP_NAME("WaAllowPMDepthAndInvocationCountAccessFromUMD, 1408556865"),
3139 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210), ENGINE_CLASS(RENDER)),
@@ -67,28 +75,6 @@ static const struct xe_rtp_entry_sr register_whitelist[] = { · 35 unmodified lines
6775 ENGINE_CLASS(RENDER)),
6876 XE_RTP_ACTIONS(WHITELIST(CSBE_DEBUG_STATUS(RENDER_RING_BASE), 0))
6977 },
70− { XE_RTP_NAME("oa_reg_render"),
71− XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED),
72− ENGINE_CLASS(RENDER)),
73− XE_RTP_ACTIONS(WHITELIST(OAG_MMIOTRIGGER,
74− RING_FORCE_TO_NONPRIV_ACCESS_RW),
75− WHITELIST(OAG_OASTATUS,
76− RING_FORCE_TO_NONPRIV_ACCESS_RD),
77− WHITELIST(OAG_OAHEADPTR,
78− RING_FORCE_TO_NONPRIV_ACCESS_RD |
79− RING_FORCE_TO_NONPRIV_RANGE_4))
80− },
81− { XE_RTP_NAME("oa_reg_compute"),
82− XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED),
83− ENGINE_CLASS(COMPUTE)),
84− XE_RTP_ACTIONS(WHITELIST(OAG_MMIOTRIGGER,
85− RING_FORCE_TO_NONPRIV_ACCESS_RW),
86− WHITELIST(OAG_OASTATUS,
87− RING_FORCE_TO_NONPRIV_ACCESS_RD),
88− WHITELIST(OAG_OAHEADPTR,
89− RING_FORCE_TO_NONPRIV_ACCESS_RD |
90− RING_FORCE_TO_NONPRIV_RANGE_4))
91− },
9278 { XE_RTP_NAME("14024997852"),
9379 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005), ENGINE_CLASS(RENDER)),
9480 XE_RTP_ACTIONS(WHITELIST(FF_MODE,
@@ -96,6 +82,57 @@ static const struct xe_rtp_entry_sr register_whitelist[] = { · 1 unmodified line
9682 WHITELIST(VFLSKPD,
9783 RING_FORCE_TO_NONPRIV_ACCESS_RW))
9884 },
85+
86+#define WHITELIST_OA_MMIO_TRG(trg, status, head) \
87+ WHITELIST(trg, RING_FORCE_TO_NONPRIV_ACCESS_RW), \
88+ WHITELIST(status, RING_FORCE_TO_NONPRIV_ACCESS_RD), \
89+ WHITELIST(head, RING_FORCE_TO_NONPRIV_ACCESS_RD | RING_FORCE_TO_NONPRIV_RANGE_4)
90+
91+#define WHITELIST_OAG_MMIO_TRG \
92+ WHITELIST_OA_MMIO_TRG(OAG_MMIOTRIGGER, OAG_OASTATUS, OAG_OAHEADPTR)
93+
94+#define WHITELIST_OAM_MMIO_TRG \
95+ WHITELIST_OA_MMIO_TRG(OAM_MMIO_TRG(XE_OAM_SAG_BASE_ADJ), \
96+ OAM_STATUS(XE_OAM_SAG_BASE_ADJ), \
97+ OAM_HEAD_POINTER(XE_OAM_SAG_BASE_ADJ)), \
98+ WHITELIST_OA_MMIO_TRG(OAM_MMIO_TRG(XE_OAM_SCMI_0_BASE_ADJ), \
99+ OAM_STATUS(XE_OAM_SCMI_0_BASE_ADJ), \
100+ OAM_HEAD_POINTER(XE_OAM_SCMI_0_BASE_ADJ)), \
101+ WHITELIST_OA_MMIO_TRG(OAM_MMIO_TRG(XE_OAM_SCMI_1_BASE_ADJ), \
102+ OAM_STATUS(XE_OAM_SCMI_1_BASE_ADJ), \
103+ OAM_HEAD_POINTER(XE_OAM_SCMI_1_BASE_ADJ))
104+
105+#define WHITELIST_OA_MERT_MMIO_TRG \
106+ WHITELIST_OA_MMIO_TRG(OAMERT_MMIO_TRG, OAMERT_STATUS, OAMERT_HEAD_POINTER)
107+
108+ { XE_RTP_NAME("oag_mmio_trg_rcs"),
109+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED),
110+ ENGINE_CLASS(RENDER)),
111+ XE_RTP_ACTIONS(WHITELIST_OAG_MMIO_TRG)
112+ },
113+ { XE_RTP_NAME("oag_mmio_trg_ccs"),
114+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED),
115+ ENGINE_CLASS(COMPUTE)),
116+ XE_RTP_ACTIONS(WHITELIST_OAG_MMIO_TRG)
117+ },
118+ { XE_RTP_NAME("oam_mmio_trg_vcs"),
119+ XE_RTP_RULES(MEDIA_VERSION_RANGE(1300, XE_RTP_END_VERSION_UNDEFINED),
120+ ENGINE_CLASS(VIDEO_DECODE)),
121+ XE_RTP_ACTIONS(WHITELIST_OAM_MMIO_TRG)
122+ },
123+ { XE_RTP_NAME("oam_mmio_trg_vecs"),
124+ XE_RTP_RULES(MEDIA_VERSION_RANGE(1300, XE_RTP_END_VERSION_UNDEFINED),
125+ ENGINE_CLASS(VIDEO_ENHANCE)),
126+ XE_RTP_ACTIONS(WHITELIST_OAM_MMIO_TRG)
127+ },
128+ { XE_RTP_NAME("oa_mert_mmio_trg_ccs"),
129+ XE_RTP_RULES(FUNC(match_has_mert), ENGINE_CLASS(COMPUTE)),
130+ XE_RTP_ACTIONS(WHITELIST_OA_MERT_MMIO_TRG)
131+ },
132+ { XE_RTP_NAME("oa_mert_mmio_trg_bcs"),
133+ XE_RTP_RULES(FUNC(match_has_mert), ENGINE_CLASS(COPY)),
134+ XE_RTP_ACTIONS(WHITELIST_OA_MERT_MMIO_TRG)
135+ },
99136 };
100137
101138 static void whitelist_apply_to_hwe(struct xe_hw_engine *hwe)
drivers/gpu/drm/xe/xe_ring_ops.c+34−34
@@ -12,7 +12,7 @@ · 11 unmodified lines
1212 #include "regs/xe_engine_regs.h"
1313 #include "regs/xe_gt_regs.h"
1414 #include "regs/xe_lrc_layout.h"
15−#include "xe_exec_queue_types.h"
15+#include "xe_exec_queue.h"
1616 #include "xe_gt.h"
1717 #include "xe_lrc.h"
1818 #include "xe_macros.h"
@@ -135,12 +135,11 @@ emit_pipe_control(u32 *dw, int i, u32 bit_group_0, u32 bit_group_1, u32 offset, · 116 unmodified lines
135135 return i;
136136 }
137137
138−static int emit_pipe_invalidate(u32 mask_flags, bool invalidate_tlb, u32 *dw,
139− int i)
138+static int emit_pipe_invalidate(struct xe_exec_queue *q, u32 mask_flags,
139+ bool invalidate_tlb, u32 *dw, int i)
140140 {
141141 u32 flags0 = 0;
142− u32 flags1 = PIPE_CONTROL_CS_STALL |
143− PIPE_CONTROL_COMMAND_CACHE_INVALIDATE |
142+ u32 flags1 = PIPE_CONTROL_COMMAND_CACHE_INVALIDATE |
144143 PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
145144 PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
146145 PIPE_CONTROL_VF_CACHE_INVALIDATE |
@@ -152,6 +151,11 @@ static int emit_pipe_invalidate(u32 mask_flags, bool invalidate_tlb, u32 *dw, · 5 unmodified lines
152151 if (invalidate_tlb)
153152 flags1 |= PIPE_CONTROL_TLB_INVALIDATE;
154153
154+ if (xe_exec_queue_is_multi_queue(q))
155+ flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
156+ else
157+ flags1 |= PIPE_CONTROL_CS_STALL;
158+
155159 flags1 &= ~mask_flags;
156160
157161 if (flags1 & PIPE_CONTROL_VF_CACHE_INVALIDATE)
@@ -175,54 +179,52 @@ static int emit_store_imm_ppgtt_posted(u64 addr, u64 value, · 17 unmodified lines
175179
176180 static int emit_render_cache_flush(struct xe_sched_job *job, u32 *dw, int i)
177181 {
178− struct xe_gt *gt = job->q->gt;
182+ struct xe_exec_queue *q = job->q;
183+ struct xe_gt *gt = q->gt;
179184 bool lacks_render = !(gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK);
180− u32 flags;
185+ u32 flags0, flags1;
181186
182187 if (XE_GT_WA(gt, 14016712196))
183188 i = emit_pipe_control(dw, i, 0, PIPE_CONTROL_DEPTH_CACHE_FLUSH,
184189 LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR, 0);
185190
186− flags = (PIPE_CONTROL_CS_STALL |
187− PIPE_CONTROL_TILE_CACHE_FLUSH |
191+ flags0 = PIPE_CONTROL0_HDC_PIPELINE_FLUSH;
192+ flags1 = (PIPE_CONTROL_TILE_CACHE_FLUSH |
188193 PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
189194 PIPE_CONTROL_DEPTH_CACHE_FLUSH |
190195 PIPE_CONTROL_DC_FLUSH_ENABLE |
191196 PIPE_CONTROL_FLUSH_ENABLE);
192197
193198 if (XE_GT_WA(gt, 1409600907))
194− flags |= PIPE_CONTROL_DEPTH_STALL;
199+ flags1 |= PIPE_CONTROL_DEPTH_STALL;
195200
196201 if (lacks_render)
197− flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
202+ flags1 &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
198203 else if (job->q->class == XE_ENGINE_CLASS_COMPUTE)
199− flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
204+ flags1 &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
200205
201− return emit_pipe_control(dw, i, PIPE_CONTROL0_HDC_PIPELINE_FLUSH, flags, 0, 0);
202−}
203−
204−static int emit_pipe_control_to_ring_end(struct xe_hw_engine *hwe, u32 *dw, int i)
205−{
206− if (hwe->class != XE_ENGINE_CLASS_RENDER)
207− return i;
206+ if (xe_exec_queue_is_multi_queue(q))
207+ flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
208+ else
209+ flags1 |= PIPE_CONTROL_CS_STALL;
208210
209− if (XE_GT_WA(hwe->gt, 16020292621))
210− i = emit_pipe_control(dw, i, 0, PIPE_CONTROL_LRI_POST_SYNC,
211− RING_NOPID(hwe->mmio_base).addr, 0);
212−
213− return i;
211+ return emit_pipe_control(dw, i, flags0, flags1, 0, 0);
214212 }
215213
216−static int emit_pipe_imm_ggtt(u32 addr, u32 value, bool stall_only, u32 *dw,
217− int i)
214+static int emit_pipe_imm_ggtt(struct xe_exec_queue *q, u32 addr, u32 value,
215+ bool stall_only, u32 *dw, int i)
218216 {
219− u32 flags = PIPE_CONTROL_CS_STALL | PIPE_CONTROL_GLOBAL_GTT_IVB |
220− PIPE_CONTROL_QW_WRITE;
217+ u32 flags0 = 0, flags1 = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_QW_WRITE;
221218
222219 if (!stall_only)
223− flags |= PIPE_CONTROL_FLUSH_ENABLE;
220+ flags1 |= PIPE_CONTROL_FLUSH_ENABLE;
224221
225− return emit_pipe_control(dw, i, 0, flags, addr, value);
222+ if (xe_exec_queue_is_multi_queue(q))
223+ flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
224+ else
225+ flags1 |= PIPE_CONTROL_CS_STALL;
226+
227+ return emit_pipe_control(dw, i, flags0, flags1, addr, value);
226228 }
227229
228230 static u32 get_ppgtt_flag(struct xe_sched_job *job)
@@ -371,7 +373,7 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job, · 142 unmodified lines
371373 mask_flags = PIPE_CONTROL_3D_ENGINE_FLAGS;
372374
373375 /* See __xe_pt_bind_vma() for a discussion on TLB invalidations. */
374− i = emit_pipe_invalidate(mask_flags, job->ring_ops_flush_tlb, dw, i);
376+ i = emit_pipe_invalidate(job->q, mask_flags, job->ring_ops_flush_tlb, dw, i);
375377
376378 /* hsdes: 1809175790 */
377379 if (has_aux_ccs(xe))
@@ -391,12 +393,10 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job, · 13 unmodified lines
391393 job->user_fence.value,
392394 dw, i);
393395
394− i = emit_pipe_imm_ggtt(xe_lrc_seqno_ggtt_addr(lrc), seqno, lacks_render, dw, i);
396+ i = emit_pipe_imm_ggtt(job->q, xe_lrc_seqno_ggtt_addr(lrc), seqno, lacks_render, dw, i);
395397
396398 i = emit_user_interrupt(dw, i);
397399
398− i = emit_pipe_control_to_ring_end(job->q->hwe, dw, i);
399−
400400 xe_gt_assert(gt, i <= MAX_JOB_SIZE_DW);
401401
402402 xe_lrc_write_ring(lrc, dw, i * sizeof(*dw));
drivers/gpu/drm/xe/xe_sa.c+66−1
@@ -29,6 +29,7 @@ static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) · 28 unmodified lines
2929 kvfree(sa_manager->cpu_ptr);
3030
3131 sa_manager->bo = NULL;
32+ sa_manager->shadow = NULL;
3233 }
3334
3435 /**
@@ -37,12 +38,14 @@ static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) · 2 unmodified lines
3738 * @size: number of bytes to allocate
3839 * @guard: number of bytes to exclude from suballocations
3940 * @align: alignment for each suballocated chunk
41+ * @flags: flags for suballocator
4042 *
4143 * Prepares the suballocation manager for suballocations.
4244 *
4345 * Return: a pointer to the &xe_sa_manager or an ERR_PTR on failure.
4446 */
45−struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align)
47+struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size,
48+ u32 guard, u32 align, u32 flags)
4649 {
4750 struct xe_device *xe = tile_to_xe(tile);
4851 struct xe_sa_manager *sa_manager;
@@ -79,6 +82,26 @@ struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u3 · 30 unmodified lines
7982 memset(sa_manager->cpu_ptr, 0, bo->ttm.base.size);
8083 }
8184
85+ if (flags & XE_SA_BO_MANAGER_FLAG_SHADOW) {
86+ struct xe_bo *shadow;
87+
88+ ret = drmm_mutex_init(&xe->drm, &sa_manager->swap_guard);
89+ if (ret)
90+ return ERR_PTR(ret);
91+
92+ shadow = xe_managed_bo_create_pin_map(xe, tile, size,
93+ XE_BO_FLAG_VRAM_IF_DGFX(tile) |
94+ XE_BO_FLAG_GGTT |
95+ XE_BO_FLAG_GGTT_INVALIDATE |
96+ XE_BO_FLAG_PINNED_NORESTORE);
97+ if (IS_ERR(shadow)) {
98+ drm_err(&xe->drm, "Failed to prepare %uKiB BO for SA manager (%pe)\n",
99+ size / SZ_1K, shadow);
100+ return ERR_CAST(shadow);
101+ }
102+ sa_manager->shadow = shadow;
103+ }
104+
82105 drm_suballoc_manager_init(&sa_manager->base, managed_size, align);
83106 ret = drmm_add_action_or_reset(&xe->drm, xe_sa_bo_manager_fini,
84107 sa_manager);
@@ -88,6 +111,48 @@ struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u3 · 3 unmodified lines
88111 return sa_manager;
89112 }
90113
114+/**
115+ * xe_sa_bo_swap_shadow() - Swap the SA BO with shadow BO.
116+ * @sa_manager: the XE sub allocator manager
117+ *
118+ * Swaps the sub-allocator primary buffer object with shadow buffer object.
119+ *
120+ * Return: None.
121+ */
122+void xe_sa_bo_swap_shadow(struct xe_sa_manager *sa_manager)
123+{
124+ struct xe_device *xe = tile_to_xe(sa_manager->bo->tile);
125+
126+ xe_assert(xe, sa_manager->shadow);
127+ lockdep_assert_held(&sa_manager->swap_guard);
128+
129+ swap(sa_manager->bo, sa_manager->shadow);
130+ if (!sa_manager->bo->vmap.is_iomem)
131+ sa_manager->cpu_ptr = sa_manager->bo->vmap.vaddr;
132+}
133+
134+/**
135+ * xe_sa_bo_sync_shadow() - Sync the SA Shadow BO with primary BO.
136+ * @sa_bo: the sub-allocator buffer object.
137+ *
138+ * Synchronize sub-allocator shadow buffer object with primary buffer object.
139+ *
140+ * Return: None.
141+ */
142+void xe_sa_bo_sync_shadow(struct drm_suballoc *sa_bo)
143+{
144+ struct xe_sa_manager *sa_manager = to_xe_sa_manager(sa_bo->manager);
145+ struct xe_device *xe = tile_to_xe(sa_manager->bo->tile);
146+
147+ xe_assert(xe, sa_manager->shadow);
148+ lockdep_assert_held(&sa_manager->swap_guard);
149+
150+ xe_map_memcpy_to(xe, &sa_manager->shadow->vmap,
151+ drm_suballoc_soffset(sa_bo),
152+ xe_sa_bo_cpu_addr(sa_bo),
153+ drm_suballoc_size(sa_bo));
154+}
155+
91156 /**
92157 * __xe_sa_bo_new() - Make a suballocation but use custom gfp flags.
93158 * @sa_manager: the &xe_sa_manager
drivers/gpu/drm/xe/xe_sa.h+18−2
@@ -14,12 +14,14 @@ · 13 unmodified lines
1414 struct dma_fence;
1515 struct xe_tile;
1616
17−struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align);
17+#define XE_SA_BO_MANAGER_FLAG_SHADOW BIT(0)
18+struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size,
19+ u32 guard, u32 align, u32 flags);
1820 struct drm_suballoc *__xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size, gfp_t gfp);
1921
2022 static inline struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align)
2123 {
22− return __xe_sa_bo_manager_init(tile, size, SZ_4K, align);
24+ return __xe_sa_bo_manager_init(tile, size, SZ_4K, align, 0);
2325 }
2426
2527 /**
@@ -69,4 +71,18 @@ static inline void *xe_sa_bo_cpu_addr(struct drm_suballoc *sa) · 43 unmodified lines
6971 drm_suballoc_soffset(sa);
7072 }
7173
74+void xe_sa_bo_swap_shadow(struct xe_sa_manager *sa_manager);
75+void xe_sa_bo_sync_shadow(struct drm_suballoc *sa_bo);
76+
77+/**
78+ * xe_sa_bo_swap_guard() - Retrieve the SA BO swap guard within sub-allocator.
79+ * @sa_manager: the &xe_sa_manager
80+ *
81+ * Return: Sub alloctor swap guard mutex.
82+ */
83+static inline struct mutex *xe_sa_bo_swap_guard(struct xe_sa_manager *sa_manager)
84+{
85+ return &sa_manager->swap_guard;
86+}
87+
7288 #endif
drivers/gpu/drm/xe/xe_sa_types.h+3−0
@@ -12,6 +12,9 @@ struct xe_bo; · 11 unmodified lines
1212 struct xe_sa_manager {
1313 struct drm_suballoc_manager base;
1414 struct xe_bo *bo;
15+ struct xe_bo *shadow;
16+ /** @swap_guard: Timeline guard updating @bo and @shadow */
17+ struct mutex swap_guard;
1518 void *cpu_ptr;
1619 bool is_iomem;
1720 };
drivers/gpu/drm/xe/xe_sriov_packet.c+1−1
@@ -358,7 +358,7 @@ ssize_t xe_sriov_packet_write_single(struct xe_device *xe, unsigned int vfid, · 357 unmodified lines
358358
359359 #define MIGRATION_DESCRIPTOR_DWORDS (GUC_KLV_LEN_MIN + MIGRATION_KLV_DEVICE_DEVID_LEN + \
360360 GUC_KLV_LEN_MIN + MIGRATION_KLV_DEVICE_REVID_LEN)
361−static size_t pf_descriptor_init(struct xe_device *xe, unsigned int vfid)
361+static int pf_descriptor_init(struct xe_device *xe, unsigned int vfid)
362362 {
363363 struct xe_sriov_packet **desc = pf_pick_descriptor(xe, vfid);
364364 struct xe_sriov_packet *data;
drivers/gpu/drm/xe/xe_sriov_pf.c+4−0
@@ -90,6 +90,7 @@ bool xe_sriov_pf_readiness(struct xe_device *xe) · 89 unmodified lines
9090 */
9191 int xe_sriov_pf_init_early(struct xe_device *xe)
9292 {
93+ struct xe_mert *mert = &xe_device_get_root_tile(xe)->mert;
9394 int err;
9495
9596 xe_assert(xe, IS_SRIOV_PF(xe));
@@ -111,6 +112,9 @@ int xe_sriov_pf_init_early(struct xe_device *xe) · 15 unmodified lines
111112
112113 xe_sriov_pf_service_init(xe);
113114
115+ spin_lock_init(&mert->lock);
116+ init_completion(&mert->tlb_inv_done);
117+
114118 return 0;
115119 }
116120
drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c+2−4
@@ -70,9 +70,8 @@ static ssize_t from_file_write_to_xe_call(struct file *file, const char __user * · 69 unmodified lines
7070 if (ret < 0)
7171 return ret;
7272 if (yes) {
73− xe_pm_runtime_get(xe);
73+ guard(xe_pm_runtime)(xe);
7474 ret = call(xe);
75− xe_pm_runtime_put(xe);
7675 }
7776 if (ret < 0)
7877 return ret;
@@ -209,9 +208,8 @@ static ssize_t from_file_write_to_vf_call(struct file *file, const char __user * · 130 unmodified lines
209208 if (ret < 0)
210209 return ret;
211210 if (yes) {
212− xe_pm_runtime_get(xe);
211+ guard(xe_pm_runtime)(xe);
213212 ret = call(xe, vfid);
214− xe_pm_runtime_put(xe);
215213 }
216214 if (ret < 0)
217215 return ret;
drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c+4−12
@@ -389,16 +389,12 @@ static ssize_t xe_sriov_dev_attr_store(struct kobject *kobj, struct attribute *a · 388 unmodified lines
389389 struct xe_sriov_dev_attr *vattr = to_xe_sriov_dev_attr(attr);
390390 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj);
391391 struct xe_device *xe = vkobj->xe;
392− ssize_t ret;
393392
394393 if (!vattr->store)
395394 return -EPERM;
396395
397− xe_pm_runtime_get(xe);
398− ret = xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, buf, count);
399− xe_pm_runtime_put(xe);
400−
401− return ret;
396+ guard(xe_pm_runtime)(xe);
397+ return xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, buf, count);
402398 }
403399
404400 static ssize_t xe_sriov_vf_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
@@ -423,18 +419,14 @@ static ssize_t xe_sriov_vf_attr_store(struct kobject *kobj, struct attribute *at · 18 unmodified lines
423419 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj);
424420 struct xe_device *xe = vkobj->xe;
425421 unsigned int vfid = vkobj->vfid;
426− ssize_t ret;
427422
428423 xe_sriov_pf_assert_vfid(xe, vfid);
429424
430425 if (!vattr->store)
431426 return -EPERM;
432427
433− xe_pm_runtime_get(xe);
434− ret = xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, vfid, buf, count);
435− xe_pm_runtime_get(xe);
436−
437− return ret;
428+ guard(xe_pm_runtime)(xe);
429+ return xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, vfid, buf, count);
438430 }
439431
440432 static const struct sysfs_ops xe_sriov_dev_sysfs_ops = {
drivers/gpu/drm/xe/xe_sriov_vf.c+80−4
@@ -49,11 +49,13 @@ · 48 unmodified lines
4949 *
5050 * As soon as Virtual GPU of the VM starts, the VF driver within receives
5151 * the MIGRATED interrupt and schedules post-migration recovery worker.
52− * That worker queries GuC for new provisioning (using MMIO communication),
52+ * That worker sends `VF2GUC_RESFIX_START` action along with non-zero
53+ * marker, queries GuC for new provisioning (using MMIO communication),
5354 * and applies fixups to any non-virtualized resources used by the VF.
5455 *
5556 * When the VF driver is ready to continue operation on the newly connected
56− * hardware, it sends `VF2GUC_NOTIFY_RESFIX_DONE` which causes it to
57+ * hardware, it sends `VF2GUC_RESFIX_DONE` action along with the same
58+ * marker which was sent with `VF2GUC_RESFIX_START` which causes it to
5759 * enter the long awaited `VF_RUNNING` state, and therefore start handling
5860 * CTB messages and scheduling workloads from the VF::
5961 *
@@ -102,12 +104,17 @@ · 42 unmodified lines
102104 * | [ ] new VF provisioning [ ]
103105 * | [ ]---------------------------> [ ]
104106 * | | [ ]
107+ * | | VF2GUC_RESFIX_START [ ]
108+ * | [ ] <---------------------------[ ]
109+ * | [ ] [ ]
110+ * | [ ] success [ ]
111+ * | [ ]---------------------------> [ ]
105112 * | | VF driver applies post [ ]
106113 * | | migration fixups -------[ ]
107114 * | | | [ ]
108115 * | | -----> [ ]
109116 * | | [ ]
110− * | | VF2GUC_NOTIFY_RESFIX_DONE [ ]
117+ * | | VF2GUC_RESFIX_DONE [ ]
111118 * | [ ] <---------------------------[ ]
112119 * | [ ] [ ]
113120 * | [ ] GuC sets new VF state to [ ]
@@ -118,6 +125,55 @@ · 4 unmodified lines
118125 * | [ ]---------------------------> [ ]
119126 * | | |
120127 * | | |
128+ *
129+ * Handling of VF double migration flow is shown below::
130+ *
131+ * GuC1 VF
132+ * | |
133+ * | [ ]<--- start fixups
134+ * | VF2GUC_RESFIX_START(marker) [ ]
135+ * [ ] <-------------------------------------------[ ]
136+ * [ ] [ ]
137+ * [ ]---\ [ ]
138+ * [ ] store marker [ ]
139+ * [ ]<--/ [ ]
140+ * [ ] [ ]
141+ * [ ] success [ ]
142+ * [ ] ------------------------------------------> [ ]
143+ * | [ ]
144+ * | [ ]---\
145+ * | [ ] do fixups
146+ * | [ ]<--/
147+ * | [ ]
148+ * -------------- VF paused / saved ----------------
149+ * :
150+ *
151+ * GuC2
152+ * |
153+ * ----------------- VF restored ------------------
154+ * |
155+ * [ ]
156+ * [ ]---\
157+ * [ ] reset marker
158+ * [ ]<--/
159+ * [ ]
160+ * ----------------- VF resumed ------------------
161+ * | [ ]
162+ * | [ ]
163+ * | VF2GUC_RESFIX_DONE(marker) [ ]
164+ * [ ] <-------------------------------------------[ ]
165+ * [ ] [ ]
166+ * [ ]---\ [ ]
167+ * [ ] check marker [ ]
168+ * [ ] (mismatch) [ ]
169+ * [ ]<--/ [ ]
170+ * [ ] [ ]
171+ * [ ] RESPONSE_VF_MIGRATED [ ]
172+ * [ ] ------------------------------------------> [ ]
173+ * | [ ]---\
174+ * | [ ] reschedule fixups
175+ * | [ ]<--/
176+ * | |
121177 */
122178
123179 /**
@@ -170,6 +226,26 @@ void xe_sriov_vf_init_early(struct xe_device *xe) · 46 unmodified lines
170226 vf_migration_init_early(xe);
171227 }
172228
229+static int vf_migration_init_late(struct xe_device *xe)
230+{
231+ struct xe_gt *gt = xe_root_mmio_gt(xe);
232+ struct xe_uc_fw_version guc_version;
233+
234+ if (!xe_sriov_vf_migration_supported(xe))
235+ return 0;
236+
237+ xe_gt_sriov_vf_guc_versions(gt, NULL, &guc_version);
238+ if (MAKE_GUC_VER_STRUCT(guc_version) < MAKE_GUC_VER(1, 27, 0)) {
239+ xe_sriov_vf_migration_disable(xe,
240+ "requires GuC ABI >= 1.27.0, but only %u.%u.%u found",
241+ guc_version.major, guc_version.minor,
242+ guc_version.patch);
243+ return 0;
244+ }
245+
246+ return xe_sriov_vf_ccs_init(xe);
247+}
248+
173249 /**
174250 * xe_sriov_vf_init_late() - SR-IOV VF late initialization functions.
175251 * @xe: the &xe_device to initialize
@@ -180,7 +256,7 @@ void xe_sriov_vf_init_early(struct xe_device *xe) · 4 unmodified lines
180256 */
181257 int xe_sriov_vf_init_late(struct xe_device *xe)
182258 {
183− return xe_sriov_vf_ccs_init(xe);
259+ return vf_migration_init_late(xe);
184260 }
185261
186262 static int sa_info_vf_ccs(struct seq_file *m, void *data)
drivers/gpu/drm/xe/xe_sriov_vf_ccs.c+19−8
@@ -150,7 +150,8 @@ static int alloc_bb_pool(struct xe_tile *tile, struct xe_sriov_vf_ccs_ctx *ctx) · 149 unmodified lines
150150 xe_sriov_info(xe, "Allocating %s CCS BB pool size = %lldMB\n",
151151 ctx->ctx_id ? "Restore" : "Save", bb_pool_size / SZ_1M);
152152
153− sa_manager = xe_sa_bo_manager_init(tile, bb_pool_size, SZ_16);
153+ sa_manager = __xe_sa_bo_manager_init(tile, bb_pool_size, SZ_4K, SZ_16,
154+ XE_SA_BO_MANAGER_FLAG_SHADOW);
154155
155156 if (IS_ERR(sa_manager)) {
156157 xe_sriov_err(xe, "Suballocator init failed with error: %pe\n",
@@ -162,9 +163,12 @@ static int alloc_bb_pool(struct xe_tile *tile, struct xe_sriov_vf_ccs_ctx *ctx) · 5 unmodified lines
162163 offset = 0;
163164 xe_map_memset(xe, &sa_manager->bo->vmap, offset, MI_NOOP,
164165 bb_pool_size);
166+ xe_map_memset(xe, &sa_manager->shadow->vmap, offset, MI_NOOP,
167+ bb_pool_size);
165168
166169 offset = bb_pool_size - sizeof(u32);
167170 xe_map_wr(xe, &sa_manager->bo->vmap, offset, u32, MI_BATCH_BUFFER_END);
171+ xe_map_wr(xe, &sa_manager->shadow->vmap, offset, u32, MI_BATCH_BUFFER_END);
168172
169173 ctx->mem.ccs_bb_pool = sa_manager;
170174
@@ -381,6 +385,18 @@ err_ret: · 210 unmodified lines
381385 return err;
382386 }
383387
388+#define XE_SRIOV_VF_CCS_RW_BB_ADDR_OFFSET (2 * sizeof(u32))
389+void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx)
390+{
391+ u64 addr = xe_sa_manager_gpu_addr(ctx->mem.ccs_bb_pool);
392+ struct xe_lrc *lrc = xe_exec_queue_lrc(ctx->mig_q);
393+ struct xe_device *xe = gt_to_xe(ctx->mig_q->gt);
394+
395+ xe_device_wmb(xe);
396+ xe_map_wr(xe, &lrc->bo->vmap, XE_SRIOV_VF_CCS_RW_BB_ADDR_OFFSET, u32, addr);
397+ xe_device_wmb(xe);
398+}
399+
384400 /**
385401 * xe_sriov_vf_ccs_attach_bo - Insert CCS read write commands in the BO.
386402 * @bo: the &buffer object to which batch buffer commands will be added.
@@ -441,9 +457,7 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo) · 54 unmodified lines
441457 if (!bb)
442458 continue;
443459
444− memset(bb->cs, MI_NOOP, bb->len * sizeof(u32));
445− xe_bb_free(bb, NULL);
446− bo->bb_ccs[ctx_id] = NULL;
460+ xe_migrate_ccs_rw_copy_clear(bo, ctx_id);
447461 }
448462 return 0;
449463 }
@@ -463,8 +477,7 @@ void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p) · 13 unmodified lines
463477 if (!IS_VF_CCS_READY(xe))
464478 return;
465479
466− xe_pm_runtime_get(xe);
467−
480+ guard(xe_pm_runtime)(xe);
468481 for_each_ccs_rw_ctx(ctx_id) {
469482 bb_pool = xe->sriov.vf.ccs.contexts[ctx_id].mem.ccs_bb_pool;
470483 if (!bb_pool)
@@ -475,6 +488,4 @@ void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p) · 4 unmodified lines
475488 drm_suballoc_dump_debug_info(&bb_pool->base, p, xe_sa_manager_gpu_addr(bb_pool));
476489 drm_puts(p, "\n");
477490 }
478−
479− xe_pm_runtime_put(xe);
480491 }
drivers/gpu/drm/xe/xe_sriov_vf_ccs.h+1−0
@@ -20,6 +20,7 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo); · 19 unmodified lines
2020 int xe_sriov_vf_ccs_register_context(struct xe_device *xe);
2121 void xe_sriov_vf_ccs_rebase(struct xe_device *xe);
2222 void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p);
23+void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx);
2324
2425 static inline bool xe_sriov_vf_ccs_ready(struct xe_device *xe)
2526 {
drivers/gpu/drm/xe/xe_survivability_mode.c+180−93
@@ -16,11 +16,10 @@ · 15 unmodified lines
1616 #include "xe_heci_gsc.h"
1717 #include "xe_i2c.h"
1818 #include "xe_mmio.h"
19+#include "xe_nvm.h"
1920 #include "xe_pcode_api.h"
2021 #include "xe_vsec.h"
2122
22−#define MAX_SCRATCH_MMIO 8
23−
2423 /**
2524 * DOC: Survivability Mode
2625 *
@@ -48,19 +47,43 @@ · 21 unmodified lines
4847 *
4948 * Refer :ref:`xe_configfs` for more details on how to use configfs
5049 *
51− * Survivability mode is indicated by the below admin-only readable sysfs which provides additional
52− * debug information::
50+ * Survivability mode is indicated by the below admin-only readable sysfs entry. It
51+ * provides information about the type of survivability mode (Boot/Runtime).
52+ *
53+ * .. code-block:: shell
54+ *
55+ * # cat /sys/bus/pci/devices/<device>/survivability_mode
56+ * Boot
57+ *
58+ *
59+ * Any additional debug information if present will be visible under the directory
60+ * ``survivability_info``::
61+ *
62+ * /sys/bus/pci/devices/<device>/survivability_info/
63+ * ├── aux_info0
64+ * ├── aux_info1
65+ * ├── aux_info2
66+ * ├── aux_info3
67+ * ├── aux_info4
68+ * ├── capability_info
69+ * ├── fdo_mode
70+ * ├── postcode_trace
71+ * └── postcode_trace_overflow
72+ *
73+ * This directory has the following attributes
74+ *
75+ * - ``capability_info`` : Indicates Boot status and support for additional information
5376 *
54− * /sys/bus/pci/devices/<device>/survivability_mode
77+ * - ``postcode_trace``, ``postcode_trace_overflow`` : Each postcode is a 8bit value and
78+ * represents a boot failure event. When a new failure event is logged by PCODE the
79+ * existing postcodes are shifted left. These entries provide a history of 8 postcodes.
5580 *
56− * Capability Information:
57− * Provides boot status
58− * Postcode Information:
59− * Provides information about the failure
60− * Overflow Information
61− * Provides history of previous failures
62− * Auxiliary Information
63− * Certain failures may have information in addition to postcode information
81+ * - ``aux_info<n>`` : Some failures have additional debug information
82+ *
83+ * - ``fdo_mode`` : To allow recovery in scenarios where MEI itself fails, a new SPI Flash
84+ * Descriptor Override (FDO) mode is added in v2 survivability breadcrumbs. This mode is enabled
85+ * by PCODE and provides the ability to directly update the firmware via SPI Driver without
86+ * any dependency on MEI. Xe KMD initializes the nvm aux driver if FDO mode is enabled.
6487 *
6588 * Runtime Survivability
6689 * =====================
@@ -68,61 +91,77 @@ · 1 unmodified line
6891 * Certain runtime firmware errors can cause the device to enter a wedged state
6992 * (:ref:`xe-device-wedging`) requiring a firmware flash to restore normal operation.
7093 * Runtime Survivability Mode indicates that a firmware flash is necessary to recover the device and
71− * is indicated by the presence of survivability mode sysfs::
94+ * is indicated by the presence of survivability mode sysfs.
95+ * Survivability mode sysfs provides information about the type of survivability mode.
7296 *
73− * /sys/bus/pci/devices/<device>/survivability_mode
97+ * .. code-block:: shell
7498 *
75− * Survivability mode sysfs provides information about the type of survivability mode.
99+ * # cat /sys/bus/pci/devices/<device>/survivability_mode
100+ * Runtime
76101 *
77102 * When such errors occur, userspace is notified with the drm device wedged uevent and runtime
78103 * survivability mode. User can then initiate a firmware flash using userspace tools like fwupd
79104 * to restore device to normal operation.
80105 */
81106
82−static u32 aux_history_offset(u32 reg_value)
107+static const char * const reg_map[] = {
108+ [CAPABILITY_INFO] = "Capability Info",
109+ [POSTCODE_TRACE] = "Postcode trace",
110+ [POSTCODE_TRACE_OVERFLOW] = "Postcode trace overflow",
111+ [AUX_INFO0] = "Auxiliary Info 0",
112+ [AUX_INFO1] = "Auxiliary Info 1",
113+ [AUX_INFO2] = "Auxiliary Info 2",
114+ [AUX_INFO3] = "Auxiliary Info 3",
115+ [AUX_INFO4] = "Auxiliary Info 4",
116+};
117+
118+#define FDO_INFO (MAX_SCRATCH_REG + 1)
119+
120+struct xe_survivability_attribute {
121+ struct device_attribute attr;
122+ u8 index;
123+};
124+
125+static struct
126+xe_survivability_attribute *dev_attr_to_survivability_attr(struct device_attribute *attr)
83127 {
84− return REG_FIELD_GET(AUXINFO_HISTORY_OFFSET, reg_value);
128+ return container_of(attr, struct xe_survivability_attribute, attr);
85129 }
86130
87−static void set_survivability_info(struct xe_mmio *mmio, struct xe_survivability_info *info,
88− int id, char *name)
131+static void set_survivability_info(struct xe_mmio *mmio, u32 *info, int id)
89132 {
90− strscpy(info[id].name, name, sizeof(info[id].name));
91− info[id].reg = PCODE_SCRATCH(id).raw;
92− info[id].value = xe_mmio_read32(mmio, PCODE_SCRATCH(id));
133+ info[id] = xe_mmio_read32(mmio, PCODE_SCRATCH(id));
93134 }
94135
95136 static void populate_survivability_info(struct xe_device *xe)
96137 {
97138 struct xe_survivability *survivability = &xe->survivability;
98− struct xe_survivability_info *info = survivability->info;
139+ u32 *info = survivability->info;
99140 struct xe_mmio *mmio;
100141 u32 id = 0, reg_value;
101− char name[NAME_MAX];
102− int index;
103142
104143 mmio = xe_root_tile_mmio(xe);
105− set_survivability_info(mmio, info, id, "Capability Info");
106− reg_value = info[id].value;
144+ set_survivability_info(mmio, info, CAPABILITY_INFO);
145+ reg_value = info[CAPABILITY_INFO];
146+
147+ survivability->version = REG_FIELD_GET(BREADCRUMB_VERSION, reg_value);
148+ /* FDO mode is exposed only from version 2 */
149+ if (survivability->version >= 2)
150+ survivability->fdo_mode = REG_FIELD_GET(FDO_MODE, reg_value);
107151
108152 if (reg_value & HISTORY_TRACKING) {
109− id++;
110− set_survivability_info(mmio, info, id, "Postcode Info");
153+ set_survivability_info(mmio, info, POSTCODE_TRACE);
111154
112− if (reg_value & OVERFLOW_SUPPORT) {
113− id = REG_FIELD_GET(OVERFLOW_REG_OFFSET, reg_value);
114− set_survivability_info(mmio, info, id, "Overflow Info");
115− }
155+ if (reg_value & OVERFLOW_SUPPORT)
156+ set_survivability_info(mmio, info, POSTCODE_TRACE_OVERFLOW);
116157 }
117158
159+ /* Traverse the linked list of aux info registers */
118160 if (reg_value & AUXINFO_SUPPORT) {
119− id = REG_FIELD_GET(AUXINFO_REG_OFFSET, reg_value);
120−
121− for (index = 0; id && reg_value; index++, reg_value = info[id].value,
122− id = aux_history_offset(reg_value)) {
123− snprintf(name, NAME_MAX, "Auxiliary Info %d", index);
124− set_survivability_info(mmio, info, id, name);
125− }
161+ for (id = REG_FIELD_GET(AUXINFO_REG_OFFSET, reg_value);
162+ id >= AUX_INFO0 && id < MAX_SCRATCH_REG;
163+ id = REG_FIELD_GET(AUXINFO_HISTORY_OFFSET, info[id]))
164+ set_survivability_info(mmio, info, id);
126165 }
127166 }
128167
@@ -130,15 +169,14 @@ static void log_survivability_info(struct pci_dev *pdev) · 1 unmodified line
130169 {
131170 struct xe_device *xe = pdev_to_xe_device(pdev);
132171 struct xe_survivability *survivability = &xe->survivability;
133− struct xe_survivability_info *info = survivability->info;
172+ u32 *info = survivability->info;
134173 int id;
135174
136175 dev_info(&pdev->dev, "Survivability Boot Status : Critical Failure (%d)\n",
137176 survivability->boot_status);
138− for (id = 0; id < MAX_SCRATCH_MMIO; id++) {
139− if (info[id].reg)
140− dev_info(&pdev->dev, "%s: 0x%x - 0x%x\n", info[id].name,
141− info[id].reg, info[id].value);
177+ for (id = 0; id < MAX_SCRATCH_REG; id++) {
178+ if (info[id])
179+ dev_info(&pdev->dev, "%s: 0x%x\n", reg_map[id], info[id]);
142180 }
143181 }
144182
@@ -156,43 +194,103 @@ static ssize_t survivability_mode_show(struct device *dev, · 11 unmodified lines
156194 struct pci_dev *pdev = to_pci_dev(dev);
157195 struct xe_device *xe = pdev_to_xe_device(pdev);
158196 struct xe_survivability *survivability = &xe->survivability;
159− struct xe_survivability_info *info = survivability->info;
160− int index = 0, count = 0;
161197
162− count += sysfs_emit_at(buff, count, "Survivability mode type: %s\n",
163− survivability->type ? "Runtime" : "Boot");
198+ return sysfs_emit(buff, "%s\n", survivability->type ? "Runtime" : "Boot");
199+}
200+
201+static DEVICE_ATTR_ADMIN_RO(survivability_mode);
164202
165− if (!check_boot_failure(xe))
166− return count;
203+static ssize_t survivability_info_show(struct device *dev,
204+ struct device_attribute *attr, char *buff)
205+{
206+ struct xe_survivability_attribute *sa = dev_attr_to_survivability_attr(attr);
207+ struct pci_dev *pdev = to_pci_dev(dev);
208+ struct xe_device *xe = pdev_to_xe_device(pdev);
209+ struct xe_survivability *survivability = &xe->survivability;
210+ u32 *info = survivability->info;
167211
168− for (index = 0; index < MAX_SCRATCH_MMIO; index++) {
169− if (info[index].reg)
170− count += sysfs_emit_at(buff, count, "%s: 0x%x - 0x%x\n", info[index].name,
171− info[index].reg, info[index].value);
172− }
212+ if (sa->index == FDO_INFO)
213+ return sysfs_emit(buff, "%s\n", str_enabled_disabled(survivability->fdo_mode));
173214
174− return count;
215+ return sysfs_emit(buff, "0x%x\n", info[sa->index]);
175216 }
176217
177−static DEVICE_ATTR_ADMIN_RO(survivability_mode);
218+#define SURVIVABILITY_ATTR_RO(name, _index) \
219+ struct xe_survivability_attribute attr_##name = { \
220+ .attr = __ATTR(name, 0400, survivability_info_show, NULL), \
221+ .index = _index, \
222+ }
223+
224+static SURVIVABILITY_ATTR_RO(capability_info, CAPABILITY_INFO);
225+static SURVIVABILITY_ATTR_RO(postcode_trace, POSTCODE_TRACE);
226+static SURVIVABILITY_ATTR_RO(postcode_trace_overflow, POSTCODE_TRACE_OVERFLOW);
227+static SURVIVABILITY_ATTR_RO(aux_info0, AUX_INFO0);
228+static SURVIVABILITY_ATTR_RO(aux_info1, AUX_INFO1);
229+static SURVIVABILITY_ATTR_RO(aux_info2, AUX_INFO2);
230+static SURVIVABILITY_ATTR_RO(aux_info3, AUX_INFO3);
231+static SURVIVABILITY_ATTR_RO(aux_info4, AUX_INFO4);
232+static SURVIVABILITY_ATTR_RO(fdo_mode, FDO_INFO);
178233
179234 static void xe_survivability_mode_fini(void *arg)
180235 {
181236 struct xe_device *xe = arg;
237+ struct xe_survivability *survivability = &xe->survivability;
182238 struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
183239 struct device *dev = &pdev->dev;
184240
185− sysfs_remove_file(&dev->kobj, &dev_attr_survivability_mode.attr);
241+ if (survivability->fdo_mode)
242+ xe_nvm_fini(xe);
243+
244+ device_remove_file(dev, &dev_attr_survivability_mode);
245+}
246+
247+static umode_t survivability_info_attrs_visible(struct kobject *kobj, struct attribute *attr,
248+ int idx)
249+{
250+ struct xe_device *xe = kdev_to_xe_device(kobj_to_dev(kobj));
251+ struct xe_survivability *survivability = &xe->survivability;
252+ u32 *info = survivability->info;
253+
254+ /*
255+ * Last index in survivability_info_attrs is fdo mode and is applicable only in
256+ * version 2 of survivability mode
257+ */
258+ if (idx == MAX_SCRATCH_REG && survivability->version >= 2)
259+ return 0400;
260+
261+ if (idx < MAX_SCRATCH_REG && info[idx])
262+ return 0400;
263+
264+ return 0;
186265 }
187266
267+/* Attributes are ordered according to enum scratch_reg */
268+static struct attribute *survivability_info_attrs[] = {
269+ &attr_capability_info.attr.attr,
270+ &attr_postcode_trace.attr.attr,
271+ &attr_postcode_trace_overflow.attr.attr,
272+ &attr_aux_info0.attr.attr,
273+ &attr_aux_info1.attr.attr,
274+ &attr_aux_info2.attr.attr,
275+ &attr_aux_info3.attr.attr,
276+ &attr_aux_info4.attr.attr,
277+ &attr_fdo_mode.attr.attr,
278+ NULL,
279+};
280+
281+static const struct attribute_group survivability_info_group = {
282+ .name = "survivability_info",
283+ .attrs = survivability_info_attrs,
284+ .is_visible = survivability_info_attrs_visible,
285+};
286+
188287 static int create_survivability_sysfs(struct pci_dev *pdev)
189288 {
190289 struct device *dev = &pdev->dev;
191290 struct xe_device *xe = pdev_to_xe_device(pdev);
192291 int ret;
193292
194− /* create survivability mode sysfs */
195− ret = sysfs_create_file(&dev->kobj, &dev_attr_survivability_mode.attr);
293+ ret = device_create_file(dev, &dev_attr_survivability_mode);
196294 if (ret) {
197295 dev_warn(dev, "Failed to create survivability sysfs files\n");
198296 return ret;
@@ -203,6 +301,12 @@ static int create_survivability_sysfs(struct pci_dev *pdev) · 4 unmodified lines
203301 if (ret)
204302 return ret;
205303
304+ if (check_boot_failure(xe)) {
305+ ret = devm_device_add_group(dev, &survivability_info_group);
306+ if (ret)
307+ return ret;
308+ }
309+
206310 return 0;
207311 }
208312
@@ -220,12 +324,16 @@ static int enable_boot_survivability_mode(struct pci_dev *pdev) · 11 unmodified lines
220324 /* Make sure xe_heci_gsc_init() knows about survivability mode */
221325 survivability->mode = true;
222326
223− ret = xe_heci_gsc_init(xe);
224− if (ret)
225− goto err;
327+ xe_heci_gsc_init(xe);
226328
227329 xe_vsec_init(xe);
228330
331+ if (survivability->fdo_mode) {
332+ ret = xe_nvm_init(xe);
333+ if (ret)
334+ goto err;
335+ }
336+
229337 ret = xe_i2c_probe(xe);
230338 if (ret)
231339 goto err;
@@ -235,29 +343,11 @@ static int enable_boot_survivability_mode(struct pci_dev *pdev) · 3 unmodified lines
235343 return 0;
236344
237345 err:
346+ dev_err(dev, "Failed to enable Survivability Mode\n");
238347 survivability->mode = false;
239348 return ret;
240349 }
241350
242−static int init_survivability_mode(struct xe_device *xe)
243−{
244− struct xe_survivability *survivability = &xe->survivability;
245− struct xe_survivability_info *info;
246−
247− survivability->size = MAX_SCRATCH_MMIO;
248−
249− info = devm_kcalloc(xe->drm.dev, survivability->size, sizeof(*info),
250− GFP_KERNEL);
251− if (!info)
252− return -ENOMEM;
253−
254− survivability->info = info;
255−
256− populate_survivability_info(xe);
257−
258− return 0;
259−}
260−
261351 /**
262352 * xe_survivability_mode_is_boot_enabled- check if boot survivability mode is enabled
263353 * @xe: xe device instance
@@ -325,9 +415,7 @@ int xe_survivability_mode_runtime_enable(struct xe_device *xe) · 61 unmodified lines
325415 return -EINVAL;
326416 }
327417
328− ret = init_survivability_mode(xe);
329− if (ret)
330− return ret;
418+ populate_survivability_info(xe);
331419
332420 ret = create_survivability_sysfs(pdev);
333421 if (ret)
@@ -356,17 +444,16 @@ int xe_survivability_mode_boot_enable(struct xe_device *xe) · 22 unmodified lines
356444 {
357445 struct xe_survivability *survivability = &xe->survivability;
358446 struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
359− int ret;
360447
361448 if (!xe_survivability_mode_is_requested(xe))
362449 return 0;
363450
364− ret = init_survivability_mode(xe);
365− if (ret)
366− return ret;
451+ populate_survivability_info(xe);
367452
368− /* Log breadcrumbs but do not enter survivability mode for Critical boot errors */
369− if (survivability->boot_status == CRITICAL_FAILURE) {
453+ /*
454+ * v2 supports survivability mode for critical errors
455+ */
456+ if (survivability->version < 2 && survivability->boot_status == CRITICAL_FAILURE) {
370457 log_survivability_info(pdev);
371458 return -ENXIO;
372459 }
drivers/gpu/drm/xe/xe_survivability_mode_types.h+20−8
@@ -9,23 +9,29 @@ · 8 unmodified lines
99 #include <linux/limits.h>
1010 #include <linux/types.h>
1111
12+enum scratch_reg {
13+ CAPABILITY_INFO,
14+ POSTCODE_TRACE,
15+ POSTCODE_TRACE_OVERFLOW,
16+ AUX_INFO0,
17+ AUX_INFO1,
18+ AUX_INFO2,
19+ AUX_INFO3,
20+ AUX_INFO4,
21+ MAX_SCRATCH_REG,
22+};
23+
1224 enum xe_survivability_type {
1325 XE_SURVIVABILITY_TYPE_BOOT,
1426 XE_SURVIVABILITY_TYPE_RUNTIME,
1527 };
1628
17−struct xe_survivability_info {
18− char name[NAME_MAX];
19− u32 reg;
20− u32 value;
21−};
22−
2329 /**
2430 * struct xe_survivability: Contains survivability mode information
2531 */
2632 struct xe_survivability {
27− /** @info: struct that holds survivability info from scratch registers */
28− struct xe_survivability_info *info;
33+ /** @info: survivability debug info */
34+ u32 info[MAX_SCRATCH_REG];
2935
3036 /** @size: number of scratch registers */
3137 u32 size;
@@ -38,6 +44,12 @@ struct xe_survivability { · 6 unmodified lines
3844
3945 /** @type: survivability type */
4046 enum xe_survivability_type type;
47+
48+ /** @fdo_mode: indicates if FDO mode is enabled */
49+ bool fdo_mode;
50+
51+ /** @version: breadcrumb version of survivability mode */
52+ u8 version;
4153 };
4254
4355 #endif /* _XE_SURVIVABILITY_MODE_TYPES_H_ */
drivers/gpu/drm/xe/xe_svm.c+42−46
@@ -176,24 +176,13 @@ xe_svm_range_notifier_event_end(struct xe_vm *vm, struct drm_gpusvm_range *r, · 175 unmodified lines
176176 mmu_range);
177177 }
178178
179−static s64 xe_svm_stats_ktime_us_delta(ktime_t start)
180−{
181− return IS_ENABLED(CONFIG_DEBUG_FS) ?
182− ktime_us_delta(ktime_get(), start) : 0;
183−}
184−
185179 static void xe_svm_tlb_inval_us_stats_incr(struct xe_gt *gt, ktime_t start)
186180 {
187− s64 us_delta = xe_svm_stats_ktime_us_delta(start);
181+ s64 us_delta = xe_gt_stats_ktime_us_delta(start);
188182
189183 xe_gt_stats_incr(gt, XE_GT_STATS_ID_SVM_TLB_INVAL_US, us_delta);
190184 }
191185
192−static ktime_t xe_svm_stats_ktime_get(void)
193−{
194− return IS_ENABLED(CONFIG_DEBUG_FS) ? ktime_get() : 0;
195−}
196−
197186 static void xe_svm_invalidate(struct drm_gpusvm *gpusvm,
198187 struct drm_gpusvm_notifier *notifier,
199188 const struct mmu_notifier_range *mmu_range)
@@ -202,7 +191,7 @@ static void xe_svm_invalidate(struct drm_gpusvm *gpusvm, · 2 unmodified lines
202191 struct xe_device *xe = vm->xe;
203192 struct drm_gpusvm_range *r, *first;
204193 struct xe_tile *tile;
205− ktime_t start = xe_svm_stats_ktime_get();
194+ ktime_t start = xe_gt_stats_ktime_get();
206195 u64 adj_start = mmu_range->start, adj_end = mmu_range->end;
207196 u8 tile_mask = 0, id;
208197 long err;
@@ -285,19 +274,21 @@ static int __xe_svm_garbage_collector(struct xe_vm *vm, · 76 unmodified lines
285274 return 0;
286275 }
287276
288−static int xe_svm_range_set_default_attr(struct xe_vm *vm, u64 range_start, u64 range_end)
277+static void xe_vma_set_default_attributes(struct xe_vma *vma)
278+{
279+ vma->attr.preferred_loc.devmem_fd = DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE;
280+ vma->attr.preferred_loc.migration_policy = DRM_XE_MIGRATE_ALL_PAGES;
281+ vma->attr.pat_index = vma->attr.default_pat_index;
282+ vma->attr.atomic_access = DRM_XE_ATOMIC_UNDEFINED;
283+}
284+
285+static int xe_svm_range_set_default_attr(struct xe_vm *vm, u64 start, u64 end)
289286 {
290287 struct xe_vma *vma;
291− struct xe_vma_mem_attr default_attr = {
292− .preferred_loc = {
293− .devmem_fd = DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE,
294− .migration_policy = DRM_XE_MIGRATE_ALL_PAGES,
295− },
296− .atomic_access = DRM_XE_ATOMIC_UNDEFINED,
297− };
298− int err = 0;
288+ bool has_default_attr;
289+ int err;
299290
300− vma = xe_vm_find_vma_by_addr(vm, range_start);
291+ vma = xe_vm_find_vma_by_addr(vm, start);
301292 if (!vma)
302293 return -EINVAL;
303294
@@ -306,25 +297,30 @@ static int xe_svm_range_set_default_attr(struct xe_vm *vm, u64 range_start, u64 · 2 unmodified lines
306297 return 0;
307298 }
308299
309− if (xe_vma_has_default_mem_attrs(vma))
310− return 0;
311−
312300 vm_dbg(&vm->xe->drm, "Existing VMA start=0x%016llx, vma_end=0x%016llx",
313301 xe_vma_start(vma), xe_vma_end(vma));
314302
315− if (xe_vma_start(vma) == range_start && xe_vma_end(vma) == range_end) {
316− default_attr.pat_index = vma->attr.default_pat_index;
317− default_attr.default_pat_index = vma->attr.default_pat_index;
318− vma->attr = default_attr;
319− } else {
320− vm_dbg(&vm->xe->drm, "Split VMA start=0x%016llx, vma_end=0x%016llx",
321− range_start, range_end);
322− err = xe_vm_alloc_cpu_addr_mirror_vma(vm, range_start, range_end - range_start);
323− if (err) {
324− drm_warn(&vm->xe->drm, "VMA SPLIT failed: %pe\n", ERR_PTR(err));
325− xe_vm_kill(vm, true);
326− return err;
327− }
303+ has_default_attr = xe_vma_has_default_mem_attrs(vma);
304+
305+ if (has_default_attr) {
306+ start = xe_vma_start(vma);
307+ end = xe_vma_end(vma);
308+ } else if (xe_vma_start(vma) == start && xe_vma_end(vma) == end) {
309+ xe_vma_set_default_attributes(vma);
310+ }
311+
312+ xe_vm_find_cpu_addr_mirror_vma_range(vm, &start, &end);
313+
314+ if (xe_vma_start(vma) == start && xe_vma_end(vma) == end && has_default_attr)
315+ return 0;
316+
317+ vm_dbg(&vm->xe->drm, "New VMA start=0x%016llx, vma_end=0x%016llx", start, end);
318+
319+ err = xe_vm_alloc_cpu_addr_mirror_vma(vm, start, end - start);
320+ if (err) {
321+ drm_warn(&vm->xe->drm, "New VMA MAP failed: %pe\n", ERR_PTR(err));
322+ xe_vm_kill(vm, true);
323+ return err;
328324 }
329325
330326 /*
@@ -435,7 +431,7 @@ static void xe_svm_copy_us_stats_incr(struct xe_gt *gt, · 104 unmodified lines
435431 unsigned long npages,
436432 ktime_t start)
437433 {
438− s64 us_delta = xe_svm_stats_ktime_us_delta(start);
434+ s64 us_delta = xe_gt_stats_ktime_us_delta(start);
439435
440436 if (dir == XE_SVM_COPY_TO_VRAM) {
441437 switch (npages) {
@@ -487,7 +483,7 @@ static int xe_svm_copy(struct page **pages, · 45 unmodified lines
487483 u64 vram_addr = XE_VRAM_ADDR_INVALID;
488484 int err = 0, pos = 0;
489485 bool sram = dir == XE_SVM_COPY_TO_SRAM;
490− ktime_t start = xe_svm_stats_ktime_get();
486+ ktime_t start = xe_gt_stats_ktime_get();
491487
492488 /*
493489 * This flow is complex: it locates physically contiguous device pages,
@@ -979,7 +975,7 @@ static void xe_svm_range_##elem##_us_stats_incr(struct xe_gt *gt, \ · 485 unmodified lines
979975 struct xe_svm_range *range, \
980976 ktime_t start) \
981977 { \
982− s64 us_delta = xe_svm_stats_ktime_us_delta(start); \
978+ s64 us_delta = xe_gt_stats_ktime_us_delta(start); \
983979 \
984980 switch (xe_svm_range_size(range)) { \
985981 case SZ_4K: \
@@ -1024,7 +1020,7 @@ static int __xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, · 38 unmodified lines
10241020 struct drm_pagemap *dpagemap;
10251021 struct xe_tile *tile = gt_to_tile(gt);
10261022 int migrate_try_count = ctx.devmem_only ? 3 : 1;
1027− ktime_t start = xe_svm_stats_ktime_get(), bind_start, get_pages_start;
1023+ ktime_t start = xe_gt_stats_ktime_get(), bind_start, get_pages_start;
10281024 int err;
10291025
10301026 lockdep_assert_held_write(&vm->lock);
@@ -1063,7 +1059,7 @@ retry: · 32 unmodified lines
10631059
10641060 if (--migrate_try_count >= 0 &&
10651061 xe_svm_range_needs_migrate_to_vram(range, vma, !!dpagemap || ctx.devmem_only)) {
1066− ktime_t migrate_start = xe_svm_stats_ktime_get();
1062+ ktime_t migrate_start = xe_gt_stats_ktime_get();
10671063
10681064 /* TODO : For multi-device dpagemap will be used to find the
10691065 * remote tile and remote device. Will need to modify
@@ -1100,7 +1096,7 @@ retry: · 30 unmodified lines
11001096 }
11011097
11021098 get_pages:
1103− get_pages_start = xe_svm_stats_ktime_get();
1099+ get_pages_start = xe_gt_stats_ktime_get();
11041100
11051101 range_debug(range, "GET PAGES");
11061102 err = xe_svm_range_get_pages(vm, range, &ctx);
@@ -1127,7 +1123,7 @@ get_pages: · 20 unmodified lines
11271123 xe_svm_range_get_pages_us_stats_incr(gt, range, get_pages_start);
11281124 range_debug(range, "PAGE FAULT - BIND");
11291125
1130− bind_start = xe_svm_stats_ktime_get();
1126+ bind_start = xe_gt_stats_ktime_get();
11311127 xe_validation_guard(&vctx, &vm->xe->val, &exec, (struct xe_val_flags) {}, err) {
11321128 err = xe_vm_drm_exec_lock(vm, &exec);
11331129 drm_exec_retry_on_contention(&exec);
drivers/gpu/drm/xe/xe_sync.c+31−2
@@ -228,6 +228,32 @@ int xe_sync_entry_add_deps(struct xe_sync_entry *sync, struct xe_sched_job *job) · 227 unmodified lines
228228 return 0;
229229 }
230230
231+/**
232+ * xe_sync_entry_wait() - Wait on in-sync
233+ * @sync: Sync object
234+ *
235+ * If the sync is in an in-sync, wait on the sync to signal.
236+ *
237+ * Return: 0 on success, -ERESTARTSYS on failure (interruption)
238+ */
239+int xe_sync_entry_wait(struct xe_sync_entry *sync)
240+{
241+ return xe_sync_needs_wait(sync) ?
242+ dma_fence_wait(sync->fence, true) : 0;
243+}
244+
245+/**
246+ * xe_sync_needs_wait() - Sync needs a wait (input dma-fence not signaled)
247+ * @sync: Sync object
248+ *
249+ * Return: True if sync needs a wait, False otherwise
250+ */
251+bool xe_sync_needs_wait(struct xe_sync_entry *sync)
252+{
253+ return sync->fence &&
254+ !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &sync->fence->flags);
255+}
256+
231257 void xe_sync_entry_signal(struct xe_sync_entry *sync, struct dma_fence *fence)
232258 {
233259 if (!(sync->flags & DRM_XE_SYNC_FLAG_SIGNAL))
@@ -311,8 +337,11 @@ xe_sync_in_fence_get(struct xe_sync_entry *sync, int num_sync, · 77 unmodified lines
311337 struct xe_tile *tile;
312338 u8 id;
313339
314− for_each_tile(tile, vm->xe, id)
315− num_fence += (1 + XE_MAX_GT_PER_TILE);
340+ for_each_tile(tile, vm->xe, id) {
341+ num_fence++;
342+ for_each_tlb_inval(i)
343+ num_fence++;
344+ }
316345
317346 fences = kmalloc_array(num_fence, sizeof(*fences),
318347 GFP_KERNEL);
drivers/gpu/drm/xe/xe_sync.h+2−0
@@ -29,6 +29,8 @@ int xe_sync_entry_add_deps(struct xe_sync_entry *sync, · 28 unmodified lines
2929 struct xe_sched_job *job);
3030 void xe_sync_entry_signal(struct xe_sync_entry *sync,
3131 struct dma_fence *fence);
32+int xe_sync_entry_wait(struct xe_sync_entry *sync);
33+bool xe_sync_needs_wait(struct xe_sync_entry *sync);
3234 void xe_sync_entry_cleanup(struct xe_sync_entry *sync);
3335 struct dma_fence *
3436 xe_sync_in_fence_get(struct xe_sync_entry *sync, int num_sync,
drivers/gpu/drm/xe/xe_tile.c+5−0
@@ -209,6 +209,11 @@ int xe_tile_init(struct xe_tile *tile) · 208 unmodified lines
209209 if (IS_ERR(tile->mem.kernel_bb_pool))
210210 return PTR_ERR(tile->mem.kernel_bb_pool);
211211
212+ /* Optimistically anticipate at most 256 TLB fences with PRL */
213+ tile->mem.reclaim_pool = xe_sa_bo_manager_init(tile, SZ_1M, XE_PAGE_RECLAIM_LIST_MAX_SIZE);
214+ if (IS_ERR(tile->mem.reclaim_pool))
215+ return PTR_ERR(tile->mem.reclaim_pool);
216+
212217 return 0;
213218 }
214219 void xe_tile_migrate_wait(struct xe_tile *tile)
drivers/gpu/drm/xe/xe_tile_debugfs.c+11−6
@@ -82,13 +82,9 @@ int xe_tile_debugfs_show_with_rpm(struct seq_file *m, void *data) · 81 unmodified lines
8282 struct drm_info_node *node = m->private;
8383 struct xe_tile *tile = node_to_tile(node);
8484 struct xe_device *xe = tile_to_xe(tile);
85− int ret;
8685
87− xe_pm_runtime_get(xe);
88− ret = xe_tile_debugfs_simple_show(m, data);
89− xe_pm_runtime_put(xe);
90−
91− return ret;
86+ guard(xe_pm_runtime)(xe);
87+ return xe_tile_debugfs_simple_show(m, data);
9288 }
9389
9490 static int ggtt(struct xe_tile *tile, struct drm_printer *p)
@@ -110,6 +106,13 @@ static const struct drm_info_list vf_safe_debugfs_list[] = { · 15 unmodified lines
110106 { "sa_info", .show = xe_tile_debugfs_show_with_rpm, .data = sa_info },
111107 };
112108
109+static void tile_debugfs_create_vram_mm(struct xe_tile *tile)
110+{
111+ if (tile->mem.vram)
112+ ttm_resource_manager_create_debugfs(&tile->mem.vram->ttm.manager, tile->debugfs,
113+ "vram_mm");
114+}
115+
113116 /**
114117 * xe_tile_debugfs_register - Register tile's debugfs attributes
115118 * @tile: the &xe_tile to register
@@ -139,4 +142,6 @@ void xe_tile_debugfs_register(struct xe_tile *tile) · 23 unmodified lines
139142 drm_debugfs_create_files(vf_safe_debugfs_list,
140143 ARRAY_SIZE(vf_safe_debugfs_list),
141144 tile->debugfs, minor);
145+
146+ tile_debugfs_create_vram_mm(tile);
142147 }
drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c+1−2
@@ -141,12 +141,11 @@ static int NAME##_set(void *data, u64 val) \ · 140 unmodified lines
141141 if (val > (TYPE)~0ull) \
142142 return -EOVERFLOW; \
143143 \
144− xe_pm_runtime_get(xe); \
144+ guard(xe_pm_runtime)(xe); \
145145 err = xe_sriov_pf_wait_ready(xe) ?: \
146146 xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val); \
147147 if (!err) \
148148 xe_sriov_pf_provision_set_custom_mode(xe); \
149− xe_pm_runtime_put(xe); \
150149 \
151150 return err; \
152151 } \
drivers/gpu/drm/xe/xe_tlb_inval.c+24−3
@@ -199,6 +199,20 @@ void xe_tlb_inval_reset(struct xe_tlb_inval *tlb_inval) · 198 unmodified lines
199199 mutex_unlock(&tlb_inval->seqno_lock);
200200 }
201201
202+/**
203+ * xe_tlb_inval_reset_timeout() - Reset TLB inval fence timeout
204+ * @tlb_inval: TLB invalidation client
205+ *
206+ * Reset the TLB invalidation timeout timer.
207+ */
208+static void xe_tlb_inval_reset_timeout(struct xe_tlb_inval *tlb_inval)
209+{
210+ lockdep_assert_held(&tlb_inval->pending_lock);
211+
212+ mod_delayed_work(system_wq, &tlb_inval->fence_tdr,
213+ tlb_inval->ops->timeout_delay(tlb_inval));
214+}
215+
202216 static bool xe_tlb_inval_seqno_past(struct xe_tlb_inval *tlb_inval, int seqno)
203217 {
204218 int seqno_recv = READ_ONCE(tlb_inval->seqno_recv);
@@ -299,6 +313,7 @@ int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval) · 94 unmodified lines
299313 * @start: start address
300314 * @end: end address
301315 * @asid: address space id
316+ * @prl_sa: suballocation of page reclaim list if used, NULL indicates PPC flush
302317 *
303318 * Issue a range based TLB invalidation if supported, if not fallback to a full
304319 * TLB invalidation. Completion of TLB is asynchronous and caller can use
@@ -308,10 +323,10 @@ int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval) · 3 unmodified lines
308323 */
309324 int xe_tlb_inval_range(struct xe_tlb_inval *tlb_inval,
310325 struct xe_tlb_inval_fence *fence, u64 start, u64 end,
311− u32 asid)
326+ u32 asid, struct drm_suballoc *prl_sa)
312327 {
313328 return xe_tlb_inval_issue(tlb_inval, fence, tlb_inval->ops->ppgtt,
314− start, end, asid);
329+ start, end, asid, prl_sa);
315330 }
316331
317332 /**
@@ -327,7 +342,7 @@ void xe_tlb_inval_vm(struct xe_tlb_inval *tlb_inval, struct xe_vm *vm) · 9 unmodified lines
327342 u64 range = 1ull << vm->xe->info.va_bits;
328343
329344 xe_tlb_inval_fence_init(tlb_inval, &fence, true);
330− xe_tlb_inval_range(tlb_inval, &fence, 0, range, vm->usm.asid);
345+ xe_tlb_inval_range(tlb_inval, &fence, 0, range, vm->usm.asid, NULL);
331346 xe_tlb_inval_fence_wait(&fence);
332347 }
333348
@@ -360,6 +375,12 @@ void xe_tlb_inval_done_handler(struct xe_tlb_inval *tlb_inval, int seqno) · 26 unmodified lines
360375 * process_g2h_msg().
361376 */
362377 spin_lock_irqsave(&tlb_inval->pending_lock, flags);
378+ if (seqno == TLB_INVALIDATION_SEQNO_INVALID) {
379+ xe_tlb_inval_reset_timeout(tlb_inval);
380+ spin_unlock_irqrestore(&tlb_inval->pending_lock, flags);
381+ return;
382+ }
383+
363384 if (xe_tlb_inval_seqno_past(tlb_inval, seqno)) {
364385 spin_unlock_irqrestore(&tlb_inval->pending_lock, flags);
365386 return;
drivers/gpu/drm/xe/xe_tlb_inval.h+1−1
@@ -23,7 +23,7 @@ int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval); · 22 unmodified lines
2323 void xe_tlb_inval_vm(struct xe_tlb_inval *tlb_inval, struct xe_vm *vm);
2424 int xe_tlb_inval_range(struct xe_tlb_inval *tlb_inval,
2525 struct xe_tlb_inval_fence *fence,
26− u64 start, u64 end, u32 asid);
26+ u64 start, u64 end, u32 asid, struct drm_suballoc *prl_sa);
2727
2828 void xe_tlb_inval_fence_init(struct xe_tlb_inval *tlb_inval,
2929 struct xe_tlb_inval_fence *fence,
drivers/gpu/drm/xe/xe_tlb_inval_job.c+35−1
@@ -7,7 +7,9 @@ · 6 unmodified lines
77 #include "xe_dep_job_types.h"
88 #include "xe_dep_scheduler.h"
99 #include "xe_exec_queue.h"
10+#include "xe_gt_printk.h"
1011 #include "xe_gt_types.h"
12+#include "xe_page_reclaim.h"
1113 #include "xe_tlb_inval.h"
1214 #include "xe_tlb_inval_job.h"
1315 #include "xe_migrate.h"
@@ -24,6 +26,8 @@ struct xe_tlb_inval_job { · 10 unmodified lines
2426 struct xe_exec_queue *q;
2527 /** @vm: VM which TLB invalidation is being issued for */
2628 struct xe_vm *vm;
29+ /** @prl: Embedded copy of page reclaim list */
30+ struct xe_page_reclaim_list prl;
2731 /** @refcount: ref count of this job */
2832 struct kref refcount;
2933 /**
@@ -47,9 +51,16 @@ static struct dma_fence *xe_tlb_inval_job_run(struct xe_dep_job *dep_job) · 17 unmodified lines
4751 container_of(dep_job, typeof(*job), dep);
4852 struct xe_tlb_inval_fence *ifence =
4953 container_of(job->fence, typeof(*ifence), base);
54+ struct drm_suballoc *prl_sa = NULL;
55+
56+ if (xe_page_reclaim_list_valid(&job->prl)) {
57+ prl_sa = xe_page_reclaim_create_prl_bo(job->tlb_inval, &job->prl, ifence);
58+ if (IS_ERR(prl_sa))
59+ prl_sa = NULL; /* Indicate fall back PPC flush with NULL */
60+ }
5061
5162 xe_tlb_inval_range(job->tlb_inval, ifence, job->start,
52− job->end, job->vm->usm.asid);
63+ job->end, job->vm->usm.asid, prl_sa);
5364
5465 return job->fence;
5566 }
@@ -107,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval, · 51 unmodified lines
107118 job->start = start;
108119 job->end = end;
109120 job->fence_armed = false;
121+ xe_page_reclaim_list_init(&job->prl);
110122 job->dep.ops = &dep_job_ops;
111123 job->type = type;
112124 kref_init(&job->refcount);
@@ -140,6 +152,25 @@ err_job: · 27 unmodified lines
140152 return ERR_PTR(err);
141153 }
142154
155+/**
156+ * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB job
157+ * @job: TLB invalidation job that may trigger reclamation
158+ * @prl: Page reclaim list populated during unbind
159+ *
160+ * Copies @prl into the job and takes an extra reference to the entry page so
161+ * ownership can transfer to the TLB fence when the job is pushed.
162+ */
163+void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
164+ struct xe_page_reclaim_list *prl)
165+{
166+ struct xe_device *xe = gt_to_xe(job->q->gt);
167+
168+ xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
169+ job->prl = *prl;
170+ /* Pair with put in job_destroy */
171+ xe_page_reclaim_entries_get(job->prl.entries);
172+}
173+
143174 static void xe_tlb_inval_job_destroy(struct kref *ref)
144175 {
145176 struct xe_tlb_inval_job *job = container_of(ref, typeof(*job),
@@ -150,6 +181,9 @@ static void xe_tlb_inval_job_destroy(struct kref *ref) · 4 unmodified lines
150181 struct xe_device *xe = gt_to_xe(q->gt);
151182 struct xe_vm *vm = job->vm;
152183
184+ /* BO creation retains a copy (if used), so no longer needed */
185+ xe_page_reclaim_entries_put(job->prl.entries);
186+
153187 if (!job->fence_armed)
154188 kfree(ifence);
155189 else
drivers/gpu/drm/xe/xe_tlb_inval_job.h+4−0
@@ -12,6 +12,7 @@ struct dma_fence; · 11 unmodified lines
1212 struct xe_dep_scheduler;
1313 struct xe_exec_queue;
1414 struct xe_migrate;
15+struct xe_page_reclaim_list;
1516 struct xe_tlb_inval;
1617 struct xe_tlb_inval_job;
1718 struct xe_vm;
@@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval, · 3 unmodified lines
2122 struct xe_dep_scheduler *dep_scheduler,
2223 struct xe_vm *vm, u64 start, u64 end, int type);
2324
25+void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
26+ struct xe_page_reclaim_list *prl);
27+
2428 int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
2529
2630 struct dma_fence *xe_tlb_inval_job_push(struct xe_tlb_inval_job *job,
drivers/gpu/drm/xe/xe_tlb_inval_types.h+4−1
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #include <linux/workqueue.h>
1010 #include <linux/dma-fence.h>
1111
12+struct drm_suballoc;
1213 struct xe_tlb_inval;
1314
1415 /** struct xe_tlb_inval_ops - TLB invalidation ops (backend) */
@@ -40,12 +41,13 @@ struct xe_tlb_inval_ops { · 25 unmodified lines
4041 * @start: Start address
4142 * @end: End address
4243 * @asid: Address space ID
44+ * @prl_sa: Suballocation for page reclaim list
4345 *
4446 * Return 0 on success, -ECANCELED if backend is mid-reset, error on
4547 * failure
4648 */
4749 int (*ppgtt)(struct xe_tlb_inval *tlb_inval, u32 seqno, u64 start,
48− u64 end, u32 asid);
50+ u64 end, u32 asid, struct drm_suballoc *prl_sa);
4951
5052 /**
5153 * @initialized: Backend is initialized
@@ -80,6 +82,7 @@ struct xe_tlb_inval { · 28 unmodified lines
8082 const struct xe_tlb_inval_ops *ops;
8183 /** @tlb_inval.seqno: TLB invalidation seqno, protected by CT lock */
8284 #define TLB_INVALIDATION_SEQNO_MAX 0x100000
85+#define TLB_INVALIDATION_SEQNO_INVALID TLB_INVALIDATION_SEQNO_MAX
8386 int seqno;
8487 /** @tlb_invalidation.seqno_lock: protects @tlb_invalidation.seqno */
8588 struct mutex seqno_lock;
drivers/gpu/drm/xe/xe_trace.h+46−0
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313 #include <linux/types.h>
1414
1515 #include "xe_exec_queue_types.h"
16+#include "xe_exec_queue.h"
1617 #include "xe_gpu_scheduler_types.h"
1718 #include "xe_gt_types.h"
1819 #include "xe_guc_exec_queue_types.h"
@@ -97,11 +98,51 @@ DECLARE_EVENT_CLASS(xe_exec_queue, · 78 unmodified lines
9798 __entry->guc_state, __entry->flags)
9899 );
99100
101+DECLARE_EVENT_CLASS(xe_exec_queue_multi_queue,
102+ TP_PROTO(struct xe_exec_queue *q),
103+ TP_ARGS(q),
104+
105+ TP_STRUCT__entry(
106+ __string(dev, __dev_name_eq(q))
107+ __field(enum xe_engine_class, class)
108+ __field(u32, logical_mask)
109+ __field(u8, gt_id)
110+ __field(u16, width)
111+ __field(u32, guc_id)
112+ __field(u32, guc_state)
113+ __field(u32, flags)
114+ __field(u32, primary)
115+ ),
116+
117+ TP_fast_assign(
118+ __assign_str(dev);
119+ __entry->class = q->class;
120+ __entry->logical_mask = q->logical_mask;
121+ __entry->gt_id = q->gt->info.id;
122+ __entry->width = q->width;
123+ __entry->guc_id = q->guc->id;
124+ __entry->guc_state = atomic_read(&q->guc->state);
125+ __entry->flags = q->flags;
126+ __entry->primary = xe_exec_queue_multi_queue_primary(q)->guc->id;
127+ ),
128+
129+ TP_printk("dev=%s, %d:0x%x, gt=%d, width=%d guc_id=%d, guc_state=0x%x, flags=0x%x, primary=%d",
130+ __get_str(dev), __entry->class, __entry->logical_mask,
131+ __entry->gt_id, __entry->width, __entry->guc_id,
132+ __entry->guc_state, __entry->flags,
133+ __entry->primary)
134+);
135+
100136 DEFINE_EVENT(xe_exec_queue, xe_exec_queue_create,
101137 TP_PROTO(struct xe_exec_queue *q),
102138 TP_ARGS(q)
103139 );
104140
141+DEFINE_EVENT(xe_exec_queue_multi_queue, xe_exec_queue_create_multi_queue,
142+ TP_PROTO(struct xe_exec_queue *q),
143+ TP_ARGS(q)
144+);
145+
105146 DEFINE_EVENT(xe_exec_queue, xe_exec_queue_supress_resume,
106147 TP_PROTO(struct xe_exec_queue *q),
107148 TP_ARGS(q)
@@ -172,6 +213,11 @@ DEFINE_EVENT(xe_exec_queue, xe_exec_queue_memory_cat_error, · 64 unmodified lines
172213 TP_ARGS(q)
173214 );
174215
216+DEFINE_EVENT(xe_exec_queue, xe_exec_queue_cgp_context_error,
217+ TP_PROTO(struct xe_exec_queue *q),
218+ TP_ARGS(q)
219+);
220+
175221 DEFINE_EVENT(xe_exec_queue, xe_exec_queue_stop,
176222 TP_PROTO(struct xe_exec_queue *q),
177223 TP_ARGS(q)
drivers/gpu/drm/xe/xe_uc.c+33−2
@@ -218,9 +218,12 @@ int xe_uc_load_hw(struct xe_uc *uc) · 217 unmodified lines
218218
219219 xe_guc_engine_activity_enable_stats(&uc->guc);
220220
221− /* We don't fail the driver load if HuC fails to auth, but let's warn */
221+ /* We don't fail the driver load if HuC fails to auth */
222222 ret = xe_huc_auth(&uc->huc, XE_HUC_AUTH_VIA_GUC);
223− xe_gt_assert(uc_to_gt(uc), !ret);
223+ if (ret)
224+ xe_gt_err(uc_to_gt(uc),
225+ "HuC authentication failed (%pe), continuing with no HuC\n",
226+ ERR_PTR(ret));
224227
225228 /* GSC load is async */
226229 xe_gsc_load_start(&uc->gsc);
@@ -301,6 +304,34 @@ int xe_uc_suspend(struct xe_uc *uc) · 74 unmodified lines
301304 return xe_guc_suspend(&uc->guc);
302305 }
303306
307+/**
308+ * xe_uc_runtime_suspend() - UC runtime suspend
309+ * @uc: the UC object
310+ *
311+ * Runtime suspend all UCs.
312+ */
313+void xe_uc_runtime_suspend(struct xe_uc *uc)
314+{
315+ if (!xe_device_uc_enabled(uc_to_xe(uc)))
316+ return;
317+
318+ xe_guc_runtime_suspend(&uc->guc);
319+}
320+
321+/**
322+ * xe_uc_runtime_resume() - UC runtime resume
323+ * @uc: the UC object
324+ *
325+ * Runtime resume all UCs.
326+ */
327+void xe_uc_runtime_resume(struct xe_uc *uc)
328+{
329+ if (!xe_device_uc_enabled(uc_to_xe(uc)))
330+ return;
331+
332+ xe_guc_runtime_resume(&uc->guc);
333+}
334+
304335 /**
305336 * xe_uc_declare_wedged() - Declare UC wedged
306337 * @uc: the UC object
drivers/gpu/drm/xe/xe_uc.h+2−0
@@ -14,6 +14,8 @@ int xe_uc_init_post_hwconfig(struct xe_uc *uc); · 13 unmodified lines
1414 int xe_uc_load_hw(struct xe_uc *uc);
1515 void xe_uc_gucrc_disable(struct xe_uc *uc);
1616 int xe_uc_reset_prepare(struct xe_uc *uc);
17+void xe_uc_runtime_resume(struct xe_uc *uc);
18+void xe_uc_runtime_suspend(struct xe_uc *uc);
1719 void xe_uc_stop_prepare(struct xe_uc *uc);
1820 void xe_uc_stop(struct xe_uc *uc);
1921 int xe_uc_start(struct xe_uc *uc);
drivers/gpu/drm/xe/xe_uc_fw.c+5−5
@@ -115,11 +115,11 @@ struct fw_blobs_by_type { · 114 unmodified lines
115115 #define XE_GT_TYPE_ANY XE_GT_TYPE_UNINITIALIZED
116116
117117 #define XE_GUC_FIRMWARE_DEFS(fw_def, mmp_ver, major_ver) \
118− fw_def(PANTHERLAKE, GT_TYPE_ANY, major_ver(xe, guc, ptl, 70, 49, 4)) \
119− fw_def(BATTLEMAGE, GT_TYPE_ANY, major_ver(xe, guc, bmg, 70, 49, 4)) \
120− fw_def(LUNARLAKE, GT_TYPE_ANY, major_ver(xe, guc, lnl, 70, 45, 2)) \
121− fw_def(METEORLAKE, GT_TYPE_ANY, major_ver(i915, guc, mtl, 70, 44, 1)) \
122− fw_def(DG2, GT_TYPE_ANY, major_ver(i915, guc, dg2, 70, 45, 2)) \
118+ fw_def(PANTHERLAKE, GT_TYPE_ANY, major_ver(xe, guc, ptl, 70, 54, 0)) \
119+ fw_def(BATTLEMAGE, GT_TYPE_ANY, major_ver(xe, guc, bmg, 70, 54, 0)) \
120+ fw_def(LUNARLAKE, GT_TYPE_ANY, major_ver(xe, guc, lnl, 70, 53, 0)) \
121+ fw_def(METEORLAKE, GT_TYPE_ANY, major_ver(i915, guc, mtl, 70, 53, 0)) \
122+ fw_def(DG2, GT_TYPE_ANY, major_ver(i915, guc, dg2, 70, 53, 0)) \
123123 fw_def(DG1, GT_TYPE_ANY, major_ver(i915, guc, dg1, 70, 44, 1)) \
124124 fw_def(ALDERLAKE_N, GT_TYPE_ANY, major_ver(i915, guc, tgl, 70, 44, 1)) \
125125 fw_def(ALDERLAKE_P, GT_TYPE_ANY, major_ver(i915, guc, adlp, 70, 44, 1)) \
drivers/gpu/drm/xe/xe_vm.c+136−18
@@ -1509,9 +1509,9 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef) · 1508 unmodified lines
15091509
15101510 INIT_LIST_HEAD(&vm->preempt.exec_queues);
15111511 if (flags & XE_VM_FLAG_FAULT_MODE)
1512− vm->preempt.min_run_period_ms = 0;
1512+ vm->preempt.min_run_period_ms = xe->min_run_period_pf_ms;
15131513 else
1514− vm->preempt.min_run_period_ms = 5;
1514+ vm->preempt.min_run_period_ms = xe->min_run_period_lr_ms;
15151515
15161516 for_each_tile(tile, xe, id)
15171517 xe_range_fence_tree_init(&vm->rftree[id]);
@@ -2236,6 +2236,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops, · 718 unmodified lines
22362236 struct drm_gpuva_ops *ops;
22372237 struct drm_gpuva_op *__op;
22382238 struct drm_gpuvm_bo *vm_bo;
2239+ u64 range_start = addr;
22392240 u64 range_end = addr + range;
22402241 int err;
22412242
@@ -2248,10 +2249,16 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops, · 6 unmodified lines
22482249
22492250 switch (operation) {
22502251 case DRM_XE_VM_BIND_OP_MAP:
2252+ if (flags & DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR) {
2253+ xe_vm_find_cpu_addr_mirror_vma_range(vm, &range_start, &range_end);
2254+ vops->flags |= XE_VMA_OPS_FLAG_ALLOW_SVM_UNMAP;
2255+ }
2256+
2257+ fallthrough;
22512258 case DRM_XE_VM_BIND_OP_MAP_USERPTR: {
22522259 struct drm_gpuvm_map_req map_req = {
2253− .map.va.addr = addr,
2254− .map.va.range = range,
2260+ .map.va.addr = range_start,
2261+ .map.va.range = range_end - range_start,
22552262 .map.gem.obj = obj,
22562263 .map.gem.offset = bo_offset_or_userptr,
22572264 };
@@ -2451,8 +2458,17 @@ static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op, · 193 unmodified lines
24512458 if (IS_ERR(vma))
24522459 return vma;
24532460
2454− if (xe_vma_is_userptr(vma))
2461+ if (xe_vma_is_userptr(vma)) {
24552462 err = xe_vma_userptr_pin_pages(to_userptr_vma(vma));
2463+ /*
2464+ * -EBUSY has dedicated meaning that a user fence
2465+ * attached to the VMA is busy, in practice
2466+ * xe_vma_userptr_pin_pages can only fail with -EBUSY if
2467+ * we are low on memory so convert this to -ENOMEM.
2468+ */
2469+ if (err == -EBUSY)
2470+ err = -ENOMEM;
2471+ }
24562472 }
24572473 if (err) {
24582474 prep_vma_destroy(vm, vma, false);
@@ -2727,7 +2743,8 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, · 268 unmodified lines
27272743
27282744 if (xe_vma_is_cpu_addr_mirror(vma) &&
27292745 xe_svm_has_mapping(vm, xe_vma_start(vma),
2730− xe_vma_end(vma)))
2746+ xe_vma_end(vma)) &&
2747+ !(vops->flags & XE_VMA_OPS_FLAG_ALLOW_SVM_UNMAP))
27312748 return -EBUSY;
27322749
27332750 if (!xe_vma_is_cpu_addr_mirror(vma))
@@ -3107,19 +3124,19 @@ static struct dma_fence *ops_execute(struct xe_vm *vm, · 373 unmodified lines
31073124 struct dma_fence *fence = NULL;
31083125 struct dma_fence **fences = NULL;
31093126 struct dma_fence_array *cf = NULL;
3110− int number_tiles = 0, current_fence = 0, n_fence = 0, err;
3127+ int number_tiles = 0, current_fence = 0, n_fence = 0, err, i;
31113128 u8 id;
31123129
31133130 number_tiles = vm_ops_setup_tile_args(vm, vops);
31143131 if (number_tiles == 0)
31153132 return ERR_PTR(-ENODATA);
31163133
3117− if (vops->flags & XE_VMA_OPS_FLAG_SKIP_TLB_WAIT) {
3118− for_each_tile(tile, vm->xe, id)
3119− ++n_fence;
3120− } else {
3121− for_each_tile(tile, vm->xe, id)
3122− n_fence += (1 + XE_MAX_GT_PER_TILE);
3134+ for_each_tile(tile, vm->xe, id) {
3135+ ++n_fence;
3136+
3137+ if (!(vops->flags & XE_VMA_OPS_FLAG_SKIP_TLB_WAIT))
3138+ for_each_tlb_inval(i)
3139+ ++n_fence;
31233140 }
31243141
31253142 fences = kmalloc_array(n_fence, sizeof(*fences), GFP_KERNEL);
@@ -3149,7 +3166,6 @@ static struct dma_fence *ops_execute(struct xe_vm *vm, · 23 unmodified lines
31493166
31503167 for_each_tile(tile, vm->xe, id) {
31513168 struct xe_exec_queue *q = vops->pt_update_ops[tile->id].q;
3152− int i;
31533169
31543170 fence = NULL;
31553171 if (!vops->pt_update_ops[id].num_ops)
@@ -3214,7 +3230,8 @@ static void op_add_ufence(struct xe_vm *vm, struct xe_vma_op *op, · 58 unmodified lines
32143230 {
32153231 switch (op->base.op) {
32163232 case DRM_GPUVA_OP_MAP:
3217− vma_add_ufence(op->map.vma, ufence);
3233+ if (!xe_vma_is_cpu_addr_mirror(op->map.vma))
3234+ vma_add_ufence(op->map.vma, ufence);
32183235 break;
32193236 case DRM_GPUVA_OP_REMAP:
32203237 if (op->remap.prev)
@@ -3490,6 +3507,10 @@ static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, · 269 unmodified lines
34903507 {
34913508 u16 coh_mode;
34923509
3510+ if (XE_IOCTL_DBG(xe, (bo->flags & XE_BO_FLAG_NO_COMPRESSION) &&
3511+ xe_pat_index_get_comp_en(xe, pat_index)))
3512+ return -EINVAL;
3513+
34933514 if (XE_IOCTL_DBG(xe, range > xe_bo_size(bo)) ||
34943515 XE_IOCTL_DBG(xe, obj_offset >
34953516 xe_bo_size(bo) - range)) {
@@ -3913,7 +3934,7 @@ int xe_vm_range_tilemask_tlb_inval(struct xe_vm *vm, u64 start, · 417 unmodified lines
39133934
39143935 err = xe_tlb_inval_range(&tile->primary_gt->tlb_inval,
39153936 &fence[fence_id], start, end,
3916− vm->usm.asid);
3937+ vm->usm.asid, NULL);
39173938 if (err)
39183939 goto wait;
39193940 ++fence_id;
@@ -3926,7 +3947,7 @@ int xe_vm_range_tilemask_tlb_inval(struct xe_vm *vm, u64 start, · 6 unmodified lines
39263947
39273948 err = xe_tlb_inval_range(&tile->media_gt->tlb_inval,
39283949 &fence[fence_id], start, end,
3929− vm->usm.asid);
3950+ vm->usm.asid, NULL);
39303951 if (err)
39313952 goto wait;
39323953 ++fence_id;
@@ -4032,10 +4053,18 @@ int xe_vm_validate_protected(struct xe_vm *vm) · 99 unmodified lines
40324053 }
40334054
40344055 struct xe_vm_snapshot {
4056+ int uapi_flags;
40354057 unsigned long num_snaps;
40364058 struct {
40374059 u64 ofs, bo_ofs;
40384060 unsigned long len;
4061+#define XE_VM_SNAP_FLAG_USERPTR BIT(0)
4062+#define XE_VM_SNAP_FLAG_READ_ONLY BIT(1)
4063+#define XE_VM_SNAP_FLAG_IS_NULL BIT(2)
4064+ unsigned long flags;
4065+ int uapi_mem_region;
4066+ int pat_index;
4067+ int cpu_caching;
40394068 struct xe_bo *bo;
40404069 void *data;
40414070 struct mm_struct *mm;
@@ -4064,6 +4093,13 @@ struct xe_vm_snapshot *xe_vm_snapshot_capture(struct xe_vm *vm) · 22 unmodified lines
40644093 goto out_unlock;
40654094 }
40664095
4096+ if (vm->flags & XE_VM_FLAG_FAULT_MODE)
4097+ snap->uapi_flags |= DRM_XE_VM_CREATE_FLAG_FAULT_MODE;
4098+ if (vm->flags & XE_VM_FLAG_LR_MODE)
4099+ snap->uapi_flags |= DRM_XE_VM_CREATE_FLAG_LR_MODE;
4100+ if (vm->flags & XE_VM_FLAG_SCRATCH_PAGE)
4101+ snap->uapi_flags |= DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE;
4102+
40674103 snap->num_snaps = num_snaps;
40684104 i = 0;
40694105 drm_gpuvm_for_each_va(gpuva, &vm->gpuvm) {
@@ -4076,9 +4112,25 @@ struct xe_vm_snapshot *xe_vm_snapshot_capture(struct xe_vm *vm) · 6 unmodified lines
40764112
40774113 snap->snap[i].ofs = xe_vma_start(vma);
40784114 snap->snap[i].len = xe_vma_size(vma);
4115+ snap->snap[i].flags = xe_vma_read_only(vma) ?
4116+ XE_VM_SNAP_FLAG_READ_ONLY : 0;
4117+ snap->snap[i].pat_index = vma->attr.pat_index;
40794118 if (bo) {
4119+ snap->snap[i].cpu_caching = bo->cpu_caching;
40804120 snap->snap[i].bo = xe_bo_get(bo);
40814121 snap->snap[i].bo_ofs = xe_vma_bo_offset(vma);
4122+ switch (bo->ttm.resource->mem_type) {
4123+ case XE_PL_SYSTEM:
4124+ case XE_PL_TT:
4125+ snap->snap[i].uapi_mem_region = 0;
4126+ break;
4127+ case XE_PL_VRAM0:
4128+ snap->snap[i].uapi_mem_region = 1;
4129+ break;
4130+ case XE_PL_VRAM1:
4131+ snap->snap[i].uapi_mem_region = 2;
4132+ break;
4133+ }
40824134 } else if (xe_vma_is_userptr(vma)) {
40834135 struct mm_struct *mm =
40844136 to_userptr_vma(vma)->userptr.notifier.mm;
@@ -4089,8 +4141,14 @@ struct xe_vm_snapshot *xe_vm_snapshot_capture(struct xe_vm *vm) · 4 unmodified lines
40894141 snap->snap[i].data = ERR_PTR(-EFAULT);
40904142
40914143 snap->snap[i].bo_ofs = xe_vma_userptr(vma);
4144+ snap->snap[i].flags |= XE_VM_SNAP_FLAG_USERPTR;
4145+ snap->snap[i].uapi_mem_region = 0;
4146+ } else if (xe_vma_is_null(vma)) {
4147+ snap->snap[i].flags |= XE_VM_SNAP_FLAG_IS_NULL;
4148+ snap->snap[i].uapi_mem_region = -1;
40924149 } else {
40934150 snap->snap[i].data = ERR_PTR(-ENOENT);
4151+ snap->snap[i].uapi_mem_region = -1;
40944152 }
40954153 i++;
40964154 }
@@ -4109,7 +4167,8 @@ void xe_vm_snapshot_capture_delayed(struct xe_vm_snapshot *snap) · 12 unmodified lines
41094167 struct xe_bo *bo = snap->snap[i].bo;
41104168 int err;
41114169
4112− if (IS_ERR(snap->snap[i].data))
4170+ if (IS_ERR(snap->snap[i].data) ||
4171+ snap->snap[i].flags & XE_VM_SNAP_FLAG_IS_NULL)
41134172 continue;
41144173
41154174 snap->snap[i].data = kvmalloc(snap->snap[i].len, GFP_USER);
@@ -4155,15 +4214,32 @@ void xe_vm_snapshot_print(struct xe_vm_snapshot *snap, struct drm_printer *p) · 39 unmodified lines
41554214 return;
41564215 }
41574216
4217+ drm_printf(p, "VM.uapi_flags: 0x%x\n", snap->uapi_flags);
41584218 for (i = 0; i < snap->num_snaps; i++) {
41594219 drm_printf(p, "[%llx].length: 0x%lx\n", snap->snap[i].ofs, snap->snap[i].len);
41604220
4221+ drm_printf(p, "[%llx].properties: %s|%s|mem_region=0x%lx|pat_index=%d|cpu_caching=%d\n",
4222+ snap->snap[i].ofs,
4223+ snap->snap[i].flags & XE_VM_SNAP_FLAG_READ_ONLY ?
4224+ "read_only" : "read_write",
4225+ snap->snap[i].flags & XE_VM_SNAP_FLAG_IS_NULL ?
4226+ "null_sparse" :
4227+ snap->snap[i].flags & XE_VM_SNAP_FLAG_USERPTR ?
4228+ "userptr" : "bo",
4229+ snap->snap[i].uapi_mem_region == -1 ? 0 :
4230+ BIT(snap->snap[i].uapi_mem_region),
4231+ snap->snap[i].pat_index,
4232+ snap->snap[i].cpu_caching);
4233+
41614234 if (IS_ERR(snap->snap[i].data)) {
41624235 drm_printf(p, "[%llx].error: %li\n", snap->snap[i].ofs,
41634236 PTR_ERR(snap->snap[i].data));
41644237 continue;
41654238 }
41664239
4240+ if (snap->snap[i].flags & XE_VM_SNAP_FLAG_IS_NULL)
4241+ continue;
4242+
41674243 drm_printf(p, "[%llx].data: ", snap->snap[i].ofs);
41684244
41694245 for (j = 0; j < snap->snap[i].len; j += sizeof(u32)) {
@@ -4317,6 +4393,8 @@ static int xe_vm_alloc_vma(struct xe_vm *vm, · 147 unmodified lines
43174393
43184394 if (is_madvise)
43194395 vops.flags |= XE_VMA_OPS_FLAG_MADVISE;
4396+ else
4397+ vops.flags |= XE_VMA_OPS_FLAG_ALLOW_SVM_UNMAP;
43204398
43214399 err = vm_bind_ioctl_ops_parse(vm, ops, &vops);
43224400 if (err)
@@ -4390,6 +4468,46 @@ int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t start, uint64_t range) · 67 unmodified lines
43904468 return xe_vm_alloc_vma(vm, &map_req, true);
43914469 }
43924470
4471+static bool is_cpu_addr_vma_with_default_attr(struct xe_vma *vma)
4472+{
4473+ return vma && xe_vma_is_cpu_addr_mirror(vma) &&
4474+ xe_vma_has_default_mem_attrs(vma);
4475+}
4476+
4477+/**
4478+ * xe_vm_find_cpu_addr_mirror_vma_range - Extend a VMA range to include adjacent CPU-mirrored VMAs
4479+ * @vm: VM to search within
4480+ * @start: Input/output pointer to the starting address of the range
4481+ * @end: Input/output pointer to the end address of the range
4482+ *
4483+ * Given a range defined by @start and @range, this function checks the VMAs
4484+ * immediately before and after the range. If those neighboring VMAs are
4485+ * CPU-address-mirrored and have default memory attributes, the function
4486+ * updates @start and @range to include them. This extended range can then
4487+ * be used for merging or other operations that require a unified VMA.
4488+ *
4489+ * The function does not perform the merge itself; it only computes the
4490+ * mergeable boundaries.
4491+ */
4492+void xe_vm_find_cpu_addr_mirror_vma_range(struct xe_vm *vm, u64 *start, u64 *end)
4493+{
4494+ struct xe_vma *prev, *next;
4495+
4496+ lockdep_assert_held(&vm->lock);
4497+
4498+ if (*start >= SZ_4K) {
4499+ prev = xe_vm_find_vma_by_addr(vm, *start - SZ_4K);
4500+ if (is_cpu_addr_vma_with_default_attr(prev))
4501+ *start = xe_vma_start(prev);
4502+ }
4503+
4504+ if (*end < vm->size) {
4505+ next = xe_vm_find_vma_by_addr(vm, *end + 1);
4506+ if (is_cpu_addr_vma_with_default_attr(next))
4507+ *end = xe_vma_end(next);
4508+ }
4509+}
4510+
43934511 /**
43944512 * xe_vm_alloc_cpu_addr_mirror_vma - Allocate CPU addr mirror vma
43954513 * @vm: Pointer to the xe_vm structure
drivers/gpu/drm/xe/xe_vm.h+3−0
@@ -68,6 +68,9 @@ xe_vm_find_overlapping_vma(struct xe_vm *vm, u64 start, u64 range); · 67 unmodified lines
6868
6969 bool xe_vma_has_default_mem_attrs(struct xe_vma *vma);
7070
71+void xe_vm_find_cpu_addr_mirror_vma_range(struct xe_vm *vm,
72+ u64 *start,
73+ u64 *end);
7174 /**
7275 * xe_vm_has_scratch() - Whether the vm is configured for scratch PTEs
7376 * @vm: The vm
drivers/gpu/drm/xe/xe_vm_types.h+1−0
@@ -467,6 +467,7 @@ struct xe_vma_ops { · 466 unmodified lines
467467 #define XE_VMA_OPS_FLAG_MADVISE BIT(1)
468468 #define XE_VMA_OPS_ARRAY_OF_BINDS BIT(2)
469469 #define XE_VMA_OPS_FLAG_SKIP_TLB_WAIT BIT(3)
470+#define XE_VMA_OPS_FLAG_ALLOW_SVM_UNMAP BIT(4)
470471 u32 flags;
471472 #ifdef TEST_VM_OPS_ERROR
472473 /** @inject_error: inject error to test error handling */
drivers/gpu/drm/xe/xe_vram.c+2−4
@@ -156,12 +156,11 @@ static int determine_lmem_bar_size(struct xe_device *xe, struct xe_vram_region * · 155 unmodified lines
156156 static int get_flat_ccs_offset(struct xe_gt *gt, u64 tile_size, u64 *poffset)
157157 {
158158 struct xe_device *xe = gt_to_xe(gt);
159− unsigned int fw_ref;
160159 u64 offset;
161160 u32 reg;
162161
163− fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
164− if (!fw_ref)
162+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
163+ if (!fw_ref.domains)
165164 return -ETIMEDOUT;
166165
167166 if (GRAPHICS_VER(xe) >= 20) {
@@ -193,7 +192,6 @@ static int get_flat_ccs_offset(struct xe_gt *gt, u64 tile_size, u64 *poffset) · 25 unmodified lines
193192 offset = (u64)REG_FIELD_GET(XEHP_FLAT_CCS_PTR, reg) * SZ_64K;
194193 }
195194
196− xe_force_wake_put(gt_to_fw(gt), fw_ref);
197195 *poffset = offset;
198196
199197 return 0;
drivers/gpu/drm/xe/xe_wa.c+6−46
@@ -15,6 +15,7 @@ · 14 unmodified lines
1515
1616 #include "regs/xe_engine_regs.h"
1717 #include "regs/xe_gt_regs.h"
18+#include "regs/xe_guc_regs.h"
1819 #include "regs/xe_regs.h"
1920 #include "xe_device_types.h"
2021 #include "xe_force_wake.h"
@@ -216,20 +217,6 @@ static const struct xe_rtp_entry_sr gt_was[] = { · 195 unmodified lines
216217 XE_RTP_ACTIONS(SET(XELPMP_SQCNT1, ENFORCE_RAR))
217218 },
218219
219− /* Xe2_LPG */
220−
221− { XE_RTP_NAME("16020975621"),
222− XE_RTP_RULES(GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0)),
223− XE_RTP_ACTIONS(SET(XEHP_SLICE_UNIT_LEVEL_CLKGATE, SBEUNIT_CLKGATE_DIS))
224− },
225− { XE_RTP_NAME("14018157293"),
226− XE_RTP_RULES(GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0)),
227− XE_RTP_ACTIONS(SET(XEHPC_L3CLOS_MASK(0), ~0),
228− SET(XEHPC_L3CLOS_MASK(1), ~0),
229− SET(XEHPC_L3CLOS_MASK(2), ~0),
230− SET(XEHPC_L3CLOS_MASK(3), ~0))
231− },
232−
233220 /* Xe2_LPM */
234221
235222 { XE_RTP_NAME("14017421178"),
@@ -315,6 +302,10 @@ static const struct xe_rtp_entry_sr gt_was[] = { · 79 unmodified lines
315302 XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), RAMDFTUNIT_CLKGATE_DIS)),
316303 XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
317304 },
305+ { XE_RTP_NAME("16028005424"),
306+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005)),
307+ XE_RTP_ACTIONS(SET(GUC_INTR_CHICKEN, DISABLE_SIGNALING_ENGINES))
308+ },
318309 };
319310
320311 static const struct xe_rtp_entry_sr engine_was[] = {
@@ -504,11 +495,6 @@ static const struct xe_rtp_entry_sr engine_was[] = { · 183 unmodified lines
504495 XE_RTP_RULES(GRAPHICS_VERSION(2004), FUNC(xe_rtp_match_first_render_or_compute)),
505496 XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, XE2_ALLOC_DPA_STARVE_FIX_DIS))
506497 },
507− { XE_RTP_NAME("14018957109"),
508− XE_RTP_RULES(GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0),
509− FUNC(xe_rtp_match_first_render_or_compute)),
510− XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN5, DISABLE_SAMPLE_G_PERFORMANCE))
511− },
512498 { XE_RTP_NAME("14020338487"),
513499 XE_RTP_RULES(GRAPHICS_VERSION(2004), FUNC(xe_rtp_match_first_render_or_compute)),
514500 XE_RTP_ACTIONS(SET(ROW_CHICKEN3, XE2_EUPEND_CHK_FLUSH_DIS))
@@ -518,11 +504,6 @@ static const struct xe_rtp_entry_sr engine_was[] = { · 3 unmodified lines
518504 FUNC(xe_rtp_match_first_render_or_compute)),
519505 XE_RTP_ACTIONS(SET(ROW_CHICKEN4, DISABLE_TDL_PUSH))
520506 },
521− { XE_RTP_NAME("14019322943"),
522− XE_RTP_RULES(GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0),
523− FUNC(xe_rtp_match_first_render_or_compute)),
524− XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0, TGM_WRITE_EOM_FORCE))
525− },
526507 { XE_RTP_NAME("14018471104"),
527508 XE_RTP_RULES(GRAPHICS_VERSION(2004), FUNC(xe_rtp_match_first_render_or_compute)),
528509 XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, ENABLE_SMP_LD_RENDER_SURFACE_CONTROL))
@@ -693,7 +674,7 @@ static const struct xe_rtp_entry_sr engine_was[] = { · 164 unmodified lines
693674 XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE))
694675 },
695676 { XE_RTP_NAME("18041344222"),
696− XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001),
677+ XE_RTP_RULES(GRAPHICS_VERSION(3000),
697678 FUNC(xe_rtp_match_first_render_or_compute),
698679 FUNC(xe_rtp_match_not_sriov_vf),
699680 FUNC(xe_rtp_match_gt_has_discontiguous_dss_groups)),
@@ -799,17 +780,6 @@ static const struct xe_rtp_entry_sr lrc_was[] = { · 99 unmodified lines
799780
800781 /* Xe2_LPG */
801782
802− { XE_RTP_NAME("16020518922"),
803− XE_RTP_RULES(GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0),
804− ENGINE_CLASS(RENDER)),
805− XE_RTP_ACTIONS(SET(FF_MODE,
806− DIS_TE_AUTOSTRIP |
807− DIS_MESH_PARTIAL_AUTOSTRIP |
808− DIS_MESH_AUTOSTRIP),
809− SET(VFLSKPD,
810− DIS_PARTIAL_AUTOSTRIP |
811− DIS_AUTOSTRIP))
812− },
813783 { XE_RTP_NAME("14019386621"),
814784 XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
815785 XE_RTP_ACTIONS(SET(VF_SCRATCHPAD, XE2_VFG_TED_CREDIT_INTERFACE_DISABLE))
@@ -818,20 +788,10 @@ static const struct xe_rtp_entry_sr lrc_was[] = { · 2 unmodified lines
818788 XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
819789 XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FD_END_COLLECT))
820790 },
821− { XE_RTP_NAME("14020013138"),
822− XE_RTP_RULES(GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0),
823− ENGINE_CLASS(RENDER)),
824− XE_RTP_ACTIONS(SET(WM_CHICKEN3, HIZ_PLANE_COMPRESSION_DIS))
825− },
826791 { XE_RTP_NAME("14019988906"),
827792 XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
828793 XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FLSH_IGNORES_PSD))
829794 },
830− { XE_RTP_NAME("16020183090"),
831− XE_RTP_RULES(GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0),
832− ENGINE_CLASS(RENDER)),
833− XE_RTP_ACTIONS(SET(INSTPM(RENDER_RING_BASE), ENABLE_SEMAPHORE_POLL_BIT))
834− },
835795 { XE_RTP_NAME("18033852989"),
836796 XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
837797 XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN1, DISABLE_BOTTOM_CLIP_RECTANGLE_TEST))
drivers/gpu/drm/xe/xe_wa_oob.rules+1−5
@@ -16,15 +16,11 @@ · 15 unmodified lines
1616 16017236439 PLATFORM(PVC)
1717 14019821291 MEDIA_VERSION_RANGE(1300, 2000)
1818 14015076503 MEDIA_VERSION(1300)
19−16020292621 GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0)
20−14018913170 GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0)
21− MEDIA_VERSION(2000), GRAPHICS_STEP(A0, A1)
22− GRAPHICS_VERSION_RANGE(1270, 1274)
19+14018913170 GRAPHICS_VERSION_RANGE(1270, 1274)
2320 MEDIA_VERSION(1300)
2421 PLATFORM(DG2)
2522 14018094691 GRAPHICS_VERSION_RANGE(2001, 2002)
2623 GRAPHICS_VERSION(2004)
27−14019882105 GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0)
2824 18024947630 GRAPHICS_VERSION(2001)
2925 GRAPHICS_VERSION(2004)
3026 MEDIA_VERSION(2000)
include/uapi/drm/xe_drm.h+78−3
@@ -106,6 +106,7 @@ extern "C" { · 105 unmodified lines
106106 #define DRM_XE_OBSERVATION 0x0b
107107 #define DRM_XE_MADVISE 0x0c
108108 #define DRM_XE_VM_QUERY_MEM_RANGE_ATTRS 0x0d
109+#define DRM_XE_EXEC_QUEUE_SET_PROPERTY 0x0e
109110
110111 /* Must be kept compact -- no holes */
111112
@@ -123,6 +124,7 @@ extern "C" { · 11 unmodified lines
123124 #define DRM_IOCTL_XE_OBSERVATION DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
124125 #define DRM_IOCTL_XE_MADVISE DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
125126 #define DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_MEM_RANGE_ATTRS, struct drm_xe_vm_query_mem_range_attr)
127+#define DRM_IOCTL_XE_EXEC_QUEUE_SET_PROPERTY DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_SET_PROPERTY, struct drm_xe_exec_queue_set_property)
126128
127129 /**
128130 * DOC: Xe IOCTL Extensions
@@ -210,8 +212,12 @@ struct drm_xe_ext_set_property { · 81 unmodified lines
210212 /** @pad: MBZ */
211213 __u32 pad;
212214
213− /** @value: property value */
214− __u64 value;
215+ union {
216+ /** @value: property value */
217+ __u64 value;
218+ /** @ptr: pointer to user value */
219+ __u64 ptr;
220+ };
215221
216222 /** @reserved: Reserved */
217223 __u64 reserved[2];
@@ -403,6 +409,9 @@ struct drm_xe_query_mem_regions { · 185 unmodified lines
403409 * has low latency hint support
404410 * - %DRM_XE_QUERY_CONFIG_FLAG_HAS_CPU_ADDR_MIRROR - Flag is set if the
405411 * device has CPU address mirroring support
412+ * - %DRM_XE_QUERY_CONFIG_FLAG_HAS_NO_COMPRESSION_HINT - Flag is set if the
413+ * device supports the userspace hint %DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION.
414+ * This is exposed only on Xe2+.
406415 * - %DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - Minimal memory alignment
407416 * required by this device, typically SZ_4K or SZ_64K
408417 * - %DRM_XE_QUERY_CONFIG_VA_BITS - Maximum bits of a virtual address
@@ -421,6 +430,7 @@ struct drm_xe_query_config { · 12 unmodified lines
421430 #define DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM (1 << 0)
422431 #define DRM_XE_QUERY_CONFIG_FLAG_HAS_LOW_LATENCY (1 << 1)
423432 #define DRM_XE_QUERY_CONFIG_FLAG_HAS_CPU_ADDR_MIRROR (1 << 2)
433+ #define DRM_XE_QUERY_CONFIG_FLAG_HAS_NO_COMPRESSION_HINT (1 << 3)
424434 #define DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT 2
425435 #define DRM_XE_QUERY_CONFIG_VA_BITS 3
426436 #define DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY 4
@@ -791,6 +801,17 @@ struct drm_xe_device_query { · 364 unmodified lines
791801 * need to use VRAM for display surfaces, therefore the kernel requires
792802 * setting this flag for such objects, otherwise an error is thrown on
793803 * small-bar systems.
804+ * - %DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION - Allows userspace to
805+ * hint that compression (CCS) should be disabled for the buffer being
806+ * created. This can avoid unnecessary memory operations and CCS state
807+ * management.
808+ * On pre-Xe2 platforms, this flag is currently rejected as compression
809+ * control is not supported via PAT index. On Xe2+ platforms, compression
810+ * is controlled via PAT entries. If this flag is set, the driver will reject
811+ * any VM bind that requests a PAT index enabling compression for this BO.
812+ * Note: On dGPU platforms, there is currently no change in behavior with
813+ * this flag, but future improvements may leverage it. The current benefit is
814+ * primarily applicable to iGPU platforms.
794815 *
795816 * @cpu_caching supports the following values:
796817 * - %DRM_XE_GEM_CPU_CACHING_WB - Allocate the pages with write-back
@@ -837,6 +858,7 @@ struct drm_xe_gem_create { · 40 unmodified lines
837858 #define DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING (1 << 0)
838859 #define DRM_XE_GEM_CREATE_FLAG_SCANOUT (1 << 1)
839860 #define DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM (1 << 2)
861+#define DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION (1 << 3)
840862 /**
841863 * @flags: Flags, currently a mask of memory instances of where BO can
842864 * be placed
@@ -1252,6 +1274,20 @@ struct drm_xe_vm_bind { · 409 unmodified lines
12521274 * Given that going into a power-saving state kills PXP HWDRM sessions,
12531275 * runtime PM will be blocked while queues of this type are alive.
12541276 * All PXP queues will be killed if a PXP invalidation event occurs.
1277+ * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP - Create a multi-queue group
1278+ * or add secondary queues to a multi-queue group.
1279+ * If the extension's 'value' field has %DRM_XE_MULTI_GROUP_CREATE flag set,
1280+ * then a new multi-queue group is created with this queue as the primary queue
1281+ * (Q0). Otherwise, the queue gets added to the multi-queue group whose primary
1282+ * queue's exec_queue_id is specified in the lower 32 bits of the 'value' field.
1283+ * If the extension's 'value' field has %DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag
1284+ * set, then the multi-queue group is kept active after the primary queue is
1285+ * destroyed.
1286+ * All the other non-relevant bits of extension's 'value' field while adding the
1287+ * primary or the secondary queues of the group must be set to 0.
1288+ * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY - Set the queue
1289+ * priority within the multi-queue group. Current valid priority values are 0–2
1290+ * (default is 1), with higher values indicating higher priority.
12551291 *
12561292 * The example below shows how to use @drm_xe_exec_queue_create to create
12571293 * a simple exec_queue (no parallel submission) of class
@@ -1292,6 +1328,11 @@ struct drm_xe_exec_queue_create { · 34 unmodified lines
12921328 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY 0
12931329 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE 1
12941330 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE 2
1331+#define DRM_XE_EXEC_QUEUE_SET_HANG_REPLAY_STATE 3
1332+#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP 4
1333+#define DRM_XE_MULTI_GROUP_CREATE (1ull << 63)
1334+#define DRM_XE_MULTI_GROUP_KEEP_ACTIVE (1ull << 62)
1335+#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY 5
12951336 /** @extensions: Pointer to the first extension struct, if any */
12961337 __u64 extensions;
12971338
@@ -1655,6 +1696,9 @@ enum drm_xe_oa_unit_type { · 357 unmodified lines
16551696
16561697 /** @DRM_XE_OA_UNIT_TYPE_OAM_SAG: OAM_SAG OA unit */
16571698 DRM_XE_OA_UNIT_TYPE_OAM_SAG,
1699+
1700+ /** @DRM_XE_OA_UNIT_TYPE_MERT: MERT OA unit */
1701+ DRM_XE_OA_UNIT_TYPE_MERT,
16581702 };
16591703
16601704 /**
@@ -1677,12 +1721,19 @@ struct drm_xe_oa_unit { · 16 unmodified lines
16771721 #define DRM_XE_OA_CAPS_OA_BUFFER_SIZE (1 << 2)
16781722 #define DRM_XE_OA_CAPS_WAIT_NUM_REPORTS (1 << 3)
16791723 #define DRM_XE_OA_CAPS_OAM (1 << 4)
1724+#define DRM_XE_OA_CAPS_OA_UNIT_GT_ID (1 << 5)
16801725
16811726 /** @oa_timestamp_freq: OA timestamp freq */
16821727 __u64 oa_timestamp_freq;
16831728
1729+ /** @gt_id: gt id for this OA unit */
1730+ __u16 gt_id;
1731+
1732+ /** @reserved1: MBZ */
1733+ __u16 reserved1[3];
1734+
16841735 /** @reserved: MBZ */
1685− __u64 reserved[4];
1736+ __u64 reserved[3];
16861737
16871738 /** @num_engines: number of engines in @eci array */
16881739 __u64 num_engines;
@@ -2274,6 +2325,30 @@ struct drm_xe_vm_query_mem_range_attr { · 585 unmodified lines
22742325
22752326 };
22762327
2328+/**
2329+ * struct drm_xe_exec_queue_set_property - exec queue set property
2330+ *
2331+ * Sets execution queue properties dynamically.
2332+ * Currently only %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY
2333+ * property can be dynamically set.
2334+ */
2335+struct drm_xe_exec_queue_set_property {
2336+ /** @extensions: Pointer to the first extension struct, if any */
2337+ __u64 extensions;
2338+
2339+ /** @exec_queue_id: Exec queue ID */
2340+ __u32 exec_queue_id;
2341+
2342+ /** @property: property to set */
2343+ __u32 property;
2344+
2345+ /** @value: property value */
2346+ __u64 value;
2347+
2348+ /** @reserved: Reserved */
2349+ __u64 reserved[2];
2350+};
2351+
22772352 #if defined(__cplusplus)
22782353 }
22792354 #endif