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

'drm/xe/hw_engine_group: Register hw engine group's exec queues

Add helpers to safely add and delete the exec queues attached to a hw
engine group, and make use them at the time of creation and destruction of
the exec queues. Keeping track of them is required to control the
execution mode of the hw engine group.

v2: Improve error handling and robustness, suspend exec queues created in
fault mode if group in dma-fence mode, init queue link (Matt Brost)

v3: Delete queue from hw engine group when it is destroyed by the user,
also clean up at the time of closing the file in case the user did
not destroy the queue

v4: Use correct list when checking if empty, do not add the queue if VM
is in xe_vm_in_preempt_fence_mode (Matt Brost)

v5: Remove unrelated newline, add checks and asserts for group, unwind on
suspend failure (Matt Brost)

Signed-off-by: Francois Dugast <francois.dugast@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240809155156.1955925-4-francois.dugast@intel.com

authored by

Francois Dugast and committed by
Matthew Brost
7970cb36 3dc6da76

+86
+3
drivers/gpu/drm/xe/xe_device.c
··· 37 37 #include "xe_gt_printk.h" 38 38 #include "xe_gt_sriov_vf.h" 39 39 #include "xe_guc.h" 40 + #include "xe_hw_engine_group.h" 40 41 #include "xe_hwmon.h" 41 42 #include "xe_irq.h" 42 43 #include "xe_memirq.h" ··· 166 165 * vm->lock taken during xe_exec_queue_kill(). 167 166 */ 168 167 xa_for_each(&xef->exec_queue.xa, idx, q) { 168 + if (q->vm && q->hwe->hw_engine_group) 169 + xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q); 169 170 xe_exec_queue_kill(q); 170 171 xe_exec_queue_put(q); 171 172 }
+11
drivers/gpu/drm/xe/xe_exec_queue.c
··· 14 14 #include "xe_device.h" 15 15 #include "xe_gt.h" 16 16 #include "xe_hw_engine_class_sysfs.h" 17 + #include "xe_hw_engine_group.h" 17 18 #include "xe_hw_fence.h" 18 19 #include "xe_lrc.h" 19 20 #include "xe_macros.h" ··· 74 73 q->ops = gt->exec_queue_ops; 75 74 INIT_LIST_HEAD(&q->lr.link); 76 75 INIT_LIST_HEAD(&q->multi_gt_link); 76 + INIT_LIST_HEAD(&q->hw_engine_group_link); 77 77 78 78 q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us; 79 79 q->sched_props.preempt_timeout_us = ··· 626 624 if (XE_IOCTL_DBG(xe, err)) 627 625 goto put_exec_queue; 628 626 } 627 + 628 + if (q->vm && q->hwe->hw_engine_group) { 629 + err = xe_hw_engine_group_add_exec_queue(q->hwe->hw_engine_group, q); 630 + if (err) 631 + goto put_exec_queue; 632 + } 629 633 } 630 634 631 635 mutex_lock(&xef->exec_queue.lock); ··· 822 814 mutex_unlock(&xef->exec_queue.lock); 823 815 if (XE_IOCTL_DBG(xe, !q)) 824 816 return -ENOENT; 817 + 818 + if (q->vm && q->hwe->hw_engine_group) 819 + xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q); 825 820 826 821 xe_exec_queue_kill(q); 827 822
+2
drivers/gpu/drm/xe/xe_exec_queue_types.h
··· 142 142 * Protected by @vm's resv. Unused if @vm == NULL. 143 143 */ 144 144 u64 tlb_flush_seqno; 145 + /** @hw_engine_group_link: link into exec queues in the same hw engine group */ 146 + struct list_head hw_engine_group_link; 145 147 /** @lrc: logical ring context for this exec queue */ 146 148 struct xe_lrc *lrc[]; 147 149 };
+66
drivers/gpu/drm/xe/xe_hw_engine_group.c
··· 5 5 6 6 #include <drm/drm_managed.h> 7 7 8 + #include "xe_assert.h" 8 9 #include "xe_device.h" 10 + #include "xe_exec_queue.h" 9 11 #include "xe_gt.h" 10 12 #include "xe_hw_engine_group.h" 13 + #include "xe_vm.h" 11 14 12 15 static void 13 16 hw_engine_group_free(struct drm_device *drm, void *arg) ··· 102 99 kfree(group_rcs_ccs); 103 100 104 101 return err; 102 + } 103 + 104 + /** 105 + * xe_hw_engine_group_add_exec_queue() - Add an exec queue to a hw engine group 106 + * @group: The hw engine group 107 + * @q: The exec_queue 108 + * 109 + * Return: 0 on success, 110 + * -EINTR if the lock could not be acquired 111 + */ 112 + int xe_hw_engine_group_add_exec_queue(struct xe_hw_engine_group *group, struct xe_exec_queue *q) 113 + { 114 + int err; 115 + struct xe_device *xe = gt_to_xe(q->gt); 116 + 117 + xe_assert(xe, group); 118 + xe_assert(xe, !(q->flags & EXEC_QUEUE_FLAG_VM)); 119 + xe_assert(xe, q->vm); 120 + 121 + if (xe_vm_in_preempt_fence_mode(q->vm)) 122 + return 0; 123 + 124 + err = down_write_killable(&group->mode_sem); 125 + if (err) 126 + return err; 127 + 128 + if (xe_vm_in_fault_mode(q->vm) && group->cur_mode == EXEC_MODE_DMA_FENCE) { 129 + q->ops->suspend(q); 130 + err = q->ops->suspend_wait(q); 131 + if (err) 132 + goto err_suspend; 133 + 134 + queue_work(group->resume_wq, &group->resume_work); 135 + } 136 + 137 + list_add(&q->hw_engine_group_link, &group->exec_queue_list); 138 + up_write(&group->mode_sem); 139 + 140 + return 0; 141 + 142 + err_suspend: 143 + up_write(&group->mode_sem); 144 + return err; 145 + } 146 + 147 + /** 148 + * xe_hw_engine_group_del_exec_queue() - Delete an exec queue from a hw engine group 149 + * @group: The hw engine group 150 + * @q: The exec_queue 151 + */ 152 + void xe_hw_engine_group_del_exec_queue(struct xe_hw_engine_group *group, struct xe_exec_queue *q) 153 + { 154 + struct xe_device *xe = gt_to_xe(q->gt); 155 + 156 + xe_assert(xe, group); 157 + xe_assert(xe, q->vm); 158 + 159 + down_write(&group->mode_sem); 160 + 161 + if (!list_empty(&q->hw_engine_group_link)) 162 + list_del(&q->hw_engine_group_link); 163 + 164 + up_write(&group->mode_sem); 105 165 }
+4
drivers/gpu/drm/xe/xe_hw_engine_group.h
··· 9 9 #include "xe_hw_engine_group_types.h" 10 10 11 11 struct drm_device; 12 + struct xe_exec_queue; 12 13 struct xe_gt; 13 14 14 15 int xe_hw_engine_setup_groups(struct xe_gt *gt); 16 + 17 + int xe_hw_engine_group_add_exec_queue(struct xe_hw_engine_group *group, struct xe_exec_queue *q); 18 + void xe_hw_engine_group_del_exec_queue(struct xe_hw_engine_group *group, struct xe_exec_queue *q); 15 19 16 20 #endif