Skip to content

Commit 5e4e06e

Browse files
committed
drm/i915: Track gt pm wakerefs
Track every intel_gt_pm_get() until its corresponding release in intel_gt_pm_put() by returning a cookie to the caller for acquire that must be passed by on released. When there is an imbalance, we can see who either tried to free a stale wakeref, or who forgot to free theirs. v2: track recently added calls in gen8_ggtt_bind_get_ce and destroyed_worker_func Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com> Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20231030-ref_tracker_i915-v1-2-006fe6b96421@intel.com
1 parent b49e894 commit 5e4e06e

24 files changed

Lines changed: 197 additions & 90 deletions

drivers/gpu/drm/i915/Kconfig.debug

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ config DRM_I915_DEBUG
4040
select DRM_I915_DEBUG_GEM_ONCE
4141
select DRM_I915_DEBUG_MMIO
4242
select DRM_I915_DEBUG_RUNTIME_PM
43+
select DRM_I915_DEBUG_WAKEREF
4344
select DRM_I915_SW_FENCE_DEBUG_OBJECTS
4445
select DRM_I915_SELFTEST
4546
default n
@@ -244,3 +245,16 @@ config DRM_I915_DEBUG_RUNTIME_PM
244245
Recommended for driver developers only.
245246

246247
If in doubt, say "N"
248+
249+
config DRM_I915_DEBUG_WAKEREF
250+
bool "Enable extra tracking for wakerefs"
251+
depends on DRM_I915
252+
select REF_TRACKER
253+
select STACKDEPOT
254+
select STACKTRACE
255+
help
256+
Choose this option to turn on extra state checking and usage
257+
tracking for the wakerefPM functionality. This may introduce
258+
overhead during driver runtime.
259+
260+
If in doubt, say "N"

drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ struct i915_execbuffer {
253253
struct intel_gt *gt; /* gt for the execbuf */
254254
struct intel_context *context; /* logical state for the request */
255255
struct i915_gem_context *gem_context; /** caller's context */
256+
intel_wakeref_t wakeref;
257+
intel_wakeref_t wakeref_gt0;
256258

257259
/** our requests to build */
258260
struct i915_request *requests[MAX_ENGINE_INSTANCE + 1];
@@ -2719,13 +2721,13 @@ eb_select_engine(struct i915_execbuffer *eb)
27192721

27202722
for_each_child(ce, child)
27212723
intel_context_get(child);
2722-
intel_gt_pm_get(gt);
2724+
eb->wakeref = intel_gt_pm_get(ce->engine->gt);
27232725
/*
27242726
* Keep GT0 active on MTL so that i915_vma_parked() doesn't
27252727
* free VMAs while execbuf ioctl is validating VMAs.
27262728
*/
27272729
if (gt->info.id)
2728-
intel_gt_pm_get(to_gt(gt->i915));
2730+
eb->wakeref_gt0 = intel_gt_pm_get(to_gt(gt->i915));
27292731

27302732
if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
27312733
err = intel_context_alloc_state(ce);
@@ -2765,9 +2767,9 @@ eb_select_engine(struct i915_execbuffer *eb)
27652767

27662768
err:
27672769
if (gt->info.id)
2768-
intel_gt_pm_put(to_gt(gt->i915));
2770+
intel_gt_pm_put(to_gt(gt->i915), eb->wakeref_gt0);
27692771

2770-
intel_gt_pm_put(gt);
2772+
intel_gt_pm_put(ce->engine->gt, eb->wakeref);
27712773
for_each_child(ce, child)
27722774
intel_context_put(child);
27732775
intel_context_put(ce);
@@ -2785,8 +2787,8 @@ eb_put_engine(struct i915_execbuffer *eb)
27852787
* i915_vma_parked() from interfering while execbuf validates vmas.
27862788
*/
27872789
if (eb->gt->info.id)
2788-
intel_gt_pm_put(to_gt(eb->gt->i915));
2789-
intel_gt_pm_put(eb->gt);
2790+
intel_gt_pm_put(to_gt(eb->gt->i915), eb->wakeref_gt0);
2791+
intel_gt_pm_put(eb->context->engine->gt, eb->wakeref);
27902792
for_each_child(eb->context, child)
27912793
intel_context_put(child);
27922794
intel_context_put(eb->context);

drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ static int cpu_get(struct context *ctx, unsigned long offset, u32 *v)
8585

8686
static int gtt_set(struct context *ctx, unsigned long offset, u32 v)
8787
{
88+
intel_wakeref_t wakeref;
8889
struct i915_vma *vma;
8990
u32 __iomem *map;
9091
int err = 0;
@@ -99,7 +100,7 @@ static int gtt_set(struct context *ctx, unsigned long offset, u32 v)
99100
if (IS_ERR(vma))
100101
return PTR_ERR(vma);
101102

102-
intel_gt_pm_get(vma->vm->gt);
103+
wakeref = intel_gt_pm_get(vma->vm->gt);
103104

104105
map = i915_vma_pin_iomap(vma);
105106
i915_vma_unpin(vma);
@@ -112,12 +113,13 @@ static int gtt_set(struct context *ctx, unsigned long offset, u32 v)
112113
i915_vma_unpin_iomap(vma);
113114

114115
out_rpm:
115-
intel_gt_pm_put(vma->vm->gt);
116+
intel_gt_pm_put(vma->vm->gt, wakeref);
116117
return err;
117118
}
118119

119120
static int gtt_get(struct context *ctx, unsigned long offset, u32 *v)
120121
{
122+
intel_wakeref_t wakeref;
121123
struct i915_vma *vma;
122124
u32 __iomem *map;
123125
int err = 0;
@@ -132,7 +134,7 @@ static int gtt_get(struct context *ctx, unsigned long offset, u32 *v)
132134
if (IS_ERR(vma))
133135
return PTR_ERR(vma);
134136

135-
intel_gt_pm_get(vma->vm->gt);
137+
wakeref = intel_gt_pm_get(vma->vm->gt);
136138

137139
map = i915_vma_pin_iomap(vma);
138140
i915_vma_unpin(vma);
@@ -145,7 +147,7 @@ static int gtt_get(struct context *ctx, unsigned long offset, u32 *v)
145147
i915_vma_unpin_iomap(vma);
146148

147149
out_rpm:
148-
intel_gt_pm_put(vma->vm->gt);
150+
intel_gt_pm_put(vma->vm->gt, wakeref);
149151
return err;
150152
}
151153

drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -630,14 +630,14 @@ static bool assert_mmap_offset(struct drm_i915_private *i915,
630630
static void disable_retire_worker(struct drm_i915_private *i915)
631631
{
632632
i915_gem_driver_unregister__shrinker(i915);
633-
intel_gt_pm_get(to_gt(i915));
633+
intel_gt_pm_get_untracked(to_gt(i915));
634634
cancel_delayed_work_sync(&to_gt(i915)->requests.retire_work);
635635
}
636636

637637
static void restore_retire_worker(struct drm_i915_private *i915)
638638
{
639639
igt_flush_test(i915);
640-
intel_gt_pm_put(to_gt(i915));
640+
intel_gt_pm_put_untracked(to_gt(i915));
641641
i915_gem_driver_register__shrinker(i915);
642642
}
643643

@@ -778,6 +778,7 @@ static int igt_mmap_offset_exhaustion(void *arg)
778778

779779
static int gtt_set(struct drm_i915_gem_object *obj)
780780
{
781+
intel_wakeref_t wakeref;
781782
struct i915_vma *vma;
782783
void __iomem *map;
783784
int err = 0;
@@ -786,7 +787,7 @@ static int gtt_set(struct drm_i915_gem_object *obj)
786787
if (IS_ERR(vma))
787788
return PTR_ERR(vma);
788789

789-
intel_gt_pm_get(vma->vm->gt);
790+
wakeref = intel_gt_pm_get(vma->vm->gt);
790791
map = i915_vma_pin_iomap(vma);
791792
i915_vma_unpin(vma);
792793
if (IS_ERR(map)) {
@@ -798,12 +799,13 @@ static int gtt_set(struct drm_i915_gem_object *obj)
798799
i915_vma_unpin_iomap(vma);
799800

800801
out:
801-
intel_gt_pm_put(vma->vm->gt);
802+
intel_gt_pm_put(vma->vm->gt, wakeref);
802803
return err;
803804
}
804805

805806
static int gtt_check(struct drm_i915_gem_object *obj)
806807
{
808+
intel_wakeref_t wakeref;
807809
struct i915_vma *vma;
808810
void __iomem *map;
809811
int err = 0;
@@ -812,7 +814,7 @@ static int gtt_check(struct drm_i915_gem_object *obj)
812814
if (IS_ERR(vma))
813815
return PTR_ERR(vma);
814816

815-
intel_gt_pm_get(vma->vm->gt);
817+
wakeref = intel_gt_pm_get(vma->vm->gt);
816818
map = i915_vma_pin_iomap(vma);
817819
i915_vma_unpin(vma);
818820
if (IS_ERR(map)) {
@@ -828,7 +830,7 @@ static int gtt_check(struct drm_i915_gem_object *obj)
828830
i915_vma_unpin_iomap(vma);
829831

830832
out:
831-
intel_gt_pm_put(vma->vm->gt);
833+
intel_gt_pm_put(vma->vm->gt, wakeref);
832834
return err;
833835
}
834836

drivers/gpu/drm/i915/gt/intel_breadcrumbs.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ static void irq_disable(struct intel_breadcrumbs *b)
2828

2929
static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
3030
{
31+
intel_wakeref_t wakeref;
32+
3133
/*
3234
* Since we are waiting on a request, the GPU should be busy
3335
* and should have its own rpm reference.
3436
*/
35-
if (GEM_WARN_ON(!intel_gt_pm_get_if_awake(b->irq_engine->gt)))
37+
wakeref = intel_gt_pm_get_if_awake(b->irq_engine->gt);
38+
if (GEM_WARN_ON(!wakeref))
3639
return;
3740

3841
/*
@@ -41,7 +44,7 @@ static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
4144
* which we can add a new waiter and avoid the cost of re-enabling
4245
* the irq.
4346
*/
44-
WRITE_ONCE(b->irq_armed, true);
47+
WRITE_ONCE(b->irq_armed, wakeref);
4548

4649
/* Requests may have completed before we could enable the interrupt. */
4750
if (!b->irq_enabled++ && b->irq_enable(b))
@@ -61,12 +64,14 @@ static void intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
6164

6265
static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
6366
{
67+
intel_wakeref_t wakeref = b->irq_armed;
68+
6469
GEM_BUG_ON(!b->irq_enabled);
6570
if (!--b->irq_enabled)
6671
b->irq_disable(b);
6772

68-
WRITE_ONCE(b->irq_armed, false);
69-
intel_gt_pm_put_async(b->irq_engine->gt);
73+
WRITE_ONCE(b->irq_armed, 0);
74+
intel_gt_pm_put_async(b->irq_engine->gt, wakeref);
7075
}
7176

7277
static void intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)

drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/types.h>
1414

1515
#include "intel_engine_types.h"
16+
#include "intel_wakeref.h"
1617

1718
/*
1819
* Rather than have every client wait upon all user interrupts,
@@ -43,7 +44,7 @@ struct intel_breadcrumbs {
4344
spinlock_t irq_lock; /* protects the interrupt from hardirq context */
4445
struct irq_work irq_work; /* for use from inside irq_lock */
4546
unsigned int irq_enabled;
46-
bool irq_armed;
47+
intel_wakeref_t irq_armed;
4748

4849
/* Not all breadcrumbs are attached to physical HW */
4950
intel_engine_mask_t engine_mask;

drivers/gpu/drm/i915/gt/intel_context.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ static inline void intel_context_enter(struct intel_context *ce)
212212
return;
213213

214214
ce->ops->enter(ce);
215-
intel_gt_pm_get(ce->vm->gt);
215+
ce->wakeref = intel_gt_pm_get(ce->vm->gt);
216216
}
217217

218218
static inline void intel_context_mark_active(struct intel_context *ce)
@@ -229,7 +229,7 @@ static inline void intel_context_exit(struct intel_context *ce)
229229
if (--ce->active_count)
230230
return;
231231

232-
intel_gt_pm_put_async(ce->vm->gt);
232+
intel_gt_pm_put_async(ce->vm->gt, ce->wakeref);
233233
ce->ops->exit(ce);
234234
}
235235

drivers/gpu/drm/i915/gt/intel_context_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "i915_utils.h"
1818
#include "intel_engine_types.h"
1919
#include "intel_sseu.h"
20+
#include "intel_wakeref.h"
2021

2122
#include "uc/intel_guc_fwif.h"
2223

@@ -112,6 +113,7 @@ struct intel_context {
112113
u32 ring_size;
113114
struct intel_ring *ring;
114115
struct intel_timeline *timeline;
116+
intel_wakeref_t wakeref;
115117

116118
unsigned long flags;
117119
#define CONTEXT_BARRIER_BIT 0

drivers/gpu/drm/i915/gt/intel_engine_pm.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static int __engine_unpark(struct intel_wakeref *wf)
6363

6464
ENGINE_TRACE(engine, "\n");
6565

66-
intel_gt_pm_get(engine->gt);
66+
engine->wakeref_track = intel_gt_pm_get(engine->gt);
6767

6868
/* Discard stale context state from across idling */
6969
ce = engine->kernel_context;
@@ -122,6 +122,7 @@ __queue_and_release_pm(struct i915_request *rq,
122122
*/
123123
GEM_BUG_ON(rq->context->active_count != 1);
124124
__intel_gt_pm_get(engine->gt);
125+
rq->context->wakeref = intel_wakeref_track(&engine->gt->wakeref);
125126

126127
/*
127128
* We have to serialise all potential retirement paths with our
@@ -285,7 +286,7 @@ static int __engine_park(struct intel_wakeref *wf)
285286
engine->park(engine);
286287

287288
/* While gt calls i915_vma_parked(), we have to break the lock cycle */
288-
intel_gt_pm_put_async(engine->gt);
289+
intel_gt_pm_put_async(engine->gt, engine->wakeref_track);
289290
return 0;
290291
}
291292

@@ -296,7 +297,7 @@ static const struct intel_wakeref_ops wf_ops = {
296297

297298
void intel_engine_init__pm(struct intel_engine_cs *engine)
298299
{
299-
intel_wakeref_init(&engine->wakeref, engine->i915, &wf_ops);
300+
intel_wakeref_init(&engine->wakeref, engine->i915, &wf_ops, engine->name);
300301
intel_engine_init_heartbeat(engine);
301302

302303
intel_gsc_idle_msg_enable(engine);

drivers/gpu/drm/i915/gt/intel_engine_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,9 @@ struct intel_engine_cs {
446446
unsigned long serial;
447447

448448
unsigned long wakeref_serial;
449+
intel_wakeref_t wakeref_track;
449450
struct intel_wakeref wakeref;
451+
450452
struct file *default_state;
451453

452454
struct {

0 commit comments

Comments
 (0)