Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

UAPI Changes:

Limit number of jobs per exec queue (Shuicheng)
Add sriov_admin sysfs tree (Michal)

Driver Changes:

Fix an uninitialized value (Thomas)
Expose a residency counter through debugfs (Mohammed Thasleem)
Workaround enabling and improvement (Tapani, Tangudu)
More Crescent Island-specific support (Sk Anirban, Lucas)
PAT entry dump imprement (Xin)
Inline gt_reset in the worker (Lucas)
Synchronize GT reset with device unbind (Balasubramani)
Do clean shutdown also when using flr (Jouni)
Fix serialization on burst of unbinds (Matt Brost)
Pagefault Refactor (Matt Brost)
Remove some unused code (Gwan-gyeong)

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Thomas Hellstrom <thomas.hellstrom@linux.intel.com>
Link: https://patch.msgid.link/aQuBECxNOhudc0Bz@fedora

+2731 -1268
+159
Documentation/ABI/testing/sysfs-driver-intel-xe-sriov
··· 1 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/ 2 + Date: October 2025 3 + KernelVersion: 6.19 4 + Contact: intel-xe@lists.freedesktop.org 5 + Description: 6 + This directory appears for the particular Intel Xe device when: 7 + 8 + - device supports SR-IOV, and 9 + - device is a Physical Function (PF), and 10 + - driver support for the SR-IOV PF is enabled on given device. 11 + 12 + This directory is used as a root for all attributes required to 13 + manage both Physical Function (PF) and Virtual Functions (VFs). 14 + 15 + 16 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/pf/ 17 + Date: October 2025 18 + KernelVersion: 6.19 19 + Contact: intel-xe@lists.freedesktop.org 20 + Description: 21 + This directory holds attributes related to the SR-IOV Physical 22 + Function (PF). 23 + 24 + 25 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/vf1/ 26 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/vf2/ 27 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/vf<N>/ 28 + Date: October 2025 29 + KernelVersion: 6.19 30 + Contact: intel-xe@lists.freedesktop.org 31 + Description: 32 + These directories hold attributes related to the SR-IOV Virtual 33 + Functions (VFs). 34 + 35 + Note that the VF number <N> is 1-based as described in PCI SR-IOV 36 + specification as the Xe driver follows that naming schema. 37 + 38 + There could be "vf1", "vf2" and so on, up to "vf<N>", where <N> 39 + matches the value of the "sriov_totalvfs" attribute. 40 + 41 + 42 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/pf/profile/exec_quantum_ms 43 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/pf/profile/preempt_timeout_us 44 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/pf/profile/sched_priority 45 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/vf<n>/profile/exec_quantum_ms 46 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/vf<n>/profile/preempt_timeout_us 47 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/vf<n>/profile/sched_priority 48 + Date: October 2025 49 + KernelVersion: 6.19 50 + Contact: intel-xe@lists.freedesktop.org 51 + Description: 52 + These files expose scheduling parameters for the PF and its VFs, and 53 + are visible only on Intel Xe platforms that use time-sliced GPU sharing. 54 + They can be changed even if VFs are enabled and running and reflect the 55 + settings of all tiles/GTs assigned to the given function. 56 + 57 + exec_quantum_ms: (RW) unsigned integer 58 + The GT execution quantum (EQ) in [ms] for the given function. 59 + Actual quantum value might be aligned per HW/FW requirements. 60 + 61 + Default is 0 (unlimited). 62 + 63 + preempt_timeout_us: (RW) unsigned integer 64 + The GT preemption timeout in [us] of the given function. 65 + Actual timeout value might be aligned per HW/FW requirements. 66 + 67 + Default is 0 (unlimited). 68 + 69 + sched_priority: (RW/RO) string 70 + The GT scheduling priority of the given function. 71 + 72 + "low" - function will be scheduled on the GPU for its EQ/PT 73 + only if function has any work already submitted. 74 + 75 + "normal" - functions will be scheduled on the GPU for its EQ/PT 76 + irrespective of whether it has submitted a work or not. 77 + 78 + "high" - function will be scheduled on the GPU for its EQ/PT 79 + in the next time-slice after the current one completes 80 + and function has a work submitted. 81 + 82 + Default is "low". 83 + 84 + When read, this file will display the current and available 85 + scheduling priorities. The currently active priority level will 86 + be enclosed in square brackets, like: 87 + 88 + [low] normal high 89 + 90 + This file can be read-only if changing the priority is not 91 + supported. 92 + 93 + Writes to these attributes may fail with errors like: 94 + -EINVAL if provided input is malformed or not recognized, 95 + -EPERM if change is not applicable on given HW/FW, 96 + -EIO if FW refuses to change the provisioning. 97 + 98 + Reads from these attributes may fail with: 99 + -EUCLEAN if value is not consistent across all tiles/GTs. 100 + 101 + 102 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/.bulk_profile/exec_quantum_ms 103 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/.bulk_profile/preempt_timeout_us 104 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/.bulk_profile/sched_priority 105 + Date: October 2025 106 + KernelVersion: 6.19 107 + Contact: intel-xe@lists.freedesktop.org 108 + Description: 109 + These files allows bulk reconfiguration of the scheduling parameters 110 + of the PF or VFs and are available only for Intel Xe platforms with 111 + GPU sharing based on the time-slice basis. These scheduling parameters 112 + can be changed even if VFs are enabled and running. 113 + 114 + exec_quantum_ms: (WO) unsigned integer 115 + The GT execution quantum (EQ) in [ms] to be applied to all functions. 116 + See sriov_admin/{pf,vf<N>}/profile/exec_quantum_ms for more details. 117 + 118 + preempt_timeout_us: (WO) unsigned integer 119 + The GT preemption timeout (PT) in [us] to be applied to all functions. 120 + See sriov_admin/{pf,vf<N>}/profile/preempt_timeout_us for more details. 121 + 122 + sched_priority: (RW/RO) string 123 + The GT scheduling priority to be applied for all functions. 124 + See sriov_admin/{pf,vf<N>}/profile/sched_priority for more details. 125 + 126 + Writes to these attributes may fail with errors like: 127 + -EINVAL if provided input is malformed or not recognized, 128 + -EPERM if change is not applicable on given HW/FW, 129 + -EIO if FW refuses to change the provisioning. 130 + 131 + 132 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/vf<n>/stop 133 + Date: October 2025 134 + KernelVersion: 6.19 135 + Contact: intel-xe@lists.freedesktop.org 136 + Description: 137 + This file allows to control scheduling of the VF on the Intel Xe GPU 138 + platforms. It allows to implement custom policy mechanism in case VFs 139 + are misbehaving or triggering adverse events above defined thresholds. 140 + 141 + stop: (WO) bool 142 + All GT executions of given function shall be immediately stopped. 143 + To allow scheduling this VF again, the VF FLR must be triggered. 144 + 145 + Writes to this attribute may fail with errors like: 146 + -EINVAL if provided input is malformed or not recognized, 147 + -EPERM if change is not applicable on given HW/FW, 148 + -EIO if FW refuses to change the scheduling. 149 + 150 + 151 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/pf/device 152 + What: /sys/bus/pci/drivers/xe/.../sriov_admin/vf<n>/device 153 + Date: October 2025 154 + KernelVersion: 6.19 155 + Contact: intel-xe@lists.freedesktop.org 156 + Description: 157 + These are symlinks to the underlying PCI device entry representing 158 + given Xe SR-IOV function. For the PF, this link is always present. 159 + For VFs, this link is present only for currently enabled VFs.
+3
Documentation/gpu/xe/xe_gt_freq.rst
··· 7 7 .. kernel-doc:: drivers/gpu/drm/xe/xe_gt_freq.c 8 8 :doc: Xe GT Frequency Management 9 9 10 + .. kernel-doc:: drivers/gpu/drm/xe/xe_gt_throttle.c 11 + :doc: Xe GT Throttle 12 + 10 13 Internal API 11 14 ============ 12 15
+3 -1
drivers/gpu/drm/xe/Makefile
··· 58 58 xe_gt_freq.o \ 59 59 xe_gt_idle.o \ 60 60 xe_gt_mcr.o \ 61 - xe_gt_pagefault.o \ 62 61 xe_gt_sysfs.o \ 63 62 xe_gt_throttle.o \ 64 63 xe_gt_topology.o \ ··· 72 73 xe_guc_id_mgr.o \ 73 74 xe_guc_klv_helpers.o \ 74 75 xe_guc_log.o \ 76 + xe_guc_pagefault.o \ 75 77 xe_guc_pc.o \ 76 78 xe_guc_submit.o \ 77 79 xe_guc_tlb_inval.o \ ··· 94 94 xe_nvm.o \ 95 95 xe_oa.o \ 96 96 xe_observation.o \ 97 + xe_pagefault.o \ 97 98 xe_pat.o \ 98 99 xe_pci.o \ 99 100 xe_pcode.o \ ··· 179 178 xe_sriov_pf_debugfs.o \ 180 179 xe_sriov_pf_provision.o \ 181 180 xe_sriov_pf_service.o \ 181 + xe_sriov_pf_sysfs.o \ 182 182 xe_tile_sriov_pf_debugfs.o 183 183 184 184 # include helpers for tests even when XE is built-in
+13
drivers/gpu/drm/xe/regs/xe_gt_regs.h
··· 590 590 #define GT_GFX_RC6 XE_REG(0x138108) 591 591 592 592 #define GT0_PERF_LIMIT_REASONS XE_REG(0x1381a8) 593 + /* Common performance limit reason bits - available on all platforms */ 593 594 #define GT0_PERF_LIMIT_REASONS_MASK 0xde3 594 595 #define PROCHOT_MASK REG_BIT(0) 595 596 #define THERMAL_LIMIT_MASK REG_BIT(1) ··· 600 599 #define POWER_LIMIT_4_MASK REG_BIT(8) 601 600 #define POWER_LIMIT_1_MASK REG_BIT(10) 602 601 #define POWER_LIMIT_2_MASK REG_BIT(11) 602 + /* Platform-specific performance limit reason bits - for Crescent Island */ 603 + #define CRI_PERF_LIMIT_REASONS_MASK 0xfdff 604 + #define SOC_THERMAL_LIMIT_MASK REG_BIT(1) 605 + #define MEM_THERMAL_MASK REG_BIT(2) 606 + #define VR_THERMAL_MASK REG_BIT(3) 607 + #define ICCMAX_MASK REG_BIT(4) 608 + #define SOC_AVG_THERMAL_MASK REG_BIT(6) 609 + #define FASTVMODE_MASK REG_BIT(7) 610 + #define PSYS_PL1_MASK REG_BIT(12) 611 + #define PSYS_PL2_MASK REG_BIT(13) 612 + #define P0_FREQ_MASK REG_BIT(14) 613 + #define PSYS_CRIT_MASK REG_BIT(15) 603 614 604 615 #define GT_PERF_STATUS XE_REG(0x1381b4) 605 616 #define VOLTAGE_MASK REG_GENMASK(10, 0)
+1
drivers/gpu/drm/xe/regs/xe_pmt.h
··· 24 24 #define BMG_MODS_RESIDENCY_OFFSET (0x4D0) 25 25 #define BMG_G2_RESIDENCY_OFFSET (0x530) 26 26 #define BMG_G6_RESIDENCY_OFFSET (0x538) 27 + #define BMG_G7_RESIDENCY_OFFSET (0x4B0) 27 28 #define BMG_G8_RESIDENCY_OFFSET (0x540) 28 29 #define BMG_G10_RESIDENCY_OFFSET (0x548) 29 30
+1
drivers/gpu/drm/xe/xe_debugfs.c
··· 142 142 } residencies[] = { 143 143 {BMG_G2_RESIDENCY_OFFSET, "Package G2"}, 144 144 {BMG_G6_RESIDENCY_OFFSET, "Package G6"}, 145 + {BMG_G7_RESIDENCY_OFFSET, "Package G7"}, 145 146 {BMG_G8_RESIDENCY_OFFSET, "Package G8"}, 146 147 {BMG_G10_RESIDENCY_OFFSET, "Package G10"}, 147 148 {BMG_MODS_RESIDENCY_OFFSET, "Package ModS"}
+14 -9
drivers/gpu/drm/xe/xe_device.c
··· 52 52 #include "xe_nvm.h" 53 53 #include "xe_oa.h" 54 54 #include "xe_observation.h" 55 + #include "xe_pagefault.h" 55 56 #include "xe_pat.h" 56 57 #include "xe_pcode.h" 57 58 #include "xe_pm.h" ··· 897 896 return err; 898 897 } 899 898 899 + err = xe_pagefault_init(xe); 900 + if (err) 901 + return err; 902 + 900 903 if (xe->tiles->media_gt && 901 904 XE_GT_WA(xe->tiles->media_gt, 15015404425_disable)) 902 905 XE_DEVICE_WA_DISABLE(xe, 15015404425); ··· 993 988 994 989 void xe_device_shutdown(struct xe_device *xe) 995 990 { 991 + struct xe_gt *gt; 992 + u8 id; 993 + 996 994 drm_dbg(&xe->drm, "Shutting down device\n"); 997 995 998 - if (xe_driver_flr_disabled(xe)) { 999 - struct xe_gt *gt; 1000 - u8 id; 996 + xe_display_pm_shutdown(xe); 1001 997 1002 - xe_display_pm_shutdown(xe); 998 + xe_irq_suspend(xe); 1003 999 1004 - xe_irq_suspend(xe); 1000 + for_each_gt(gt, xe, id) 1001 + xe_gt_shutdown(gt); 1005 1002 1006 - for_each_gt(gt, xe, id) 1007 - xe_gt_shutdown(gt); 1003 + xe_display_pm_shutdown_late(xe); 1008 1004 1009 - xe_display_pm_shutdown_late(xe); 1010 - } else { 1005 + if (!xe_driver_flr_disabled(xe)) { 1011 1006 /* BOOM! */ 1012 1007 __xe_driver_flr(xe); 1013 1008 }
+11
drivers/gpu/drm/xe/xe_device_types.h
··· 18 18 #include "xe_lmtt_types.h" 19 19 #include "xe_memirq_types.h" 20 20 #include "xe_oa_types.h" 21 + #include "xe_pagefault_types.h" 21 22 #include "xe_platform_types.h" 22 23 #include "xe_pmu_types.h" 23 24 #include "xe_pt_types.h" ··· 419 418 u32 next_asid; 420 419 /** @usm.lock: protects UM state */ 421 420 struct rw_semaphore lock; 421 + /** @usm.pf_wq: page fault work queue, unbound, high priority */ 422 + struct workqueue_struct *pf_wq; 423 + /* 424 + * We pick 4 here because, in the current implementation, it 425 + * yields the best bandwidth utilization of the kernel paging 426 + * engine. 427 + */ 428 + #define XE_PAGEFAULT_QUEUE_COUNT 4 429 + /** @usm.pf_queue: Page fault queues */ 430 + struct xe_pagefault_queue pf_queue[XE_PAGEFAULT_QUEUE_COUNT]; 422 431 } usm; 423 432 424 433 /** @pinned: pinned BO state */
+9 -5
drivers/gpu/drm/xe/xe_exec.c
··· 21 21 #include "xe_sched_job.h" 22 22 #include "xe_sync.h" 23 23 #include "xe_svm.h" 24 + #include "xe_trace.h" 24 25 #include "xe_vm.h" 25 26 26 27 /** ··· 155 154 goto err_exec_queue; 156 155 } 157 156 157 + if (atomic_read(&q->job_cnt) >= XE_MAX_JOB_COUNT_PER_EXEC_QUEUE) { 158 + trace_xe_exec_queue_reach_max_job_count(q, XE_MAX_JOB_COUNT_PER_EXEC_QUEUE); 159 + err = -EAGAIN; 160 + goto err_exec_queue; 161 + } 162 + 158 163 if (args->num_syncs) { 159 164 syncs = kcalloc(args->num_syncs, sizeof(*syncs), GFP_KERNEL); 160 165 if (!syncs) { ··· 173 166 174 167 for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) { 175 168 err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs], 176 - &syncs_user[num_syncs], SYNC_PARSE_FLAG_EXEC | 169 + &syncs_user[num_syncs], NULL, 0, 170 + SYNC_PARSE_FLAG_EXEC | 177 171 (xe_vm_in_lr_mode(vm) ? 178 172 SYNC_PARSE_FLAG_LR_MODE : 0)); 179 173 if (err) ··· 302 294 goto err_put_job; 303 295 304 296 if (!xe_vm_in_lr_mode(vm)) { 305 - err = xe_sched_job_last_fence_add_dep(job, vm); 306 - if (err) 307 - goto err_put_job; 308 - 309 297 err = xe_svm_notifier_lock_interruptible(vm); 310 298 if (err) 311 299 goto err_put_job;
+109 -15
drivers/gpu/drm/xe/xe_exec_queue.c
··· 10 10 #include <drm/drm_device.h> 11 11 #include <drm/drm_drv.h> 12 12 #include <drm/drm_file.h> 13 + #include <drm/drm_syncobj.h> 13 14 #include <uapi/drm/xe_drm.h> 14 15 15 16 #include "xe_dep_scheduler.h" ··· 369 368 } 370 369 xe_vm_put(migrate_vm); 371 370 371 + if (!IS_ERR(q)) { 372 + int err = drm_syncobj_create(&q->ufence_syncobj, 373 + DRM_SYNCOBJ_CREATE_SIGNALED, 374 + NULL); 375 + if (err) { 376 + xe_exec_queue_put(q); 377 + return ERR_PTR(err); 378 + } 379 + } 380 + 372 381 return q; 373 382 } 374 383 ALLOW_ERROR_INJECTION(xe_exec_queue_create_bind, ERRNO); ··· 387 376 { 388 377 struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount); 389 378 struct xe_exec_queue *eq, *next; 379 + int i; 380 + 381 + xe_assert(gt_to_xe(q->gt), atomic_read(&q->job_cnt) == 0); 382 + 383 + if (q->ufence_syncobj) 384 + drm_syncobj_put(q->ufence_syncobj); 390 385 391 386 if (xe_exec_queue_uses_pxp(q)) 392 387 xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q); 393 388 394 389 xe_exec_queue_last_fence_put_unlocked(q); 390 + for_each_tlb_inval(i) 391 + xe_exec_queue_tlb_inval_last_fence_put_unlocked(q, i); 392 + 395 393 if (!(q->flags & EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD)) { 396 394 list_for_each_entry_safe(eq, next, &q->multi_gt_list, 397 395 multi_gt_link) ··· 1018 998 static void xe_exec_queue_last_fence_lockdep_assert(struct xe_exec_queue *q, 1019 999 struct xe_vm *vm) 1020 1000 { 1021 - if (q->flags & EXEC_QUEUE_FLAG_VM) { 1001 + if (q->flags & EXEC_QUEUE_FLAG_MIGRATE) { 1002 + xe_migrate_job_lock_assert(q); 1003 + } else if (q->flags & EXEC_QUEUE_FLAG_VM) { 1022 1004 lockdep_assert_held(&vm->lock); 1023 1005 } else { 1024 1006 xe_vm_assert_held(vm); ··· 1119 1097 struct dma_fence *fence) 1120 1098 { 1121 1099 xe_exec_queue_last_fence_lockdep_assert(q, vm); 1100 + xe_assert(vm->xe, !dma_fence_is_container(fence)); 1122 1101 1123 1102 xe_exec_queue_last_fence_put(q, vm); 1124 1103 q->last_fence = dma_fence_get(fence); 1125 1104 } 1126 1105 1127 1106 /** 1128 - * xe_exec_queue_last_fence_test_dep - Test last fence dependency of queue 1107 + * xe_exec_queue_tlb_inval_last_fence_put() - Drop ref to last TLB invalidation fence 1129 1108 * @q: The exec queue 1130 - * @vm: The VM the engine does a bind or exec for 1131 - * 1132 - * Returns: 1133 - * -ETIME if there exists an unsignalled last fence dependency, zero otherwise. 1109 + * @vm: The VM the engine does a bind for 1110 + * @type: Either primary or media GT 1134 1111 */ 1135 - int xe_exec_queue_last_fence_test_dep(struct xe_exec_queue *q, struct xe_vm *vm) 1112 + void xe_exec_queue_tlb_inval_last_fence_put(struct xe_exec_queue *q, 1113 + struct xe_vm *vm, 1114 + unsigned int type) 1115 + { 1116 + xe_exec_queue_last_fence_lockdep_assert(q, vm); 1117 + xe_assert(vm->xe, type == XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT || 1118 + type == XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT); 1119 + 1120 + xe_exec_queue_tlb_inval_last_fence_put_unlocked(q, type); 1121 + } 1122 + 1123 + /** 1124 + * xe_exec_queue_tlb_inval_last_fence_put_unlocked() - Drop ref to last TLB 1125 + * invalidation fence unlocked 1126 + * @q: The exec queue 1127 + * @type: Either primary or media GT 1128 + * 1129 + * Only safe to be called from xe_exec_queue_destroy(). 1130 + */ 1131 + void xe_exec_queue_tlb_inval_last_fence_put_unlocked(struct xe_exec_queue *q, 1132 + unsigned int type) 1133 + { 1134 + xe_assert(q->vm->xe, type == XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT || 1135 + type == XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT); 1136 + 1137 + dma_fence_put(q->tlb_inval[type].last_fence); 1138 + q->tlb_inval[type].last_fence = NULL; 1139 + } 1140 + 1141 + /** 1142 + * xe_exec_queue_tlb_inval_last_fence_get() - Get last fence for TLB invalidation 1143 + * @q: The exec queue 1144 + * @vm: The VM the engine does a bind for 1145 + * @type: Either primary or media GT 1146 + * 1147 + * Get last fence, takes a ref 1148 + * 1149 + * Returns: last fence if not signaled, dma fence stub if signaled 1150 + */ 1151 + struct dma_fence *xe_exec_queue_tlb_inval_last_fence_get(struct xe_exec_queue *q, 1152 + struct xe_vm *vm, 1153 + unsigned int type) 1136 1154 { 1137 1155 struct dma_fence *fence; 1138 - int err = 0; 1139 1156 1140 - fence = xe_exec_queue_last_fence_get(q, vm); 1141 - if (fence) { 1142 - err = test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) ? 1143 - 0 : -ETIME; 1144 - dma_fence_put(fence); 1145 - } 1157 + xe_exec_queue_last_fence_lockdep_assert(q, vm); 1158 + xe_assert(vm->xe, type == XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT || 1159 + type == XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT); 1160 + xe_assert(vm->xe, q->flags & (EXEC_QUEUE_FLAG_VM | 1161 + EXEC_QUEUE_FLAG_MIGRATE)); 1146 1162 1147 - return err; 1163 + if (q->tlb_inval[type].last_fence && 1164 + test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, 1165 + &q->tlb_inval[type].last_fence->flags)) 1166 + xe_exec_queue_tlb_inval_last_fence_put(q, vm, type); 1167 + 1168 + fence = q->tlb_inval[type].last_fence ?: dma_fence_get_stub(); 1169 + dma_fence_get(fence); 1170 + return fence; 1171 + } 1172 + 1173 + /** 1174 + * xe_exec_queue_tlb_inval_last_fence_set() - Set last fence for TLB invalidation 1175 + * @q: The exec queue 1176 + * @vm: The VM the engine does a bind for 1177 + * @fence: The fence 1178 + * @type: Either primary or media GT 1179 + * 1180 + * Set the last fence for the tlb invalidation type on the queue. Increases 1181 + * reference count for fence, when closing queue 1182 + * xe_exec_queue_tlb_inval_last_fence_put should be called. 1183 + */ 1184 + void xe_exec_queue_tlb_inval_last_fence_set(struct xe_exec_queue *q, 1185 + struct xe_vm *vm, 1186 + struct dma_fence *fence, 1187 + unsigned int type) 1188 + { 1189 + xe_exec_queue_last_fence_lockdep_assert(q, vm); 1190 + xe_assert(vm->xe, type == XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT || 1191 + type == XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT); 1192 + xe_assert(vm->xe, q->flags & (EXEC_QUEUE_FLAG_VM | 1193 + EXEC_QUEUE_FLAG_MIGRATE)); 1194 + xe_assert(vm->xe, !dma_fence_is_container(fence)); 1195 + 1196 + xe_exec_queue_tlb_inval_last_fence_put(q, vm, type); 1197 + q->tlb_inval[type].last_fence = dma_fence_get(fence); 1148 1198 } 1149 1199 1150 1200 /**
+21 -2
drivers/gpu/drm/xe/xe_exec_queue.h
··· 14 14 struct xe_device; 15 15 struct xe_file; 16 16 17 + #define for_each_tlb_inval(__i) \ 18 + for (__i = XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT; \ 19 + __i <= XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT; ++__i) 20 + 17 21 struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *vm, 18 22 u32 logical_mask, u16 width, 19 23 struct xe_hw_engine *hw_engine, u32 flags, ··· 88 84 struct xe_vm *vm); 89 85 void xe_exec_queue_last_fence_set(struct xe_exec_queue *e, struct xe_vm *vm, 90 86 struct dma_fence *fence); 91 - int xe_exec_queue_last_fence_test_dep(struct xe_exec_queue *q, 92 - struct xe_vm *vm); 87 + 88 + void xe_exec_queue_tlb_inval_last_fence_put(struct xe_exec_queue *q, 89 + struct xe_vm *vm, 90 + unsigned int type); 91 + 92 + void xe_exec_queue_tlb_inval_last_fence_put_unlocked(struct xe_exec_queue *q, 93 + unsigned int type); 94 + 95 + struct dma_fence *xe_exec_queue_tlb_inval_last_fence_get(struct xe_exec_queue *q, 96 + struct xe_vm *vm, 97 + unsigned int type); 98 + 99 + void xe_exec_queue_tlb_inval_last_fence_set(struct xe_exec_queue *q, 100 + struct xe_vm *vm, 101 + struct dma_fence *fence, 102 + unsigned int type); 103 + 93 104 void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q); 94 105 95 106 int xe_exec_queue_contexts_hwsp_rebase(struct xe_exec_queue *q, void *scratch);
+17
drivers/gpu/drm/xe/xe_exec_queue_types.h
··· 15 15 #include "xe_hw_fence_types.h" 16 16 #include "xe_lrc_types.h" 17 17 18 + struct drm_syncobj; 18 19 struct xe_execlist_exec_queue; 19 20 struct xe_gt; 20 21 struct xe_guc_exec_queue; ··· 146 145 * dependency scheduler 147 146 */ 148 147 struct xe_dep_scheduler *dep_scheduler; 148 + /** 149 + * @last_fence: last fence for tlb invalidation, protected by 150 + * vm->lock in write mode 151 + */ 152 + struct dma_fence *last_fence; 149 153 } tlb_inval[XE_EXEC_QUEUE_TLB_INVAL_COUNT]; 150 154 151 155 /** @pxp: PXP info tracking */ ··· 161 155 struct list_head link; 162 156 } pxp; 163 157 158 + /** @ufence_syncobj: User fence syncobj */ 159 + struct drm_syncobj *ufence_syncobj; 160 + 161 + /** @ufence_timeline_value: User fence timeline value */ 162 + u64 ufence_timeline_value; 163 + 164 164 /** @ops: submission backend exec queue operations */ 165 165 const struct xe_exec_queue_ops *ops; 166 166 ··· 174 162 const struct xe_ring_ops *ring_ops; 175 163 /** @entity: DRM sched entity for this exec queue (1 to 1 relationship) */ 176 164 struct drm_sched_entity *entity; 165 + 166 + #define XE_MAX_JOB_COUNT_PER_EXEC_QUEUE 1000 167 + /** @job_cnt: number of drm jobs in this exec queue */ 168 + atomic_t job_cnt; 169 + 177 170 /** 178 171 * @tlb_flush_seqno: The seqno of the last rebind tlb flush performed 179 172 * Protected by @vm's resv. Unused if @vm == NULL.
+20 -24
drivers/gpu/drm/xe/xe_gt.c
··· 32 32 #include "xe_gt_freq.h" 33 33 #include "xe_gt_idle.h" 34 34 #include "xe_gt_mcr.h" 35 - #include "xe_gt_pagefault.h" 36 35 #include "xe_gt_printk.h" 37 36 #include "xe_gt_sriov_pf.h" 38 37 #include "xe_gt_sriov_vf.h" ··· 48 49 #include "xe_map.h" 49 50 #include "xe_migrate.h" 50 51 #include "xe_mmio.h" 52 + #include "xe_pagefault.h" 51 53 #include "xe_pat.h" 52 54 #include "xe_pm.h" 53 55 #include "xe_mocs.h" ··· 607 607 struct xe_gt *gt = arg; 608 608 int i; 609 609 610 + if (disable_work_sync(&gt->reset.worker)) 611 + /* 612 + * If gt_reset_worker was halted from executing, take care of 613 + * releasing the rpm reference here. 614 + */ 615 + xe_pm_runtime_put(gt_to_xe(gt)); 616 + 610 617 for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) 611 618 xe_hw_fence_irq_finish(&gt->fence_irq[i]); 612 619 ··· 641 634 return err; 642 635 643 636 err = gt_init_with_gt_forcewake(gt); 644 - if (err) 645 - return err; 646 - 647 - err = xe_gt_pagefault_init(gt); 648 637 if (err) 649 638 return err; 650 639 ··· 816 813 return 0; 817 814 } 818 815 819 - static int gt_reset(struct xe_gt *gt) 816 + static void gt_reset_worker(struct work_struct *w) 820 817 { 818 + struct xe_gt *gt = container_of(w, typeof(*gt), reset.worker); 821 819 unsigned int fw_ref; 822 820 int err; 823 821 824 - if (xe_device_wedged(gt_to_xe(gt))) { 825 - err = -ECANCELED; 822 + if (xe_device_wedged(gt_to_xe(gt))) 826 823 goto err_pm_put; 827 - } 828 824 829 825 /* We only support GT resets with GuC submission */ 830 - if (!xe_device_uc_enabled(gt_to_xe(gt))) { 831 - err = -ENODEV; 826 + if (!xe_device_uc_enabled(gt_to_xe(gt))) 832 827 goto err_pm_put; 833 - } 834 828 835 829 xe_gt_info(gt, "reset started\n"); 836 830 ··· 849 849 850 850 xe_uc_gucrc_disable(&gt->uc); 851 851 xe_uc_stop_prepare(&gt->uc); 852 - xe_gt_pagefault_reset(gt); 852 + xe_pagefault_reset(gt_to_xe(gt), gt); 853 853 854 854 xe_uc_stop(&gt->uc); 855 855 ··· 864 864 goto err_out; 865 865 866 866 xe_force_wake_put(gt_to_fw(gt), fw_ref); 867 + 868 + /* Pair with get while enqueueing the work in xe_gt_reset_async() */ 867 869 xe_pm_runtime_put(gt_to_xe(gt)); 868 870 869 871 xe_gt_info(gt, "reset done\n"); 870 872 871 - return 0; 873 + return; 872 874 873 875 err_out: 874 876 xe_force_wake_put(gt_to_fw(gt), fw_ref); 875 877 XE_WARN_ON(xe_uc_start(&gt->uc)); 878 + 876 879 err_fail: 877 880 xe_gt_err(gt, "reset failed (%pe)\n", ERR_PTR(err)); 878 - 879 881 xe_device_declare_wedged(gt_to_xe(gt)); 882 + 880 883 err_pm_put: 881 884 xe_pm_runtime_put(gt_to_xe(gt)); 882 - 883 - return err; 884 - } 885 - 886 - static void gt_reset_worker(struct work_struct *w) 887 - { 888 - struct xe_gt *gt = container_of(w, typeof(*gt), reset.worker); 889 - 890 - gt_reset(gt); 891 885 } 892 886 893 887 void xe_gt_reset_async(struct xe_gt *gt) ··· 893 899 return; 894 900 895 901 xe_gt_info(gt, "reset queued\n"); 902 + 903 + /* Pair with put in gt_reset_worker() if work is enqueued */ 896 904 xe_pm_runtime_get_noresume(gt_to_xe(gt)); 897 905 if (!queue_work(gt->ordered_wq, &gt->reset.worker)) 898 906 xe_pm_runtime_put(gt_to_xe(gt));
+16 -14
drivers/gpu/drm/xe/xe_gt_freq.c
··· 29 29 * PCODE is the ultimate decision maker of the actual running frequency, based 30 30 * on thermal and other running conditions. 31 31 * 32 - * Xe's Freq provides a sysfs API for frequency management: 32 + * Xe's Freq provides a sysfs API for frequency management under 33 + * ``<device>/tile#/gt#/freq0/`` directory. 33 34 * 34 - * device/tile#/gt#/freq0/<item>_freq *read-only* files: 35 + * **Read-only** attributes: 35 36 * 36 - * - act_freq: The actual resolved frequency decided by PCODE. 37 - * - cur_freq: The current one requested by GuC PC to the PCODE. 38 - * - rpn_freq: The Render Performance (RP) N level, which is the minimal one. 39 - * - rpa_freq: The Render Performance (RP) A level, which is the achievable one. 40 - * Calculated by PCODE at runtime based on multiple running conditions 41 - * - rpe_freq: The Render Performance (RP) E level, which is the efficient one. 42 - * Calculated by PCODE at runtime based on multiple running conditions 43 - * - rp0_freq: The Render Performance (RP) 0 level, which is the maximum one. 37 + * - ``act_freq``: The actual resolved frequency decided by PCODE. 38 + * - ``cur_freq``: The current one requested by GuC PC to the PCODE. 39 + * - ``rpn_freq``: The Render Performance (RP) N level, which is the minimal one. 40 + * - ``rpa_freq``: The Render Performance (RP) A level, which is the achievable one. 41 + * Calculated by PCODE at runtime based on multiple running conditions 42 + * - ``rpe_freq``: The Render Performance (RP) E level, which is the efficient one. 43 + * Calculated by PCODE at runtime based on multiple running conditions 44 + * - ``rp0_freq``: The Render Performance (RP) 0 level, which is the maximum one. 44 45 * 45 - * device/tile#/gt#/freq0/<item>_freq *read-write* files: 46 + * **Read-write** attributes: 46 47 * 47 - * - min_freq: Min frequency request. 48 - * - max_freq: Max frequency request. 49 - * If max <= min, then freq_min becomes a fixed frequency request. 48 + * - ``min_freq``: Min frequency request. 49 + * - ``max_freq``: Max frequency request. 50 + * If max <= min, then freq_min becomes a fixed frequency 51 + * request. 50 52 */ 51 53 52 54 static struct xe_guc_pc *
-679
drivers/gpu/drm/xe/xe_gt_pagefault.c
··· 1 - // SPDX-License-Identifier: MIT 2 - /* 3 - * Copyright © 2022 Intel Corporation 4 - */ 5 - 6 - #include "xe_gt_pagefault.h" 7 - 8 - #include <linux/bitfield.h> 9 - #include <linux/circ_buf.h> 10 - 11 - #include <drm/drm_exec.h> 12 - #include <drm/drm_managed.h> 13 - 14 - #include "abi/guc_actions_abi.h" 15 - #include "xe_bo.h" 16 - #include "xe_gt.h" 17 - #include "xe_gt_printk.h" 18 - #include "xe_gt_stats.h" 19 - #include "xe_guc.h" 20 - #include "xe_guc_ct.h" 21 - #include "xe_migrate.h" 22 - #include "xe_svm.h" 23 - #include "xe_trace_bo.h" 24 - #include "xe_vm.h" 25 - #include "xe_vram_types.h" 26 - 27 - struct pagefault { 28 - u64 page_addr; 29 - u32 asid; 30 - u16 pdata; 31 - u8 vfid; 32 - u8 access_type; 33 - u8 fault_type; 34 - u8 fault_level; 35 - u8 engine_class; 36 - u8 engine_instance; 37 - u8 fault_unsuccessful; 38 - bool trva_fault; 39 - }; 40 - 41 - enum access_type { 42 - ACCESS_TYPE_READ = 0, 43 - ACCESS_TYPE_WRITE = 1, 44 - ACCESS_TYPE_ATOMIC = 2, 45 - ACCESS_TYPE_RESERVED = 3, 46 - }; 47 - 48 - enum fault_type { 49 - NOT_PRESENT = 0, 50 - WRITE_ACCESS_VIOLATION = 1, 51 - ATOMIC_ACCESS_VIOLATION = 2, 52 - }; 53 - 54 - struct acc { 55 - u64 va_range_base; 56 - u32 asid; 57 - u32 sub_granularity; 58 - u8 granularity; 59 - u8 vfid; 60 - u8 access_type; 61 - u8 engine_class; 62 - u8 engine_instance; 63 - }; 64 - 65 - static bool access_is_atomic(enum access_type access_type) 66 - { 67 - return access_type == ACCESS_TYPE_ATOMIC; 68 - } 69 - 70 - static bool vma_is_valid(struct xe_tile *tile, struct xe_vma *vma) 71 - { 72 - return xe_vm_has_valid_gpu_mapping(tile, vma->tile_present, 73 - vma->tile_invalidated); 74 - } 75 - 76 - static int xe_pf_begin(struct drm_exec *exec, struct xe_vma *vma, 77 - bool need_vram_move, struct xe_vram_region *vram) 78 - { 79 - struct xe_bo *bo = xe_vma_bo(vma); 80 - struct xe_vm *vm = xe_vma_vm(vma); 81 - int err; 82 - 83 - err = xe_vm_lock_vma(exec, vma); 84 - if (err) 85 - return err; 86 - 87 - if (!bo) 88 - return 0; 89 - 90 - return need_vram_move ? xe_bo_migrate(bo, vram->placement, NULL, exec) : 91 - xe_bo_validate(bo, vm, true, exec); 92 - } 93 - 94 - static int handle_vma_pagefault(struct xe_gt *gt, struct xe_vma *vma, 95 - bool atomic) 96 - { 97 - struct xe_vm *vm = xe_vma_vm(vma); 98 - struct xe_tile *tile = gt_to_tile(gt); 99 - struct xe_validation_ctx ctx; 100 - struct drm_exec exec; 101 - struct dma_fence *fence; 102 - int err, needs_vram; 103 - 104 - lockdep_assert_held_write(&vm->lock); 105 - 106 - needs_vram = xe_vma_need_vram_for_atomic(vm->xe, vma, atomic); 107 - if (needs_vram < 0 || (needs_vram && xe_vma_is_userptr(vma))) 108 - return needs_vram < 0 ? needs_vram : -EACCES; 109 - 110 - xe_gt_stats_incr(gt, XE_GT_STATS_ID_VMA_PAGEFAULT_COUNT, 1); 111 - xe_gt_stats_incr(gt, XE_GT_STATS_ID_VMA_PAGEFAULT_KB, xe_vma_size(vma) / 1024); 112 - 113 - trace_xe_vma_pagefault(vma); 114 - 115 - /* Check if VMA is valid, opportunistic check only */ 116 - if (vma_is_valid(tile, vma) && !atomic) 117 - return 0; 118 - 119 - retry_userptr: 120 - if (xe_vma_is_userptr(vma) && 121 - xe_vma_userptr_check_repin(to_userptr_vma(vma))) { 122 - struct xe_userptr_vma *uvma = to_userptr_vma(vma); 123 - 124 - err = xe_vma_userptr_pin_pages(uvma); 125 - if (err) 126 - return err; 127 - } 128 - 129 - /* Lock VM and BOs dma-resv */ 130 - xe_validation_ctx_init(&ctx, &vm->xe->val, &exec, (struct xe_val_flags) {}); 131 - drm_exec_until_all_locked(&exec) { 132 - err = xe_pf_begin(&exec, vma, needs_vram == 1, tile->mem.vram); 133 - drm_exec_retry_on_contention(&exec); 134 - xe_validation_retry_on_oom(&ctx, &err); 135 - if (err) 136 - goto unlock_dma_resv; 137 - 138 - /* Bind VMA only to the GT that has faulted */ 139 - trace_xe_vma_pf_bind(vma); 140 - xe_vm_set_validation_exec(vm, &exec); 141 - fence = xe_vma_rebind(vm, vma, BIT(tile->id)); 142 - xe_vm_set_validation_exec(vm, NULL); 143 - if (IS_ERR(fence)) { 144 - err = PTR_ERR(fence); 145 - xe_validation_retry_on_oom(&ctx, &err); 146 - goto unlock_dma_resv; 147 - } 148 - } 149 - 150 - dma_fence_wait(fence, false); 151 - dma_fence_put(fence); 152 - 153 - unlock_dma_resv: 154 - xe_validation_ctx_fini(&ctx); 155 - if (err == -EAGAIN) 156 - goto retry_userptr; 157 - 158 - return err; 159 - } 160 - 161 - static struct xe_vm *asid_to_vm(struct xe_device *xe, u32 asid) 162 - { 163 - struct xe_vm *vm; 164 - 165 - down_read(&xe->usm.lock); 166 - vm = xa_load(&xe->usm.asid_to_vm, asid); 167 - if (vm && xe_vm_in_fault_mode(vm)) 168 - xe_vm_get(vm); 169 - else 170 - vm = ERR_PTR(-EINVAL); 171 - up_read(&xe->usm.lock); 172 - 173 - return vm; 174 - } 175 - 176 - static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf) 177 - { 178 - struct xe_device *xe = gt_to_xe(gt); 179 - struct xe_vm *vm; 180 - struct xe_vma *vma = NULL; 181 - int err; 182 - bool atomic; 183 - 184 - /* SW isn't expected to handle TRTT faults */ 185 - if (pf->trva_fault) 186 - return -EFAULT; 187 - 188 - vm = asid_to_vm(xe, pf->asid); 189 - if (IS_ERR(vm)) 190 - return PTR_ERR(vm); 191 - 192 - /* 193 - * TODO: Change to read lock? Using write lock for simplicity. 194 - */ 195 - down_write(&vm->lock); 196 - 197 - if (xe_vm_is_closed(vm)) { 198 - err = -ENOENT; 199 - goto unlock_vm; 200 - } 201 - 202 - vma = xe_vm_find_vma_by_addr(vm, pf->page_addr); 203 - if (!vma) { 204 - err = -EINVAL; 205 - goto unlock_vm; 206 - } 207 - 208 - atomic = access_is_atomic(pf->access_type); 209 - 210 - if (xe_vma_is_cpu_addr_mirror(vma)) 211 - err = xe_svm_handle_pagefault(vm, vma, gt, 212 - pf->page_addr, atomic); 213 - else 214 - err = handle_vma_pagefault(gt, vma, atomic); 215 - 216 - unlock_vm: 217 - if (!err) 218 - vm->usm.last_fault_vma = vma; 219 - up_write(&vm->lock); 220 - xe_vm_put(vm); 221 - 222 - return err; 223 - } 224 - 225 - static int send_pagefault_reply(struct xe_guc *guc, 226 - struct xe_guc_pagefault_reply *reply) 227 - { 228 - u32 action[] = { 229 - XE_GUC_ACTION_PAGE_FAULT_RES_DESC, 230 - reply->dw0, 231 - reply->dw1, 232 - }; 233 - 234 - return xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0); 235 - } 236 - 237 - static void print_pagefault(struct xe_gt *gt, struct pagefault *pf) 238 - { 239 - xe_gt_dbg(gt, "\n\tASID: %d\n" 240 - "\tVFID: %d\n" 241 - "\tPDATA: 0x%04x\n" 242 - "\tFaulted Address: 0x%08x%08x\n" 243 - "\tFaultType: %d\n" 244 - "\tAccessType: %d\n" 245 - "\tFaultLevel: %d\n" 246 - "\tEngineClass: %d %s\n" 247 - "\tEngineInstance: %d\n", 248 - pf->asid, pf->vfid, pf->pdata, upper_32_bits(pf->page_addr), 249 - lower_32_bits(pf->page_addr), 250 - pf->fault_type, pf->access_type, pf->fault_level, 251 - pf->engine_class, xe_hw_engine_class_to_str(pf->engine_class), 252 - pf->engine_instance); 253 - } 254 - 255 - #define PF_MSG_LEN_DW 4 256 - 257 - static bool get_pagefault(struct pf_queue *pf_queue, struct pagefault *pf) 258 - { 259 - const struct xe_guc_pagefault_desc *desc; 260 - bool ret = false; 261 - 262 - spin_lock_irq(&pf_queue->lock); 263 - if (pf_queue->tail != pf_queue->head) { 264 - desc = (const struct xe_guc_pagefault_desc *) 265 - (pf_queue->data + pf_queue->tail); 266 - 267 - pf->fault_level = FIELD_GET(PFD_FAULT_LEVEL, desc->dw0); 268 - pf->trva_fault = FIELD_GET(XE2_PFD_TRVA_FAULT, desc->dw0); 269 - pf->engine_class = FIELD_GET(PFD_ENG_CLASS, desc->dw0); 270 - pf->engine_instance = FIELD_GET(PFD_ENG_INSTANCE, desc->dw0); 271 - pf->pdata = FIELD_GET(PFD_PDATA_HI, desc->dw1) << 272 - PFD_PDATA_HI_SHIFT; 273 - pf->pdata |= FIELD_GET(PFD_PDATA_LO, desc->dw0); 274 - pf->asid = FIELD_GET(PFD_ASID, desc->dw1); 275 - pf->vfid = FIELD_GET(PFD_VFID, desc->dw2); 276 - pf->access_type = FIELD_GET(PFD_ACCESS_TYPE, desc->dw2); 277 - pf->fault_type = FIELD_GET(PFD_FAULT_TYPE, desc->dw2); 278 - pf->page_addr = (u64)(FIELD_GET(PFD_VIRTUAL_ADDR_HI, desc->dw3)) << 279 - PFD_VIRTUAL_ADDR_HI_SHIFT; 280 - pf->page_addr |= FIELD_GET(PFD_VIRTUAL_ADDR_LO, desc->dw2) << 281 - PFD_VIRTUAL_ADDR_LO_SHIFT; 282 - 283 - pf_queue->tail = (pf_queue->tail + PF_MSG_LEN_DW) % 284 - pf_queue->num_dw; 285 - ret = true; 286 - } 287 - spin_unlock_irq(&pf_queue->lock); 288 - 289 - return ret; 290 - } 291 - 292 - static bool pf_queue_full(struct pf_queue *pf_queue) 293 - { 294 - lockdep_assert_held(&pf_queue->lock); 295 - 296 - return CIRC_SPACE(pf_queue->head, pf_queue->tail, 297 - pf_queue->num_dw) <= 298 - PF_MSG_LEN_DW; 299 - } 300 - 301 - int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len) 302 - { 303 - struct xe_gt *gt = guc_to_gt(guc); 304 - struct pf_queue *pf_queue; 305 - unsigned long flags; 306 - u32 asid; 307 - bool full; 308 - 309 - if (unlikely(len != PF_MSG_LEN_DW)) 310 - return -EPROTO; 311 - 312 - asid = FIELD_GET(PFD_ASID, msg[1]); 313 - pf_queue = gt->usm.pf_queue + (asid % NUM_PF_QUEUE); 314 - 315 - /* 316 - * The below logic doesn't work unless PF_QUEUE_NUM_DW % PF_MSG_LEN_DW == 0 317 - */ 318 - xe_gt_assert(gt, !(pf_queue->num_dw % PF_MSG_LEN_DW)); 319 - 320 - spin_lock_irqsave(&pf_queue->lock, flags); 321 - full = pf_queue_full(pf_queue); 322 - if (!full) { 323 - memcpy(pf_queue->data + pf_queue->head, msg, len * sizeof(u32)); 324 - pf_queue->head = (pf_queue->head + len) % 325 - pf_queue->num_dw; 326 - queue_work(gt->usm.pf_wq, &pf_queue->worker); 327 - } else { 328 - xe_gt_warn(gt, "PageFault Queue full, shouldn't be possible\n"); 329 - } 330 - spin_unlock_irqrestore(&pf_queue->lock, flags); 331 - 332 - return full ? -ENOSPC : 0; 333 - } 334 - 335 - #define USM_QUEUE_MAX_RUNTIME_MS 20 336 - 337 - static void pf_queue_work_func(struct work_struct *w) 338 - { 339 - struct pf_queue *pf_queue = container_of(w, struct pf_queue, worker); 340 - struct xe_gt *gt = pf_queue->gt; 341 - struct xe_guc_pagefault_reply reply = {}; 342 - struct pagefault pf = {}; 343 - unsigned long threshold; 344 - int ret; 345 - 346 - threshold = jiffies + msecs_to_jiffies(USM_QUEUE_MAX_RUNTIME_MS); 347 - 348 - while (get_pagefault(pf_queue, &pf)) { 349 - ret = handle_pagefault(gt, &pf); 350 - if (unlikely(ret)) { 351 - print_pagefault(gt, &pf); 352 - pf.fault_unsuccessful = 1; 353 - xe_gt_dbg(gt, "Fault response: Unsuccessful %pe\n", ERR_PTR(ret)); 354 - } 355 - 356 - reply.dw0 = FIELD_PREP(PFR_VALID, 1) | 357 - FIELD_PREP(PFR_SUCCESS, pf.fault_unsuccessful) | 358 - FIELD_PREP(PFR_REPLY, PFR_ACCESS) | 359 - FIELD_PREP(PFR_DESC_TYPE, FAULT_RESPONSE_DESC) | 360 - FIELD_PREP(PFR_ASID, pf.asid); 361 - 362 - reply.dw1 = FIELD_PREP(PFR_VFID, pf.vfid) | 363 - FIELD_PREP(PFR_ENG_INSTANCE, pf.engine_instance) | 364 - FIELD_PREP(PFR_ENG_CLASS, pf.engine_class) | 365 - FIELD_PREP(PFR_PDATA, pf.pdata); 366 - 367 - send_pagefault_reply(&gt->uc.guc, &reply); 368 - 369 - if (time_after(jiffies, threshold) && 370 - pf_queue->tail != pf_queue->head) { 371 - queue_work(gt->usm.pf_wq, w); 372 - break; 373 - } 374 - } 375 - } 376 - 377 - static void acc_queue_work_func(struct work_struct *w); 378 - 379 - static void pagefault_fini(void *arg) 380 - { 381 - struct xe_gt *gt = arg; 382 - struct xe_device *xe = gt_to_xe(gt); 383 - 384 - if (!xe->info.has_usm) 385 - return; 386 - 387 - destroy_workqueue(gt->usm.acc_wq); 388 - destroy_workqueue(gt->usm.pf_wq); 389 - } 390 - 391 - static int xe_alloc_pf_queue(struct xe_gt *gt, struct pf_queue *pf_queue) 392 - { 393 - struct xe_device *xe = gt_to_xe(gt); 394 - xe_dss_mask_t all_dss; 395 - int num_dss, num_eus; 396 - 397 - bitmap_or(all_dss, gt->fuse_topo.g_dss_mask, gt->fuse_topo.c_dss_mask, 398 - XE_MAX_DSS_FUSE_BITS); 399 - 400 - num_dss = bitmap_weight(all_dss, XE_MAX_DSS_FUSE_BITS); 401 - num_eus = bitmap_weight(gt->fuse_topo.eu_mask_per_dss, 402 - XE_MAX_EU_FUSE_BITS) * num_dss; 403 - 404 - /* 405 - * user can issue separate page faults per EU and per CS 406 - * 407 - * XXX: Multiplier required as compute UMD are getting PF queue errors 408 - * without it. Follow on why this multiplier is required. 409 - */ 410 - #define PF_MULTIPLIER 8 411 - pf_queue->num_dw = 412 - (num_eus + XE_NUM_HW_ENGINES) * PF_MSG_LEN_DW * PF_MULTIPLIER; 413 - pf_queue->num_dw = roundup_pow_of_two(pf_queue->num_dw); 414 - #undef PF_MULTIPLIER 415 - 416 - pf_queue->gt = gt; 417 - pf_queue->data = devm_kcalloc(xe->drm.dev, pf_queue->num_dw, 418 - sizeof(u32), GFP_KERNEL); 419 - if (!pf_queue->data) 420 - return -ENOMEM; 421 - 422 - spin_lock_init(&pf_queue->lock); 423 - INIT_WORK(&pf_queue->worker, pf_queue_work_func); 424 - 425 - return 0; 426 - } 427 - 428 - int xe_gt_pagefault_init(struct xe_gt *gt) 429 - { 430 - struct xe_device *xe = gt_to_xe(gt); 431 - int i, ret = 0; 432 - 433 - if (!xe->info.has_usm) 434 - return 0; 435 - 436 - for (i = 0; i < NUM_PF_QUEUE; ++i) { 437 - ret = xe_alloc_pf_queue(gt, &gt->usm.pf_queue[i]); 438 - if (ret) 439 - return ret; 440 - } 441 - for (i = 0; i < NUM_ACC_QUEUE; ++i) { 442 - gt->usm.acc_queue[i].gt = gt; 443 - spin_lock_init(&gt->usm.acc_queue[i].lock); 444 - INIT_WORK(&gt->usm.acc_queue[i].worker, acc_queue_work_func); 445 - } 446 - 447 - gt->usm.pf_wq = alloc_workqueue("xe_gt_page_fault_work_queue", 448 - WQ_UNBOUND | WQ_HIGHPRI, NUM_PF_QUEUE); 449 - if (!gt->usm.pf_wq) 450 - return -ENOMEM; 451 - 452 - gt->usm.acc_wq = alloc_workqueue("xe_gt_access_counter_work_queue", 453 - WQ_UNBOUND | WQ_HIGHPRI, 454 - NUM_ACC_QUEUE); 455 - if (!gt->usm.acc_wq) { 456 - destroy_workqueue(gt->usm.pf_wq); 457 - return -ENOMEM; 458 - } 459 - 460 - return devm_add_action_or_reset(xe->drm.dev, pagefault_fini, gt); 461 - } 462 - 463 - void xe_gt_pagefault_reset(struct xe_gt *gt) 464 - { 465 - struct xe_device *xe = gt_to_xe(gt); 466 - int i; 467 - 468 - if (!xe->info.has_usm) 469 - return; 470 - 471 - for (i = 0; i < NUM_PF_QUEUE; ++i) { 472 - spin_lock_irq(&gt->usm.pf_queue[i].lock); 473 - gt->usm.pf_queue[i].head = 0; 474 - gt->usm.pf_queue[i].tail = 0; 475 - spin_unlock_irq(&gt->usm.pf_queue[i].lock); 476 - } 477 - 478 - for (i = 0; i < NUM_ACC_QUEUE; ++i) { 479 - spin_lock(&gt->usm.acc_queue[i].lock); 480 - gt->usm.acc_queue[i].head = 0; 481 - gt->usm.acc_queue[i].tail = 0; 482 - spin_unlock(&gt->usm.acc_queue[i].lock); 483 - } 484 - } 485 - 486 - static int granularity_in_byte(int val) 487 - { 488 - switch (val) { 489 - case 0: 490 - return SZ_128K; 491 - case 1: 492 - return SZ_2M; 493 - case 2: 494 - return SZ_16M; 495 - case 3: 496 - return SZ_64M; 497 - default: 498 - return 0; 499 - } 500 - } 501 - 502 - static int sub_granularity_in_byte(int val) 503 - { 504 - return (granularity_in_byte(val) / 32); 505 - } 506 - 507 - static void print_acc(struct xe_gt *gt, struct acc *acc) 508 - { 509 - xe_gt_warn(gt, "Access counter request:\n" 510 - "\tType: %s\n" 511 - "\tASID: %d\n" 512 - "\tVFID: %d\n" 513 - "\tEngine: %d:%d\n" 514 - "\tGranularity: 0x%x KB Region/ %d KB sub-granularity\n" 515 - "\tSub_Granularity Vector: 0x%08x\n" 516 - "\tVA Range base: 0x%016llx\n", 517 - acc->access_type ? "AC_NTFY_VAL" : "AC_TRIG_VAL", 518 - acc->asid, acc->vfid, acc->engine_class, acc->engine_instance, 519 - granularity_in_byte(acc->granularity) / SZ_1K, 520 - sub_granularity_in_byte(acc->granularity) / SZ_1K, 521 - acc->sub_granularity, acc->va_range_base); 522 - } 523 - 524 - static struct xe_vma *get_acc_vma(struct xe_vm *vm, struct acc *acc) 525 - { 526 - u64 page_va = acc->va_range_base + (ffs(acc->sub_granularity) - 1) * 527 - sub_granularity_in_byte(acc->granularity); 528 - 529 - return xe_vm_find_overlapping_vma(vm, page_va, SZ_4K); 530 - } 531 - 532 - static int handle_acc(struct xe_gt *gt, struct acc *acc) 533 - { 534 - struct xe_device *xe = gt_to_xe(gt); 535 - struct xe_tile *tile = gt_to_tile(gt); 536 - struct xe_validation_ctx ctx; 537 - struct drm_exec exec; 538 - struct xe_vm *vm; 539 - struct xe_vma *vma; 540 - int ret = 0; 541 - 542 - /* We only support ACC_TRIGGER at the moment */ 543 - if (acc->access_type != ACC_TRIGGER) 544 - return -EINVAL; 545 - 546 - vm = asid_to_vm(xe, acc->asid); 547 - if (IS_ERR(vm)) 548 - return PTR_ERR(vm); 549 - 550 - down_read(&vm->lock); 551 - 552 - /* Lookup VMA */ 553 - vma = get_acc_vma(vm, acc); 554 - if (!vma) { 555 - ret = -EINVAL; 556 - goto unlock_vm; 557 - } 558 - 559 - trace_xe_vma_acc(vma); 560 - 561 - /* Userptr or null can't be migrated, nothing to do */ 562 - if (xe_vma_has_no_bo(vma)) 563 - goto unlock_vm; 564 - 565 - /* Lock VM and BOs dma-resv */ 566 - xe_validation_ctx_init(&ctx, &vm->xe->val, &exec, (struct xe_val_flags) {}); 567 - drm_exec_until_all_locked(&exec) { 568 - ret = xe_pf_begin(&exec, vma, IS_DGFX(vm->xe), tile->mem.vram); 569 - drm_exec_retry_on_contention(&exec); 570 - xe_validation_retry_on_oom(&ctx, &ret); 571 - } 572 - 573 - xe_validation_ctx_fini(&ctx); 574 - unlock_vm: 575 - up_read(&vm->lock); 576 - xe_vm_put(vm); 577 - 578 - return ret; 579 - } 580 - 581 - #define make_u64(hi__, low__) ((u64)(hi__) << 32 | (u64)(low__)) 582 - 583 - #define ACC_MSG_LEN_DW 4 584 - 585 - static bool get_acc(struct acc_queue *acc_queue, struct acc *acc) 586 - { 587 - const struct xe_guc_acc_desc *desc; 588 - bool ret = false; 589 - 590 - spin_lock(&acc_queue->lock); 591 - if (acc_queue->tail != acc_queue->head) { 592 - desc = (const struct xe_guc_acc_desc *) 593 - (acc_queue->data + acc_queue->tail); 594 - 595 - acc->granularity = FIELD_GET(ACC_GRANULARITY, desc->dw2); 596 - acc->sub_granularity = FIELD_GET(ACC_SUBG_HI, desc->dw1) << 31 | 597 - FIELD_GET(ACC_SUBG_LO, desc->dw0); 598 - acc->engine_class = FIELD_GET(ACC_ENG_CLASS, desc->dw1); 599 - acc->engine_instance = FIELD_GET(ACC_ENG_INSTANCE, desc->dw1); 600 - acc->asid = FIELD_GET(ACC_ASID, desc->dw1); 601 - acc->vfid = FIELD_GET(ACC_VFID, desc->dw2); 602 - acc->access_type = FIELD_GET(ACC_TYPE, desc->dw0); 603 - acc->va_range_base = make_u64(desc->dw3 & ACC_VIRTUAL_ADDR_RANGE_HI, 604 - desc->dw2 & ACC_VIRTUAL_ADDR_RANGE_LO); 605 - 606 - acc_queue->tail = (acc_queue->tail + ACC_MSG_LEN_DW) % 607 - ACC_QUEUE_NUM_DW; 608 - ret = true; 609 - } 610 - spin_unlock(&acc_queue->lock); 611 - 612 - return ret; 613 - } 614 - 615 - static void acc_queue_work_func(struct work_struct *w) 616 - { 617 - struct acc_queue *acc_queue = container_of(w, struct acc_queue, worker); 618 - struct xe_gt *gt = acc_queue->gt; 619 - struct acc acc = {}; 620 - unsigned long threshold; 621 - int ret; 622 - 623 - threshold = jiffies + msecs_to_jiffies(USM_QUEUE_MAX_RUNTIME_MS); 624 - 625 - while (get_acc(acc_queue, &acc)) { 626 - ret = handle_acc(gt, &acc); 627 - if (unlikely(ret)) { 628 - print_acc(gt, &acc); 629 - xe_gt_warn(gt, "ACC: Unsuccessful %pe\n", ERR_PTR(ret)); 630 - } 631 - 632 - if (time_after(jiffies, threshold) && 633 - acc_queue->tail != acc_queue->head) { 634 - queue_work(gt->usm.acc_wq, w); 635 - break; 636 - } 637 - } 638 - } 639 - 640 - static bool acc_queue_full(struct acc_queue *acc_queue) 641 - { 642 - lockdep_assert_held(&acc_queue->lock); 643 - 644 - return CIRC_SPACE(acc_queue->head, acc_queue->tail, ACC_QUEUE_NUM_DW) <= 645 - ACC_MSG_LEN_DW; 646 - } 647 - 648 - int xe_guc_access_counter_notify_handler(struct xe_guc *guc, u32 *msg, u32 len) 649 - { 650 - struct xe_gt *gt = guc_to_gt(guc); 651 - struct acc_queue *acc_queue; 652 - u32 asid; 653 - bool full; 654 - 655 - /* 656 - * The below logic doesn't work unless ACC_QUEUE_NUM_DW % ACC_MSG_LEN_DW == 0 657 - */ 658 - BUILD_BUG_ON(ACC_QUEUE_NUM_DW % ACC_MSG_LEN_DW); 659 - 660 - if (unlikely(len != ACC_MSG_LEN_DW)) 661 - return -EPROTO; 662 - 663 - asid = FIELD_GET(ACC_ASID, msg[1]); 664 - acc_queue = &gt->usm.acc_queue[asid % NUM_ACC_QUEUE]; 665 - 666 - spin_lock(&acc_queue->lock); 667 - full = acc_queue_full(acc_queue); 668 - if (!full) { 669 - memcpy(acc_queue->data + acc_queue->head, msg, 670 - len * sizeof(u32)); 671 - acc_queue->head = (acc_queue->head + len) % ACC_QUEUE_NUM_DW; 672 - queue_work(gt->usm.acc_wq, &acc_queue->worker); 673 - } else { 674 - xe_gt_warn(gt, "ACC Queue full, dropping ACC\n"); 675 - } 676 - spin_unlock(&acc_queue->lock); 677 - 678 - return full ? -ENOSPC : 0; 679 - }
-19
drivers/gpu/drm/xe/xe_gt_pagefault.h
··· 1 - /* SPDX-License-Identifier: MIT */ 2 - /* 3 - * Copyright © 2022 Intel Corporation 4 - */ 5 - 6 - #ifndef _XE_GT_PAGEFAULT_H_ 7 - #define _XE_GT_PAGEFAULT_H_ 8 - 9 - #include <linux/types.h> 10 - 11 - struct xe_gt; 12 - struct xe_guc; 13 - 14 - int xe_gt_pagefault_init(struct xe_gt *gt); 15 - void xe_gt_pagefault_reset(struct xe_gt *gt); 16 - int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len); 17 - int xe_guc_access_counter_notify_handler(struct xe_guc *guc, u32 *msg, u32 len); 18 - 19 - #endif /* _XE_GT_PAGEFAULT_ */
+165 -43
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
··· 924 924 const char *what, const char *(*unit)(u32), 925 925 unsigned int last, int err) 926 926 { 927 - xe_gt_assert(gt, first); 927 + char name[8]; 928 + 928 929 xe_gt_assert(gt, num_vfs); 929 930 xe_gt_assert(gt, first <= last); 930 931 ··· 933 932 return pf_config_set_u32_done(gt, first, value, get(gt, first), what, unit, err); 934 933 935 934 if (unlikely(err)) { 936 - xe_gt_sriov_notice(gt, "Failed to bulk provision VF%u..VF%u with %s\n", 937 - first, first + num_vfs - 1, what); 935 + xe_gt_sriov_notice(gt, "Failed to bulk provision %s..VF%u with %s\n", 936 + xe_sriov_function_name(first, name, sizeof(name)), 937 + first + num_vfs - 1, what); 938 938 if (last > first) 939 939 pf_config_bulk_set_u32_done(gt, first, last - first, value, 940 940 get, what, unit, last, 0); ··· 944 942 945 943 /* pick actual value from first VF - bulk provisioning shall be equal across all VFs */ 946 944 value = get(gt, first); 947 - xe_gt_sriov_info(gt, "VF%u..VF%u provisioned with %u%s %s\n", 948 - first, first + num_vfs - 1, value, unit(value), what); 945 + xe_gt_sriov_info(gt, "%s..VF%u provisioned with %u%s %s\n", 946 + xe_sriov_function_name(first, name, sizeof(name)), 947 + first + num_vfs - 1, value, unit(value), what); 949 948 return 0; 950 949 } 951 950 ··· 1727 1724 return 0; 1728 1725 } 1729 1726 1730 - static int pf_get_exec_quantum(struct xe_gt *gt, unsigned int vfid) 1727 + static u32 pf_get_exec_quantum(struct xe_gt *gt, unsigned int vfid) 1731 1728 { 1732 1729 struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); 1733 1730 ··· 1735 1732 } 1736 1733 1737 1734 /** 1738 - * xe_gt_sriov_pf_config_set_exec_quantum - Configure execution quantum for the VF. 1735 + * xe_gt_sriov_pf_config_set_exec_quantum_locked() - Configure PF/VF execution quantum. 1739 1736 * @gt: the &xe_gt 1740 - * @vfid: the VF identifier 1737 + * @vfid: the PF or VF identifier 1738 + * @exec_quantum: requested execution quantum in milliseconds (0 is infinity) 1739 + * 1740 + * This function can only be called on PF with the master mutex hold. 1741 + * It will log the provisioned value or an error in case of the failure. 1742 + * 1743 + * Return: 0 on success or a negative error code on failure. 1744 + */ 1745 + int xe_gt_sriov_pf_config_set_exec_quantum_locked(struct xe_gt *gt, unsigned int vfid, 1746 + u32 exec_quantum) 1747 + { 1748 + int err; 1749 + 1750 + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 1751 + 1752 + err = pf_provision_exec_quantum(gt, vfid, exec_quantum); 1753 + 1754 + return pf_config_set_u32_done(gt, vfid, exec_quantum, 1755 + pf_get_exec_quantum(gt, vfid), 1756 + "execution quantum", exec_quantum_unit, err); 1757 + } 1758 + 1759 + /** 1760 + * xe_gt_sriov_pf_config_set_exec_quantum() - Configure PF/VF execution quantum. 1761 + * @gt: the &xe_gt 1762 + * @vfid: the PF or VF identifier 1741 1763 * @exec_quantum: requested execution quantum in milliseconds (0 is infinity) 1742 1764 * 1743 1765 * This function can only be called on PF. 1766 + * It will log the provisioned value or an error in case of the failure. 1744 1767 * 1745 1768 * Return: 0 on success or a negative error code on failure. 1746 1769 */ 1747 1770 int xe_gt_sriov_pf_config_set_exec_quantum(struct xe_gt *gt, unsigned int vfid, 1748 1771 u32 exec_quantum) 1749 1772 { 1750 - int err; 1773 + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); 1751 1774 1752 - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 1753 - err = pf_provision_exec_quantum(gt, vfid, exec_quantum); 1754 - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 1755 - 1756 - return pf_config_set_u32_done(gt, vfid, exec_quantum, 1757 - xe_gt_sriov_pf_config_get_exec_quantum(gt, vfid), 1758 - "execution quantum", exec_quantum_unit, err); 1775 + return xe_gt_sriov_pf_config_set_exec_quantum_locked(gt, vfid, exec_quantum); 1759 1776 } 1760 1777 1761 1778 /** 1762 - * xe_gt_sriov_pf_config_get_exec_quantum - Get VF's execution quantum. 1779 + * xe_gt_sriov_pf_config_get_exec_quantum_locked() - Get PF/VF execution quantum. 1763 1780 * @gt: the &xe_gt 1764 - * @vfid: the VF identifier 1781 + * @vfid: the PF or VF identifier 1782 + * 1783 + * This function can only be called on PF with the master mutex hold. 1784 + * 1785 + * Return: execution quantum in milliseconds (or 0 if infinity). 1786 + */ 1787 + u32 xe_gt_sriov_pf_config_get_exec_quantum_locked(struct xe_gt *gt, unsigned int vfid) 1788 + { 1789 + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 1790 + 1791 + return pf_get_exec_quantum(gt, vfid); 1792 + } 1793 + 1794 + /** 1795 + * xe_gt_sriov_pf_config_get_exec_quantum() - Get PF/VF execution quantum. 1796 + * @gt: the &xe_gt 1797 + * @vfid: the PF or VF identifier 1765 1798 * 1766 1799 * This function can only be called on PF. 1767 1800 * 1768 - * Return: VF's (or PF's) execution quantum in milliseconds. 1801 + * Return: execution quantum in milliseconds (or 0 if infinity). 1769 1802 */ 1770 1803 u32 xe_gt_sriov_pf_config_get_exec_quantum(struct xe_gt *gt, unsigned int vfid) 1771 1804 { 1772 - u32 exec_quantum; 1805 + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); 1773 1806 1774 - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 1775 - exec_quantum = pf_get_exec_quantum(gt, vfid); 1776 - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 1807 + return pf_get_exec_quantum(gt, vfid); 1808 + } 1777 1809 1778 - return exec_quantum; 1810 + /** 1811 + * xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked() - Configure EQ for PF and VFs. 1812 + * @gt: the &xe_gt to configure 1813 + * @exec_quantum: requested execution quantum in milliseconds (0 is infinity) 1814 + * 1815 + * This function can only be called on PF with the master mutex hold. 1816 + * 1817 + * Return: 0 on success or a negative error code on failure. 1818 + */ 1819 + int xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked(struct xe_gt *gt, u32 exec_quantum) 1820 + { 1821 + unsigned int totalvfs = xe_gt_sriov_pf_get_totalvfs(gt); 1822 + unsigned int n; 1823 + int err = 0; 1824 + 1825 + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 1826 + 1827 + for (n = 0; n <= totalvfs; n++) { 1828 + err = pf_provision_exec_quantum(gt, VFID(n), exec_quantum); 1829 + if (err) 1830 + break; 1831 + } 1832 + 1833 + return pf_config_bulk_set_u32_done(gt, 0, 1 + totalvfs, exec_quantum, 1834 + pf_get_exec_quantum, "execution quantum", 1835 + exec_quantum_unit, n, err); 1779 1836 } 1780 1837 1781 1838 static const char *preempt_timeout_unit(u32 preempt_timeout) ··· 1858 1795 return 0; 1859 1796 } 1860 1797 1861 - static int pf_get_preempt_timeout(struct xe_gt *gt, unsigned int vfid) 1798 + static u32 pf_get_preempt_timeout(struct xe_gt *gt, unsigned int vfid) 1862 1799 { 1863 1800 struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); 1864 1801 ··· 1866 1803 } 1867 1804 1868 1805 /** 1869 - * xe_gt_sriov_pf_config_set_preempt_timeout - Configure preemption timeout for the VF. 1806 + * xe_gt_sriov_pf_config_set_preempt_timeout_locked() - Configure PF/VF preemption timeout. 1870 1807 * @gt: the &xe_gt 1871 - * @vfid: the VF identifier 1808 + * @vfid: the PF or VF identifier 1809 + * @preempt_timeout: requested preemption timeout in microseconds (0 is infinity) 1810 + * 1811 + * This function can only be called on PF with the master mutex hold. 1812 + * It will log the provisioned value or an error in case of the failure. 1813 + * 1814 + * Return: 0 on success or a negative error code on failure. 1815 + */ 1816 + int xe_gt_sriov_pf_config_set_preempt_timeout_locked(struct xe_gt *gt, unsigned int vfid, 1817 + u32 preempt_timeout) 1818 + { 1819 + int err; 1820 + 1821 + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 1822 + 1823 + err = pf_provision_preempt_timeout(gt, vfid, preempt_timeout); 1824 + 1825 + return pf_config_set_u32_done(gt, vfid, preempt_timeout, 1826 + pf_get_preempt_timeout(gt, vfid), 1827 + "preemption timeout", preempt_timeout_unit, err); 1828 + } 1829 + 1830 + /** 1831 + * xe_gt_sriov_pf_config_set_preempt_timeout() - Configure PF/VF preemption timeout. 1832 + * @gt: the &xe_gt 1833 + * @vfid: the PF or VF identifier 1872 1834 * @preempt_timeout: requested preemption timeout in microseconds (0 is infinity) 1873 1835 * 1874 1836 * This function can only be called on PF. ··· 1903 1815 int xe_gt_sriov_pf_config_set_preempt_timeout(struct xe_gt *gt, unsigned int vfid, 1904 1816 u32 preempt_timeout) 1905 1817 { 1906 - int err; 1818 + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); 1907 1819 1908 - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 1909 - err = pf_provision_preempt_timeout(gt, vfid, preempt_timeout); 1910 - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 1911 - 1912 - return pf_config_set_u32_done(gt, vfid, preempt_timeout, 1913 - xe_gt_sriov_pf_config_get_preempt_timeout(gt, vfid), 1914 - "preemption timeout", preempt_timeout_unit, err); 1820 + return xe_gt_sriov_pf_config_set_preempt_timeout_locked(gt, vfid, preempt_timeout); 1915 1821 } 1916 1822 1917 1823 /** 1918 - * xe_gt_sriov_pf_config_get_preempt_timeout - Get VF's preemption timeout. 1824 + * xe_gt_sriov_pf_config_get_preempt_timeout_locked() - Get PF/VF preemption timeout. 1919 1825 * @gt: the &xe_gt 1920 - * @vfid: the VF identifier 1826 + * @vfid: the PF or VF identifier 1827 + * 1828 + * This function can only be called on PF with the master mutex hold. 1829 + * 1830 + * Return: preemption timeout in microseconds (or 0 if infinity). 1831 + */ 1832 + u32 xe_gt_sriov_pf_config_get_preempt_timeout_locked(struct xe_gt *gt, unsigned int vfid) 1833 + { 1834 + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 1835 + 1836 + return pf_get_preempt_timeout(gt, vfid); 1837 + } 1838 + 1839 + /** 1840 + * xe_gt_sriov_pf_config_get_preempt_timeout() - Get PF/VF preemption timeout. 1841 + * @gt: the &xe_gt 1842 + * @vfid: the PF or VF identifier 1921 1843 * 1922 1844 * This function can only be called on PF. 1923 1845 * 1924 - * Return: VF's (or PF's) preemption timeout in microseconds. 1846 + * Return: preemption timeout in microseconds (or 0 if infinity). 1925 1847 */ 1926 1848 u32 xe_gt_sriov_pf_config_get_preempt_timeout(struct xe_gt *gt, unsigned int vfid) 1927 1849 { 1928 - u32 preempt_timeout; 1850 + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); 1929 1851 1930 - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 1931 - preempt_timeout = pf_get_preempt_timeout(gt, vfid); 1932 - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 1852 + return pf_get_preempt_timeout(gt, vfid); 1853 + } 1933 1854 1934 - return preempt_timeout; 1855 + /** 1856 + * xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked() - Configure PT for PF and VFs. 1857 + * @gt: the &xe_gt to configure 1858 + * @preempt_timeout: requested preemption timeout in microseconds (0 is infinity) 1859 + * 1860 + * This function can only be called on PF with the master mutex hold. 1861 + * 1862 + * Return: 0 on success or a negative error code on failure. 1863 + */ 1864 + int xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked(struct xe_gt *gt, u32 preempt_timeout) 1865 + { 1866 + unsigned int totalvfs = xe_gt_sriov_pf_get_totalvfs(gt); 1867 + unsigned int n; 1868 + int err = 0; 1869 + 1870 + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 1871 + 1872 + for (n = 0; n <= totalvfs; n++) { 1873 + err = pf_provision_preempt_timeout(gt, VFID(n), preempt_timeout); 1874 + if (err) 1875 + break; 1876 + } 1877 + 1878 + return pf_config_bulk_set_u32_done(gt, 0, 1 + totalvfs, preempt_timeout, 1879 + pf_get_preempt_timeout, "preemption timeout", 1880 + preempt_timeout_unit, n, err); 1935 1881 } 1936 1882 1937 1883 static const char *sched_priority_unit(u32 priority)
+10
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h
··· 40 40 u32 xe_gt_sriov_pf_config_get_exec_quantum(struct xe_gt *gt, unsigned int vfid); 41 41 int xe_gt_sriov_pf_config_set_exec_quantum(struct xe_gt *gt, unsigned int vfid, u32 exec_quantum); 42 42 43 + u32 xe_gt_sriov_pf_config_get_exec_quantum_locked(struct xe_gt *gt, unsigned int vfid); 44 + int xe_gt_sriov_pf_config_set_exec_quantum_locked(struct xe_gt *gt, unsigned int vfid, 45 + u32 exec_quantum); 46 + int xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked(struct xe_gt *gt, u32 exec_quantum); 47 + 43 48 u32 xe_gt_sriov_pf_config_get_preempt_timeout(struct xe_gt *gt, unsigned int vfid); 44 49 int xe_gt_sriov_pf_config_set_preempt_timeout(struct xe_gt *gt, unsigned int vfid, 45 50 u32 preempt_timeout); 51 + 52 + u32 xe_gt_sriov_pf_config_get_preempt_timeout_locked(struct xe_gt *gt, unsigned int vfid); 53 + int xe_gt_sriov_pf_config_set_preempt_timeout_locked(struct xe_gt *gt, unsigned int vfid, 54 + u32 preempt_timeout); 55 + int xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked(struct xe_gt *gt, u32 preempt_timeout); 46 56 47 57 u32 xe_gt_sriov_pf_config_get_sched_priority(struct xe_gt *gt, unsigned int vfid); 48 58 int xe_gt_sriov_pf_config_set_sched_priority(struct xe_gt *gt, unsigned int vfid, u32 priority);
+148 -183
drivers/gpu/drm/xe/xe_gt_throttle.c
··· 8 8 #include <regs/xe_gt_regs.h> 9 9 #include "xe_device.h" 10 10 #include "xe_gt.h" 11 - #include "xe_gt_printk.h" 12 11 #include "xe_gt_sysfs.h" 13 12 #include "xe_gt_throttle.h" 14 13 #include "xe_mmio.h" 14 + #include "xe_platform_types.h" 15 15 #include "xe_pm.h" 16 16 17 17 /** 18 18 * DOC: Xe GT Throttle 19 19 * 20 - * Provides sysfs entries and other helpers for frequency throttle reasons in GT 20 + * The GT frequency may be throttled by hardware/firmware for various reasons 21 + * that are provided through attributes under the ``freq0/throttle/`` directory. 22 + * Their availability depend on the platform and some may not be visible if that 23 + * reason is not available. 21 24 * 22 - * device/gt#/freq0/throttle/status - Overall status 23 - * device/gt#/freq0/throttle/reason_pl1 - Frequency throttle due to PL1 24 - * device/gt#/freq0/throttle/reason_pl2 - Frequency throttle due to PL2 25 - * device/gt#/freq0/throttle/reason_pl4 - Frequency throttle due to PL4, Iccmax etc. 26 - * device/gt#/freq0/throttle/reason_thermal - Frequency throttle due to thermal 27 - * device/gt#/freq0/throttle/reason_prochot - Frequency throttle due to prochot 28 - * device/gt#/freq0/throttle/reason_ratl - Frequency throttle due to RATL 29 - * device/gt#/freq0/throttle/reason_vr_thermalert - Frequency throttle due to VR THERMALERT 30 - * device/gt#/freq0/throttle/reason_vr_tdc - Frequency throttle due to VR TDC 25 + * The following attributes are available on Crescent Island platform: 26 + * 27 + * - ``status``: Overall throttle status 28 + * - ``reason_pl1``: package PL1 29 + * - ``reason_pl2``: package PL2 30 + * - ``reason_pl4``: package PL4 31 + * - ``reason_prochot``: prochot 32 + * - ``reason_soc_thermal``: SoC thermal 33 + * - ``reason_mem_thermal``: Memory thermal 34 + * - ``reason_vr_thermal``: VR thermal 35 + * - ``reason_iccmax``: ICCMAX 36 + * - ``reason_ratl``: RATL thermal algorithm 37 + * - ``reason_soc_avg_thermal``: SoC average temp 38 + * - ``reason_fastvmode``: VR is hitting FastVMode 39 + * - ``reason_psys_pl1``: PSYS PL1 40 + * - ``reason_psys_pl2``: PSYS PL2 41 + * - ``reason_p0_freq``: P0 frequency 42 + * - ``reason_psys_crit``: PSYS critical 43 + * 44 + * Other platforms support the following reasons: 45 + * 46 + * - ``status``: Overall status 47 + * - ``reason_pl1``: package PL1 48 + * - ``reason_pl2``: package PL2 49 + * - ``reason_pl4``: package PL4, Iccmax etc. 50 + * - ``reason_thermal``: thermal 51 + * - ``reason_prochot``: prochot 52 + * - ``reason_ratl``: RATL hermal algorithm 53 + * - ``reason_vr_thermalert``: VR THERMALERT 54 + * - ``reason_vr_tdc``: VR TDC 31 55 */ 32 56 33 - static struct xe_gt * 34 - dev_to_gt(struct device *dev) 57 + struct throttle_attribute { 58 + struct kobj_attribute attr; 59 + u32 mask; 60 + }; 61 + 62 + static struct xe_gt *dev_to_gt(struct device *dev) 35 63 { 36 64 return kobj_to_gt(dev->kobj.parent); 37 65 } 38 66 67 + static struct xe_gt *throttle_to_gt(struct kobject *kobj) 68 + { 69 + return dev_to_gt(kobj_to_dev(kobj)); 70 + } 71 + 72 + static struct throttle_attribute *kobj_attribute_to_throttle(struct kobj_attribute *attr) 73 + { 74 + return container_of(attr, struct throttle_attribute, attr); 75 + } 76 + 39 77 u32 xe_gt_throttle_get_limit_reasons(struct xe_gt *gt) 40 78 { 41 - u32 reg; 79 + struct xe_device *xe = gt_to_xe(gt); 80 + struct xe_reg reg; 81 + u32 val, mask; 42 82 43 - xe_pm_runtime_get(gt_to_xe(gt)); 44 83 if (xe_gt_is_media_type(gt)) 45 - reg = xe_mmio_read32(&gt->mmio, MTL_MEDIA_PERF_LIMIT_REASONS); 84 + reg = MTL_MEDIA_PERF_LIMIT_REASONS; 46 85 else 47 - reg = xe_mmio_read32(&gt->mmio, GT0_PERF_LIMIT_REASONS); 48 - xe_pm_runtime_put(gt_to_xe(gt)); 86 + reg = GT0_PERF_LIMIT_REASONS; 49 87 50 - return reg; 88 + if (xe->info.platform == XE_CRESCENTISLAND) 89 + mask = CRI_PERF_LIMIT_REASONS_MASK; 90 + else 91 + mask = GT0_PERF_LIMIT_REASONS_MASK; 92 + 93 + xe_pm_runtime_get(xe); 94 + val = xe_mmio_read32(&gt->mmio, reg) & mask; 95 + xe_pm_runtime_put(xe); 96 + 97 + return val; 51 98 } 52 99 53 - static u32 read_status(struct xe_gt *gt) 100 + static bool is_throttled_by(struct xe_gt *gt, u32 mask) 54 101 { 55 - u32 status = xe_gt_throttle_get_limit_reasons(gt) & GT0_PERF_LIMIT_REASONS_MASK; 56 - 57 - xe_gt_dbg(gt, "throttle reasons: 0x%08x\n", status); 58 - return status; 102 + return xe_gt_throttle_get_limit_reasons(gt) & mask; 59 103 } 60 104 61 - static u32 read_reason_pl1(struct xe_gt *gt) 62 - { 63 - u32 pl1 = xe_gt_throttle_get_limit_reasons(gt) & POWER_LIMIT_1_MASK; 64 - 65 - return pl1; 66 - } 67 - 68 - static u32 read_reason_pl2(struct xe_gt *gt) 69 - { 70 - u32 pl2 = xe_gt_throttle_get_limit_reasons(gt) & POWER_LIMIT_2_MASK; 71 - 72 - return pl2; 73 - } 74 - 75 - static u32 read_reason_pl4(struct xe_gt *gt) 76 - { 77 - u32 pl4 = xe_gt_throttle_get_limit_reasons(gt) & POWER_LIMIT_4_MASK; 78 - 79 - return pl4; 80 - } 81 - 82 - static u32 read_reason_thermal(struct xe_gt *gt) 83 - { 84 - u32 thermal = xe_gt_throttle_get_limit_reasons(gt) & THERMAL_LIMIT_MASK; 85 - 86 - return thermal; 87 - } 88 - 89 - static u32 read_reason_prochot(struct xe_gt *gt) 90 - { 91 - u32 prochot = xe_gt_throttle_get_limit_reasons(gt) & PROCHOT_MASK; 92 - 93 - return prochot; 94 - } 95 - 96 - static u32 read_reason_ratl(struct xe_gt *gt) 97 - { 98 - u32 ratl = xe_gt_throttle_get_limit_reasons(gt) & RATL_MASK; 99 - 100 - return ratl; 101 - } 102 - 103 - static u32 read_reason_vr_thermalert(struct xe_gt *gt) 104 - { 105 - u32 thermalert = xe_gt_throttle_get_limit_reasons(gt) & VR_THERMALERT_MASK; 106 - 107 - return thermalert; 108 - } 109 - 110 - static u32 read_reason_vr_tdc(struct xe_gt *gt) 111 - { 112 - u32 tdc = xe_gt_throttle_get_limit_reasons(gt) & VR_TDC_MASK; 113 - 114 - return tdc; 115 - } 116 - 117 - static ssize_t status_show(struct kobject *kobj, 105 + static ssize_t reason_show(struct kobject *kobj, 118 106 struct kobj_attribute *attr, char *buff) 119 107 { 120 - struct device *dev = kobj_to_dev(kobj); 121 - struct xe_gt *gt = dev_to_gt(dev); 122 - bool status = !!read_status(gt); 108 + struct throttle_attribute *ta = kobj_attribute_to_throttle(attr); 109 + struct xe_gt *gt = throttle_to_gt(kobj); 123 110 124 - return sysfs_emit(buff, "%u\n", status); 111 + return sysfs_emit(buff, "%u\n", is_throttled_by(gt, ta->mask)); 125 112 } 126 - static struct kobj_attribute attr_status = __ATTR_RO(status); 127 113 128 - static ssize_t reason_pl1_show(struct kobject *kobj, 129 - struct kobj_attribute *attr, char *buff) 130 - { 131 - struct device *dev = kobj_to_dev(kobj); 132 - struct xe_gt *gt = dev_to_gt(dev); 133 - bool pl1 = !!read_reason_pl1(gt); 114 + #define THROTTLE_ATTR_RO(name, _mask) \ 115 + struct throttle_attribute attr_##name = { \ 116 + .attr = __ATTR(name, 0444, reason_show, NULL), \ 117 + .mask = _mask, \ 118 + } 134 119 135 - return sysfs_emit(buff, "%u\n", pl1); 136 - } 137 - static struct kobj_attribute attr_reason_pl1 = __ATTR_RO(reason_pl1); 138 - 139 - static ssize_t reason_pl2_show(struct kobject *kobj, 140 - struct kobj_attribute *attr, char *buff) 141 - { 142 - struct device *dev = kobj_to_dev(kobj); 143 - struct xe_gt *gt = dev_to_gt(dev); 144 - bool pl2 = !!read_reason_pl2(gt); 145 - 146 - return sysfs_emit(buff, "%u\n", pl2); 147 - } 148 - static struct kobj_attribute attr_reason_pl2 = __ATTR_RO(reason_pl2); 149 - 150 - static ssize_t reason_pl4_show(struct kobject *kobj, 151 - struct kobj_attribute *attr, char *buff) 152 - { 153 - struct device *dev = kobj_to_dev(kobj); 154 - struct xe_gt *gt = dev_to_gt(dev); 155 - bool pl4 = !!read_reason_pl4(gt); 156 - 157 - return sysfs_emit(buff, "%u\n", pl4); 158 - } 159 - static struct kobj_attribute attr_reason_pl4 = __ATTR_RO(reason_pl4); 160 - 161 - static ssize_t reason_thermal_show(struct kobject *kobj, 162 - struct kobj_attribute *attr, char *buff) 163 - { 164 - struct device *dev = kobj_to_dev(kobj); 165 - struct xe_gt *gt = dev_to_gt(dev); 166 - bool thermal = !!read_reason_thermal(gt); 167 - 168 - return sysfs_emit(buff, "%u\n", thermal); 169 - } 170 - static struct kobj_attribute attr_reason_thermal = __ATTR_RO(reason_thermal); 171 - 172 - static ssize_t reason_prochot_show(struct kobject *kobj, 173 - struct kobj_attribute *attr, char *buff) 174 - { 175 - struct device *dev = kobj_to_dev(kobj); 176 - struct xe_gt *gt = dev_to_gt(dev); 177 - bool prochot = !!read_reason_prochot(gt); 178 - 179 - return sysfs_emit(buff, "%u\n", prochot); 180 - } 181 - static struct kobj_attribute attr_reason_prochot = __ATTR_RO(reason_prochot); 182 - 183 - static ssize_t reason_ratl_show(struct kobject *kobj, 184 - struct kobj_attribute *attr, char *buff) 185 - { 186 - struct device *dev = kobj_to_dev(kobj); 187 - struct xe_gt *gt = dev_to_gt(dev); 188 - bool ratl = !!read_reason_ratl(gt); 189 - 190 - return sysfs_emit(buff, "%u\n", ratl); 191 - } 192 - static struct kobj_attribute attr_reason_ratl = __ATTR_RO(reason_ratl); 193 - 194 - static ssize_t reason_vr_thermalert_show(struct kobject *kobj, 195 - struct kobj_attribute *attr, char *buff) 196 - { 197 - struct device *dev = kobj_to_dev(kobj); 198 - struct xe_gt *gt = dev_to_gt(dev); 199 - bool thermalert = !!read_reason_vr_thermalert(gt); 200 - 201 - return sysfs_emit(buff, "%u\n", thermalert); 202 - } 203 - static struct kobj_attribute attr_reason_vr_thermalert = __ATTR_RO(reason_vr_thermalert); 204 - 205 - static ssize_t reason_vr_tdc_show(struct kobject *kobj, 206 - struct kobj_attribute *attr, char *buff) 207 - { 208 - struct device *dev = kobj_to_dev(kobj); 209 - struct xe_gt *gt = dev_to_gt(dev); 210 - bool tdc = !!read_reason_vr_tdc(gt); 211 - 212 - return sysfs_emit(buff, "%u\n", tdc); 213 - } 214 - static struct kobj_attribute attr_reason_vr_tdc = __ATTR_RO(reason_vr_tdc); 120 + static THROTTLE_ATTR_RO(status, U32_MAX); 121 + static THROTTLE_ATTR_RO(reason_pl1, POWER_LIMIT_1_MASK); 122 + static THROTTLE_ATTR_RO(reason_pl2, POWER_LIMIT_2_MASK); 123 + static THROTTLE_ATTR_RO(reason_pl4, POWER_LIMIT_4_MASK); 124 + static THROTTLE_ATTR_RO(reason_thermal, THERMAL_LIMIT_MASK); 125 + static THROTTLE_ATTR_RO(reason_prochot, PROCHOT_MASK); 126 + static THROTTLE_ATTR_RO(reason_ratl, RATL_MASK); 127 + static THROTTLE_ATTR_RO(reason_vr_thermalert, VR_THERMALERT_MASK); 128 + static THROTTLE_ATTR_RO(reason_vr_tdc, VR_TDC_MASK); 215 129 216 130 static struct attribute *throttle_attrs[] = { 217 - &attr_status.attr, 218 - &attr_reason_pl1.attr, 219 - &attr_reason_pl2.attr, 220 - &attr_reason_pl4.attr, 221 - &attr_reason_thermal.attr, 222 - &attr_reason_prochot.attr, 223 - &attr_reason_ratl.attr, 224 - &attr_reason_vr_thermalert.attr, 225 - &attr_reason_vr_tdc.attr, 131 + &attr_status.attr.attr, 132 + &attr_reason_pl1.attr.attr, 133 + &attr_reason_pl2.attr.attr, 134 + &attr_reason_pl4.attr.attr, 135 + &attr_reason_thermal.attr.attr, 136 + &attr_reason_prochot.attr.attr, 137 + &attr_reason_ratl.attr.attr, 138 + &attr_reason_vr_thermalert.attr.attr, 139 + &attr_reason_vr_tdc.attr.attr, 140 + NULL 141 + }; 142 + 143 + static THROTTLE_ATTR_RO(reason_vr_thermal, VR_THERMAL_MASK); 144 + static THROTTLE_ATTR_RO(reason_soc_thermal, SOC_THERMAL_LIMIT_MASK); 145 + static THROTTLE_ATTR_RO(reason_mem_thermal, MEM_THERMAL_MASK); 146 + static THROTTLE_ATTR_RO(reason_iccmax, ICCMAX_MASK); 147 + static THROTTLE_ATTR_RO(reason_soc_avg_thermal, SOC_AVG_THERMAL_MASK); 148 + static THROTTLE_ATTR_RO(reason_fastvmode, FASTVMODE_MASK); 149 + static THROTTLE_ATTR_RO(reason_psys_pl1, PSYS_PL1_MASK); 150 + static THROTTLE_ATTR_RO(reason_psys_pl2, PSYS_PL2_MASK); 151 + static THROTTLE_ATTR_RO(reason_p0_freq, P0_FREQ_MASK); 152 + static THROTTLE_ATTR_RO(reason_psys_crit, PSYS_CRIT_MASK); 153 + 154 + static struct attribute *cri_throttle_attrs[] = { 155 + /* Common */ 156 + &attr_status.attr.attr, 157 + &attr_reason_pl1.attr.attr, 158 + &attr_reason_pl2.attr.attr, 159 + &attr_reason_pl4.attr.attr, 160 + &attr_reason_prochot.attr.attr, 161 + &attr_reason_ratl.attr.attr, 162 + /* CRI */ 163 + &attr_reason_vr_thermal.attr.attr, 164 + &attr_reason_soc_thermal.attr.attr, 165 + &attr_reason_mem_thermal.attr.attr, 166 + &attr_reason_iccmax.attr.attr, 167 + &attr_reason_soc_avg_thermal.attr.attr, 168 + &attr_reason_fastvmode.attr.attr, 169 + &attr_reason_psys_pl1.attr.attr, 170 + &attr_reason_psys_pl2.attr.attr, 171 + &attr_reason_p0_freq.attr.attr, 172 + &attr_reason_psys_crit.attr.attr, 226 173 NULL 227 174 }; 228 175 ··· 178 231 .attrs = throttle_attrs, 179 232 }; 180 233 234 + static const struct attribute_group cri_throttle_group_attrs = { 235 + .name = "throttle", 236 + .attrs = cri_throttle_attrs, 237 + }; 238 + 239 + static const struct attribute_group *get_platform_throttle_group(struct xe_device *xe) 240 + { 241 + switch (xe->info.platform) { 242 + case XE_CRESCENTISLAND: 243 + return &cri_throttle_group_attrs; 244 + default: 245 + return &throttle_group_attrs; 246 + } 247 + } 248 + 181 249 static void gt_throttle_sysfs_fini(void *arg) 182 250 { 183 251 struct xe_gt *gt = arg; 252 + struct xe_device *xe = gt_to_xe(gt); 253 + const struct attribute_group *group = get_platform_throttle_group(xe); 184 254 185 - sysfs_remove_group(gt->freq, &throttle_group_attrs); 255 + sysfs_remove_group(gt->freq, group); 186 256 } 187 257 188 258 int xe_gt_throttle_init(struct xe_gt *gt) 189 259 { 190 260 struct xe_device *xe = gt_to_xe(gt); 261 + const struct attribute_group *group = get_platform_throttle_group(xe); 191 262 int err; 192 263 193 - err = sysfs_create_group(gt->freq, &throttle_group_attrs); 264 + err = sysfs_create_group(gt->freq, group); 194 265 if (err) 195 266 return err; 196 267
-65
drivers/gpu/drm/xe/xe_gt_types.h
··· 220 220 * operations (e.g. migrations, fixing page tables) 221 221 */ 222 222 u16 reserved_bcs_instance; 223 - /** @usm.pf_wq: page fault work queue, unbound, high priority */ 224 - struct workqueue_struct *pf_wq; 225 - /** @usm.acc_wq: access counter work queue, unbound, high priority */ 226 - struct workqueue_struct *acc_wq; 227 - /** 228 - * @usm.pf_queue: Page fault queue used to sync faults so faults can 229 - * be processed not under the GuC CT lock. The queue is sized so 230 - * it can sync all possible faults (1 per physical engine). 231 - * Multiple queues exist for page faults from different VMs to be 232 - * processed in parallel. 233 - */ 234 - struct pf_queue { 235 - /** @usm.pf_queue.gt: back pointer to GT */ 236 - struct xe_gt *gt; 237 - /** @usm.pf_queue.data: data in the page fault queue */ 238 - u32 *data; 239 - /** 240 - * @usm.pf_queue.num_dw: number of DWORDS in the page 241 - * fault queue. Dynamically calculated based on the number 242 - * of compute resources available. 243 - */ 244 - u32 num_dw; 245 - /** 246 - * @usm.pf_queue.tail: tail pointer in DWs for page fault queue, 247 - * moved by worker which processes faults (consumer). 248 - */ 249 - u16 tail; 250 - /** 251 - * @usm.pf_queue.head: head pointer in DWs for page fault queue, 252 - * moved by G2H handler (producer). 253 - */ 254 - u16 head; 255 - /** @usm.pf_queue.lock: protects page fault queue */ 256 - spinlock_t lock; 257 - /** @usm.pf_queue.worker: to process page faults */ 258 - struct work_struct worker; 259 - #define NUM_PF_QUEUE 4 260 - } pf_queue[NUM_PF_QUEUE]; 261 - /** 262 - * @usm.acc_queue: Same as page fault queue, cannot process access 263 - * counters under CT lock. 264 - */ 265 - struct acc_queue { 266 - /** @usm.acc_queue.gt: back pointer to GT */ 267 - struct xe_gt *gt; 268 - #define ACC_QUEUE_NUM_DW 128 269 - /** @usm.acc_queue.data: data in the page fault queue */ 270 - u32 data[ACC_QUEUE_NUM_DW]; 271 - /** 272 - * @usm.acc_queue.tail: tail pointer in DWs for access counter queue, 273 - * moved by worker which processes counters 274 - * (consumer). 275 - */ 276 - u16 tail; 277 - /** 278 - * @usm.acc_queue.head: head pointer in DWs for access counter queue, 279 - * moved by G2H handler (producer). 280 - */ 281 - u16 head; 282 - /** @usm.acc_queue.lock: protects page fault queue */ 283 - spinlock_t lock; 284 - /** @usm.acc_queue.worker: to process access counters */ 285 - struct work_struct worker; 286 - #define NUM_ACC_QUEUE 4 287 - } acc_queue[NUM_ACC_QUEUE]; 288 223 } usm; 289 224 290 225 /** @ordered_wq: used to serialize GT resets and TDRs */
+4 -5
drivers/gpu/drm/xe/xe_guc_ct.c
··· 21 21 #include "xe_devcoredump.h" 22 22 #include "xe_device.h" 23 23 #include "xe_gt.h" 24 - #include "xe_gt_pagefault.h" 25 24 #include "xe_gt_printk.h" 26 25 #include "xe_gt_sriov_pf_control.h" 27 26 #include "xe_gt_sriov_pf_monitor.h" 28 27 #include "xe_guc.h" 29 28 #include "xe_guc_log.h" 29 + #include "xe_guc_pagefault.h" 30 30 #include "xe_guc_relay.h" 31 31 #include "xe_guc_submit.h" 32 32 #include "xe_guc_tlb_inval.h" ··· 199 199 { 200 200 struct xe_guc_ct *ct = arg; 201 201 202 + #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) 203 + cancel_work_sync(&ct->dead.worker); 204 + #endif 202 205 ct_exit_safe_mode(ct); 203 206 destroy_workqueue(ct->g2h_wq); 204 207 xa_destroy(&ct->fence_lookup); ··· 1547 1544 break; 1548 1545 case XE_GUC_ACTION_TLB_INVALIDATION_DONE: 1549 1546 ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len); 1550 - break; 1551 - case XE_GUC_ACTION_ACCESS_COUNTER_NOTIFY: 1552 - ret = xe_guc_access_counter_notify_handler(guc, payload, 1553 - adj_len); 1554 1547 break; 1555 1548 case XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF: 1556 1549 ret = xe_guc_relay_process_guc2pf(&guc->relay, hxg, hxg_len);
+95
drivers/gpu/drm/xe/xe_guc_pagefault.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include "abi/guc_actions_abi.h" 7 + #include "xe_guc.h" 8 + #include "xe_guc_ct.h" 9 + #include "xe_guc_pagefault.h" 10 + #include "xe_pagefault.h" 11 + 12 + static void guc_ack_fault(struct xe_pagefault *pf, int err) 13 + { 14 + u32 vfid = FIELD_GET(PFD_VFID, pf->producer.msg[2]); 15 + u32 engine_instance = FIELD_GET(PFD_ENG_INSTANCE, pf->producer.msg[0]); 16 + u32 engine_class = FIELD_GET(PFD_ENG_CLASS, pf->producer.msg[0]); 17 + u32 pdata = FIELD_GET(PFD_PDATA_LO, pf->producer.msg[0]) | 18 + (FIELD_GET(PFD_PDATA_HI, pf->producer.msg[1]) << 19 + PFD_PDATA_HI_SHIFT); 20 + u32 action[] = { 21 + XE_GUC_ACTION_PAGE_FAULT_RES_DESC, 22 + 23 + FIELD_PREP(PFR_VALID, 1) | 24 + FIELD_PREP(PFR_SUCCESS, !!err) | 25 + FIELD_PREP(PFR_REPLY, PFR_ACCESS) | 26 + FIELD_PREP(PFR_DESC_TYPE, FAULT_RESPONSE_DESC) | 27 + FIELD_PREP(PFR_ASID, pf->consumer.asid), 28 + 29 + FIELD_PREP(PFR_VFID, vfid) | 30 + FIELD_PREP(PFR_ENG_INSTANCE, engine_instance) | 31 + FIELD_PREP(PFR_ENG_CLASS, engine_class) | 32 + FIELD_PREP(PFR_PDATA, pdata), 33 + }; 34 + struct xe_guc *guc = pf->producer.private; 35 + 36 + xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0); 37 + } 38 + 39 + static const struct xe_pagefault_ops guc_pagefault_ops = { 40 + .ack_fault = guc_ack_fault, 41 + }; 42 + 43 + /** 44 + * xe_guc_pagefault_handler() - G2H page fault handler 45 + * @guc: GuC object 46 + * @msg: G2H message 47 + * @len: Length of G2H message 48 + * 49 + * Parse GuC to host (G2H) message into a struct xe_pagefault and forward onto 50 + * the Xe page fault layer. 51 + * 52 + * Return: 0 on success, errno on failure 53 + */ 54 + int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len) 55 + { 56 + struct xe_pagefault pf; 57 + int i; 58 + 59 + #define GUC_PF_MSG_LEN_DW \ 60 + (sizeof(struct xe_guc_pagefault_desc) / sizeof(u32)) 61 + 62 + BUILD_BUG_ON(GUC_PF_MSG_LEN_DW > XE_PAGEFAULT_PRODUCER_MSG_LEN_DW); 63 + 64 + if (len != GUC_PF_MSG_LEN_DW) 65 + return -EPROTO; 66 + 67 + pf.gt = guc_to_gt(guc); 68 + 69 + /* 70 + * XXX: These values happen to match the enum in xe_pagefault_types.h. 71 + * If that changes, we’ll need to remap them here. 72 + */ 73 + pf.consumer.page_addr = ((u64)FIELD_GET(PFD_VIRTUAL_ADDR_HI, msg[3]) 74 + << PFD_VIRTUAL_ADDR_HI_SHIFT) | 75 + (FIELD_GET(PFD_VIRTUAL_ADDR_LO, msg[2]) << 76 + PFD_VIRTUAL_ADDR_LO_SHIFT); 77 + pf.consumer.asid = FIELD_GET(PFD_ASID, msg[1]); 78 + pf.consumer.access_type = FIELD_GET(PFD_ACCESS_TYPE, msg[2]); 79 + pf.consumer.fault_type = FIELD_GET(PFD_FAULT_TYPE, msg[2]); 80 + if (FIELD_GET(XE2_PFD_TRVA_FAULT, msg[0])) 81 + pf.consumer.fault_level = XE_PAGEFAULT_LEVEL_NACK; 82 + else 83 + pf.consumer.fault_level = FIELD_GET(PFD_FAULT_LEVEL, msg[0]); 84 + pf.consumer.engine_class = FIELD_GET(PFD_ENG_CLASS, msg[0]); 85 + pf.consumer.engine_instance = FIELD_GET(PFD_ENG_INSTANCE, msg[0]); 86 + 87 + pf.producer.private = guc; 88 + pf.producer.ops = &guc_pagefault_ops; 89 + for (i = 0; i < GUC_PF_MSG_LEN_DW; ++i) 90 + pf.producer.msg[i] = msg[i]; 91 + 92 + #undef GUC_PF_MSG_LEN_DW 93 + 94 + return xe_pagefault_handler(guc_to_xe(guc), &pf); 95 + }
+15
drivers/gpu/drm/xe/xe_guc_pagefault.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_GUC_PAGEFAULT_H_ 7 + #define _XE_GUC_PAGEFAULT_H_ 8 + 9 + #include <linux/types.h> 10 + 11 + struct xe_guc; 12 + 13 + int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len); 14 + 15 + #endif
+14
drivers/gpu/drm/xe/xe_migrate.c
··· 2333 2333 xe_vm_assert_held(q->vm); /* User queues VM's should be locked */ 2334 2334 } 2335 2335 2336 + #if IS_ENABLED(CONFIG_PROVE_LOCKING) 2337 + /** 2338 + * xe_migrate_job_lock_assert() - Assert migrate job lock held of queue 2339 + * @q: Migrate queue 2340 + */ 2341 + void xe_migrate_job_lock_assert(struct xe_exec_queue *q) 2342 + { 2343 + struct xe_migrate *m = gt_to_tile(q->gt)->migrate; 2344 + 2345 + xe_gt_assert(q->gt, q == m->q); 2346 + lockdep_assert_held(&m->job_mutex); 2347 + } 2348 + #endif 2349 + 2336 2350 #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST) 2337 2351 #include "tests/xe_migrate.c" 2338 2352 #endif
+8
drivers/gpu/drm/xe/xe_migrate.h
··· 152 152 153 153 void xe_migrate_wait(struct xe_migrate *m); 154 154 155 + #if IS_ENABLED(CONFIG_PROVE_LOCKING) 156 + void xe_migrate_job_lock_assert(struct xe_exec_queue *q); 157 + #else 158 + static inline void xe_migrate_job_lock_assert(struct xe_exec_queue *q) 159 + { 160 + } 161 + #endif 162 + 155 163 void xe_migrate_job_lock(struct xe_migrate *m, struct xe_exec_queue *q); 156 164 void xe_migrate_job_unlock(struct xe_migrate *m, struct xe_exec_queue *q); 157 165
+30 -15
drivers/gpu/drm/xe/xe_oa.c
··· 10 10 11 11 #include <drm/drm_drv.h> 12 12 #include <drm/drm_managed.h> 13 + #include <drm/drm_syncobj.h> 13 14 #include <uapi/drm/xe_drm.h> 14 15 15 16 #include <generated/xe_wa_oob.h> ··· 1391 1390 return 0; 1392 1391 } 1393 1392 1394 - static int xe_oa_parse_syncs(struct xe_oa *oa, struct xe_oa_open_param *param) 1393 + static int xe_oa_parse_syncs(struct xe_oa *oa, 1394 + struct xe_oa_stream *stream, 1395 + struct xe_oa_open_param *param) 1395 1396 { 1396 1397 int ret, num_syncs, num_ufence = 0; 1397 1398 ··· 1413 1410 1414 1411 for (num_syncs = 0; num_syncs < param->num_syncs; num_syncs++) { 1415 1412 ret = xe_sync_entry_parse(oa->xe, param->xef, &param->syncs[num_syncs], 1416 - &param->syncs_user[num_syncs], 0); 1413 + &param->syncs_user[num_syncs], 1414 + stream->ufence_syncobj, 1415 + ++stream->ufence_timeline_value, 0); 1417 1416 if (ret) 1418 1417 goto err_syncs; 1419 1418 ··· 1545 1540 return -ENODEV; 1546 1541 1547 1542 param.xef = stream->xef; 1548 - err = xe_oa_parse_syncs(stream->oa, &param); 1543 + err = xe_oa_parse_syncs(stream->oa, stream, &param); 1549 1544 if (err) 1550 1545 goto err_config_put; 1551 1546 ··· 1641 1636 if (stream->exec_q) 1642 1637 xe_exec_queue_put(stream->exec_q); 1643 1638 1639 + drm_syncobj_put(stream->ufence_syncobj); 1644 1640 kfree(stream); 1645 1641 } 1646 1642 ··· 1833 1827 struct xe_oa_open_param *param) 1834 1828 { 1835 1829 struct xe_oa_stream *stream; 1830 + struct drm_syncobj *ufence_syncobj; 1836 1831 int stream_fd; 1837 1832 int ret; 1838 1833 ··· 1844 1837 goto exit; 1845 1838 } 1846 1839 1840 + ret = drm_syncobj_create(&ufence_syncobj, DRM_SYNCOBJ_CREATE_SIGNALED, 1841 + NULL); 1842 + if (ret) 1843 + goto exit; 1844 + 1847 1845 stream = kzalloc(sizeof(*stream), GFP_KERNEL); 1848 1846 if (!stream) { 1849 1847 ret = -ENOMEM; 1850 - goto exit; 1848 + goto err_syncobj; 1851 1849 } 1852 - 1850 + stream->ufence_syncobj = ufence_syncobj; 1853 1851 stream->oa = oa; 1854 - ret = xe_oa_stream_init(stream, param); 1852 + 1853 + ret = xe_oa_parse_syncs(oa, stream, param); 1855 1854 if (ret) 1856 1855 goto err_free; 1856 + 1857 + ret = xe_oa_stream_init(stream, param); 1858 + if (ret) { 1859 + while (param->num_syncs--) 1860 + xe_sync_entry_cleanup(&param->syncs[param->num_syncs]); 1861 + kfree(param->syncs); 1862 + goto err_free; 1863 + } 1857 1864 1858 1865 if (!param->disabled) { 1859 1866 ret = xe_oa_enable_locked(stream); ··· 1892 1871 xe_oa_stream_destroy(stream); 1893 1872 err_free: 1894 1873 kfree(stream); 1874 + err_syncobj: 1875 + drm_syncobj_put(ufence_syncobj); 1895 1876 exit: 1896 1877 return ret; 1897 1878 } ··· 2107 2084 goto err_exec_q; 2108 2085 } 2109 2086 2110 - ret = xe_oa_parse_syncs(oa, &param); 2111 - if (ret) 2112 - goto err_exec_q; 2113 - 2114 2087 mutex_lock(&param.hwe->gt->oa.gt_lock); 2115 2088 ret = xe_oa_stream_open_ioctl_locked(oa, &param); 2116 2089 mutex_unlock(&param.hwe->gt->oa.gt_lock); 2117 2090 if (ret < 0) 2118 - goto err_sync_cleanup; 2091 + goto err_exec_q; 2119 2092 2120 2093 return ret; 2121 2094 2122 - err_sync_cleanup: 2123 - while (param.num_syncs--) 2124 - xe_sync_entry_cleanup(&param.syncs[param.num_syncs]); 2125 - kfree(param.syncs); 2126 2095 err_exec_q: 2127 2096 if (param.exec_q) 2128 2097 xe_exec_queue_put(param.exec_q);
+8
drivers/gpu/drm/xe/xe_oa_types.h
··· 15 15 #include "regs/xe_reg_defs.h" 16 16 #include "xe_hw_engine_types.h" 17 17 18 + struct drm_syncobj; 19 + 18 20 #define DEFAULT_XE_OA_BUFFER_SIZE SZ_16M 19 21 20 22 enum xe_oa_report_header { ··· 249 247 250 248 /** @xef: xe_file with which the stream was opened */ 251 249 struct xe_file *xef; 250 + 251 + /** @ufence_syncobj: User fence syncobj */ 252 + struct drm_syncobj *ufence_syncobj; 253 + 254 + /** @ufence_timeline_value: User fence timeline value */ 255 + u64 ufence_timeline_value; 252 256 253 257 /** @last_fence: fence to use in stream destroy when needed */ 254 258 struct dma_fence *last_fence;
+445
drivers/gpu/drm/xe/xe_pagefault.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include <linux/circ_buf.h> 7 + 8 + #include <drm/drm_exec.h> 9 + #include <drm/drm_managed.h> 10 + 11 + #include "xe_bo.h" 12 + #include "xe_device.h" 13 + #include "xe_gt_printk.h" 14 + #include "xe_gt_types.h" 15 + #include "xe_gt_stats.h" 16 + #include "xe_hw_engine.h" 17 + #include "xe_pagefault.h" 18 + #include "xe_pagefault_types.h" 19 + #include "xe_svm.h" 20 + #include "xe_trace_bo.h" 21 + #include "xe_vm.h" 22 + 23 + /** 24 + * DOC: Xe page faults 25 + * 26 + * Xe page faults are handled in two layers. The producer layer interacts with 27 + * hardware or firmware to receive and parse faults into struct xe_pagefault, 28 + * then forwards them to the consumer. The consumer layer services the faults 29 + * (e.g., memory migration, page table updates) and acknowledges the result back 30 + * to the producer, which then forwards the results to the hardware or firmware. 31 + * The consumer uses a page fault queue sized to absorb all potential faults and 32 + * a multi-threaded worker to process them. Multiple producers are supported, 33 + * with a single shared consumer. 34 + * 35 + * xe_pagefault.c implements the consumer layer. 36 + */ 37 + 38 + static int xe_pagefault_entry_size(void) 39 + { 40 + /* 41 + * Power of two alignment is not a hardware requirement, rather a 42 + * software restriction which makes the math for page fault queue 43 + * management simplier. 44 + */ 45 + return roundup_pow_of_two(sizeof(struct xe_pagefault)); 46 + } 47 + 48 + static int xe_pagefault_begin(struct drm_exec *exec, struct xe_vma *vma, 49 + struct xe_vram_region *vram, bool need_vram_move) 50 + { 51 + struct xe_bo *bo = xe_vma_bo(vma); 52 + struct xe_vm *vm = xe_vma_vm(vma); 53 + int err; 54 + 55 + err = xe_vm_lock_vma(exec, vma); 56 + if (err) 57 + return err; 58 + 59 + if (!bo) 60 + return 0; 61 + 62 + return need_vram_move ? xe_bo_migrate(bo, vram->placement, NULL, exec) : 63 + xe_bo_validate(bo, vm, true, exec); 64 + } 65 + 66 + static int xe_pagefault_handle_vma(struct xe_gt *gt, struct xe_vma *vma, 67 + bool atomic) 68 + { 69 + struct xe_vm *vm = xe_vma_vm(vma); 70 + struct xe_tile *tile = gt_to_tile(gt); 71 + struct xe_validation_ctx ctx; 72 + struct drm_exec exec; 73 + struct dma_fence *fence; 74 + int err, needs_vram; 75 + 76 + lockdep_assert_held_write(&vm->lock); 77 + 78 + needs_vram = xe_vma_need_vram_for_atomic(vm->xe, vma, atomic); 79 + if (needs_vram < 0 || (needs_vram && xe_vma_is_userptr(vma))) 80 + return needs_vram < 0 ? needs_vram : -EACCES; 81 + 82 + xe_gt_stats_incr(gt, XE_GT_STATS_ID_VMA_PAGEFAULT_COUNT, 1); 83 + xe_gt_stats_incr(gt, XE_GT_STATS_ID_VMA_PAGEFAULT_KB, 84 + xe_vma_size(vma) / SZ_1K); 85 + 86 + trace_xe_vma_pagefault(vma); 87 + 88 + /* Check if VMA is valid, opportunistic check only */ 89 + if (xe_vm_has_valid_gpu_mapping(tile, vma->tile_present, 90 + vma->tile_invalidated) && !atomic) 91 + return 0; 92 + 93 + retry_userptr: 94 + if (xe_vma_is_userptr(vma) && 95 + xe_vma_userptr_check_repin(to_userptr_vma(vma))) { 96 + struct xe_userptr_vma *uvma = to_userptr_vma(vma); 97 + 98 + err = xe_vma_userptr_pin_pages(uvma); 99 + if (err) 100 + return err; 101 + } 102 + 103 + /* Lock VM and BOs dma-resv */ 104 + xe_validation_ctx_init(&ctx, &vm->xe->val, &exec, (struct xe_val_flags) {}); 105 + drm_exec_init(&exec, 0, 0); 106 + drm_exec_until_all_locked(&exec) { 107 + err = xe_pagefault_begin(&exec, vma, tile->mem.vram, 108 + needs_vram == 1); 109 + drm_exec_retry_on_contention(&exec); 110 + xe_validation_retry_on_oom(&ctx, &err); 111 + if (err) 112 + goto unlock_dma_resv; 113 + 114 + /* Bind VMA only to the GT that has faulted */ 115 + trace_xe_vma_pf_bind(vma); 116 + xe_vm_set_validation_exec(vm, &exec); 117 + fence = xe_vma_rebind(vm, vma, BIT(tile->id)); 118 + xe_vm_set_validation_exec(vm, NULL); 119 + if (IS_ERR(fence)) { 120 + err = PTR_ERR(fence); 121 + xe_validation_retry_on_oom(&ctx, &err); 122 + goto unlock_dma_resv; 123 + } 124 + } 125 + 126 + dma_fence_wait(fence, false); 127 + dma_fence_put(fence); 128 + 129 + unlock_dma_resv: 130 + xe_validation_ctx_fini(&ctx); 131 + if (err == -EAGAIN) 132 + goto retry_userptr; 133 + 134 + return err; 135 + } 136 + 137 + static bool 138 + xe_pagefault_access_is_atomic(enum xe_pagefault_access_type access_type) 139 + { 140 + return access_type == XE_PAGEFAULT_ACCESS_TYPE_ATOMIC; 141 + } 142 + 143 + static struct xe_vm *xe_pagefault_asid_to_vm(struct xe_device *xe, u32 asid) 144 + { 145 + struct xe_vm *vm; 146 + 147 + down_read(&xe->usm.lock); 148 + vm = xa_load(&xe->usm.asid_to_vm, asid); 149 + if (vm && xe_vm_in_fault_mode(vm)) 150 + xe_vm_get(vm); 151 + else 152 + vm = ERR_PTR(-EINVAL); 153 + up_read(&xe->usm.lock); 154 + 155 + return vm; 156 + } 157 + 158 + static int xe_pagefault_service(struct xe_pagefault *pf) 159 + { 160 + struct xe_gt *gt = pf->gt; 161 + struct xe_device *xe = gt_to_xe(gt); 162 + struct xe_vm *vm; 163 + struct xe_vma *vma = NULL; 164 + int err; 165 + bool atomic; 166 + 167 + /* Producer flagged this fault to be nacked */ 168 + if (pf->consumer.fault_level == XE_PAGEFAULT_LEVEL_NACK) 169 + return -EFAULT; 170 + 171 + vm = xe_pagefault_asid_to_vm(xe, pf->consumer.asid); 172 + if (IS_ERR(vm)) 173 + return PTR_ERR(vm); 174 + 175 + /* 176 + * TODO: Change to read lock? Using write lock for simplicity. 177 + */ 178 + down_write(&vm->lock); 179 + 180 + if (xe_vm_is_closed(vm)) { 181 + err = -ENOENT; 182 + goto unlock_vm; 183 + } 184 + 185 + vma = xe_vm_find_vma_by_addr(vm, pf->consumer.page_addr); 186 + if (!vma) { 187 + err = -EINVAL; 188 + goto unlock_vm; 189 + } 190 + 191 + atomic = xe_pagefault_access_is_atomic(pf->consumer.access_type); 192 + 193 + if (xe_vma_is_cpu_addr_mirror(vma)) 194 + err = xe_svm_handle_pagefault(vm, vma, gt, 195 + pf->consumer.page_addr, atomic); 196 + else 197 + err = xe_pagefault_handle_vma(gt, vma, atomic); 198 + 199 + unlock_vm: 200 + if (!err) 201 + vm->usm.last_fault_vma = vma; 202 + up_write(&vm->lock); 203 + xe_vm_put(vm); 204 + 205 + return err; 206 + } 207 + 208 + static bool xe_pagefault_queue_pop(struct xe_pagefault_queue *pf_queue, 209 + struct xe_pagefault *pf) 210 + { 211 + bool found_fault = false; 212 + 213 + spin_lock_irq(&pf_queue->lock); 214 + if (pf_queue->tail != pf_queue->head) { 215 + memcpy(pf, pf_queue->data + pf_queue->tail, sizeof(*pf)); 216 + pf_queue->tail = (pf_queue->tail + xe_pagefault_entry_size()) % 217 + pf_queue->size; 218 + found_fault = true; 219 + } 220 + spin_unlock_irq(&pf_queue->lock); 221 + 222 + return found_fault; 223 + } 224 + 225 + static void xe_pagefault_print(struct xe_pagefault *pf) 226 + { 227 + xe_gt_dbg(pf->gt, "\n\tASID: %d\n" 228 + "\tFaulted Address: 0x%08x%08x\n" 229 + "\tFaultType: %d\n" 230 + "\tAccessType: %d\n" 231 + "\tFaultLevel: %d\n" 232 + "\tEngineClass: %d %s\n" 233 + "\tEngineInstance: %d\n", 234 + pf->consumer.asid, 235 + upper_32_bits(pf->consumer.page_addr), 236 + lower_32_bits(pf->consumer.page_addr), 237 + pf->consumer.fault_type, 238 + pf->consumer.access_type, 239 + pf->consumer.fault_level, 240 + pf->consumer.engine_class, 241 + xe_hw_engine_class_to_str(pf->consumer.engine_class), 242 + pf->consumer.engine_instance); 243 + } 244 + 245 + static void xe_pagefault_queue_work(struct work_struct *w) 246 + { 247 + struct xe_pagefault_queue *pf_queue = 248 + container_of(w, typeof(*pf_queue), worker); 249 + struct xe_pagefault pf; 250 + unsigned long threshold; 251 + 252 + #define USM_QUEUE_MAX_RUNTIME_MS 20 253 + threshold = jiffies + msecs_to_jiffies(USM_QUEUE_MAX_RUNTIME_MS); 254 + 255 + while (xe_pagefault_queue_pop(pf_queue, &pf)) { 256 + int err; 257 + 258 + if (!pf.gt) /* Fault squashed during reset */ 259 + continue; 260 + 261 + err = xe_pagefault_service(&pf); 262 + if (err) { 263 + xe_pagefault_print(&pf); 264 + xe_gt_dbg(pf.gt, "Fault response: Unsuccessful %pe\n", 265 + ERR_PTR(err)); 266 + } 267 + 268 + pf.producer.ops->ack_fault(&pf, err); 269 + 270 + if (time_after(jiffies, threshold)) { 271 + queue_work(gt_to_xe(pf.gt)->usm.pf_wq, w); 272 + break; 273 + } 274 + } 275 + #undef USM_QUEUE_MAX_RUNTIME_MS 276 + } 277 + 278 + static int xe_pagefault_queue_init(struct xe_device *xe, 279 + struct xe_pagefault_queue *pf_queue) 280 + { 281 + struct xe_gt *gt; 282 + int total_num_eus = 0; 283 + u8 id; 284 + 285 + for_each_gt(gt, xe, id) { 286 + xe_dss_mask_t all_dss; 287 + int num_dss, num_eus; 288 + 289 + bitmap_or(all_dss, gt->fuse_topo.g_dss_mask, 290 + gt->fuse_topo.c_dss_mask, XE_MAX_DSS_FUSE_BITS); 291 + 292 + num_dss = bitmap_weight(all_dss, XE_MAX_DSS_FUSE_BITS); 293 + num_eus = bitmap_weight(gt->fuse_topo.eu_mask_per_dss, 294 + XE_MAX_EU_FUSE_BITS) * num_dss; 295 + 296 + total_num_eus += num_eus; 297 + } 298 + 299 + xe_assert(xe, total_num_eus); 300 + 301 + /* 302 + * user can issue separate page faults per EU and per CS 303 + * 304 + * XXX: Multiplier required as compute UMD are getting PF queue errors 305 + * without it. Follow on why this multiplier is required. 306 + */ 307 + #define PF_MULTIPLIER 8 308 + pf_queue->size = (total_num_eus + XE_NUM_HW_ENGINES) * 309 + xe_pagefault_entry_size() * PF_MULTIPLIER; 310 + pf_queue->size = roundup_pow_of_two(pf_queue->size); 311 + #undef PF_MULTIPLIER 312 + 313 + drm_dbg(&xe->drm, "xe_pagefault_entry_size=%d, total_num_eus=%d, pf_queue->size=%u", 314 + xe_pagefault_entry_size(), total_num_eus, pf_queue->size); 315 + 316 + spin_lock_init(&pf_queue->lock); 317 + INIT_WORK(&pf_queue->worker, xe_pagefault_queue_work); 318 + 319 + pf_queue->data = drmm_kzalloc(&xe->drm, pf_queue->size, GFP_KERNEL); 320 + if (!pf_queue->data) 321 + return -ENOMEM; 322 + 323 + return 0; 324 + } 325 + 326 + static void xe_pagefault_fini(void *arg) 327 + { 328 + struct xe_device *xe = arg; 329 + 330 + destroy_workqueue(xe->usm.pf_wq); 331 + } 332 + 333 + /** 334 + * xe_pagefault_init() - Page fault init 335 + * @xe: xe device instance 336 + * 337 + * Initialize Xe page fault state. Must be done after reading fuses. 338 + * 339 + * Return: 0 on Success, errno on failure 340 + */ 341 + int xe_pagefault_init(struct xe_device *xe) 342 + { 343 + int err, i; 344 + 345 + if (!xe->info.has_usm) 346 + return 0; 347 + 348 + xe->usm.pf_wq = alloc_workqueue("xe_page_fault_work_queue", 349 + WQ_UNBOUND | WQ_HIGHPRI, 350 + XE_PAGEFAULT_QUEUE_COUNT); 351 + if (!xe->usm.pf_wq) 352 + return -ENOMEM; 353 + 354 + for (i = 0; i < XE_PAGEFAULT_QUEUE_COUNT; ++i) { 355 + err = xe_pagefault_queue_init(xe, xe->usm.pf_queue + i); 356 + if (err) 357 + goto err_out; 358 + } 359 + 360 + return devm_add_action_or_reset(xe->drm.dev, xe_pagefault_fini, xe); 361 + 362 + err_out: 363 + destroy_workqueue(xe->usm.pf_wq); 364 + return err; 365 + } 366 + 367 + static void xe_pagefault_queue_reset(struct xe_device *xe, struct xe_gt *gt, 368 + struct xe_pagefault_queue *pf_queue) 369 + { 370 + u32 i; 371 + 372 + /* Driver load failure guard / USM not enabled guard */ 373 + if (!pf_queue->data) 374 + return; 375 + 376 + /* Squash all pending faults on the GT */ 377 + 378 + spin_lock_irq(&pf_queue->lock); 379 + for (i = pf_queue->tail; i != pf_queue->head; 380 + i = (i + xe_pagefault_entry_size()) % pf_queue->size) { 381 + struct xe_pagefault *pf = pf_queue->data + i; 382 + 383 + if (pf->gt == gt) 384 + pf->gt = NULL; 385 + } 386 + spin_unlock_irq(&pf_queue->lock); 387 + } 388 + 389 + /** 390 + * xe_pagefault_reset() - Page fault reset for a GT 391 + * @xe: xe device instance 392 + * @gt: GT being reset 393 + * 394 + * Reset the Xe page fault state for a GT; that is, squash any pending faults on 395 + * the GT. 396 + */ 397 + void xe_pagefault_reset(struct xe_device *xe, struct xe_gt *gt) 398 + { 399 + int i; 400 + 401 + for (i = 0; i < XE_PAGEFAULT_QUEUE_COUNT; ++i) 402 + xe_pagefault_queue_reset(xe, gt, xe->usm.pf_queue + i); 403 + } 404 + 405 + static bool xe_pagefault_queue_full(struct xe_pagefault_queue *pf_queue) 406 + { 407 + lockdep_assert_held(&pf_queue->lock); 408 + 409 + return CIRC_SPACE(pf_queue->head, pf_queue->tail, pf_queue->size) <= 410 + xe_pagefault_entry_size(); 411 + } 412 + 413 + /** 414 + * xe_pagefault_handler() - Page fault handler 415 + * @xe: xe device instance 416 + * @pf: Page fault 417 + * 418 + * Sink the page fault to a queue (i.e., a memory buffer) and queue a worker to 419 + * service it. Safe to be called from IRQ or process context. Reclaim safe. 420 + * 421 + * Return: 0 on success, errno on failure 422 + */ 423 + int xe_pagefault_handler(struct xe_device *xe, struct xe_pagefault *pf) 424 + { 425 + struct xe_pagefault_queue *pf_queue = xe->usm.pf_queue + 426 + (pf->consumer.asid % XE_PAGEFAULT_QUEUE_COUNT); 427 + unsigned long flags; 428 + bool full; 429 + 430 + spin_lock_irqsave(&pf_queue->lock, flags); 431 + full = xe_pagefault_queue_full(pf_queue); 432 + if (!full) { 433 + memcpy(pf_queue->data + pf_queue->head, pf, sizeof(*pf)); 434 + pf_queue->head = (pf_queue->head + xe_pagefault_entry_size()) % 435 + pf_queue->size; 436 + queue_work(xe->usm.pf_wq, &pf_queue->worker); 437 + } else { 438 + drm_warn(&xe->drm, 439 + "PageFault Queue (%d) full, shouldn't be possible\n", 440 + pf->consumer.asid % XE_PAGEFAULT_QUEUE_COUNT); 441 + } 442 + spin_unlock_irqrestore(&pf_queue->lock, flags); 443 + 444 + return full ? -ENOSPC : 0; 445 + }
+19
drivers/gpu/drm/xe/xe_pagefault.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_PAGEFAULT_H_ 7 + #define _XE_PAGEFAULT_H_ 8 + 9 + struct xe_device; 10 + struct xe_gt; 11 + struct xe_pagefault; 12 + 13 + int xe_pagefault_init(struct xe_device *xe); 14 + 15 + void xe_pagefault_reset(struct xe_device *xe, struct xe_gt *gt); 16 + 17 + int xe_pagefault_handler(struct xe_device *xe, struct xe_pagefault *pf); 18 + 19 + #endif
+136
drivers/gpu/drm/xe/xe_pagefault_types.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_PAGEFAULT_TYPES_H_ 7 + #define _XE_PAGEFAULT_TYPES_H_ 8 + 9 + #include <linux/workqueue.h> 10 + 11 + struct xe_gt; 12 + struct xe_pagefault; 13 + 14 + /** enum xe_pagefault_access_type - Xe page fault access type */ 15 + enum xe_pagefault_access_type { 16 + /** @XE_PAGEFAULT_ACCESS_TYPE_READ: Read access type */ 17 + XE_PAGEFAULT_ACCESS_TYPE_READ = 0, 18 + /** @XE_PAGEFAULT_ACCESS_TYPE_WRITE: Write access type */ 19 + XE_PAGEFAULT_ACCESS_TYPE_WRITE = 1, 20 + /** @XE_PAGEFAULT_ACCESS_TYPE_ATOMIC: Atomic access type */ 21 + XE_PAGEFAULT_ACCESS_TYPE_ATOMIC = 2, 22 + }; 23 + 24 + /** enum xe_pagefault_type - Xe page fault type */ 25 + enum xe_pagefault_type { 26 + /** @XE_PAGEFAULT_TYPE_NOT_PRESENT: Not present */ 27 + XE_PAGEFAULT_TYPE_NOT_PRESENT = 0, 28 + /** @XE_PAGEFAULT_TYPE_WRITE_ACCESS_VIOLATION: Write access violation */ 29 + XE_PAGEFAULT_TYPE_WRITE_ACCESS_VIOLATION = 1, 30 + /** @XE_PAGEFAULT_TYPE_ATOMIC_ACCESS_VIOLATION: Atomic access violation */ 31 + XE_PAGEFAULT_TYPE_ATOMIC_ACCESS_VIOLATION = 2, 32 + }; 33 + 34 + /** struct xe_pagefault_ops - Xe pagefault ops (producer) */ 35 + struct xe_pagefault_ops { 36 + /** 37 + * @ack_fault: Ack fault 38 + * @pf: Page fault 39 + * @err: Error state of fault 40 + * 41 + * Page fault producer receives acknowledgment from the consumer and 42 + * sends the result to the HW/FW interface. 43 + */ 44 + void (*ack_fault)(struct xe_pagefault *pf, int err); 45 + }; 46 + 47 + /** 48 + * struct xe_pagefault - Xe page fault 49 + * 50 + * Generic page fault structure for communication between producer and consumer. 51 + * Carefully sized to be 64 bytes. Upon a device page fault, the producer 52 + * populates this structure, and the consumer copies it into the page-fault 53 + * queue for deferred handling. 54 + */ 55 + struct xe_pagefault { 56 + /** 57 + * @gt: GT of fault 58 + */ 59 + struct xe_gt *gt; 60 + /** 61 + * @consumer: State for the software handling the fault. Populated by 62 + * the producer and may be modified by the consumer to communicate 63 + * information back to the producer upon fault acknowledgment. 64 + */ 65 + struct { 66 + /** @consumer.page_addr: address of page fault */ 67 + u64 page_addr; 68 + /** @consumer.asid: address space ID */ 69 + u32 asid; 70 + /** 71 + * @consumer.access_type: access type, u8 rather than enum to 72 + * keep size compact 73 + */ 74 + u8 access_type; 75 + /** 76 + * @consumer.fault_type: fault type, u8 rather than enum to 77 + * keep size compact 78 + */ 79 + u8 fault_type; 80 + #define XE_PAGEFAULT_LEVEL_NACK 0xff /* Producer indicates nack fault */ 81 + /** @consumer.fault_level: fault level */ 82 + u8 fault_level; 83 + /** @consumer.engine_class: engine class */ 84 + u8 engine_class; 85 + /** @consumer.engine_instance: engine instance */ 86 + u8 engine_instance; 87 + /** consumer.reserved: reserved bits for future expansion */ 88 + u8 reserved[7]; 89 + } consumer; 90 + /** 91 + * @producer: State for the producer (i.e., HW/FW interface). Populated 92 + * by the producer and should not be modified—or even inspected—by the 93 + * consumer, except for calling operations. 94 + */ 95 + struct { 96 + /** @producer.private: private pointer */ 97 + void *private; 98 + /** @producer.ops: operations */ 99 + const struct xe_pagefault_ops *ops; 100 + #define XE_PAGEFAULT_PRODUCER_MSG_LEN_DW 4 101 + /** 102 + * @producer.msg: page fault message, used by producer in fault 103 + * acknowledgment to formulate response to HW/FW interface. 104 + * Included in the page-fault message because the producer 105 + * typically receives the fault in a context where memory cannot 106 + * be allocated (e.g., atomic context or the reclaim path). 107 + */ 108 + u32 msg[XE_PAGEFAULT_PRODUCER_MSG_LEN_DW]; 109 + } producer; 110 + }; 111 + 112 + /** 113 + * struct xe_pagefault_queue: Xe pagefault queue (consumer) 114 + * 115 + * Used to capture all device page faults for deferred processing. Size this 116 + * queue to absorb the device’s worst-case number of outstanding faults. 117 + */ 118 + struct xe_pagefault_queue { 119 + /** 120 + * @data: Data in queue containing struct xe_pagefault, protected by 121 + * @lock 122 + */ 123 + void *data; 124 + /** @size: Size of queue in bytes */ 125 + u32 size; 126 + /** @head: Head pointer in bytes, moved by producer, protected by @lock */ 127 + u32 head; 128 + /** @tail: Tail pointer in bytes, moved by consumer, protected by @lock */ 129 + u32 tail; 130 + /** @lock: protects page fault queue */ 131 + spinlock_t lock; 132 + /** @worker: to process page faults */ 133 + struct work_struct worker; 134 + }; 135 + 136 + #endif
+8 -7
drivers/gpu/drm/xe/xe_pat.c
··· 115 115 REG_FIELD_PREP(XE2_L4_POLICY, l4_policy) | \ 116 116 REG_FIELD_PREP(XE2_COH_MODE, __coh_mode), \ 117 117 .coh_mode = (BUILD_BUG_ON_ZERO(__coh_mode && comp_en) || __coh_mode) ? \ 118 - XE_COH_AT_LEAST_1WAY : XE_COH_NONE \ 118 + XE_COH_AT_LEAST_1WAY : XE_COH_NONE, \ 119 + .valid = 1 \ 119 120 } 120 121 121 122 static const struct xe_pat_table_entry xe2_pat_table[] = { ··· 369 368 if (!fw_ref) 370 369 return -ETIMEDOUT; 371 370 372 - drm_printf(p, "PAT table:\n"); 371 + drm_printf(p, "PAT table: (* = reserved entry)\n"); 373 372 374 373 for (i = 0; i < xe->pat.n_entries; i++) { 375 374 if (xe_gt_is_media_type(gt)) ··· 377 376 else 378 377 pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i))); 379 378 380 - drm_printf(p, "PAT[%2d] = [ %u, %u, %u, %u, %u, %u ] (%#8x)\n", i, 379 + drm_printf(p, "PAT[%2d] = [ %u, %u, %u, %u, %u, %u ] (%#8x)%s\n", i, 381 380 !!(pat & XE2_NO_PROMOTE), 382 381 !!(pat & XE2_COMP_EN), 383 382 REG_FIELD_GET(XE2_L3_CLOS, pat), 384 383 REG_FIELD_GET(XE2_L3_POLICY, pat), 385 384 REG_FIELD_GET(XE2_L4_POLICY, pat), 386 385 REG_FIELD_GET(XE2_COH_MODE, pat), 387 - pat); 386 + pat, xe->pat.table[i].valid ? "" : " *"); 388 387 } 389 388 390 389 /* ··· 427 426 if (!fw_ref) 428 427 return -ETIMEDOUT; 429 428 430 - drm_printf(p, "PAT table:\n"); 429 + drm_printf(p, "PAT table: (* = reserved entry)\n"); 431 430 432 431 for (i = 0; i < xe->pat.n_entries; i++) { 433 432 pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i))); 434 433 435 - drm_printf(p, "PAT[%2d] = [ %u, %u, %u, %u, %u ] (%#8x)\n", i, 434 + drm_printf(p, "PAT[%2d] = [ %u, %u, %u, %u, %u ] (%#8x)%s\n", i, 436 435 !!(pat & XE2_NO_PROMOTE), 437 436 REG_FIELD_GET(XE2_L3_CLOS, pat), 438 437 REG_FIELD_GET(XE2_L3_POLICY, pat), 439 438 REG_FIELD_GET(XE2_L4_POLICY, pat), 440 439 REG_FIELD_GET(XE2_COH_MODE, pat), 441 - pat); 440 + pat, xe->pat.table[i].valid ? "" : " *"); 442 441 } 443 442 444 443 /*
+5
drivers/gpu/drm/xe/xe_pat.h
··· 29 29 #define XE_COH_NONE 1 30 30 #define XE_COH_AT_LEAST_1WAY 2 31 31 u16 coh_mode; 32 + 33 + /** 34 + * @valid: Set to 1 if the entry is valid, 0 if it's reserved. 35 + */ 36 + u16 valid; 32 37 }; 33 38 34 39 /**
+28 -13
drivers/gpu/drm/xe/xe_pci_sriov.c
··· 20 20 #include "xe_sriov_pf_control.h" 21 21 #include "xe_sriov_pf_helpers.h" 22 22 #include "xe_sriov_pf_provision.h" 23 + #include "xe_sriov_pf_sysfs.h" 23 24 #include "xe_sriov_printk.h" 24 25 25 26 static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs) ··· 29 28 30 29 for (n = 1; n <= num_vfs; n++) 31 30 xe_sriov_pf_control_reset_vf(xe, n); 32 - } 33 - 34 - static struct pci_dev *xe_pci_pf_get_vf_dev(struct xe_device *xe, unsigned int vf_id) 35 - { 36 - struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 37 - 38 - xe_assert(xe, IS_SRIOV_PF(xe)); 39 - 40 - /* caller must use pci_dev_put() */ 41 - return pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), 42 - pdev->bus->number, 43 - pci_iov_virtfn_devfn(pdev, vf_id)); 44 31 } 45 32 46 33 static void pf_link_vfs(struct xe_device *xe, int num_vfs) ··· 49 60 * enforce correct resume order. 50 61 */ 51 62 for (n = 1; n <= num_vfs; n++) { 52 - pdev_vf = xe_pci_pf_get_vf_dev(xe, n - 1); 63 + pdev_vf = xe_pci_sriov_get_vf_pdev(pdev_pf, n); 53 64 54 65 /* unlikely, something weird is happening, abort */ 55 66 if (!pdev_vf) { ··· 139 150 xe_sriov_info(xe, "Enabled %u of %u VF%s\n", 140 151 num_vfs, total_vfs, str_plural(total_vfs)); 141 152 153 + xe_sriov_pf_sysfs_link_vfs(xe, num_vfs); 154 + 142 155 pf_engine_activity_stats(xe, num_vfs, true); 143 156 144 157 return num_vfs; ··· 167 176 return 0; 168 177 169 178 pf_engine_activity_stats(xe, num_vfs, false); 179 + 180 + xe_sriov_pf_sysfs_unlink_vfs(xe, num_vfs); 170 181 171 182 pci_disable_sriov(pdev); 172 183 ··· 220 227 xe_pm_runtime_put(xe); 221 228 222 229 return ret; 230 + } 231 + 232 + /** 233 + * xe_pci_sriov_get_vf_pdev() - Lookup the VF's PCI device using the VF identifier. 234 + * @pdev: the PF's &pci_dev 235 + * @vfid: VF identifier (1-based) 236 + * 237 + * The caller must decrement the reference count by calling pci_dev_put(). 238 + * 239 + * Return: the VF's &pci_dev or NULL if the VF device was not found. 240 + */ 241 + struct pci_dev *xe_pci_sriov_get_vf_pdev(struct pci_dev *pdev, unsigned int vfid) 242 + { 243 + struct xe_device *xe = pdev_to_xe_device(pdev); 244 + 245 + xe_assert(xe, dev_is_pf(&pdev->dev)); 246 + xe_assert(xe, vfid); 247 + xe_assert(xe, vfid <= pci_sriov_get_totalvfs(pdev)); 248 + 249 + return pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), 250 + pdev->bus->number, 251 + pci_iov_virtfn_devfn(pdev, vfid - 1)); 223 252 }
+1
drivers/gpu/drm/xe/xe_pci_sriov.h
··· 10 10 11 11 #ifdef CONFIG_PCI_IOV 12 12 int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs); 13 + struct pci_dev *xe_pci_sriov_get_vf_pdev(struct pci_dev *pdev, unsigned int vfid); 13 14 #else 14 15 static inline int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) 15 16 {
+27 -53
drivers/gpu/drm/xe/xe_pt.c
··· 3 3 * Copyright © 2022 Intel Corporation 4 4 */ 5 5 6 - #include <linux/dma-fence-array.h> 7 - 8 6 #include "xe_pt.h" 9 7 10 8 #include "regs/xe_gtt_defs.h" ··· 1338 1340 return err; 1339 1341 } 1340 1342 1341 - if (!(pt_update_ops->q->flags & EXEC_QUEUE_FLAG_KERNEL)) { 1342 - if (job) 1343 - err = xe_sched_job_last_fence_add_dep(job, vm); 1344 - else 1345 - err = xe_exec_queue_last_fence_test_dep(pt_update_ops->q, vm); 1346 - } 1347 - 1348 1343 for (i = 0; job && !err && i < vops->num_syncs; i++) 1349 1344 err = xe_sync_entry_add_deps(&vops->syncs[i], job); 1350 1345 ··· 2350 2359 struct xe_vm *vm = vops->vm; 2351 2360 struct xe_vm_pgtable_update_ops *pt_update_ops = 2352 2361 &vops->pt_update_ops[tile->id]; 2353 - struct dma_fence *fence, *ifence, *mfence; 2362 + struct xe_exec_queue *q = pt_update_ops->q; 2363 + struct dma_fence *fence, *ifence = NULL, *mfence = NULL; 2354 2364 struct xe_tlb_inval_job *ijob = NULL, *mjob = NULL; 2355 - struct dma_fence **fences = NULL; 2356 - struct dma_fence_array *cf = NULL; 2357 2365 struct xe_range_fence *rfence; 2358 2366 struct xe_vma_op *op; 2359 2367 int err = 0, i; ··· 2380 2390 #endif 2381 2391 2382 2392 if (pt_update_ops->needs_invalidation) { 2383 - struct xe_exec_queue *q = pt_update_ops->q; 2384 2393 struct xe_dep_scheduler *dep_scheduler = 2385 2394 to_dep_scheduler(q, tile->primary_gt); 2386 2395 2387 2396 ijob = xe_tlb_inval_job_create(q, &tile->primary_gt->tlb_inval, 2388 - dep_scheduler, 2397 + dep_scheduler, vm, 2389 2398 pt_update_ops->start, 2390 2399 pt_update_ops->last, 2391 - vm->usm.asid); 2400 + XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT); 2392 2401 if (IS_ERR(ijob)) { 2393 2402 err = PTR_ERR(ijob); 2394 2403 goto kill_vm_tile1; ··· 2399 2410 2400 2411 mjob = xe_tlb_inval_job_create(q, 2401 2412 &tile->media_gt->tlb_inval, 2402 - dep_scheduler, 2413 + dep_scheduler, vm, 2403 2414 pt_update_ops->start, 2404 2415 pt_update_ops->last, 2405 - vm->usm.asid); 2416 + XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT); 2406 2417 if (IS_ERR(mjob)) { 2407 2418 err = PTR_ERR(mjob); 2408 2419 goto free_ijob; 2409 2420 } 2410 2421 update.mjob = mjob; 2411 - 2412 - fences = kmalloc_array(2, sizeof(*fences), GFP_KERNEL); 2413 - if (!fences) { 2414 - err = -ENOMEM; 2415 - goto free_ijob; 2416 - } 2417 - cf = dma_fence_array_alloc(2); 2418 - if (!cf) { 2419 - err = -ENOMEM; 2420 - goto free_ijob; 2421 - } 2422 2422 } 2423 2423 } 2424 2424 ··· 2438 2460 pt_update_ops->last, fence)) 2439 2461 dma_fence_wait(fence, false); 2440 2462 2441 - /* tlb invalidation must be done before signaling unbind/rebind */ 2442 - if (ijob) { 2443 - struct dma_fence *__fence; 2444 - 2463 + if (ijob) 2445 2464 ifence = xe_tlb_inval_job_push(ijob, tile->migrate, fence); 2446 - __fence = ifence; 2465 + if (mjob) 2466 + mfence = xe_tlb_inval_job_push(mjob, tile->migrate, fence); 2447 2467 2448 - if (mjob) { 2449 - fences[0] = ifence; 2450 - mfence = xe_tlb_inval_job_push(mjob, tile->migrate, 2451 - fence); 2452 - fences[1] = mfence; 2453 - 2454 - dma_fence_array_init(cf, 2, fences, 2455 - vm->composite_fence_ctx, 2456 - vm->composite_fence_seqno++, 2457 - false); 2458 - __fence = &cf->base; 2459 - } 2460 - 2461 - dma_fence_put(fence); 2462 - fence = __fence; 2463 - } 2464 - 2465 - if (!mjob) { 2468 + if (!mjob && !ijob) { 2466 2469 dma_resv_add_fence(xe_vm_resv(vm), fence, 2467 2470 pt_update_ops->wait_vm_bookkeep ? 2468 2471 DMA_RESV_USAGE_KERNEL : ··· 2451 2492 2452 2493 list_for_each_entry(op, &vops->list, link) 2453 2494 op_commit(vops->vm, tile, pt_update_ops, op, fence, NULL); 2495 + } else if (ijob && !mjob) { 2496 + dma_resv_add_fence(xe_vm_resv(vm), ifence, 2497 + pt_update_ops->wait_vm_bookkeep ? 2498 + DMA_RESV_USAGE_KERNEL : 2499 + DMA_RESV_USAGE_BOOKKEEP); 2500 + 2501 + list_for_each_entry(op, &vops->list, link) 2502 + op_commit(vops->vm, tile, pt_update_ops, op, ifence, NULL); 2454 2503 } else { 2455 2504 dma_resv_add_fence(xe_vm_resv(vm), ifence, 2456 2505 pt_update_ops->wait_vm_bookkeep ? ··· 2478 2511 if (pt_update_ops->needs_svm_lock) 2479 2512 xe_svm_notifier_unlock(vm); 2480 2513 2514 + /* 2515 + * The last fence is only used for zero bind queue idling; migrate 2516 + * queues are not exposed to user space. 2517 + */ 2518 + if (!(q->flags & EXEC_QUEUE_FLAG_MIGRATE)) 2519 + xe_exec_queue_last_fence_set(q, vm, fence); 2520 + 2481 2521 xe_tlb_inval_job_put(mjob); 2482 2522 xe_tlb_inval_job_put(ijob); 2523 + dma_fence_put(ifence); 2524 + dma_fence_put(mfence); 2483 2525 2484 2526 return fence; 2485 2527 2486 2528 free_rfence: 2487 2529 kfree(rfence); 2488 2530 free_ijob: 2489 - kfree(cf); 2490 - kfree(fences); 2491 2531 xe_tlb_inval_job_put(mjob); 2492 2532 xe_tlb_inval_job_put(ijob); 2493 2533 kill_vm_tile1:
+7
drivers/gpu/drm/xe/xe_reg_whitelist.c
··· 89 89 RING_FORCE_TO_NONPRIV_ACCESS_RD | 90 90 RING_FORCE_TO_NONPRIV_RANGE_4)) 91 91 }, 92 + { XE_RTP_NAME("14024997852"), 93 + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005), ENGINE_CLASS(RENDER)), 94 + XE_RTP_ACTIONS(WHITELIST(FF_MODE, 95 + RING_FORCE_TO_NONPRIV_ACCESS_RW), 96 + WHITELIST(VFLSKPD, 97 + RING_FORCE_TO_NONPRIV_ACCESS_RW)) 98 + }, 92 99 }; 93 100 94 101 static void whitelist_apply_to_hwe(struct xe_hw_engine *hwe)
+2 -17
drivers/gpu/drm/xe/xe_sched_job.c
··· 146 146 for (i = 0; i < width; ++i) 147 147 job->ptrs[i].batch_addr = batch_addr[i]; 148 148 149 + atomic_inc(&q->job_cnt); 149 150 xe_pm_runtime_get_noresume(job_to_xe(job)); 150 151 trace_xe_sched_job_create(job); 151 152 return job; ··· 178 177 dma_fence_put(job->fence); 179 178 drm_sched_job_cleanup(&job->drm); 180 179 job_free(job); 180 + atomic_dec(&q->job_cnt); 181 181 xe_exec_queue_put(q); 182 182 xe_pm_runtime_put(xe); 183 183 } ··· 295 293 trace_xe_sched_job_exec(job); 296 294 drm_sched_entity_push_job(&job->drm); 297 295 xe_sched_job_put(job); 298 - } 299 - 300 - /** 301 - * xe_sched_job_last_fence_add_dep - Add last fence dependency to job 302 - * @job:job to add the last fence dependency to 303 - * @vm: virtual memory job belongs to 304 - * 305 - * Returns: 306 - * 0 on success, or an error on failing to expand the array. 307 - */ 308 - int xe_sched_job_last_fence_add_dep(struct xe_sched_job *job, struct xe_vm *vm) 309 - { 310 - struct dma_fence *fence; 311 - 312 - fence = xe_exec_queue_last_fence_get(job->q, vm); 313 - 314 - return drm_sched_job_add_dependency(&job->drm, fence); 315 296 } 316 297 317 298 /**
-1
drivers/gpu/drm/xe/xe_sched_job.h
··· 58 58 void xe_sched_job_arm(struct xe_sched_job *job); 59 59 void xe_sched_job_push(struct xe_sched_job *job); 60 60 61 - int xe_sched_job_last_fence_add_dep(struct xe_sched_job *job, struct xe_vm *vm); 62 61 void xe_sched_job_init_user_fence(struct xe_sched_job *job, 63 62 struct xe_sync_entry *sync); 64 63
+5
drivers/gpu/drm/xe/xe_sriov_pf.c
··· 16 16 #include "xe_sriov_pf.h" 17 17 #include "xe_sriov_pf_helpers.h" 18 18 #include "xe_sriov_pf_service.h" 19 + #include "xe_sriov_pf_sysfs.h" 19 20 #include "xe_sriov_printk.h" 20 21 21 22 static unsigned int wanted_max_vfs(struct xe_device *xe) ··· 128 127 if (err) 129 128 return err; 130 129 } 130 + 131 + err = xe_sriov_pf_sysfs_init(xe); 132 + if (err) 133 + return err; 131 134 132 135 return 0; 133 136 }
+284
drivers/gpu/drm/xe/xe_sriov_pf_provision.c
··· 6 6 #include "xe_assert.h" 7 7 #include "xe_device.h" 8 8 #include "xe_gt_sriov_pf_config.h" 9 + #include "xe_gt_sriov_pf_policy.h" 9 10 #include "xe_sriov.h" 10 11 #include "xe_sriov_pf_helpers.h" 11 12 #include "xe_sriov_pf_provision.h" ··· 152 151 mode_to_string(mode), __builtin_return_address(0)); 153 152 xe->sriov.pf.provision.mode = mode; 154 153 return 0; 154 + } 155 + 156 + /** 157 + * xe_sriov_pf_provision_bulk_apply_eq() - Change execution quantum for all VFs and PF. 158 + * @xe: the PF &xe_device 159 + * @eq: execution quantum in [ms] to set 160 + * 161 + * Change execution quantum (EQ) provisioning on all tiles/GTs. 162 + * 163 + * This function can only be called on PF. 164 + * 165 + * Return: 0 on success or a negative error code on failure. 166 + */ 167 + int xe_sriov_pf_provision_bulk_apply_eq(struct xe_device *xe, u32 eq) 168 + { 169 + struct xe_gt *gt; 170 + unsigned int id; 171 + int result = 0; 172 + int err; 173 + 174 + guard(mutex)(xe_sriov_pf_master_mutex(xe)); 175 + 176 + for_each_gt(gt, xe, id) { 177 + err = xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked(gt, eq); 178 + result = result ?: err; 179 + } 180 + 181 + return result; 182 + } 183 + 184 + /** 185 + * xe_sriov_pf_provision_apply_vf_eq() - Change VF's execution quantum. 186 + * @xe: the PF &xe_device 187 + * @vfid: the VF identifier 188 + * @eq: execution quantum in [ms] to set 189 + * 190 + * Change VF's execution quantum (EQ) provisioning on all tiles/GTs. 191 + * 192 + * This function can only be called on PF. 193 + * 194 + * Return: 0 on success or a negative error code on failure. 195 + */ 196 + int xe_sriov_pf_provision_apply_vf_eq(struct xe_device *xe, unsigned int vfid, u32 eq) 197 + { 198 + struct xe_gt *gt; 199 + unsigned int id; 200 + int result = 0; 201 + int err; 202 + 203 + guard(mutex)(xe_sriov_pf_master_mutex(xe)); 204 + 205 + for_each_gt(gt, xe, id) { 206 + err = xe_gt_sriov_pf_config_set_exec_quantum_locked(gt, vfid, eq); 207 + result = result ?: err; 208 + } 209 + 210 + return result; 211 + } 212 + 213 + static int pf_report_unclean(struct xe_gt *gt, unsigned int vfid, 214 + const char *what, u32 found, u32 expected) 215 + { 216 + char name[8]; 217 + 218 + xe_sriov_dbg(gt_to_xe(gt), "%s on GT%u has %s=%u (expected %u)\n", 219 + xe_sriov_function_name(vfid, name, sizeof(name)), 220 + gt->info.id, what, found, expected); 221 + return -EUCLEAN; 222 + } 223 + 224 + /** 225 + * xe_sriov_pf_provision_query_vf_eq() - Query VF's execution quantum. 226 + * @xe: the PF &xe_device 227 + * @vfid: the VF identifier 228 + * @eq: placeholder for the returned execution quantum in [ms] 229 + * 230 + * Query VF's execution quantum (EQ) provisioning from all tiles/GTs. 231 + * If values across tiles/GTs are inconsistent then -EUCLEAN error will be returned. 232 + * 233 + * This function can only be called on PF. 234 + * 235 + * Return: 0 on success or a negative error code on failure. 236 + */ 237 + int xe_sriov_pf_provision_query_vf_eq(struct xe_device *xe, unsigned int vfid, u32 *eq) 238 + { 239 + struct xe_gt *gt; 240 + unsigned int id; 241 + int count = 0; 242 + u32 value; 243 + 244 + guard(mutex)(xe_sriov_pf_master_mutex(xe)); 245 + 246 + for_each_gt(gt, xe, id) { 247 + value = xe_gt_sriov_pf_config_get_exec_quantum_locked(gt, vfid); 248 + if (!count++) 249 + *eq = value; 250 + else if (value != *eq) 251 + return pf_report_unclean(gt, vfid, "EQ", value, *eq); 252 + } 253 + 254 + return !count ? -ENODATA : 0; 255 + } 256 + 257 + /** 258 + * xe_sriov_pf_provision_bulk_apply_pt() - Change preemption timeout for all VFs and PF. 259 + * @xe: the PF &xe_device 260 + * @pt: preemption timeout in [us] to set 261 + * 262 + * Change preemption timeout (PT) provisioning on all tiles/GTs. 263 + * 264 + * This function can only be called on PF. 265 + * 266 + * Return: 0 on success or a negative error code on failure. 267 + */ 268 + int xe_sriov_pf_provision_bulk_apply_pt(struct xe_device *xe, u32 pt) 269 + { 270 + struct xe_gt *gt; 271 + unsigned int id; 272 + int result = 0; 273 + int err; 274 + 275 + guard(mutex)(xe_sriov_pf_master_mutex(xe)); 276 + 277 + for_each_gt(gt, xe, id) { 278 + err = xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked(gt, pt); 279 + result = result ?: err; 280 + } 281 + 282 + return result; 283 + } 284 + 285 + /** 286 + * xe_sriov_pf_provision_apply_vf_pt() - Change VF's preemption timeout. 287 + * @xe: the PF &xe_device 288 + * @vfid: the VF identifier 289 + * @pt: preemption timeout in [us] to set 290 + * 291 + * Change VF's preemption timeout (PT) provisioning on all tiles/GTs. 292 + * 293 + * This function can only be called on PF. 294 + * 295 + * Return: 0 on success or a negative error code on failure. 296 + */ 297 + int xe_sriov_pf_provision_apply_vf_pt(struct xe_device *xe, unsigned int vfid, u32 pt) 298 + { 299 + struct xe_gt *gt; 300 + unsigned int id; 301 + int result = 0; 302 + int err; 303 + 304 + guard(mutex)(xe_sriov_pf_master_mutex(xe)); 305 + 306 + for_each_gt(gt, xe, id) { 307 + err = xe_gt_sriov_pf_config_set_preempt_timeout_locked(gt, vfid, pt); 308 + result = result ?: err; 309 + } 310 + 311 + return result; 312 + } 313 + 314 + /** 315 + * xe_sriov_pf_provision_query_vf_pt() - Query VF's preemption timeout. 316 + * @xe: the PF &xe_device 317 + * @vfid: the VF identifier 318 + * @pt: placeholder for the returned preemption timeout in [us] 319 + * 320 + * Query VF's preemption timeout (PT) provisioning from all tiles/GTs. 321 + * If values across tiles/GTs are inconsistent then -EUCLEAN error will be returned. 322 + * 323 + * This function can only be called on PF. 324 + * 325 + * Return: 0 on success or a negative error code on failure. 326 + */ 327 + int xe_sriov_pf_provision_query_vf_pt(struct xe_device *xe, unsigned int vfid, u32 *pt) 328 + { 329 + struct xe_gt *gt; 330 + unsigned int id; 331 + int count = 0; 332 + u32 value; 333 + 334 + guard(mutex)(xe_sriov_pf_master_mutex(xe)); 335 + 336 + for_each_gt(gt, xe, id) { 337 + value = xe_gt_sriov_pf_config_get_preempt_timeout_locked(gt, vfid); 338 + if (!count++) 339 + *pt = value; 340 + else if (value != *pt) 341 + return pf_report_unclean(gt, vfid, "PT", value, *pt); 342 + } 343 + 344 + return !count ? -ENODATA : 0; 345 + } 346 + 347 + /** 348 + * xe_sriov_pf_provision_bulk_apply_priority() - Change scheduling priority of all VFs and PF. 349 + * @xe: the PF &xe_device 350 + * @prio: scheduling priority to set 351 + * 352 + * Change the scheduling priority provisioning on all tiles/GTs. 353 + * 354 + * This function can only be called on PF. 355 + * 356 + * Return: 0 on success or a negative error code on failure. 357 + */ 358 + int xe_sriov_pf_provision_bulk_apply_priority(struct xe_device *xe, u32 prio) 359 + { 360 + bool sched_if_idle; 361 + struct xe_gt *gt; 362 + unsigned int id; 363 + int result = 0; 364 + int err; 365 + 366 + /* 367 + * Currently, priority changes that involves VFs are only allowed using 368 + * the 'sched_if_idle' policy KLV, so only LOW and NORMAL are supported. 369 + */ 370 + xe_assert(xe, prio < GUC_SCHED_PRIORITY_HIGH); 371 + sched_if_idle = prio == GUC_SCHED_PRIORITY_NORMAL; 372 + 373 + for_each_gt(gt, xe, id) { 374 + err = xe_gt_sriov_pf_policy_set_sched_if_idle(gt, sched_if_idle); 375 + result = result ?: err; 376 + } 377 + 378 + return result; 379 + } 380 + 381 + /** 382 + * xe_sriov_pf_provision_apply_vf_priority() - Change VF's scheduling priority. 383 + * @xe: the PF &xe_device 384 + * @vfid: the VF identifier 385 + * @prio: scheduling priority to set 386 + * 387 + * Change VF's scheduling priority provisioning on all tiles/GTs. 388 + * 389 + * This function can only be called on PF. 390 + * 391 + * Return: 0 on success or a negative error code on failure. 392 + */ 393 + int xe_sriov_pf_provision_apply_vf_priority(struct xe_device *xe, unsigned int vfid, u32 prio) 394 + { 395 + struct xe_gt *gt; 396 + unsigned int id; 397 + int result = 0; 398 + int err; 399 + 400 + for_each_gt(gt, xe, id) { 401 + err = xe_gt_sriov_pf_config_set_sched_priority(gt, vfid, prio); 402 + result = result ?: err; 403 + } 404 + 405 + return result; 406 + } 407 + 408 + /** 409 + * xe_sriov_pf_provision_query_vf_priority() - Query VF's scheduling priority. 410 + * @xe: the PF &xe_device 411 + * @vfid: the VF identifier 412 + * @prio: placeholder for the returned scheduling priority 413 + * 414 + * Query VF's scheduling priority provisioning from all tiles/GTs. 415 + * If values across tiles/GTs are inconsistent then -EUCLEAN error will be returned. 416 + * 417 + * This function can only be called on PF. 418 + * 419 + * Return: 0 on success or a negative error code on failure. 420 + */ 421 + int xe_sriov_pf_provision_query_vf_priority(struct xe_device *xe, unsigned int vfid, u32 *prio) 422 + { 423 + struct xe_gt *gt; 424 + unsigned int id; 425 + int count = 0; 426 + u32 value; 427 + 428 + for_each_gt(gt, xe, id) { 429 + value = xe_gt_sriov_pf_config_get_sched_priority(gt, vfid); 430 + if (!count++) 431 + *prio = value; 432 + else if (value != *prio) 433 + return pf_report_unclean(gt, vfid, "priority", value, *prio); 434 + } 435 + 436 + return !count ? -ENODATA : 0; 155 437 }
+14
drivers/gpu/drm/xe/xe_sriov_pf_provision.h
··· 6 6 #ifndef _XE_SRIOV_PF_PROVISION_H_ 7 7 #define _XE_SRIOV_PF_PROVISION_H_ 8 8 9 + #include <linux/types.h> 10 + 9 11 #include "xe_sriov_pf_provision_types.h" 10 12 11 13 struct xe_device; 14 + 15 + int xe_sriov_pf_provision_bulk_apply_eq(struct xe_device *xe, u32 eq); 16 + int xe_sriov_pf_provision_apply_vf_eq(struct xe_device *xe, unsigned int vfid, u32 eq); 17 + int xe_sriov_pf_provision_query_vf_eq(struct xe_device *xe, unsigned int vfid, u32 *eq); 18 + 19 + int xe_sriov_pf_provision_bulk_apply_pt(struct xe_device *xe, u32 pt); 20 + int xe_sriov_pf_provision_apply_vf_pt(struct xe_device *xe, unsigned int vfid, u32 pt); 21 + int xe_sriov_pf_provision_query_vf_pt(struct xe_device *xe, unsigned int vfid, u32 *pt); 22 + 23 + int xe_sriov_pf_provision_bulk_apply_priority(struct xe_device *xe, u32 prio); 24 + int xe_sriov_pf_provision_apply_vf_priority(struct xe_device *xe, unsigned int vfid, u32 prio); 25 + int xe_sriov_pf_provision_query_vf_priority(struct xe_device *xe, unsigned int vfid, u32 *prio); 12 26 13 27 int xe_sriov_pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs); 14 28 int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs);
+647
drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include <linux/kobject.h> 7 + #include <linux/sysfs.h> 8 + 9 + #include <drm/drm_managed.h> 10 + 11 + #include "xe_assert.h" 12 + #include "xe_pci_sriov.h" 13 + #include "xe_pm.h" 14 + #include "xe_sriov.h" 15 + #include "xe_sriov_pf.h" 16 + #include "xe_sriov_pf_control.h" 17 + #include "xe_sriov_pf_helpers.h" 18 + #include "xe_sriov_pf_provision.h" 19 + #include "xe_sriov_pf_sysfs.h" 20 + #include "xe_sriov_printk.h" 21 + 22 + static int emit_choice(char *buf, int choice, const char * const *array, size_t size) 23 + { 24 + int pos = 0; 25 + int n; 26 + 27 + for (n = 0; n < size; n++) { 28 + pos += sysfs_emit_at(buf, pos, "%s%s%s%s", 29 + n ? " " : "", 30 + n == choice ? "[" : "", 31 + array[n], 32 + n == choice ? "]" : ""); 33 + } 34 + pos += sysfs_emit_at(buf, pos, "\n"); 35 + 36 + return pos; 37 + } 38 + 39 + /* 40 + * /sys/bus/pci/drivers/xe/BDF/ 41 + * : 42 + * ├── sriov_admin/ 43 + * ├── ... 44 + * ├── .bulk_profile 45 + * │ ├── exec_quantum_ms 46 + * │ ├── preempt_timeout_us 47 + * │ └── sched_priority 48 + * ├── pf/ 49 + * │ ├── ... 50 + * │ ├── device -> ../../../BDF 51 + * │ └── profile 52 + * │ ├── exec_quantum_ms 53 + * │ ├── preempt_timeout_us 54 + * │ └── sched_priority 55 + * ├── vf1/ 56 + * │ ├── ... 57 + * │ ├── device -> ../../../BDF.1 58 + * │ ├── stop 59 + * │ └── profile 60 + * │ ├── exec_quantum_ms 61 + * │ ├── preempt_timeout_us 62 + * │ └── sched_priority 63 + * ├── vf2/ 64 + * : 65 + * └── vfN/ 66 + */ 67 + 68 + struct xe_sriov_kobj { 69 + struct kobject base; 70 + struct xe_device *xe; 71 + unsigned int vfid; 72 + }; 73 + #define to_xe_sriov_kobj(p) container_of_const((p), struct xe_sriov_kobj, base) 74 + 75 + struct xe_sriov_dev_attr { 76 + struct attribute attr; 77 + ssize_t (*show)(struct xe_device *xe, char *buf); 78 + ssize_t (*store)(struct xe_device *xe, const char *buf, size_t count); 79 + }; 80 + #define to_xe_sriov_dev_attr(p) container_of_const((p), struct xe_sriov_dev_attr, attr) 81 + 82 + #define XE_SRIOV_DEV_ATTR(NAME) \ 83 + struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \ 84 + __ATTR(NAME, 0644, xe_sriov_dev_attr_##NAME##_show, xe_sriov_dev_attr_##NAME##_store) 85 + 86 + #define XE_SRIOV_DEV_ATTR_RO(NAME) \ 87 + struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \ 88 + __ATTR(NAME, 0444, xe_sriov_dev_attr_##NAME##_show, NULL) 89 + 90 + #define XE_SRIOV_DEV_ATTR_WO(NAME) \ 91 + struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \ 92 + __ATTR(NAME, 0200, NULL, xe_sriov_dev_attr_##NAME##_store) 93 + 94 + struct xe_sriov_vf_attr { 95 + struct attribute attr; 96 + ssize_t (*show)(struct xe_device *xe, unsigned int vfid, char *buf); 97 + ssize_t (*store)(struct xe_device *xe, unsigned int vfid, const char *buf, size_t count); 98 + }; 99 + #define to_xe_sriov_vf_attr(p) container_of_const((p), struct xe_sriov_vf_attr, attr) 100 + 101 + #define XE_SRIOV_VF_ATTR(NAME) \ 102 + struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \ 103 + __ATTR(NAME, 0644, xe_sriov_vf_attr_##NAME##_show, xe_sriov_vf_attr_##NAME##_store) 104 + 105 + #define XE_SRIOV_VF_ATTR_RO(NAME) \ 106 + struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \ 107 + __ATTR(NAME, 0444, xe_sriov_vf_attr_##NAME##_show, NULL) 108 + 109 + #define XE_SRIOV_VF_ATTR_WO(NAME) \ 110 + struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \ 111 + __ATTR(NAME, 0200, NULL, xe_sriov_vf_attr_##NAME##_store) 112 + 113 + /* device level attributes go here */ 114 + 115 + #define DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(NAME, ITEM, TYPE) \ 116 + \ 117 + static ssize_t xe_sriov_dev_attr_##NAME##_store(struct xe_device *xe, \ 118 + const char *buf, size_t count) \ 119 + { \ 120 + TYPE value; \ 121 + int err; \ 122 + \ 123 + err = kstrto##TYPE(buf, 0, &value); \ 124 + if (err) \ 125 + return err; \ 126 + \ 127 + err = xe_sriov_pf_provision_bulk_apply_##ITEM(xe, value); \ 128 + return err ?: count; \ 129 + } \ 130 + \ 131 + static XE_SRIOV_DEV_ATTR_WO(NAME) 132 + 133 + DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(exec_quantum_ms, eq, u32); 134 + DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(preempt_timeout_us, pt, u32); 135 + 136 + static const char * const sched_priority_names[] = { 137 + [GUC_SCHED_PRIORITY_LOW] = "low", 138 + [GUC_SCHED_PRIORITY_NORMAL] = "normal", 139 + [GUC_SCHED_PRIORITY_HIGH] = "high", 140 + }; 141 + 142 + static bool sched_priority_change_allowed(unsigned int vfid) 143 + { 144 + /* As of today GuC FW allows to selectively change only the PF priority. */ 145 + return vfid == PFID; 146 + } 147 + 148 + static bool sched_priority_high_allowed(unsigned int vfid) 149 + { 150 + /* As of today GuC FW allows to select 'high' priority only for the PF. */ 151 + return vfid == PFID; 152 + } 153 + 154 + static bool sched_priority_bulk_high_allowed(struct xe_device *xe) 155 + { 156 + /* all VFs are equal - it's sufficient to check VF1 only */ 157 + return sched_priority_high_allowed(VFID(1)); 158 + } 159 + 160 + static ssize_t xe_sriov_dev_attr_sched_priority_store(struct xe_device *xe, 161 + const char *buf, size_t count) 162 + { 163 + size_t num_priorities = ARRAY_SIZE(sched_priority_names); 164 + int match; 165 + int err; 166 + 167 + if (!sched_priority_bulk_high_allowed(xe)) 168 + num_priorities--; 169 + 170 + match = __sysfs_match_string(sched_priority_names, num_priorities, buf); 171 + if (match < 0) 172 + return -EINVAL; 173 + 174 + err = xe_sriov_pf_provision_bulk_apply_priority(xe, match); 175 + return err ?: count; 176 + } 177 + 178 + static XE_SRIOV_DEV_ATTR_WO(sched_priority); 179 + 180 + static struct attribute *bulk_profile_dev_attrs[] = { 181 + &xe_sriov_dev_attr_exec_quantum_ms.attr, 182 + &xe_sriov_dev_attr_preempt_timeout_us.attr, 183 + &xe_sriov_dev_attr_sched_priority.attr, 184 + NULL 185 + }; 186 + 187 + static const struct attribute_group bulk_profile_dev_attr_group = { 188 + .name = ".bulk_profile", 189 + .attrs = bulk_profile_dev_attrs, 190 + }; 191 + 192 + static const struct attribute_group *xe_sriov_dev_attr_groups[] = { 193 + &bulk_profile_dev_attr_group, 194 + NULL 195 + }; 196 + 197 + /* and VF-level attributes go here */ 198 + 199 + #define DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(NAME, ITEM, TYPE, FORMAT) \ 200 + static ssize_t xe_sriov_vf_attr_##NAME##_show(struct xe_device *xe, unsigned int vfid, \ 201 + char *buf) \ 202 + { \ 203 + TYPE value = 0; \ 204 + int err; \ 205 + \ 206 + err = xe_sriov_pf_provision_query_vf_##ITEM(xe, vfid, &value); \ 207 + if (err) \ 208 + return err; \ 209 + \ 210 + return sysfs_emit(buf, FORMAT, value); \ 211 + } \ 212 + \ 213 + static ssize_t xe_sriov_vf_attr_##NAME##_store(struct xe_device *xe, unsigned int vfid, \ 214 + const char *buf, size_t count) \ 215 + { \ 216 + TYPE value; \ 217 + int err; \ 218 + \ 219 + err = kstrto##TYPE(buf, 0, &value); \ 220 + if (err) \ 221 + return err; \ 222 + \ 223 + err = xe_sriov_pf_provision_apply_vf_##ITEM(xe, vfid, value); \ 224 + return err ?: count; \ 225 + } \ 226 + \ 227 + static XE_SRIOV_VF_ATTR(NAME) 228 + 229 + DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(exec_quantum_ms, eq, u32, "%u\n"); 230 + DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(preempt_timeout_us, pt, u32, "%u\n"); 231 + 232 + static ssize_t xe_sriov_vf_attr_sched_priority_show(struct xe_device *xe, unsigned int vfid, 233 + char *buf) 234 + { 235 + size_t num_priorities = ARRAY_SIZE(sched_priority_names); 236 + u32 priority; 237 + int err; 238 + 239 + err = xe_sriov_pf_provision_query_vf_priority(xe, vfid, &priority); 240 + if (err) 241 + return err; 242 + 243 + if (!sched_priority_high_allowed(vfid)) 244 + num_priorities--; 245 + 246 + xe_assert(xe, priority < num_priorities); 247 + return emit_choice(buf, priority, sched_priority_names, num_priorities); 248 + } 249 + 250 + static ssize_t xe_sriov_vf_attr_sched_priority_store(struct xe_device *xe, unsigned int vfid, 251 + const char *buf, size_t count) 252 + { 253 + size_t num_priorities = ARRAY_SIZE(sched_priority_names); 254 + int match; 255 + int err; 256 + 257 + if (!sched_priority_change_allowed(vfid)) 258 + return -EOPNOTSUPP; 259 + 260 + if (!sched_priority_high_allowed(vfid)) 261 + num_priorities--; 262 + 263 + match = __sysfs_match_string(sched_priority_names, num_priorities, buf); 264 + if (match < 0) 265 + return -EINVAL; 266 + 267 + err = xe_sriov_pf_provision_apply_vf_priority(xe, vfid, match); 268 + return err ?: count; 269 + } 270 + 271 + static XE_SRIOV_VF_ATTR(sched_priority); 272 + 273 + static struct attribute *profile_vf_attrs[] = { 274 + &xe_sriov_vf_attr_exec_quantum_ms.attr, 275 + &xe_sriov_vf_attr_preempt_timeout_us.attr, 276 + &xe_sriov_vf_attr_sched_priority.attr, 277 + NULL 278 + }; 279 + 280 + static umode_t profile_vf_attr_is_visible(struct kobject *kobj, 281 + struct attribute *attr, int index) 282 + { 283 + struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 284 + 285 + if (attr == &xe_sriov_vf_attr_sched_priority.attr && 286 + !sched_priority_change_allowed(vkobj->vfid)) 287 + return attr->mode & 0444; 288 + 289 + return attr->mode; 290 + } 291 + 292 + static const struct attribute_group profile_vf_attr_group = { 293 + .name = "profile", 294 + .attrs = profile_vf_attrs, 295 + .is_visible = profile_vf_attr_is_visible, 296 + }; 297 + 298 + #define DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(NAME) \ 299 + \ 300 + static ssize_t xe_sriov_vf_attr_##NAME##_store(struct xe_device *xe, unsigned int vfid, \ 301 + const char *buf, size_t count) \ 302 + { \ 303 + bool yes; \ 304 + int err; \ 305 + \ 306 + if (!vfid) \ 307 + return -EPERM; \ 308 + \ 309 + err = kstrtobool(buf, &yes); \ 310 + if (err) \ 311 + return err; \ 312 + if (!yes) \ 313 + return count; \ 314 + \ 315 + err = xe_sriov_pf_control_##NAME##_vf(xe, vfid); \ 316 + return err ?: count; \ 317 + } \ 318 + \ 319 + static XE_SRIOV_VF_ATTR_WO(NAME) 320 + 321 + DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(stop); 322 + 323 + static struct attribute *control_vf_attrs[] = { 324 + &xe_sriov_vf_attr_stop.attr, 325 + NULL 326 + }; 327 + 328 + static umode_t control_vf_attr_is_visible(struct kobject *kobj, 329 + struct attribute *attr, int index) 330 + { 331 + struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 332 + 333 + if (vkobj->vfid == PFID) 334 + return 0; 335 + 336 + return attr->mode; 337 + } 338 + 339 + static const struct attribute_group control_vf_attr_group = { 340 + .attrs = control_vf_attrs, 341 + .is_visible = control_vf_attr_is_visible, 342 + }; 343 + 344 + static const struct attribute_group *xe_sriov_vf_attr_groups[] = { 345 + &profile_vf_attr_group, 346 + &control_vf_attr_group, 347 + NULL 348 + }; 349 + 350 + /* no user serviceable parts below */ 351 + 352 + static struct kobject *create_xe_sriov_kobj(struct xe_device *xe, unsigned int vfid) 353 + { 354 + struct xe_sriov_kobj *vkobj; 355 + 356 + xe_sriov_pf_assert_vfid(xe, vfid); 357 + 358 + vkobj = kzalloc(sizeof(*vkobj), GFP_KERNEL); 359 + if (!vkobj) 360 + return NULL; 361 + 362 + vkobj->xe = xe; 363 + vkobj->vfid = vfid; 364 + return &vkobj->base; 365 + } 366 + 367 + static void release_xe_sriov_kobj(struct kobject *kobj) 368 + { 369 + struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 370 + 371 + kfree(vkobj); 372 + } 373 + 374 + static ssize_t xe_sriov_dev_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) 375 + { 376 + struct xe_sriov_dev_attr *vattr = to_xe_sriov_dev_attr(attr); 377 + struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 378 + struct xe_device *xe = vkobj->xe; 379 + 380 + if (!vattr->show) 381 + return -EPERM; 382 + 383 + return vattr->show(xe, buf); 384 + } 385 + 386 + static ssize_t xe_sriov_dev_attr_store(struct kobject *kobj, struct attribute *attr, 387 + const char *buf, size_t count) 388 + { 389 + struct xe_sriov_dev_attr *vattr = to_xe_sriov_dev_attr(attr); 390 + struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 391 + struct xe_device *xe = vkobj->xe; 392 + ssize_t ret; 393 + 394 + if (!vattr->store) 395 + return -EPERM; 396 + 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; 402 + } 403 + 404 + static ssize_t xe_sriov_vf_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) 405 + { 406 + struct xe_sriov_vf_attr *vattr = to_xe_sriov_vf_attr(attr); 407 + struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 408 + struct xe_device *xe = vkobj->xe; 409 + unsigned int vfid = vkobj->vfid; 410 + 411 + xe_sriov_pf_assert_vfid(xe, vfid); 412 + 413 + if (!vattr->show) 414 + return -EPERM; 415 + 416 + return vattr->show(xe, vfid, buf); 417 + } 418 + 419 + static ssize_t xe_sriov_vf_attr_store(struct kobject *kobj, struct attribute *attr, 420 + const char *buf, size_t count) 421 + { 422 + struct xe_sriov_vf_attr *vattr = to_xe_sriov_vf_attr(attr); 423 + struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 424 + struct xe_device *xe = vkobj->xe; 425 + unsigned int vfid = vkobj->vfid; 426 + ssize_t ret; 427 + 428 + xe_sriov_pf_assert_vfid(xe, vfid); 429 + 430 + if (!vattr->store) 431 + return -EPERM; 432 + 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; 438 + } 439 + 440 + static const struct sysfs_ops xe_sriov_dev_sysfs_ops = { 441 + .show = xe_sriov_dev_attr_show, 442 + .store = xe_sriov_dev_attr_store, 443 + }; 444 + 445 + static const struct sysfs_ops xe_sriov_vf_sysfs_ops = { 446 + .show = xe_sriov_vf_attr_show, 447 + .store = xe_sriov_vf_attr_store, 448 + }; 449 + 450 + static const struct kobj_type xe_sriov_dev_ktype = { 451 + .release = release_xe_sriov_kobj, 452 + .sysfs_ops = &xe_sriov_dev_sysfs_ops, 453 + .default_groups = xe_sriov_dev_attr_groups, 454 + }; 455 + 456 + static const struct kobj_type xe_sriov_vf_ktype = { 457 + .release = release_xe_sriov_kobj, 458 + .sysfs_ops = &xe_sriov_vf_sysfs_ops, 459 + .default_groups = xe_sriov_vf_attr_groups, 460 + }; 461 + 462 + static int pf_sysfs_error(struct xe_device *xe, int err, const char *what) 463 + { 464 + if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) 465 + xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err)); 466 + return err; 467 + } 468 + 469 + static void pf_sysfs_note(struct xe_device *xe, int err, const char *what) 470 + { 471 + xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err)); 472 + } 473 + 474 + static void action_put_kobject(void *arg) 475 + { 476 + struct kobject *kobj = arg; 477 + 478 + kobject_put(kobj); 479 + } 480 + 481 + static int pf_setup_root(struct xe_device *xe) 482 + { 483 + struct kobject *parent = &xe->drm.dev->kobj; 484 + struct kobject *root; 485 + int err; 486 + 487 + root = create_xe_sriov_kobj(xe, PFID); 488 + if (!root) 489 + return pf_sysfs_error(xe, -ENOMEM, "root obj"); 490 + 491 + err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root); 492 + if (err) 493 + return pf_sysfs_error(xe, err, "root action"); 494 + 495 + err = kobject_init_and_add(root, &xe_sriov_dev_ktype, parent, "sriov_admin"); 496 + if (err) 497 + return pf_sysfs_error(xe, err, "root init"); 498 + 499 + xe_assert(xe, IS_SRIOV_PF(xe)); 500 + xe_assert(xe, !xe->sriov.pf.sysfs.root); 501 + xe->sriov.pf.sysfs.root = root; 502 + return 0; 503 + } 504 + 505 + static int pf_setup_tree(struct xe_device *xe) 506 + { 507 + unsigned int totalvfs = xe_sriov_pf_get_totalvfs(xe); 508 + struct kobject *root, *kobj; 509 + unsigned int n; 510 + int err; 511 + 512 + xe_assert(xe, IS_SRIOV_PF(xe)); 513 + root = xe->sriov.pf.sysfs.root; 514 + 515 + for (n = 0; n <= totalvfs; n++) { 516 + kobj = create_xe_sriov_kobj(xe, VFID(n)); 517 + if (!kobj) 518 + return pf_sysfs_error(xe, -ENOMEM, "tree obj"); 519 + 520 + err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root); 521 + if (err) 522 + return pf_sysfs_error(xe, err, "tree action"); 523 + 524 + if (n) 525 + err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype, 526 + root, "vf%u", n); 527 + else 528 + err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype, 529 + root, "pf"); 530 + if (err) 531 + return pf_sysfs_error(xe, err, "tree init"); 532 + 533 + xe_assert(xe, !xe->sriov.pf.vfs[n].kobj); 534 + xe->sriov.pf.vfs[n].kobj = kobj; 535 + } 536 + 537 + return 0; 538 + } 539 + 540 + static void action_rm_device_link(void *arg) 541 + { 542 + struct kobject *kobj = arg; 543 + 544 + sysfs_remove_link(kobj, "device"); 545 + } 546 + 547 + static int pf_link_pf_device(struct xe_device *xe) 548 + { 549 + struct kobject *kobj = xe->sriov.pf.vfs[PFID].kobj; 550 + int err; 551 + 552 + err = sysfs_create_link(kobj, &xe->drm.dev->kobj, "device"); 553 + if (err) 554 + return pf_sysfs_error(xe, err, "PF device link"); 555 + 556 + err = devm_add_action_or_reset(xe->drm.dev, action_rm_device_link, kobj); 557 + if (err) 558 + return pf_sysfs_error(xe, err, "PF unlink action"); 559 + 560 + return 0; 561 + } 562 + 563 + /** 564 + * xe_sriov_pf_sysfs_init() - Setup PF's SR-IOV sysfs tree. 565 + * @xe: the PF &xe_device to setup sysfs 566 + * 567 + * This function will create additional nodes that will represent PF and VFs 568 + * devices, each populated with SR-IOV Xe specific attributes. 569 + * 570 + * Return: 0 on success or a negative error code on failure. 571 + */ 572 + int xe_sriov_pf_sysfs_init(struct xe_device *xe) 573 + { 574 + int err; 575 + 576 + err = pf_setup_root(xe); 577 + if (err) 578 + return err; 579 + 580 + err = pf_setup_tree(xe); 581 + if (err) 582 + return err; 583 + 584 + err = pf_link_pf_device(xe); 585 + if (err) 586 + return err; 587 + 588 + return 0; 589 + } 590 + 591 + /** 592 + * xe_sriov_pf_sysfs_link_vfs() - Add VF's links in SR-IOV sysfs tree. 593 + * @xe: the &xe_device where to update sysfs 594 + * @num_vfs: number of enabled VFs to link 595 + * 596 + * This function is specific for the PF driver. 597 + * 598 + * This function will add symbolic links between VFs represented in the SR-IOV 599 + * sysfs tree maintained by the PF and enabled VF PCI devices. 600 + * 601 + * The @xe_sriov_pf_sysfs_unlink_vfs() shall be used to remove those links. 602 + */ 603 + void xe_sriov_pf_sysfs_link_vfs(struct xe_device *xe, unsigned int num_vfs) 604 + { 605 + unsigned int totalvfs = xe_sriov_pf_get_totalvfs(xe); 606 + struct pci_dev *pf_pdev = to_pci_dev(xe->drm.dev); 607 + struct pci_dev *vf_pdev = NULL; 608 + unsigned int n; 609 + int err; 610 + 611 + xe_assert(xe, IS_SRIOV_PF(xe)); 612 + xe_assert(xe, num_vfs <= totalvfs); 613 + 614 + for (n = 1; n <= num_vfs; n++) { 615 + vf_pdev = xe_pci_sriov_get_vf_pdev(pf_pdev, VFID(n)); 616 + if (!vf_pdev) 617 + return pf_sysfs_note(xe, -ENOENT, "VF link"); 618 + 619 + err = sysfs_create_link(xe->sriov.pf.vfs[VFID(n)].kobj, 620 + &vf_pdev->dev.kobj, "device"); 621 + 622 + /* must balance xe_pci_sriov_get_vf_pdev() */ 623 + pci_dev_put(vf_pdev); 624 + 625 + if (err) 626 + return pf_sysfs_note(xe, err, "VF link"); 627 + } 628 + } 629 + 630 + /** 631 + * xe_sriov_pf_sysfs_unlink_vfs() - Remove VF's links from SR-IOV sysfs tree. 632 + * @xe: the &xe_device where to update sysfs 633 + * @num_vfs: number of VFs to unlink 634 + * 635 + * This function shall be called only on the PF. 636 + * This function will remove "device" links added by @xe_sriov_sysfs_link_vfs(). 637 + */ 638 + void xe_sriov_pf_sysfs_unlink_vfs(struct xe_device *xe, unsigned int num_vfs) 639 + { 640 + unsigned int n; 641 + 642 + xe_assert(xe, IS_SRIOV_PF(xe)); 643 + xe_assert(xe, num_vfs <= xe_sriov_pf_get_totalvfs(xe)); 644 + 645 + for (n = 1; n <= num_vfs; n++) 646 + sysfs_remove_link(xe->sriov.pf.vfs[VFID(n)].kobj, "device"); 647 + }
+16
drivers/gpu/drm/xe/xe_sriov_pf_sysfs.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_SRIOV_PF_SYSFS_H_ 7 + #define _XE_SRIOV_PF_SYSFS_H_ 8 + 9 + struct xe_device; 10 + 11 + int xe_sriov_pf_sysfs_init(struct xe_device *xe); 12 + 13 + void xe_sriov_pf_sysfs_link_vfs(struct xe_device *xe, unsigned int num_vfs); 14 + void xe_sriov_pf_sysfs_unlink_vfs(struct xe_device *xe, unsigned int num_vfs); 15 + 16 + #endif
+11
drivers/gpu/drm/xe/xe_sriov_pf_types.h
··· 12 12 #include "xe_sriov_pf_provision_types.h" 13 13 #include "xe_sriov_pf_service_types.h" 14 14 15 + struct kobject; 16 + 15 17 /** 16 18 * struct xe_sriov_metadata - per-VF device level metadata 17 19 */ 18 20 struct xe_sriov_metadata { 21 + /** @kobj: kobject representing VF in PF's SR-IOV sysfs tree. */ 22 + struct kobject *kobj; 23 + 19 24 /** @version: negotiated VF/PF ABI version */ 20 25 struct xe_sriov_pf_service_version version; 21 26 }; ··· 46 41 47 42 /** @service: device level service data. */ 48 43 struct xe_sriov_pf_service service; 44 + 45 + /** @sysfs: device level sysfs data. */ 46 + struct { 47 + /** @sysfs.root: the root kobject for all SR-IOV entries in sysfs. */ 48 + struct kobject *root; 49 + } sysfs; 49 50 50 51 /** @vfs: metadata for all VFs. */ 51 52 struct xe_sriov_metadata *vfs;
+1 -2
drivers/gpu/drm/xe/xe_svm.c
··· 104 104 &vm->svm.garbage_collector.range_list); 105 105 spin_unlock(&vm->svm.garbage_collector.lock); 106 106 107 - queue_work(xe_device_get_root_tile(xe)->primary_gt->usm.pf_wq, 108 - &vm->svm.garbage_collector.work); 107 + queue_work(xe->usm.pf_wq, &vm->svm.garbage_collector.work); 109 108 } 110 109 111 110 static void xe_svm_tlb_inval_count_stats_incr(struct xe_gt *gt)
+58 -37
drivers/gpu/drm/xe/xe_sync.c
··· 14 14 #include <drm/drm_syncobj.h> 15 15 #include <uapi/drm/xe_drm.h> 16 16 17 - #include "xe_device_types.h" 17 + #include "xe_device.h" 18 18 #include "xe_exec_queue.h" 19 19 #include "xe_macros.h" 20 20 #include "xe_sched_job_types.h" ··· 113 113 int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef, 114 114 struct xe_sync_entry *sync, 115 115 struct drm_xe_sync __user *sync_user, 116 + struct drm_syncobj *ufence_syncobj, 117 + u64 ufence_timeline_value, 116 118 unsigned int flags) 117 119 { 118 120 struct drm_xe_sync sync_in; ··· 194 192 if (exec) { 195 193 sync->addr = sync_in.addr; 196 194 } else { 195 + sync->ufence_timeline_value = ufence_timeline_value; 197 196 sync->ufence = user_fence_create(xe, sync_in.addr, 198 197 sync_in.timeline_value); 199 198 if (XE_IOCTL_DBG(xe, IS_ERR(sync->ufence))) 200 199 return PTR_ERR(sync->ufence); 200 + sync->ufence_chain_fence = dma_fence_chain_alloc(); 201 + if (!sync->ufence_chain_fence) 202 + return -ENOMEM; 203 + sync->ufence_syncobj = ufence_syncobj; 201 204 } 202 205 203 206 break; ··· 246 239 } else if (sync->ufence) { 247 240 int err; 248 241 249 - dma_fence_get(fence); 242 + drm_syncobj_add_point(sync->ufence_syncobj, 243 + sync->ufence_chain_fence, 244 + fence, sync->ufence_timeline_value); 245 + sync->ufence_chain_fence = NULL; 246 + 247 + fence = drm_syncobj_fence_get(sync->ufence_syncobj); 250 248 user_fence_get(sync->ufence); 251 249 err = dma_fence_add_callback(fence, &sync->ufence->cb, 252 250 user_fence_cb); ··· 271 259 drm_syncobj_put(sync->syncobj); 272 260 dma_fence_put(sync->fence); 273 261 dma_fence_chain_free(sync->chain_fence); 274 - if (sync->ufence) 262 + dma_fence_chain_free(sync->ufence_chain_fence); 263 + if (!IS_ERR_OR_NULL(sync->ufence)) 275 264 user_fence_put(sync->ufence); 276 265 } 277 266 ··· 297 284 struct dma_fence **fences = NULL; 298 285 struct dma_fence_array *cf = NULL; 299 286 struct dma_fence *fence; 300 - int i, num_in_fence = 0, current_fence = 0; 287 + int i, num_fence = 0, current_fence = 0; 301 288 302 289 lockdep_assert_held(&vm->lock); 303 290 304 - /* Count in-fences */ 305 - for (i = 0; i < num_sync; ++i) { 306 - if (sync[i].fence) { 307 - ++num_in_fence; 308 - fence = sync[i].fence; 291 + /* Reject in fences */ 292 + for (i = 0; i < num_sync; ++i) 293 + if (sync[i].fence) 294 + return ERR_PTR(-EOPNOTSUPP); 295 + 296 + if (q->flags & EXEC_QUEUE_FLAG_VM) { 297 + struct xe_exec_queue *__q; 298 + struct xe_tile *tile; 299 + u8 id; 300 + 301 + for_each_tile(tile, vm->xe, id) 302 + num_fence += (1 + XE_MAX_GT_PER_TILE); 303 + 304 + fences = kmalloc_array(num_fence, sizeof(*fences), 305 + GFP_KERNEL); 306 + if (!fences) 307 + return ERR_PTR(-ENOMEM); 308 + 309 + fences[current_fence++] = 310 + xe_exec_queue_last_fence_get(q, vm); 311 + for_each_tlb_inval(i) 312 + fences[current_fence++] = 313 + xe_exec_queue_tlb_inval_last_fence_get(q, vm, i); 314 + list_for_each_entry(__q, &q->multi_gt_list, 315 + multi_gt_link) { 316 + fences[current_fence++] = 317 + xe_exec_queue_last_fence_get(__q, vm); 318 + for_each_tlb_inval(i) 319 + fences[current_fence++] = 320 + xe_exec_queue_tlb_inval_last_fence_get(__q, vm, i); 309 321 } 322 + 323 + xe_assert(vm->xe, current_fence == num_fence); 324 + cf = dma_fence_array_create(num_fence, fences, 325 + dma_fence_context_alloc(1), 326 + 1, false); 327 + if (!cf) 328 + goto err_out; 329 + 330 + return &cf->base; 310 331 } 311 332 312 - /* Easy case... */ 313 - if (!num_in_fence) { 314 - fence = xe_exec_queue_last_fence_get(q, vm); 315 - return fence; 316 - } 317 - 318 - /* Create composite fence */ 319 - fences = kmalloc_array(num_in_fence + 1, sizeof(*fences), GFP_KERNEL); 320 - if (!fences) 321 - return ERR_PTR(-ENOMEM); 322 - for (i = 0; i < num_sync; ++i) { 323 - if (sync[i].fence) { 324 - dma_fence_get(sync[i].fence); 325 - fences[current_fence++] = sync[i].fence; 326 - } 327 - } 328 - fences[current_fence++] = xe_exec_queue_last_fence_get(q, vm); 329 - cf = dma_fence_array_create(num_in_fence, fences, 330 - vm->composite_fence_ctx, 331 - vm->composite_fence_seqno++, 332 - false); 333 - if (!cf) { 334 - --vm->composite_fence_seqno; 335 - goto err_out; 336 - } 337 - 338 - return &cf->base; 333 + fence = xe_exec_queue_last_fence_get(q, vm); 334 + return fence; 339 335 340 336 err_out: 341 337 while (current_fence) 342 338 dma_fence_put(fences[--current_fence]); 343 339 kfree(fences); 344 - kfree(cf); 345 340 346 341 return ERR_PTR(-ENOMEM); 347 342 }
+3
drivers/gpu/drm/xe/xe_sync.h
··· 8 8 9 9 #include "xe_sync_types.h" 10 10 11 + struct drm_syncobj; 11 12 struct xe_device; 12 13 struct xe_exec_queue; 13 14 struct xe_file; ··· 22 21 int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef, 23 22 struct xe_sync_entry *sync, 24 23 struct drm_xe_sync __user *sync_user, 24 + struct drm_syncobj *ufence_syncobj, 25 + u64 ufence_timeline_value, 25 26 unsigned int flags); 26 27 int xe_sync_entry_add_deps(struct xe_sync_entry *sync, 27 28 struct xe_sched_job *job);
+3
drivers/gpu/drm/xe/xe_sync_types.h
··· 18 18 struct drm_syncobj *syncobj; 19 19 struct dma_fence *fence; 20 20 struct dma_fence_chain *chain_fence; 21 + struct dma_fence_chain *ufence_chain_fence; 22 + struct drm_syncobj *ufence_syncobj; 21 23 struct xe_user_fence *ufence; 22 24 u64 addr; 23 25 u64 timeline_value; 26 + u64 ufence_timeline_value; 24 27 u32 type; 25 28 u32 flags; 26 29 };
+24 -7
drivers/gpu/drm/xe/xe_tlb_inval_job.c
··· 12 12 #include "xe_tlb_inval_job.h" 13 13 #include "xe_migrate.h" 14 14 #include "xe_pm.h" 15 + #include "xe_vm.h" 15 16 16 17 /** struct xe_tlb_inval_job - TLB invalidation job */ 17 18 struct xe_tlb_inval_job { ··· 22 21 struct xe_tlb_inval *tlb_inval; 23 22 /** @q: exec queue issuing the invalidate */ 24 23 struct xe_exec_queue *q; 24 + /** @vm: VM which TLB invalidation is being issued for */ 25 + struct xe_vm *vm; 25 26 /** @refcount: ref count of this job */ 26 27 struct kref refcount; 27 28 /** ··· 35 32 u64 start; 36 33 /** @end: End address to invalidate */ 37 34 u64 end; 38 - /** @asid: Address space ID to invalidate */ 39 - u32 asid; 35 + /** @type: GT type */ 36 + int type; 40 37 /** @fence_armed: Fence has been armed */ 41 38 bool fence_armed; 42 39 }; ··· 49 46 container_of(job->fence, typeof(*ifence), base); 50 47 51 48 xe_tlb_inval_range(job->tlb_inval, ifence, job->start, 52 - job->end, job->asid); 49 + job->end, job->vm->usm.asid); 53 50 54 51 return job->fence; 55 52 } ··· 73 70 * @q: exec queue issuing the invalidate 74 71 * @tlb_inval: TLB invalidation client 75 72 * @dep_scheduler: Dependency scheduler for job 73 + * @vm: VM which TLB invalidation is being issued for 76 74 * @start: Start address to invalidate 77 75 * @end: End address to invalidate 78 - * @asid: Address space ID to invalidate 76 + * @type: GT type 79 77 * 80 78 * Create a TLB invalidation job and initialize internal fields. The caller is 81 79 * responsible for releasing the creation reference. ··· 85 81 */ 86 82 struct xe_tlb_inval_job * 87 83 xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval, 88 - struct xe_dep_scheduler *dep_scheduler, u64 start, 89 - u64 end, u32 asid) 84 + struct xe_dep_scheduler *dep_scheduler, 85 + struct xe_vm *vm, u64 start, u64 end, int type) 90 86 { 91 87 struct xe_tlb_inval_job *job; 92 88 struct drm_sched_entity *entity = ··· 94 90 struct xe_tlb_inval_fence *ifence; 95 91 int err; 96 92 93 + xe_assert(vm->xe, type == XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT || 94 + type == XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT); 95 + 97 96 job = kmalloc(sizeof(*job), GFP_KERNEL); 98 97 if (!job) 99 98 return ERR_PTR(-ENOMEM); 100 99 101 100 job->q = q; 101 + job->vm = vm; 102 102 job->tlb_inval = tlb_inval; 103 103 job->start = start; 104 104 job->end = end; 105 - job->asid = asid; 106 105 job->fence_armed = false; 107 106 job->dep.ops = &dep_job_ops; 107 + job->type = type; 108 108 kref_init(&job->refcount); 109 109 xe_exec_queue_get(q); /* Pairs with put in xe_tlb_inval_job_destroy */ 110 + xe_vm_get(vm); /* Pairs with put in xe_tlb_inval_job_destroy */ 110 111 111 112 ifence = kmalloc(sizeof(*ifence), GFP_KERNEL); 112 113 if (!ifence) { ··· 133 124 err_fence: 134 125 kfree(ifence); 135 126 err_job: 127 + xe_vm_put(vm); 136 128 xe_exec_queue_put(q); 137 129 kfree(job); 138 130 ··· 148 138 container_of(job->fence, typeof(*ifence), base); 149 139 struct xe_exec_queue *q = job->q; 150 140 struct xe_device *xe = gt_to_xe(q->gt); 141 + struct xe_vm *vm = job->vm; 151 142 152 143 if (!job->fence_armed) 153 144 kfree(ifence); ··· 158 147 159 148 drm_sched_job_cleanup(&job->dep.drm); 160 149 kfree(job); 150 + xe_vm_put(vm); /* Pairs with get from xe_tlb_inval_job_create */ 161 151 xe_exec_queue_put(q); /* Pairs with get from xe_tlb_inval_job_create */ 162 152 xe_pm_runtime_put(xe); /* Pairs with get from xe_tlb_inval_job_create */ 163 153 } ··· 242 230 */ 243 231 dma_fence_get(&job->dep.drm.s_fence->finished); 244 232 drm_sched_entity_push_job(&job->dep.drm); 233 + 234 + /* Let the upper layers fish this out */ 235 + xe_exec_queue_tlb_inval_last_fence_set(job->q, job->vm, 236 + &job->dep.drm.s_fence->finished, 237 + job->type); 245 238 246 239 xe_migrate_job_unlock(m, job->q); 247 240
+3 -2
drivers/gpu/drm/xe/xe_tlb_inval_job.h
··· 11 11 struct dma_fence; 12 12 struct xe_dep_scheduler; 13 13 struct xe_exec_queue; 14 + struct xe_migrate; 14 15 struct xe_tlb_inval; 15 16 struct xe_tlb_inval_job; 16 - struct xe_migrate; 17 + struct xe_vm; 17 18 18 19 struct xe_tlb_inval_job * 19 20 xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval, 20 21 struct xe_dep_scheduler *dep_scheduler, 21 - u64 start, u64 end, u32 asid); 22 + struct xe_vm *vm, u64 start, u64 end, int type); 22 23 23 24 int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job); 24 25
+23
drivers/gpu/drm/xe/xe_trace.h
··· 441 441 __entry->read_size, __entry->total_size) 442 442 ); 443 443 444 + TRACE_EVENT(xe_exec_queue_reach_max_job_count, 445 + TP_PROTO(struct xe_exec_queue *q, int max_cnt), 446 + TP_ARGS(q, max_cnt), 447 + 448 + TP_STRUCT__entry(__string(dev, __dev_name_eq(q)) 449 + __field(enum xe_engine_class, class) 450 + __field(u32, logical_mask) 451 + __field(u16, guc_id) 452 + __field(int, max_cnt) 453 + ), 454 + 455 + TP_fast_assign(__assign_str(dev); 456 + __entry->class = q->class; 457 + __entry->logical_mask = q->logical_mask; 458 + __entry->guc_id = q->guc->id; 459 + __entry->max_cnt = max_cnt; 460 + ), 461 + 462 + TP_printk("dev=%s, job count exceeded the maximum limit (%d) per exec queue. engine_class=0x%x, logical_mask=0x%x, guc_id=%d", 463 + __get_str(dev), __entry->max_cnt, 464 + __entry->class, __entry->logical_mask, __entry->guc_id) 465 + ); 466 + 444 467 #endif 445 468 446 469 /* This part must be outside protection */
+4 -4
drivers/gpu/drm/xe/xe_validation.h
··· 166 166 */ 167 167 DEFINE_CLASS(xe_validation, struct xe_validation_ctx *, 168 168 if (_T) xe_validation_ctx_fini(_T);, 169 - ({_ret = xe_validation_ctx_init(_ctx, _val, _exec, _flags); 170 - _ret ? NULL : _ctx; }), 169 + ({*_ret = xe_validation_ctx_init(_ctx, _val, _exec, _flags); 170 + *_ret ? NULL : _ctx; }), 171 171 struct xe_validation_ctx *_ctx, struct xe_validation_device *_val, 172 - struct drm_exec *_exec, const struct xe_val_flags _flags, int _ret); 172 + struct drm_exec *_exec, const struct xe_val_flags _flags, int *_ret); 173 173 static inline void *class_xe_validation_lock_ptr(class_xe_validation_t *_T) 174 174 {return *_T; } 175 175 #define class_xe_validation_is_conditional true ··· 186 186 * exhaustive eviction. 187 187 */ 188 188 #define xe_validation_guard(_ctx, _val, _exec, _flags, _ret) \ 189 - scoped_guard(xe_validation, _ctx, _val, _exec, _flags, _ret) \ 189 + scoped_guard(xe_validation, _ctx, _val, _exec, _flags, &_ret) \ 190 190 drm_exec_until_all_locked(_exec) 191 191 192 192 #endif
+60 -41
drivers/gpu/drm/xe/xe_vm.c
··· 27 27 #include "xe_device.h" 28 28 #include "xe_drm_client.h" 29 29 #include "xe_exec_queue.h" 30 - #include "xe_gt_pagefault.h" 31 30 #include "xe_migrate.h" 32 31 #include "xe_pat.h" 33 32 #include "xe_pm.h" ··· 754 755 xe_assert(vm->xe, xe_vm_in_fault_mode(vm)); 755 756 756 757 xe_vma_ops_init(&vops, vm, NULL, NULL, 0); 758 + vops.flags |= XE_VMA_OPS_FLAG_SKIP_TLB_WAIT; 757 759 for_each_tile(tile, vm->xe, id) { 758 760 vops.pt_update_ops[id].wait_vm_bookkeep = true; 759 761 vops.pt_update_ops[tile->id].q = ··· 845 845 xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(vma)); 846 846 847 847 xe_vma_ops_init(&vops, vm, NULL, NULL, 0); 848 + vops.flags |= XE_VMA_OPS_FLAG_SKIP_TLB_WAIT; 848 849 for_each_tile(tile, vm->xe, id) { 849 850 vops.pt_update_ops[id].wait_vm_bookkeep = true; 850 851 vops.pt_update_ops[tile->id].q = ··· 1459 1458 struct xe_validation_ctx ctx; 1460 1459 struct drm_exec exec; 1461 1460 struct xe_vm *vm; 1462 - int err, number_tiles = 0; 1461 + int err; 1463 1462 struct xe_tile *tile; 1464 1463 u8 id; 1465 1464 ··· 1620 1619 goto err_close; 1621 1620 } 1622 1621 vm->q[id] = q; 1623 - number_tiles++; 1624 1622 } 1625 1623 } 1626 - 1627 - if (number_tiles > 1) 1628 - vm->composite_fence_ctx = dma_fence_context_alloc(1); 1629 1624 1630 1625 if (xef && xe->info.has_asid) { 1631 1626 u32 asid; ··· 1728 1731 1729 1732 down_write(&vm->lock); 1730 1733 for_each_tile(tile, xe, id) { 1731 - if (vm->q[id]) 1734 + if (vm->q[id]) { 1735 + int i; 1736 + 1732 1737 xe_exec_queue_last_fence_put(vm->q[id], vm); 1738 + for_each_tlb_inval(i) 1739 + xe_exec_queue_tlb_inval_last_fence_put(vm->q[id], vm, i); 1740 + } 1733 1741 } 1734 1742 up_write(&vm->lock); 1735 1743 ··· 3104 3102 struct dma_fence *fence = NULL; 3105 3103 struct dma_fence **fences = NULL; 3106 3104 struct dma_fence_array *cf = NULL; 3107 - int number_tiles = 0, current_fence = 0, err; 3105 + int number_tiles = 0, current_fence = 0, n_fence = 0, err; 3108 3106 u8 id; 3109 3107 3110 3108 number_tiles = vm_ops_setup_tile_args(vm, vops); 3111 3109 if (number_tiles == 0) 3112 3110 return ERR_PTR(-ENODATA); 3113 3111 3114 - if (number_tiles > 1) { 3115 - fences = kmalloc_array(number_tiles, sizeof(*fences), 3116 - GFP_KERNEL); 3117 - if (!fences) { 3118 - fence = ERR_PTR(-ENOMEM); 3119 - goto err_trace; 3120 - } 3112 + if (vops->flags & XE_VMA_OPS_FLAG_SKIP_TLB_WAIT) { 3113 + for_each_tile(tile, vm->xe, id) 3114 + ++n_fence; 3115 + } else { 3116 + for_each_tile(tile, vm->xe, id) 3117 + n_fence += (1 + XE_MAX_GT_PER_TILE); 3118 + } 3119 + 3120 + fences = kmalloc_array(n_fence, sizeof(*fences), GFP_KERNEL); 3121 + if (!fences) { 3122 + fence = ERR_PTR(-ENOMEM); 3123 + goto err_trace; 3124 + } 3125 + 3126 + cf = dma_fence_array_alloc(n_fence); 3127 + if (!cf) { 3128 + fence = ERR_PTR(-ENOMEM); 3129 + goto err_out; 3121 3130 } 3122 3131 3123 3132 for_each_tile(tile, vm->xe, id) { ··· 3145 3132 trace_xe_vm_ops_execute(vops); 3146 3133 3147 3134 for_each_tile(tile, vm->xe, id) { 3135 + struct xe_exec_queue *q = vops->pt_update_ops[tile->id].q; 3136 + int i; 3137 + 3138 + fence = NULL; 3148 3139 if (!vops->pt_update_ops[id].num_ops) 3149 - continue; 3140 + goto collect_fences; 3150 3141 3151 3142 fence = xe_pt_update_ops_run(tile, vops); 3152 3143 if (IS_ERR(fence)) 3153 3144 goto err_out; 3154 3145 3155 - if (fences) 3156 - fences[current_fence++] = fence; 3146 + collect_fences: 3147 + fences[current_fence++] = fence ?: dma_fence_get_stub(); 3148 + if (vops->flags & XE_VMA_OPS_FLAG_SKIP_TLB_WAIT) 3149 + continue; 3150 + 3151 + xe_migrate_job_lock(tile->migrate, q); 3152 + for_each_tlb_inval(i) 3153 + fences[current_fence++] = 3154 + xe_exec_queue_tlb_inval_last_fence_get(q, vm, i); 3155 + xe_migrate_job_unlock(tile->migrate, q); 3157 3156 } 3158 3157 3159 - if (fences) { 3160 - cf = dma_fence_array_create(number_tiles, fences, 3161 - vm->composite_fence_ctx, 3162 - vm->composite_fence_seqno++, 3163 - false); 3164 - if (!cf) { 3165 - --vm->composite_fence_seqno; 3166 - fence = ERR_PTR(-ENOMEM); 3167 - goto err_out; 3168 - } 3169 - fence = &cf->base; 3170 - } 3158 + xe_assert(vm->xe, current_fence == n_fence); 3159 + dma_fence_array_init(cf, n_fence, fences, dma_fence_context_alloc(1), 3160 + 1, false); 3161 + fence = &cf->base; 3171 3162 3172 3163 for_each_tile(tile, vm->xe, id) { 3173 3164 if (!vops->pt_update_ops[id].num_ops) ··· 3232 3215 static void vm_bind_ioctl_ops_fini(struct xe_vm *vm, struct xe_vma_ops *vops, 3233 3216 struct dma_fence *fence) 3234 3217 { 3235 - struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, vops->q); 3236 3218 struct xe_user_fence *ufence; 3237 3219 struct xe_vma_op *op; 3238 3220 int i; ··· 3252 3236 if (fence) { 3253 3237 for (i = 0; i < vops->num_syncs; i++) 3254 3238 xe_sync_entry_signal(vops->syncs + i, fence); 3255 - xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence); 3256 3239 } 3257 3240 } 3258 3241 ··· 3445 3430 struct xe_sync_entry *syncs, 3446 3431 int num_syncs) 3447 3432 { 3448 - struct dma_fence *fence; 3433 + struct dma_fence *fence = NULL; 3449 3434 int i, err = 0; 3450 3435 3451 - fence = xe_sync_in_fence_get(syncs, num_syncs, 3452 - to_wait_exec_queue(vm, q), vm); 3453 - if (IS_ERR(fence)) 3454 - return PTR_ERR(fence); 3436 + if (num_syncs) { 3437 + fence = xe_sync_in_fence_get(syncs, num_syncs, 3438 + to_wait_exec_queue(vm, q), vm); 3439 + if (IS_ERR(fence)) 3440 + return PTR_ERR(fence); 3455 3441 3456 - for (i = 0; i < num_syncs; i++) 3457 - xe_sync_entry_signal(&syncs[i], fence); 3442 + for (i = 0; i < num_syncs; i++) 3443 + xe_sync_entry_signal(&syncs[i], fence); 3444 + } 3458 3445 3459 - xe_exec_queue_last_fence_set(to_wait_exec_queue(vm, q), vm, 3460 - fence); 3461 3446 dma_fence_put(fence); 3462 3447 3463 3448 return err; ··· 3648 3633 3649 3634 syncs_user = u64_to_user_ptr(args->syncs); 3650 3635 for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) { 3636 + struct xe_exec_queue *__q = q ?: vm->q[0]; 3637 + 3651 3638 err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs], 3652 3639 &syncs_user[num_syncs], 3640 + __q->ufence_syncobj, 3641 + ++__q->ufence_timeline_value, 3653 3642 (xe_vm_in_lr_mode(vm) ? 3654 3643 SYNC_PARSE_FLAG_LR_MODE : 0) | 3655 3644 (!args->num_binds ?
+1 -5
drivers/gpu/drm/xe/xe_vm_types.h
··· 221 221 #define XE_VM_FLAG_GSC BIT(8) 222 222 unsigned long flags; 223 223 224 - /** @composite_fence_ctx: context composite fence */ 225 - u64 composite_fence_ctx; 226 - /** @composite_fence_seqno: seqno for composite fence */ 227 - u32 composite_fence_seqno; 228 - 229 224 /** 230 225 * @lock: outer most lock, protects objects of anything attached to this 231 226 * VM ··· 466 471 #define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0) 467 472 #define XE_VMA_OPS_FLAG_MADVISE BIT(1) 468 473 #define XE_VMA_OPS_ARRAY_OF_BINDS BIT(2) 474 + #define XE_VMA_OPS_FLAG_SKIP_TLB_WAIT BIT(3) 469 475 u32 flags; 470 476 #ifdef TEST_VM_OPS_ERROR 471 477 /** @inject_error: inject error to test error handling */
+2
drivers/gpu/drm/xe/xe_wa.c
··· 679 679 }, 680 680 { XE_RTP_NAME("14023061436"), 681 681 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001), 682 + FUNC(xe_rtp_match_first_render_or_compute), OR, 683 + GRAPHICS_VERSION_RANGE(3003, 3005), 682 684 FUNC(xe_rtp_match_first_render_or_compute)), 683 685 XE_RTP_ACTIONS(SET(TDL_CHICKEN, QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE)) 684 686 },