[Intel-gfx] [PATCH 2/2] drm/i915: Use rcu instead of stop_machine in set_wedged

Daniel Vetter daniel.vetter at ffwll.ch
Tue Oct 10 14:09:06 UTC 2017


On Tue, Oct 10, 2017 at 3:39 PM, Chris Wilson <chris at chris-wilson.co.uk> wrote:
> Style nits:
>
> Quoting Daniel Vetter (2017-10-09 17:44:01)
>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>> index 82a10036fb38..8d7d8d1f78db 100644
>> --- a/drivers/gpu/drm/i915/i915_gem.c
>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>> @@ -3057,49 +3057,71 @@ static void nop_submit_request(struct drm_i915_gem_request *request)
>>
>>         spin_lock_irqsave(&request->engine->timeline->lock, flags);
>>         __i915_gem_request_submit(request);
>> -       intel_engine_init_global_seqno(request->engine, request->global_seqno);
>>         spin_unlock_irqrestore(&request->engine->timeline->lock, flags);
>
> This reduced to i915_gem_request_submit().
>
> Hah, you can just engine->submit_request = i915_gem_request_submit, and
> keep the nop_submit_request for the second phase! That may make the
> diff neater?

We need to call dma_fence_set_error still, and we need to start doing
that before we start calling ->cancel_request, or we might miss some
requests.

I'll do all the other suggestions and resubmit.
-Daniel

>> -static int __i915_gem_set_wedged_BKL(void *data)
>> +void i915_gem_set_wedged(struct drm_i915_private *i915)
>>  {
>> -       struct drm_i915_private *i915 = data;
>>         struct intel_engine_cs *engine;
>>         enum intel_engine_id id;
>>
>> +       /* First, stop submission to hw, but do not yet complete requests by
>> +        * rolling the global seqno forward (since this would complete requests
>> +        * for which we haven't set the fence error to EIO yet).
>> +        */
>
> I'm doing a quiet fixup of all my comments to follow
> /*
>  * The core convention, which you normally use anyway.
>  */
>
>>         for_each_engine(engine, i915, id)
>> -               engine_set_wedged(engine);
>> +               engine->submit_request = nop_submit_request;
>>
>> -       set_bit(I915_WEDGED, &i915->gpu_error.flags);
>> -       wake_up_all(&i915->gpu_error.reset_queue);
>> +       /* Make sure no one is running the old callback before we proceed with
>> +        * cancelling requests and resetting the completion tracking. Otherwise
>> +        * we might submit a request to the hardware which never completes.
>> +        */
>> +       synchronize_rcu();
>>
>> -       return 0;
>> -}
>> +       for_each_engine(engine, i915, id) {
>> +               /* Mark all executing requests as skipped */
>> +               engine->cancel_requests(engine);
>>
>> -void i915_gem_set_wedged(struct drm_i915_private *dev_priv)
>> -{
>> -       stop_machine(__i915_gem_set_wedged_BKL, dev_priv, NULL);
>> +               /* Only once we've force-cancelled all in-flight requests can we
>> +                * start to complete all requests.
>> +                */
>> +               engine->submit_request = nop_complete_submit_request;
>> +       }
>> +
>> +       /* Make sure no request can slip through without getting completed by
>> +        * either this call here to intel_engine_init_global_seqno, or the one
>> +        * in nop_complete_submit_request.
>> +        */
>> +       synchronize_rcu();
>> +
>> +       for_each_engine(engine, i915, id) {
>> +               unsigned long flags;
>> +
>> +               /* Mark all pending requests as complete so that any concurrent
>> +                * (lockless) lookup doesn't try and wait upon the request as we
>> +                * reset it.
>> +                */
>> +               spin_lock_irqsave(&engine->timeline->lock, flags);
>> +               intel_engine_init_global_seqno(engine,
>> +                                              intel_engine_last_submit(engine));
>> +               spin_unlock_irqrestore(&engine->timeline->lock, flags);
>> +       }
>> +
>> +       set_bit(I915_WEDGED, &i915->gpu_error.flags);
>> +       wake_up_all(&i915->gpu_error.reset_queue);
>>  }
>>
>>  bool i915_gem_unset_wedged(struct drm_i915_private *i915)
>> diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
>> index b100b38f1dd2..ef78a85cb845 100644
>> --- a/drivers/gpu/drm/i915/i915_gem_request.c
>> +++ b/drivers/gpu/drm/i915/i915_gem_request.c
>> @@ -556,7 +556,9 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
>>         switch (state) {
>>         case FENCE_COMPLETE:
>>                 trace_i915_gem_request_submit(request);
>> +               rcu_read_lock();
>
> This trick needs a comment.
>
> /*
>  * We need to serialize use of the submit_request() callback with its
>  * hotplugging performed during an emergency i915_gem_set_wedged().
>  * We use the RCU mechanism to mark the critical section in order to
>  * force i915_gem_set_wedged() to wait until the submit_request() is
>  * completed before proceeding.
>  */
> -Chris



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


More information about the Intel-gfx mailing list