Skip to content

Commit ca65fc0

Browse files
icklerodrigovivi
authored andcommitted
drm/i915/gt: Always send a pulse down the engine after disabling heartbeat
Currently, we check we can send a pulse prior to disabling the heartbeat to verify that we can change the heartbeat, but since we may re-evaluate execution upon changing the heartbeat interval we need another pulse afterwards to refresh execution. v2: Tvrtko asked if we could reduce the double pulse to a single, which opened up a discussion of how we should handle the pulse-error after attempting to change the property, and the desire to serialise adjustment of the property with its validating pulse, and unwind upon failure. Fixes: 9a40bdd ("drm/i915/gt: Expose heartbeat interval via sysfs") Signed-off-by: Chris Wilson <[email protected]> Cc: Joonas Lahtinen <[email protected]> Cc: Tvrtko Ursulin <[email protected]> Cc: <[email protected]> # v5.7+ Reviewed-by: Tvrtko Ursulin <[email protected]> Acked-by: Joonas Lahtinen <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit 3dd66a9) Signed-off-by: Rodrigo Vivi <[email protected]>
1 parent 7d442ea commit ca65fc0

File tree

1 file changed

+67
-39
lines changed

1 file changed

+67
-39
lines changed

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

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -177,36 +177,82 @@ void intel_engine_init_heartbeat(struct intel_engine_cs *engine)
177177
INIT_DELAYED_WORK(&engine->heartbeat.work, heartbeat);
178178
}
179179

180+
static int __intel_engine_pulse(struct intel_engine_cs *engine)
181+
{
182+
struct i915_sched_attr attr = { .priority = I915_PRIORITY_BARRIER };
183+
struct intel_context *ce = engine->kernel_context;
184+
struct i915_request *rq;
185+
186+
lockdep_assert_held(&ce->timeline->mutex);
187+
GEM_BUG_ON(!intel_engine_has_preemption(engine));
188+
GEM_BUG_ON(!intel_engine_pm_is_awake(engine));
189+
190+
intel_context_enter(ce);
191+
rq = __i915_request_create(ce, GFP_NOWAIT | __GFP_NOWARN);
192+
intel_context_exit(ce);
193+
if (IS_ERR(rq))
194+
return PTR_ERR(rq);
195+
196+
__set_bit(I915_FENCE_FLAG_SENTINEL, &rq->fence.flags);
197+
idle_pulse(engine, rq);
198+
199+
__i915_request_commit(rq);
200+
__i915_request_queue(rq, &attr);
201+
GEM_BUG_ON(rq->sched.attr.priority < I915_PRIORITY_BARRIER);
202+
203+
return 0;
204+
}
205+
206+
static unsigned long set_heartbeat(struct intel_engine_cs *engine,
207+
unsigned long delay)
208+
{
209+
unsigned long old;
210+
211+
old = xchg(&engine->props.heartbeat_interval_ms, delay);
212+
if (delay)
213+
intel_engine_unpark_heartbeat(engine);
214+
else
215+
intel_engine_park_heartbeat(engine);
216+
217+
return old;
218+
}
219+
180220
int intel_engine_set_heartbeat(struct intel_engine_cs *engine,
181221
unsigned long delay)
182222
{
183-
int err;
223+
struct intel_context *ce = engine->kernel_context;
224+
int err = 0;
184225

185-
/* Send one last pulse before to cleanup persistent hogs */
186-
if (!delay && IS_ACTIVE(CONFIG_DRM_I915_PREEMPT_TIMEOUT)) {
187-
err = intel_engine_pulse(engine);
188-
if (err)
189-
return err;
190-
}
226+
if (!delay && !intel_engine_has_preempt_reset(engine))
227+
return -ENODEV;
228+
229+
intel_engine_pm_get(engine);
230+
231+
err = mutex_lock_interruptible(&ce->timeline->mutex);
232+
if (err)
233+
goto out_rpm;
191234

192-
WRITE_ONCE(engine->props.heartbeat_interval_ms, delay);
235+
if (delay != engine->props.heartbeat_interval_ms) {
236+
unsigned long saved = set_heartbeat(engine, delay);
193237

194-
if (intel_engine_pm_get_if_awake(engine)) {
195-
if (delay)
196-
intel_engine_unpark_heartbeat(engine);
197-
else
198-
intel_engine_park_heartbeat(engine);
199-
intel_engine_pm_put(engine);
238+
/* recheck current execution */
239+
if (intel_engine_has_preemption(engine)) {
240+
err = __intel_engine_pulse(engine);
241+
if (err)
242+
set_heartbeat(engine, saved);
243+
}
200244
}
201245

202-
return 0;
246+
mutex_unlock(&ce->timeline->mutex);
247+
248+
out_rpm:
249+
intel_engine_pm_put(engine);
250+
return err;
203251
}
204252

205253
int intel_engine_pulse(struct intel_engine_cs *engine)
206254
{
207-
struct i915_sched_attr attr = { .priority = I915_PRIORITY_BARRIER };
208255
struct intel_context *ce = engine->kernel_context;
209-
struct i915_request *rq;
210256
int err;
211257

212258
if (!intel_engine_has_preemption(engine))
@@ -215,30 +261,12 @@ int intel_engine_pulse(struct intel_engine_cs *engine)
215261
if (!intel_engine_pm_get_if_awake(engine))
216262
return 0;
217263

218-
if (mutex_lock_interruptible(&ce->timeline->mutex)) {
219-
err = -EINTR;
220-
goto out_rpm;
221-
}
222-
223-
intel_context_enter(ce);
224-
rq = __i915_request_create(ce, GFP_NOWAIT | __GFP_NOWARN);
225-
intel_context_exit(ce);
226-
if (IS_ERR(rq)) {
227-
err = PTR_ERR(rq);
228-
goto out_unlock;
264+
err = -EINTR;
265+
if (!mutex_lock_interruptible(&ce->timeline->mutex)) {
266+
err = __intel_engine_pulse(engine);
267+
mutex_unlock(&ce->timeline->mutex);
229268
}
230269

231-
__set_bit(I915_FENCE_FLAG_SENTINEL, &rq->fence.flags);
232-
idle_pulse(engine, rq);
233-
234-
__i915_request_commit(rq);
235-
__i915_request_queue(rq, &attr);
236-
GEM_BUG_ON(rq->sched.attr.priority < I915_PRIORITY_BARRIER);
237-
err = 0;
238-
239-
out_unlock:
240-
mutex_unlock(&ce->timeline->mutex);
241-
out_rpm:
242270
intel_engine_pm_put(engine);
243271
return err;
244272
}

0 commit comments

Comments
 (0)