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

Configure Feed

Select the types of activity you want to include in your feed.

drm/xe/multi_queue: Protect priority against concurrent access

Use a spinlock to protect multi-queue priority being concurrently
updated by multiple set_priority ioctls and to protect against
concurrent read and write to this field.

v2: Update documentation, remove WRITE/READ_LOCK() (Thomas)
Use scoped_guard, reduced lock scope (Matt Brost)
v3: Fix author (checkpatch)

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Link: https://patch.msgid.link/20260126174241.3470390-2-niranjana.vishwanathapura@intel.com

+22 -5
+1
drivers/gpu/drm/xe/xe_exec_queue.c
··· 230 230 INIT_LIST_HEAD(&q->multi_gt_link); 231 231 INIT_LIST_HEAD(&q->hw_engine_group_link); 232 232 INIT_LIST_HEAD(&q->pxp.link); 233 + spin_lock_init(&q->multi_queue.lock); 233 234 q->multi_queue.priority = XE_MULTI_QUEUE_PRIORITY_NORMAL; 234 235 235 236 q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us;
+6 -1
drivers/gpu/drm/xe/xe_exec_queue_types.h
··· 161 161 struct xe_exec_queue_group *group; 162 162 /** @multi_queue.link: Link into group's secondary queues list */ 163 163 struct list_head link; 164 - /** @multi_queue.priority: Queue priority within the multi-queue group */ 164 + /** 165 + * @multi_queue.priority: Queue priority within the multi-queue group. 166 + * It is protected by @multi_queue.lock. 167 + */ 165 168 enum xe_multi_queue_priority priority; 169 + /** @multi_queue.lock: Lock for protecting certain members */ 170 + spinlock_t lock; 166 171 /** @multi_queue.pos: Position of queue within the multi-queue group */ 167 172 u8 pos; 168 173 /** @multi_queue.valid: Queue belongs to a multi queue group */
+15 -4
drivers/gpu/drm/xe/xe_guc_submit.c
··· 804 804 { 805 805 struct xe_exec_queue_group *group = q->multi_queue.group; 806 806 struct xe_device *xe = guc_to_xe(guc); 807 + enum xe_multi_queue_priority priority; 807 808 long ret; 808 809 809 810 /* ··· 828 827 return; 829 828 } 830 829 831 - xe_lrc_set_multi_queue_priority(q->lrc[0], q->multi_queue.priority); 830 + scoped_guard(spinlock, &q->multi_queue.lock) 831 + priority = q->multi_queue.priority; 832 + 833 + xe_lrc_set_multi_queue_priority(q->lrc[0], priority); 832 834 xe_guc_exec_queue_group_cgp_update(xe, q); 833 835 834 836 WRITE_ONCE(group->sync_pending, true); ··· 2185 2181 2186 2182 xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)), xe_exec_queue_is_multi_queue(q)); 2187 2183 2188 - if (q->multi_queue.priority == priority || 2189 - exec_queue_killed_or_banned_or_wedged(q)) 2184 + if (exec_queue_killed_or_banned_or_wedged(q)) 2190 2185 return 0; 2191 2186 2192 2187 msg = kmalloc(sizeof(*msg), GFP_KERNEL); 2193 2188 if (!msg) 2194 2189 return -ENOMEM; 2195 2190 2196 - q->multi_queue.priority = priority; 2191 + scoped_guard(spinlock, &q->multi_queue.lock) { 2192 + if (q->multi_queue.priority == priority) { 2193 + kfree(msg); 2194 + return 0; 2195 + } 2196 + 2197 + q->multi_queue.priority = priority; 2198 + } 2199 + 2197 2200 guc_exec_queue_add_msg(q, msg, SET_MULTI_QUEUE_PRIORITY); 2198 2201 2199 2202 return 0;