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

drm/i915/guc: Take engine PM when a context is pinned with GuC submission

Taking a PM reference to prevent intel_gt_wait_for_idle from short
circuiting while any user context has scheduling enabled. Returning GT
idle when it is not can cause all sorts of issues throughout the stack.

v2:
(Daniel Vetter)
- Add might_lock annotations to pin / unpin function
v3:
(CI)
- Drop intel_engine_pm_might_put from unpin path as an async put is
used
v4:
(John Harrison)
- Make intel_engine_pm_might_get/put work with GuC virtual engines
- Update commit message
v5:
- Update commit message again

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: John Harrison <John.C.Harrison@Intel.com>
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211014172005.27155-4-matthew.brost@intel.com

authored by

Matthew Brost and committed by
John Harrison
f61eae18 1a52faed

+89 -3
+2
drivers/gpu/drm/i915/gt/intel_context.c
··· 240 240 if (err) 241 241 goto err_post_unpin; 242 242 243 + intel_engine_pm_might_get(ce->engine); 244 + 243 245 if (unlikely(intel_context_is_closed(ce))) { 244 246 err = -ENOENT; 245 247 goto err_unlock;
+32
drivers/gpu/drm/i915/gt/intel_engine_pm.h
··· 6 6 #ifndef INTEL_ENGINE_PM_H 7 7 #define INTEL_ENGINE_PM_H 8 8 9 + #include "i915_drv.h" 9 10 #include "i915_request.h" 10 11 #include "intel_engine_types.h" 11 12 #include "intel_wakeref.h" 13 + #include "intel_gt_pm.h" 12 14 13 15 static inline bool 14 16 intel_engine_pm_is_awake(const struct intel_engine_cs *engine) ··· 33 31 return intel_wakeref_get_if_active(&engine->wakeref); 34 32 } 35 33 34 + static inline void intel_engine_pm_might_get(struct intel_engine_cs *engine) 35 + { 36 + if (!intel_engine_is_virtual(engine)) { 37 + intel_wakeref_might_get(&engine->wakeref); 38 + } else { 39 + struct intel_gt *gt = engine->gt; 40 + struct intel_engine_cs *tengine; 41 + intel_engine_mask_t tmp, mask = engine->mask; 42 + 43 + for_each_engine_masked(tengine, gt, mask, tmp) 44 + intel_wakeref_might_get(&tengine->wakeref); 45 + } 46 + intel_gt_pm_might_get(engine->gt); 47 + } 48 + 36 49 static inline void intel_engine_pm_put(struct intel_engine_cs *engine) 37 50 { 38 51 intel_wakeref_put(&engine->wakeref); ··· 67 50 static inline void intel_engine_pm_flush(struct intel_engine_cs *engine) 68 51 { 69 52 intel_wakeref_unlock_wait(&engine->wakeref); 53 + } 54 + 55 + static inline void intel_engine_pm_might_put(struct intel_engine_cs *engine) 56 + { 57 + if (!intel_engine_is_virtual(engine)) { 58 + intel_wakeref_might_put(&engine->wakeref); 59 + } else { 60 + struct intel_gt *gt = engine->gt; 61 + struct intel_engine_cs *tengine; 62 + intel_engine_mask_t tmp, mask = engine->mask; 63 + 64 + for_each_engine_masked(tengine, gt, mask, tmp) 65 + intel_wakeref_might_put(&tengine->wakeref); 66 + } 67 + intel_gt_pm_might_put(engine->gt); 70 68 } 71 69 72 70 static inline struct i915_request *
+10
drivers/gpu/drm/i915/gt/intel_gt_pm.h
··· 31 31 return intel_wakeref_get_if_active(&gt->wakeref); 32 32 } 33 33 34 + static inline void intel_gt_pm_might_get(struct intel_gt *gt) 35 + { 36 + intel_wakeref_might_get(&gt->wakeref); 37 + } 38 + 34 39 static inline void intel_gt_pm_put(struct intel_gt *gt) 35 40 { 36 41 intel_wakeref_put(&gt->wakeref); ··· 44 39 static inline void intel_gt_pm_put_async(struct intel_gt *gt) 45 40 { 46 41 intel_wakeref_put_async(&gt->wakeref); 42 + } 43 + 44 + static inline void intel_gt_pm_might_put(struct intel_gt *gt) 45 + { 46 + intel_wakeref_might_put(&gt->wakeref); 47 47 } 48 48 49 49 #define with_intel_gt_pm(gt, tmp) \
+33 -3
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
··· 1571 1571 1572 1572 static int guc_context_pin(struct intel_context *ce, void *vaddr) 1573 1573 { 1574 - return __guc_context_pin(ce, ce->engine, vaddr); 1574 + int ret = __guc_context_pin(ce, ce->engine, vaddr); 1575 + 1576 + if (likely(!ret && !intel_context_is_barrier(ce))) 1577 + intel_engine_pm_get(ce->engine); 1578 + 1579 + return ret; 1575 1580 } 1576 1581 1577 1582 static void guc_context_unpin(struct intel_context *ce) ··· 1585 1580 1586 1581 unpin_guc_id(guc, ce); 1587 1582 lrc_unpin(ce); 1583 + 1584 + if (likely(!intel_context_is_barrier(ce))) 1585 + intel_engine_pm_put_async(ce->engine); 1588 1586 } 1589 1587 1590 1588 static void guc_context_post_unpin(struct intel_context *ce) ··· 2349 2341 static int guc_virtual_context_pin(struct intel_context *ce, void *vaddr) 2350 2342 { 2351 2343 struct intel_engine_cs *engine = guc_virtual_get_sibling(ce->engine, 0); 2344 + int ret = __guc_context_pin(ce, engine, vaddr); 2345 + intel_engine_mask_t tmp, mask = ce->engine->mask; 2352 2346 2353 - return __guc_context_pin(ce, engine, vaddr); 2347 + if (likely(!ret)) 2348 + for_each_engine_masked(engine, ce->engine->gt, mask, tmp) 2349 + intel_engine_pm_get(engine); 2350 + 2351 + return ret; 2352 + } 2353 + 2354 + static void guc_virtual_context_unpin(struct intel_context *ce) 2355 + { 2356 + intel_engine_mask_t tmp, mask = ce->engine->mask; 2357 + struct intel_engine_cs *engine; 2358 + struct intel_guc *guc = ce_to_guc(ce); 2359 + 2360 + GEM_BUG_ON(context_enabled(ce)); 2361 + GEM_BUG_ON(intel_context_is_barrier(ce)); 2362 + 2363 + unpin_guc_id(guc, ce); 2364 + lrc_unpin(ce); 2365 + 2366 + for_each_engine_masked(engine, ce->engine->gt, mask, tmp) 2367 + intel_engine_pm_put_async(engine); 2354 2368 } 2355 2369 2356 2370 static void guc_virtual_context_enter(struct intel_context *ce) ··· 2409 2379 2410 2380 .pre_pin = guc_virtual_context_pre_pin, 2411 2381 .pin = guc_virtual_context_pin, 2412 - .unpin = guc_context_unpin, 2382 + .unpin = guc_virtual_context_unpin, 2413 2383 .post_unpin = guc_context_post_unpin, 2414 2384 2415 2385 .ban = guc_context_ban,
+12
drivers/gpu/drm/i915/intel_wakeref.h
··· 123 123 __INTEL_WAKEREF_PUT_LAST_BIT__ 124 124 }; 125 125 126 + static inline void 127 + intel_wakeref_might_get(struct intel_wakeref *wf) 128 + { 129 + might_lock(&wf->mutex); 130 + } 131 + 126 132 /** 127 133 * intel_wakeref_put_flags: Release the wakeref 128 134 * @wf: the wakeref ··· 174 168 __intel_wakeref_put(wf, 175 169 INTEL_WAKEREF_PUT_ASYNC | 176 170 FIELD_PREP(INTEL_WAKEREF_PUT_DELAY, delay)); 171 + } 172 + 173 + static inline void 174 + intel_wakeref_might_put(struct intel_wakeref *wf) 175 + { 176 + might_lock(&wf->mutex); 177 177 } 178 178 179 179 /**