2 * SPDX-License-Identifier: MIT
4 * Copyright © 2018 Intel Corporation
7 #include <linux/sort.h>
11 #include "intel_gt_requests.h"
12 #include "i915_selftest.h"
13 #include "selftest_engine_heartbeat.h"
15 static int timeline_sync(struct intel_timeline
*tl
)
17 struct dma_fence
*fence
;
20 fence
= i915_active_fence_get(&tl
->last_request
);
24 timeout
= dma_fence_wait_timeout(fence
, true, HZ
/ 2);
32 static int engine_sync_barrier(struct intel_engine_cs
*engine
)
34 return timeline_sync(engine
->kernel_context
->timeline
);
38 struct i915_active active
;
42 static int pulse_active(struct i915_active
*active
)
44 kref_get(&container_of(active
, struct pulse
, active
)->kref
);
48 static void pulse_free(struct kref
*kref
)
50 struct pulse
*p
= container_of(kref
, typeof(*p
), kref
);
52 i915_active_fini(&p
->active
);
56 static void pulse_put(struct pulse
*p
)
58 kref_put(&p
->kref
, pulse_free
);
61 static void pulse_retire(struct i915_active
*active
)
63 pulse_put(container_of(active
, struct pulse
, active
));
66 static struct pulse
*pulse_create(void)
70 p
= kmalloc(sizeof(*p
), GFP_KERNEL
);
75 i915_active_init(&p
->active
, pulse_active
, pulse_retire
);
80 static void pulse_unlock_wait(struct pulse
*p
)
82 i915_active_unlock_wait(&p
->active
);
85 static int __live_idle_pulse(struct intel_engine_cs
*engine
,
86 int (*fn
)(struct intel_engine_cs
*cs
))
91 GEM_BUG_ON(!intel_engine_pm_is_awake(engine
));
97 err
= i915_active_acquire(&p
->active
);
101 err
= i915_active_acquire_preallocate_barrier(&p
->active
, engine
);
103 i915_active_release(&p
->active
);
107 i915_active_acquire_barrier(&p
->active
);
108 i915_active_release(&p
->active
);
110 GEM_BUG_ON(i915_active_is_idle(&p
->active
));
111 GEM_BUG_ON(llist_empty(&engine
->barrier_tasks
));
117 GEM_BUG_ON(!llist_empty(&engine
->barrier_tasks
));
119 if (engine_sync_barrier(engine
)) {
120 struct drm_printer m
= drm_err_printer("pulse");
122 pr_err("%s: no heartbeat pulse?\n", engine
->name
);
123 intel_engine_dump(engine
, &m
, "%s", engine
->name
);
129 GEM_BUG_ON(READ_ONCE(engine
->serial
) != engine
->wakeref_serial
);
131 pulse_unlock_wait(p
); /* synchronize with the retirement callback */
133 if (!i915_active_is_idle(&p
->active
)) {
134 struct drm_printer m
= drm_err_printer("pulse");
136 pr_err("%s: heartbeat pulse did not flush idle tasks\n",
138 i915_active_print(&p
->active
, &m
);
149 static int live_idle_flush(void *arg
)
151 struct intel_gt
*gt
= arg
;
152 struct intel_engine_cs
*engine
;
153 enum intel_engine_id id
;
156 /* Check that we can flush the idle barriers */
158 for_each_engine(engine
, gt
, id
) {
159 st_engine_heartbeat_disable(engine
);
160 err
= __live_idle_pulse(engine
, intel_engine_flush_barriers
);
161 st_engine_heartbeat_enable(engine
);
169 static int live_idle_pulse(void *arg
)
171 struct intel_gt
*gt
= arg
;
172 struct intel_engine_cs
*engine
;
173 enum intel_engine_id id
;
176 /* Check that heartbeat pulses flush the idle barriers */
178 for_each_engine(engine
, gt
, id
) {
179 st_engine_heartbeat_disable(engine
);
180 err
= __live_idle_pulse(engine
, intel_engine_pulse
);
181 st_engine_heartbeat_enable(engine
);
182 if (err
&& err
!= -ENODEV
)
191 static int cmp_u32(const void *_a
, const void *_b
)
193 const u32
*a
= _a
, *b
= _b
;
198 static int __live_heartbeat_fast(struct intel_engine_cs
*engine
)
200 struct intel_context
*ce
;
201 struct i915_request
*rq
;
207 ce
= intel_context_create(engine
);
211 intel_engine_pm_get(engine
);
213 err
= intel_engine_set_heartbeat(engine
, 1);
217 for (i
= 0; i
< ARRAY_SIZE(times
); i
++) {
219 /* Manufacture a tick */
220 intel_engine_park_heartbeat(engine
);
221 GEM_BUG_ON(engine
->heartbeat
.systole
);
222 engine
->serial
++; /* pretend we are not idle! */
223 intel_engine_unpark_heartbeat(engine
);
225 flush_delayed_work(&engine
->heartbeat
.work
);
226 if (!delayed_work_pending(&engine
->heartbeat
.work
)) {
227 pr_err("%s: heartbeat %d did not start\n",
234 rq
= READ_ONCE(engine
->heartbeat
.systole
);
236 rq
= i915_request_get_rcu(rq
);
241 while (rq
== READ_ONCE(engine
->heartbeat
.systole
))
242 yield(); /* work is on the local cpu! */
245 i915_request_put(rq
);
246 times
[i
] = ktime_us_delta(t1
, t0
);
249 sort(times
, ARRAY_SIZE(times
), sizeof(times
[0]), cmp_u32
, NULL
);
251 pr_info("%s: Heartbeat delay: %uus [%u, %u]\n",
253 times
[ARRAY_SIZE(times
) / 2],
255 times
[ARRAY_SIZE(times
) - 1]);
257 /* Min work delay is 2 * 2 (worst), +1 for scheduling, +1 for slack */
258 if (times
[ARRAY_SIZE(times
) / 2] > jiffies_to_usecs(6)) {
259 pr_err("%s: Heartbeat delay was %uus, expected less than %dus\n",
261 times
[ARRAY_SIZE(times
) / 2],
262 jiffies_to_usecs(6));
266 intel_engine_set_heartbeat(engine
, CONFIG_DRM_I915_HEARTBEAT_INTERVAL
);
268 intel_engine_pm_put(engine
);
269 intel_context_put(ce
);
273 static int live_heartbeat_fast(void *arg
)
275 struct intel_gt
*gt
= arg
;
276 struct intel_engine_cs
*engine
;
277 enum intel_engine_id id
;
280 /* Check that the heartbeat ticks at the desired rate. */
281 if (!CONFIG_DRM_I915_HEARTBEAT_INTERVAL
)
284 for_each_engine(engine
, gt
, id
) {
285 err
= __live_heartbeat_fast(engine
);
293 static int __live_heartbeat_off(struct intel_engine_cs
*engine
)
297 intel_engine_pm_get(engine
);
300 flush_delayed_work(&engine
->heartbeat
.work
);
301 if (!delayed_work_pending(&engine
->heartbeat
.work
)) {
302 pr_err("%s: heartbeat not running\n",
308 err
= intel_engine_set_heartbeat(engine
, 0);
313 flush_delayed_work(&engine
->heartbeat
.work
);
314 if (delayed_work_pending(&engine
->heartbeat
.work
)) {
315 pr_err("%s: heartbeat still running\n",
321 if (READ_ONCE(engine
->heartbeat
.systole
)) {
322 pr_err("%s: heartbeat still allocated\n",
329 intel_engine_set_heartbeat(engine
, CONFIG_DRM_I915_HEARTBEAT_INTERVAL
);
331 intel_engine_pm_put(engine
);
335 static int live_heartbeat_off(void *arg
)
337 struct intel_gt
*gt
= arg
;
338 struct intel_engine_cs
*engine
;
339 enum intel_engine_id id
;
342 /* Check that we can turn off heartbeat and not interrupt VIP */
343 if (!CONFIG_DRM_I915_HEARTBEAT_INTERVAL
)
346 for_each_engine(engine
, gt
, id
) {
347 if (!intel_engine_has_preemption(engine
))
350 err
= __live_heartbeat_off(engine
);
358 int intel_heartbeat_live_selftests(struct drm_i915_private
*i915
)
360 static const struct i915_subtest tests
[] = {
361 SUBTEST(live_idle_flush
),
362 SUBTEST(live_idle_pulse
),
363 SUBTEST(live_heartbeat_fast
),
364 SUBTEST(live_heartbeat_off
),
369 if (intel_gt_is_wedged(&i915
->gt
))
372 saved_hangcheck
= i915
->params
.enable_hangcheck
;
373 i915
->params
.enable_hangcheck
= INT_MAX
;
375 err
= intel_gt_live_subtests(tests
, &i915
->gt
);
377 i915
->params
.enable_hangcheck
= saved_hangcheck
;
381 void st_engine_heartbeat_disable(struct intel_engine_cs
*engine
)
383 engine
->props
.heartbeat_interval_ms
= 0;
385 intel_engine_pm_get(engine
);
386 intel_engine_park_heartbeat(engine
);
389 void st_engine_heartbeat_enable(struct intel_engine_cs
*engine
)
391 intel_engine_pm_put(engine
);
393 engine
->props
.heartbeat_interval_ms
=
394 engine
->defaults
.heartbeat_interval_ms
;