5252
5353#if IS_ENABLED (CONFIG_DRM_I915_DEBUG_RUNTIME_PM )
5454
55- #include <linux/sort.h>
56-
57- #define STACKDEPTH 8
58-
59- static noinline depot_stack_handle_t __save_depot_stack (void )
60- {
61- unsigned long entries [STACKDEPTH ];
62- unsigned int n ;
63-
64- n = stack_trace_save (entries , ARRAY_SIZE (entries ), 1 );
65- return stack_depot_save (entries , n , GFP_NOWAIT | __GFP_NOWARN );
66- }
67-
6855static void init_intel_runtime_pm_wakeref (struct intel_runtime_pm * rpm )
6956{
70- spin_lock_init (& rpm -> debug .lock );
71- stack_depot_init ();
57+ ref_tracker_dir_init (& rpm -> debug , INTEL_REFTRACK_DEAD_COUNT , dev_name (rpm -> kdev ));
7258}
7359
74- static noinline depot_stack_handle_t
60+ static intel_wakeref_t
7561track_intel_runtime_pm_wakeref (struct intel_runtime_pm * rpm )
7662{
77- depot_stack_handle_t stack , * stacks ;
78- unsigned long flags ;
79-
80- if (rpm -> no_wakeref_tracking )
81- return -1 ;
82-
83- stack = __save_depot_stack ();
84- if (!stack )
63+ if (!rpm -> available || rpm -> no_wakeref_tracking )
8564 return -1 ;
8665
87- spin_lock_irqsave (& rpm -> debug .lock , flags );
88-
89- if (!rpm -> debug .count )
90- rpm -> debug .last_acquire = stack ;
91-
92- stacks = krealloc (rpm -> debug .owners ,
93- (rpm -> debug .count + 1 ) * sizeof (* stacks ),
94- GFP_NOWAIT | __GFP_NOWARN );
95- if (stacks ) {
96- stacks [rpm -> debug .count ++ ] = stack ;
97- rpm -> debug .owners = stacks ;
98- } else {
99- stack = -1 ;
100- }
101-
102- spin_unlock_irqrestore (& rpm -> debug .lock , flags );
103-
104- return stack ;
66+ return intel_ref_tracker_alloc (& rpm -> debug );
10567}
10668
10769static void untrack_intel_runtime_pm_wakeref (struct intel_runtime_pm * rpm ,
108- depot_stack_handle_t stack )
70+ intel_wakeref_t wakeref )
10971{
110- struct drm_i915_private * i915 = container_of (rpm ,
111- struct drm_i915_private ,
112- runtime_pm );
113- unsigned long flags , n ;
114- bool found = false;
115-
116- if (unlikely (stack == -1 ))
72+ if (!rpm -> available || rpm -> no_wakeref_tracking )
11773 return ;
11874
119- spin_lock_irqsave (& rpm -> debug .lock , flags );
120- for (n = rpm -> debug .count ; n -- ; ) {
121- if (rpm -> debug .owners [n ] == stack ) {
122- memmove (rpm -> debug .owners + n ,
123- rpm -> debug .owners + n + 1 ,
124- (-- rpm -> debug .count - n ) * sizeof (stack ));
125- found = true;
126- break ;
127- }
128- }
129- spin_unlock_irqrestore (& rpm -> debug .lock , flags );
130-
131- if (drm_WARN (& i915 -> drm , !found ,
132- "Unmatched wakeref (tracking %lu), count %u\n" ,
133- rpm -> debug .count , atomic_read (& rpm -> wakeref_count ))) {
134- char * buf ;
135-
136- buf = kmalloc (PAGE_SIZE , GFP_NOWAIT | __GFP_NOWARN );
137- if (!buf )
138- return ;
139-
140- stack_depot_snprint (stack , buf , PAGE_SIZE , 2 );
141- DRM_DEBUG_DRIVER ("wakeref %x from\n%s" , stack , buf );
142-
143- stack = READ_ONCE (rpm -> debug .last_release );
144- if (stack ) {
145- stack_depot_snprint (stack , buf , PAGE_SIZE , 2 );
146- DRM_DEBUG_DRIVER ("wakeref last released at\n%s" , buf );
147- }
148-
149- kfree (buf );
150- }
75+ intel_ref_tracker_free (& rpm -> debug , wakeref );
15176}
15277
153- static int cmphandle ( const void * _a , const void * _b )
78+ static void untrack_all_intel_runtime_pm_wakerefs ( struct intel_runtime_pm * rpm )
15479{
155- const depot_stack_handle_t * const a = _a , * const b = _b ;
156-
157- if (* a < * b )
158- return -1 ;
159- else if (* a > * b )
160- return 1 ;
161- else
162- return 0 ;
163- }
164-
165- static void
166- __print_intel_runtime_pm_wakeref (struct drm_printer * p ,
167- const struct intel_runtime_pm_debug * dbg )
168- {
169- unsigned long i ;
170- char * buf ;
171-
172- buf = kmalloc (PAGE_SIZE , GFP_NOWAIT | __GFP_NOWARN );
173- if (!buf )
174- return ;
175-
176- if (dbg -> last_acquire ) {
177- stack_depot_snprint (dbg -> last_acquire , buf , PAGE_SIZE , 2 );
178- drm_printf (p , "Wakeref last acquired:\n%s" , buf );
179- }
180-
181- if (dbg -> last_release ) {
182- stack_depot_snprint (dbg -> last_release , buf , PAGE_SIZE , 2 );
183- drm_printf (p , "Wakeref last released:\n%s" , buf );
184- }
185-
186- drm_printf (p , "Wakeref count: %lu\n" , dbg -> count );
187-
188- sort (dbg -> owners , dbg -> count , sizeof (* dbg -> owners ), cmphandle , NULL );
189-
190- for (i = 0 ; i < dbg -> count ; i ++ ) {
191- depot_stack_handle_t stack = dbg -> owners [i ];
192- unsigned long rep ;
193-
194- rep = 1 ;
195- while (i + 1 < dbg -> count && dbg -> owners [i + 1 ] == stack )
196- rep ++ , i ++ ;
197- stack_depot_snprint (stack , buf , PAGE_SIZE , 2 );
198- drm_printf (p , "Wakeref x%lu taken at:\n%s" , rep , buf );
199- }
200-
201- kfree (buf );
202- }
203-
204- static noinline void
205- __untrack_all_wakerefs (struct intel_runtime_pm_debug * debug ,
206- struct intel_runtime_pm_debug * saved )
207- {
208- * saved = * debug ;
209-
210- debug -> owners = NULL ;
211- debug -> count = 0 ;
212- debug -> last_release = __save_depot_stack ();
213- }
214-
215- static void
216- dump_and_free_wakeref_tracking (struct intel_runtime_pm_debug * debug )
217- {
218- if (debug -> count ) {
219- struct drm_printer p = drm_debug_printer ("i915" );
220-
221- __print_intel_runtime_pm_wakeref (& p , debug );
222- }
223-
224- kfree (debug -> owners );
80+ ref_tracker_dir_exit (& rpm -> debug );
22581}
22682
22783static noinline void
22884__intel_wakeref_dec_and_check_tracking (struct intel_runtime_pm * rpm )
22985{
230- struct intel_runtime_pm_debug dbg = {};
23186 unsigned long flags ;
23287
23388 if (!atomic_dec_and_lock_irqsave (& rpm -> wakeref_count ,
23489 & rpm -> debug .lock ,
23590 flags ))
23691 return ;
23792
238- __untrack_all_wakerefs (& rpm -> debug , & dbg );
93+ ref_tracker_dir_print_locked (& rpm -> debug , INTEL_REFTRACK_PRINT_LIMIT );
23994 spin_unlock_irqrestore (& rpm -> debug .lock , flags );
240-
241- dump_and_free_wakeref_tracking (& dbg );
242- }
243-
244- static noinline void
245- untrack_all_intel_runtime_pm_wakerefs (struct intel_runtime_pm * rpm )
246- {
247- struct intel_runtime_pm_debug dbg = {};
248- unsigned long flags ;
249-
250- spin_lock_irqsave (& rpm -> debug .lock , flags );
251- __untrack_all_wakerefs (& rpm -> debug , & dbg );
252- spin_unlock_irqrestore (& rpm -> debug .lock , flags );
253-
254- dump_and_free_wakeref_tracking (& dbg );
25595}
25696
25797void print_intel_runtime_pm_wakeref (struct intel_runtime_pm * rpm ,
25898 struct drm_printer * p )
25999{
260- struct intel_runtime_pm_debug dbg = {};
261-
262- do {
263- unsigned long alloc = dbg .count ;
264- depot_stack_handle_t * s ;
265-
266- spin_lock_irq (& rpm -> debug .lock );
267- dbg .count = rpm -> debug .count ;
268- if (dbg .count <= alloc ) {
269- memcpy (dbg .owners ,
270- rpm -> debug .owners ,
271- dbg .count * sizeof (* s ));
272- }
273- dbg .last_acquire = rpm -> debug .last_acquire ;
274- dbg .last_release = rpm -> debug .last_release ;
275- spin_unlock_irq (& rpm -> debug .lock );
276- if (dbg .count <= alloc )
277- break ;
278-
279- s = krealloc (dbg .owners ,
280- dbg .count * sizeof (* s ),
281- GFP_NOWAIT | __GFP_NOWARN );
282- if (!s )
283- goto out ;
284-
285- dbg .owners = s ;
286- } while (1 );
287-
288- __print_intel_runtime_pm_wakeref (p , & dbg );
289-
290- out :
291- kfree (dbg .owners );
100+ intel_ref_tracker_show (& rpm -> debug , p );
292101}
293102
294103#else
@@ -297,14 +106,14 @@ static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm)
297106{
298107}
299108
300- static depot_stack_handle_t
109+ static intel_wakeref_t
301110track_intel_runtime_pm_wakeref (struct intel_runtime_pm * rpm )
302111{
303112 return -1 ;
304113}
305114
306115static void untrack_intel_runtime_pm_wakeref (struct intel_runtime_pm * rpm ,
307- intel_wakeref_t wref )
116+ intel_wakeref_t wakeref )
308117{
309118}
310119
@@ -639,7 +448,11 @@ void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm)
639448 "i915 raw-wakerefs=%d wakelocks=%d on cleanup\n" ,
640449 intel_rpm_raw_wakeref_count (count ),
641450 intel_rpm_wakelock_count (count ));
451+ }
642452
453+ void intel_runtime_pm_driver_last_release (struct intel_runtime_pm * rpm )
454+ {
455+ intel_runtime_pm_driver_release (rpm );
643456 untrack_all_intel_runtime_pm_wakerefs (rpm );
644457}
645458
0 commit comments