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

drm/xe: Protect against unset LRC when pausing submissions

While pausing submissions, it is possible to encouner an exec queue
which is during creation, and therefore doesn't have a valid xe_lrc
struct reference.

Protect agains such situation, by checking for NULL before access.

Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Fixes: c25c1010df88 ("drm/xe/vf: Replay GuC submission state on pause / unpause")
Signed-off-by: Tomasz Lis <tomasz.lis@intel.com>
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Link: https://patch.msgid.link/20251124222853.1900800-1-tomasz.lis@intel.com
(cherry picked from commit 07cf4b864f523f01d2bb522a05813df30b076ba8)
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>

authored by

Tomasz Lis and committed by
Thomas Hellström
d72312d7 3d98a716

+16 -6
+16 -6
drivers/gpu/drm/xe/xe_guc_submit.c
··· 2112 2112 q->guc->resume_time = 0; 2113 2113 } 2114 2114 2115 + static void lrc_parallel_clear(struct xe_lrc *lrc) 2116 + { 2117 + struct xe_device *xe = gt_to_xe(lrc->gt); 2118 + struct iosys_map map = xe_lrc_parallel_map(lrc); 2119 + int i; 2120 + 2121 + for (i = 0; i < WQ_SIZE / sizeof(u32); ++i) 2122 + parallel_write(xe, map, wq[i], 2123 + FIELD_PREP(WQ_TYPE_MASK, WQ_TYPE_NOOP) | 2124 + FIELD_PREP(WQ_LEN_MASK, 0)); 2125 + } 2126 + 2115 2127 /* 2116 2128 * This function is quite complex but only real way to ensure no state is lost 2117 2129 * during VF resume flows. The function scans the queue state, make adjustments ··· 2147 2135 guc_exec_queue_revert_pending_state_change(guc, q); 2148 2136 2149 2137 if (xe_exec_queue_is_parallel(q)) { 2150 - struct xe_device *xe = guc_to_xe(guc); 2151 - struct iosys_map map = xe_lrc_parallel_map(q->lrc[0]); 2138 + /* Pairs with WRITE_ONCE in __xe_exec_queue_init */ 2139 + struct xe_lrc *lrc = READ_ONCE(q->lrc[0]); 2152 2140 2153 2141 /* 2154 2142 * NOP existing WQ commands that may contain stale GGTT ··· 2156 2144 * seems to get confused if the WQ head/tail pointers are 2157 2145 * adjusted. 2158 2146 */ 2159 - for (i = 0; i < WQ_SIZE / sizeof(u32); ++i) 2160 - parallel_write(xe, map, wq[i], 2161 - FIELD_PREP(WQ_TYPE_MASK, WQ_TYPE_NOOP) | 2162 - FIELD_PREP(WQ_LEN_MASK, 0)); 2147 + if (lrc) 2148 + lrc_parallel_clear(lrc); 2163 2149 } 2164 2150 2165 2151 job = xe_sched_first_pending_job(sched);