- Fixes for potential use-after-free and double-free (Rob) - GuC locking and refcount fixes (John) - Display's reference clock value fix (Chaitanya) Signed-off-by: Dave Airlie <airlied@redhat.com>
Unified · Split
| @@ -1319,7 +1319,7 @@ static const struct intel_cdclk_vals adlp_cdclk_table[] = { · 1318 unmodified lines | |||
| 1319 | { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 }, | 1319 | { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 }, |
| 1320 | { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 }, | 1320 | { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 }, |
| 1321 | { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 }, | 1321 | { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 }, |
| 1322 | { .refclk = 24400, .cdclk = 648000, .divider = 2, .ratio = 54 }, | 1322 | { .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 }, |
| 1323 | 1323 | ||
| 1324 | { .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 }, | 1324 | { .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 }, |
| 1325 | { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 }, | 1325 | { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 }, |
| @@ -1861,11 +1861,19 @@ static int get_ppgtt(struct drm_i915_file_private *file_priv, · 1860 unmodified lines | |||
| 1861 | vm = ctx->vm; | 1861 | vm = ctx->vm; |
| 1862 | GEM_BUG_ON(!vm); | 1862 | GEM_BUG_ON(!vm); |
| 1863 | 1863 | ||
| 1864 | /* | ||
| 1865 | * Get a reference for the allocated handle. Once the handle is | ||
| 1866 | * visible in the vm_xa table, userspace could try to close it | ||
| 1867 | * from under our feet, so we need to hold the extra reference | ||
| 1868 | * first. | ||
| 1869 | */ | ||
| 1870 | i915_vm_get(vm); | ||
| 1871 | |||
| 1864 | err = xa_alloc(&file_priv->vm_xa, &id, vm, xa_limit_32b, GFP_KERNEL); | 1872 | err = xa_alloc(&file_priv->vm_xa, &id, vm, xa_limit_32b, GFP_KERNEL); |
| 1865 | if (err) | 1873 | if (err) { |
| 1874 | i915_vm_put(vm); | ||
| 1866 | return err; | 1875 | return err; |
| 1867 | 1876 | } | |
| 1868 | i915_vm_get(vm); | ||
| 1869 | 1877 | ||
| 1870 | GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */ | 1878 | GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */ |
| 1871 | args->value = id; | 1879 | args->value = id; |
| @@ -305,10 +305,6 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, · 304 unmodified lines | |||
| 305 | spin_unlock(&obj->vma.lock); | 305 | spin_unlock(&obj->vma.lock); |
| 306 | 306 | ||
| 307 | obj->tiling_and_stride = tiling | stride; | 307 | obj->tiling_and_stride = tiling | stride; |
| 308 | i915_gem_object_unlock(obj); | ||
| 309 | |||
| 310 | /* Force the fence to be reacquired for GTT access */ | ||
| 311 | i915_gem_object_release_mmap_gtt(obj); | ||
| 312 | 308 | ||
| 313 | /* Try to preallocate memory required to save swizzling on put-pages */ | 309 | /* Try to preallocate memory required to save swizzling on put-pages */ |
| 314 | if (i915_gem_object_needs_bit17_swizzle(obj)) { | 310 | if (i915_gem_object_needs_bit17_swizzle(obj)) { |
| @@ -321,6 +317,11 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, · 6 unmodified lines | |||
| 321 | obj->bit_17 = NULL; | 317 | obj->bit_17 = NULL; |
| 322 | } | 318 | } |
| 323 | 319 | ||
| 320 | i915_gem_object_unlock(obj); | ||
| 321 | |||
| 322 | /* Force the fence to be reacquired for GTT access */ | ||
| 323 | i915_gem_object_release_mmap_gtt(obj); | ||
| 324 | |||
| 324 | return 0; | 325 | return 0; |
| 325 | } | 326 | } |
| 326 | 327 | ||
| @@ -528,7 +528,7 @@ retry: · 527 unmodified lines | |||
| 528 | return rq; | 528 | return rq; |
| 529 | } | 529 | } |
| 530 | 530 | ||
| 531 | struct i915_request *intel_context_find_active_request(struct intel_context *ce) | 531 | struct i915_request *intel_context_get_active_request(struct intel_context *ce) |
| 532 | { | 532 | { |
| 533 | struct intel_context *parent = intel_context_to_parent(ce); | 533 | struct intel_context *parent = intel_context_to_parent(ce); |
| 534 | struct i915_request *rq, *active = NULL; | 534 | struct i915_request *rq, *active = NULL; |
| @@ -552,6 +552,8 @@ struct i915_request *intel_context_find_active_request(struct intel_context *ce) · 17 unmodified lines | |||
| 552 | 552 | ||
| 553 | active = rq; | 553 | active = rq; |
| 554 | } | 554 | } |
| 555 | if (active) | ||
| 556 | active = i915_request_get_rcu(active); | ||
| 555 | spin_unlock_irqrestore(&parent->guc_state.lock, flags); | 557 | spin_unlock_irqrestore(&parent->guc_state.lock, flags); |
| 556 | 558 | ||
| 557 | return active; | 559 | return active; |
| @@ -268,8 +268,7 @@ int intel_context_prepare_remote_request(struct intel_context *ce, · 267 unmodified lines | |||
| 268 | 268 | ||
| 269 | struct i915_request *intel_context_create_request(struct intel_context *ce); | 269 | struct i915_request *intel_context_create_request(struct intel_context *ce); |
| 270 | 270 | ||
| 271 | struct i915_request * | 271 | struct i915_request *intel_context_get_active_request(struct intel_context *ce); |
| 272 | intel_context_find_active_request(struct intel_context *ce); | ||
| 273 | 272 | ||
| 274 | static inline bool intel_context_is_barrier(const struct intel_context *ce) | 273 | static inline bool intel_context_is_barrier(const struct intel_context *ce) |
| 275 | { | 274 | { |
| @@ -248,8 +248,8 @@ void intel_engine_dump_active_requests(struct list_head *requests, · 247 unmodified lines | |||
| 248 | ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, | 248 | ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, |
| 249 | ktime_t *now); | 249 | ktime_t *now); |
| 250 | 250 | ||
| 251 | struct i915_request * | 251 | void intel_engine_get_hung_entity(struct intel_engine_cs *engine, |
| 252 | intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine); | 252 | struct intel_context **ce, struct i915_request **rq); |
| 253 | 253 | ||
| 254 | u32 intel_engine_context_size(struct intel_gt *gt, u8 class); | 254 | u32 intel_engine_context_size(struct intel_gt *gt, u8 class); |
| 255 | struct intel_context * | 255 | struct intel_context * |
| @@ -2094,17 +2094,6 @@ static void print_request_ring(struct drm_printer *m, struct i915_request *rq) · 2093 unmodified lines | |||
| 2094 | } | 2094 | } |
| 2095 | } | 2095 | } |
| 2096 | 2096 | ||
| 2097 | static unsigned long list_count(struct list_head *list) | ||
| 2098 | { | ||
| 2099 | struct list_head *pos; | ||
| 2100 | unsigned long count = 0; | ||
| 2101 | |||
| 2102 | list_for_each(pos, list) | ||
| 2103 | count++; | ||
| 2104 | |||
| 2105 | return count; | ||
| 2106 | } | ||
| 2107 | |||
| 2108 | static unsigned long read_ul(void *p, size_t x) | 2097 | static unsigned long read_ul(void *p, size_t x) |
| 2109 | { | 2098 | { |
| 2110 | return *(unsigned long *)(p + x); | 2099 | return *(unsigned long *)(p + x); |
| @@ -2196,11 +2185,11 @@ void intel_engine_dump_active_requests(struct list_head *requests, · 85 unmodified lines | |||
| 2196 | } | 2185 | } |
| 2197 | } | 2186 | } |
| 2198 | 2187 | ||
| 2199 | static void engine_dump_active_requests(struct intel_engine_cs *engine, struct drm_printer *m) | 2188 | static void engine_dump_active_requests(struct intel_engine_cs *engine, |
| 2189 | struct drm_printer *m) | ||
| 2200 | { | 2190 | { |
| 2191 | struct intel_context *hung_ce = NULL; | ||
| 2201 | struct i915_request *hung_rq = NULL; | 2192 | struct i915_request *hung_rq = NULL; |
| 2202 | struct intel_context *ce; | ||
| 2203 | bool guc; | ||
| 2204 | 2193 | ||
| 2205 | /* | 2194 | /* |
| 2206 | * No need for an engine->irq_seqno_barrier() before the seqno reads. | 2195 | * No need for an engine->irq_seqno_barrier() before the seqno reads. |
| @@ -2209,27 +2198,22 @@ static void engine_dump_active_requests(struct intel_engine_cs *engine, struct d · 2 unmodified lines | |||
| 2209 | * But the intention here is just to report an instantaneous snapshot | 2198 | * But the intention here is just to report an instantaneous snapshot |
| 2210 | * so that's fine. | 2199 | * so that's fine. |
| 2211 | */ | 2200 | */ |
| 2212 | lockdep_assert_held(&engine->sched_engine->lock); | 2201 | intel_engine_get_hung_entity(engine, &hung_ce, &hung_rq); |
| 2213 | 2202 | ||
| 2214 | drm_printf(m, "\tRequests:\n"); | 2203 | drm_printf(m, "\tRequests:\n"); |
| 2215 | 2204 | ||
| 2216 | guc = intel_uc_uses_guc_submission(&engine->gt->uc); | ||
| 2217 | if (guc) { | ||
| 2218 | ce = intel_engine_get_hung_context(engine); | ||
| 2219 | if (ce) | ||
| 2220 | hung_rq = intel_context_find_active_request(ce); | ||
| 2221 | } else { | ||
| 2222 | hung_rq = intel_engine_execlist_find_hung_request(engine); | ||
| 2223 | } | ||
| 2224 | |||
| 2225 | if (hung_rq) | 2205 | if (hung_rq) |
| 2226 | engine_dump_request(hung_rq, m, "\t\thung"); | 2206 | engine_dump_request(hung_rq, m, "\t\thung"); |
| 2207 | else if (hung_ce) | ||
| 2208 | drm_printf(m, "\t\tGot hung ce but no hung rq!\n"); | ||
| 2227 | 2209 | ||
| 2228 | if (guc) | 2210 | if (intel_uc_uses_guc_submission(&engine->gt->uc)) |
| 2229 | intel_guc_dump_active_requests(engine, hung_rq, m); | 2211 | intel_guc_dump_active_requests(engine, hung_rq, m); |
| 2230 | else | 2212 | else |
| 2231 | intel_engine_dump_active_requests(&engine->sched_engine->requests, | 2213 | intel_execlists_dump_active_requests(engine, hung_rq, m); |
| 2232 | hung_rq, m); | 2214 | |
| 2215 | if (hung_rq) | ||
| 2216 | i915_request_put(hung_rq); | ||
| 2233 | } | 2217 | } |
| 2234 | 2218 | ||
| 2235 | void intel_engine_dump(struct intel_engine_cs *engine, | 2219 | void intel_engine_dump(struct intel_engine_cs *engine, |
| @@ -2239,7 +2223,6 @@ void intel_engine_dump(struct intel_engine_cs *engine, · 3 unmodified lines | |||
| 2239 | struct i915_gpu_error * const error = &engine->i915->gpu_error; | 2223 | struct i915_gpu_error * const error = &engine->i915->gpu_error; |
| 2240 | struct i915_request *rq; | 2224 | struct i915_request *rq; |
| 2241 | intel_wakeref_t wakeref; | 2225 | intel_wakeref_t wakeref; |
| 2242 | unsigned long flags; | ||
| 2243 | ktime_t dummy; | 2226 | ktime_t dummy; |
| 2244 | 2227 | ||
| 2245 | if (header) { | 2228 | if (header) { |
| @@ -2276,13 +2259,8 @@ void intel_engine_dump(struct intel_engine_cs *engine, · 30 unmodified lines | |||
| 2276 | i915_reset_count(error)); | 2259 | i915_reset_count(error)); |
| 2277 | print_properties(engine, m); | 2260 | print_properties(engine, m); |
| 2278 | 2261 | ||
| 2279 | spin_lock_irqsave(&engine->sched_engine->lock, flags); | ||
| 2280 | engine_dump_active_requests(engine, m); | 2262 | engine_dump_active_requests(engine, m); |
| 2281 | 2263 | ||
| 2282 | drm_printf(m, "\tOn hold?: %lu\n", | ||
| 2283 | list_count(&engine->sched_engine->hold)); | ||
| 2284 | spin_unlock_irqrestore(&engine->sched_engine->lock, flags); | ||
| 2285 | |||
| 2286 | drm_printf(m, "\tMMIO base: 0x%08x\n", engine->mmio_base); | 2264 | drm_printf(m, "\tMMIO base: 0x%08x\n", engine->mmio_base); |
| 2287 | wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm); | 2265 | wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm); |
| 2288 | if (wakeref) { | 2266 | if (wakeref) { |
| @@ -2328,8 +2306,7 @@ intel_engine_create_virtual(struct intel_engine_cs **siblings, · 39 unmodified lines | |||
| 2328 | return siblings[0]->cops->create_virtual(siblings, count, flags); | 2306 | return siblings[0]->cops->create_virtual(siblings, count, flags); |
| 2329 | } | 2307 | } |
| 2330 | 2308 | ||
| 2331 | struct i915_request * | 2309 | static struct i915_request *engine_execlist_find_hung_request(struct intel_engine_cs *engine) |
| 2332 | intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine) | ||
| 2333 | { | 2310 | { |
| 2334 | struct i915_request *request, *active = NULL; | 2311 | struct i915_request *request, *active = NULL; |
| 2335 | 2312 | ||
| @@ -2381,6 +2358,33 @@ intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine) · 45 unmodified lines | |||
| 2381 | return active; | 2358 | return active; |
| 2382 | } | 2359 | } |
| 2383 | 2360 | ||
| 2361 | void intel_engine_get_hung_entity(struct intel_engine_cs *engine, | ||
| 2362 | struct intel_context **ce, struct i915_request **rq) | ||
| 2363 | { | ||
| 2364 | unsigned long flags; | ||
| 2365 | |||
| 2366 | *ce = intel_engine_get_hung_context(engine); | ||
| 2367 | if (*ce) { | ||
| 2368 | intel_engine_clear_hung_context(engine); | ||
| 2369 | |||
| 2370 | *rq = intel_context_get_active_request(*ce); | ||
| 2371 | return; | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | /* | ||
| 2375 | * Getting here with GuC enabled means it is a forced error capture | ||
| 2376 | * with no actual hang. So, no need to attempt the execlist search. | ||
| 2377 | */ | ||
| 2378 | if (intel_uc_uses_guc_submission(&engine->gt->uc)) | ||
| 2379 | return; | ||
| 2380 | |||
| 2381 | spin_lock_irqsave(&engine->sched_engine->lock, flags); | ||
| 2382 | *rq = engine_execlist_find_hung_request(engine); | ||
| 2383 | if (*rq) | ||
| 2384 | *rq = i915_request_get_rcu(*rq); | ||
| 2385 | spin_unlock_irqrestore(&engine->sched_engine->lock, flags); | ||
| 2386 | } | ||
| 2387 | |||
| 2384 | void xehp_enable_ccs_engines(struct intel_engine_cs *engine) | 2388 | void xehp_enable_ccs_engines(struct intel_engine_cs *engine) |
| 2385 | { | 2389 | { |
| 2386 | /* | 2390 | /* |
| @@ -4148,6 +4148,33 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine, · 4147 unmodified lines | |||
| 4148 | spin_unlock_irqrestore(&sched_engine->lock, flags); | 4148 | spin_unlock_irqrestore(&sched_engine->lock, flags); |
| 4149 | } | 4149 | } |
| 4150 | 4150 | ||
| 4151 | static unsigned long list_count(struct list_head *list) | ||
| 4152 | { | ||
| 4153 | struct list_head *pos; | ||
| 4154 | unsigned long count = 0; | ||
| 4155 | |||
| 4156 | list_for_each(pos, list) | ||
| 4157 | count++; | ||
| 4158 | |||
| 4159 | return count; | ||
| 4160 | } | ||
| 4161 | |||
| 4162 | void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, | ||
| 4163 | struct i915_request *hung_rq, | ||
| 4164 | struct drm_printer *m) | ||
| 4165 | { | ||
| 4166 | unsigned long flags; | ||
| 4167 | |||
| 4168 | spin_lock_irqsave(&engine->sched_engine->lock, flags); | ||
| 4169 | |||
| 4170 | intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m); | ||
| 4171 | |||
| 4172 | drm_printf(m, "\tOn hold?: %lu\n", | ||
| 4173 | list_count(&engine->sched_engine->hold)); | ||
| 4174 | |||
| 4175 | spin_unlock_irqrestore(&engine->sched_engine->lock, flags); | ||
| 4176 | } | ||
| 4177 | |||
| 4151 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | 4178 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) |
| 4152 | #include "selftest_execlists.c" | 4179 | #include "selftest_execlists.c" |
| 4153 | #endif | 4180 | #endif |
| @@ -32,6 +32,10 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine, · 31 unmodified lines | |||
| 32 | int indent), | 32 | int indent), |
| 33 | unsigned int max); | 33 | unsigned int max); |
| 34 | 34 | ||
| 35 | void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, | ||
| 36 | struct i915_request *hung_rq, | ||
| 37 | struct drm_printer *m); | ||
| 38 | |||
| 35 | bool | 39 | bool |
| 36 | intel_engine_in_execlists_submission_mode(const struct intel_engine_cs *engine); | 40 | intel_engine_in_execlists_submission_mode(const struct intel_engine_cs *engine); |
| 37 | 41 | ||
| @@ -1702,7 +1702,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st · 1701 unmodified lines | |||
| 1702 | goto next_context; | 1702 | goto next_context; |
| 1703 | 1703 | ||
| 1704 | guilty = false; | 1704 | guilty = false; |
| 1705 | rq = intel_context_find_active_request(ce); | 1705 | rq = intel_context_get_active_request(ce); |
| 1706 | if (!rq) { | 1706 | if (!rq) { |
| 1707 | head = ce->ring->tail; | 1707 | head = ce->ring->tail; |
| 1708 | goto out_replay; | 1708 | goto out_replay; |
| @@ -1715,6 +1715,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st · 6 unmodified lines | |||
| 1715 | head = intel_ring_wrap(ce->ring, rq->head); | 1715 | head = intel_ring_wrap(ce->ring, rq->head); |
| 1716 | 1716 | ||
| 1717 | __i915_request_reset(rq, guilty); | 1717 | __i915_request_reset(rq, guilty); |
| 1718 | i915_request_put(rq); | ||
| 1718 | out_replay: | 1719 | out_replay: |
| 1719 | guc_reset_state(ce, head, guilty); | 1720 | guc_reset_state(ce, head, guilty); |
| 1720 | next_context: | 1721 | next_context: |
| @@ -4817,6 +4818,8 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) · 3096 unmodified lines | |||
| 4817 | 4818 | ||
| 4818 | xa_lock_irqsave(&guc->context_lookup, flags); | 4819 | xa_lock_irqsave(&guc->context_lookup, flags); |
| 4819 | xa_for_each(&guc->context_lookup, index, ce) { | 4820 | xa_for_each(&guc->context_lookup, index, ce) { |
| 4821 | bool found; | ||
| 4822 | |||
| 4820 | if (!kref_get_unless_zero(&ce->ref)) | 4823 | if (!kref_get_unless_zero(&ce->ref)) |
| 4821 | continue; | 4824 | continue; |
| 4822 | 4825 | ||
| @@ -4833,10 +4836,18 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) · 10 unmodified lines | |||
| 4833 | goto next; | 4836 | goto next; |
| 4834 | } | 4837 | } |
| 4835 | 4838 | ||
| 4839 | found = false; | ||
| 4840 | spin_lock(&ce->guc_state.lock); | ||
| 4836 | list_for_each_entry(rq, &ce->guc_state.requests, sched.link) { | 4841 | list_for_each_entry(rq, &ce->guc_state.requests, sched.link) { |
| 4837 | if (i915_test_request_state(rq) != I915_REQUEST_ACTIVE) | 4842 | if (i915_test_request_state(rq) != I915_REQUEST_ACTIVE) |
| 4838 | continue; | 4843 | continue; |
| 4839 | 4844 | ||
| 4845 | found = true; | ||
| 4846 | break; | ||
| 4847 | } | ||
| 4848 | spin_unlock(&ce->guc_state.lock); | ||
| 4849 | |||
| 4850 | if (found) { | ||
| 4840 | intel_engine_set_hung_context(engine, ce); | 4851 | intel_engine_set_hung_context(engine, ce); |
| 4841 | 4852 | ||
| 4842 | /* Can only cope with one hang at a time... */ | 4853 | /* Can only cope with one hang at a time... */ |
| @@ -4844,6 +4855,7 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) · 1 unmodified line | |||
| 4844 | xa_lock(&guc->context_lookup); | 4855 | xa_lock(&guc->context_lookup); |
| 4845 | goto done; | 4856 | goto done; |
| 4846 | } | 4857 | } |
| 4858 | |||
| 4847 | next: | 4859 | next: |
| 4848 | intel_context_put(ce); | 4860 | intel_context_put(ce); |
| 4849 | xa_lock(&guc->context_lookup); | 4861 | xa_lock(&guc->context_lookup); |
| @@ -1596,43 +1596,20 @@ capture_engine(struct intel_engine_cs *engine, · 1595 unmodified lines | |||
| 1596 | { | 1596 | { |
| 1597 | struct intel_engine_capture_vma *capture = NULL; | 1597 | struct intel_engine_capture_vma *capture = NULL; |
| 1598 | struct intel_engine_coredump *ee; | 1598 | struct intel_engine_coredump *ee; |
| 1599 | struct intel_context *ce; | 1599 | struct intel_context *ce = NULL; |
| 1600 | struct i915_request *rq = NULL; | 1600 | struct i915_request *rq = NULL; |
| 1601 | unsigned long flags; | ||
| 1602 | 1601 | ||
| 1603 | ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags); | 1602 | ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags); |
| 1604 | if (!ee) | 1603 | if (!ee) |
| 1605 | return NULL; | 1604 | return NULL; |
| 1606 | 1605 | ||
| 1607 | ce = intel_engine_get_hung_context(engine); | 1606 | intel_engine_get_hung_entity(engine, &ce, &rq); |
| 1608 | if (ce) { | 1607 | if (!rq || !i915_request_started(rq)) |
| 1609 | intel_engine_clear_hung_context(engine); | ||
| 1610 | rq = intel_context_find_active_request(ce); | ||
| 1611 | if (!rq || !i915_request_started(rq)) | ||
| 1612 | goto no_request_capture; | ||
| 1613 | } else { | ||
| 1614 | /* | ||
| 1615 | * Getting here with GuC enabled means it is a forced error capture | ||
| 1616 | * with no actual hang. So, no need to attempt the execlist search. | ||
| 1617 | */ | ||
| 1618 | if (!intel_uc_uses_guc_submission(&engine->gt->uc)) { | ||
| 1619 | spin_lock_irqsave(&engine->sched_engine->lock, flags); | ||
| 1620 | rq = intel_engine_execlist_find_hung_request(engine); | ||
| 1621 | spin_unlock_irqrestore(&engine->sched_engine->lock, | ||
| 1622 | flags); | ||
| 1623 | } | ||
| 1624 | } | ||
| 1625 | if (rq) | ||
| 1626 | rq = i915_request_get_rcu(rq); | ||
| 1627 | |||
| 1628 | if (!rq) | ||
| 1629 | goto no_request_capture; | 1608 | goto no_request_capture; |
| 1630 | 1609 | ||
| 1631 | capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL); | 1610 | capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL); |
| 1632 | if (!capture) { | 1611 | if (!capture) |
| 1633 | i915_request_put(rq); | ||
| 1634 | goto no_request_capture; | 1612 | goto no_request_capture; |
| 1635 | } | ||
| 1636 | if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) | 1613 | if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) |
| 1637 | intel_guc_capture_get_matching_node(engine->gt, ee, ce); | 1614 | intel_guc_capture_get_matching_node(engine->gt, ee, ce); |
| 1638 | 1615 | ||
| @@ -1642,6 +1619,8 @@ capture_engine(struct intel_engine_cs *engine, · 3 unmodified lines | |||
| 1642 | return ee; | 1619 | return ee; |
| 1643 | 1620 | ||
| 1644 | no_request_capture: | 1621 | no_request_capture: |
| 1622 | if (rq) | ||
| 1623 | i915_request_put(rq); | ||
| 1645 | kfree(ee); | 1624 | kfree(ee); |
| 1646 | return NULL; | 1625 | return NULL; |
| 1647 | } | 1626 | } |