[Intel-gfx] [PATCH 10/11] drm/i915: Use a preemption timeout to enforce interactivity

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Tue Mar 27 08:57:48 UTC 2018


On 27/03/2018 09:39, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2018-03-27 09:35:17)
>>
>> On 26/03/2018 12:50, Chris Wilson wrote:
>>> Use a liberal timeout of 20ms to ensure that the rendering for an
>>> interactive pageflip is started in a timely fashion, and that
>>> user interaction is not blocked by GPU, or CPU, hogs. This is at the cost
>>> of resetting whoever was blocking the preemption, likely leading to that
>>> context/process being banned from submitting future requests.
>>>
>>> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
>>> ---
>>>    drivers/gpu/drm/i915/i915_drv.h      |  3 ++-
>>>    drivers/gpu/drm/i915/i915_gem.c      | 18 ++++++++++--------
>>>    drivers/gpu/drm/i915/intel_display.c | 18 +++++++++++++++++-
>>>    3 files changed, 29 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>>> index 800230ba1c3b..87388feb973d 100644
>>> --- a/drivers/gpu/drm/i915/i915_drv.h
>>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>>> @@ -3150,8 +3150,9 @@ int i915_gem_object_wait(struct drm_i915_gem_object *obj,
>>>                         struct intel_rps_client *rps);
>>>    int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
>>>                                  unsigned int flags,
>>> -                               int priority);
>>> +                               int priority, unsigned int timeout);
>>>    #define I915_PRIORITY_DISPLAY I915_PRIORITY_MAX
>>> +#define I915_PREEMPTION_TIMEOUT_DISPLAY (20 * 1000 * 1000) /* 20 ms */
>>>    
>>>    int __must_check
>>>    i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write);
>>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>>> index 675d6bb59337..252c6b58e739 100644
>>> --- a/drivers/gpu/drm/i915/i915_gem.c
>>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>>> @@ -469,7 +469,8 @@ i915_gem_object_wait_reservation(struct reservation_object *resv,
>>>        return timeout;
>>>    }
>>>    
>>> -static void __fence_set_priority(struct dma_fence *fence, int prio)
>>> +static void __fence_set_priority(struct dma_fence *fence,
>>> +                              int prio, unsigned int timeout)
>>>    {
>>>        struct i915_request *rq;
>>>        struct intel_engine_cs *engine;
>>> @@ -482,11 +483,12 @@ static void __fence_set_priority(struct dma_fence *fence, int prio)
>>>    
>>>        rcu_read_lock();
>>>        if (engine->schedule)
>>> -             engine->schedule(rq, prio, 0);
>>> +             engine->schedule(rq, prio, timeout);
>>>        rcu_read_unlock();
>>>    }
>>>    
>>> -static void fence_set_priority(struct dma_fence *fence, int prio)
>>> +static void fence_set_priority(struct dma_fence *fence,
>>> +                            int prio, unsigned int timeout)
>>>    {
>>>        /* Recurse once into a fence-array */
>>>        if (dma_fence_is_array(fence)) {
>>> @@ -494,16 +496,16 @@ static void fence_set_priority(struct dma_fence *fence, int prio)
>>>                int i;
>>>    
>>>                for (i = 0; i < array->num_fences; i++)
>>> -                     __fence_set_priority(array->fences[i], prio);
>>> +                     __fence_set_priority(array->fences[i], prio, timeout);
>>>        } else {
>>> -             __fence_set_priority(fence, prio);
>>> +             __fence_set_priority(fence, prio, timeout);
>>>        }
>>>    }
>>>    
>>>    int
>>>    i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
>>>                              unsigned int flags,
>>> -                           int prio)
>>> +                           int prio, unsigned int timeout)
>>>    {
>>>        struct dma_fence *excl;
>>>    
>>> @@ -518,7 +520,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
>>>                        return ret;
>>>    
>>>                for (i = 0; i < count; i++) {
>>> -                     fence_set_priority(shared[i], prio);
>>> +                     fence_set_priority(shared[i], prio, timeout);
>>>                        dma_fence_put(shared[i]);
>>>                }
>>>    
>>> @@ -528,7 +530,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
>>>        }
>>>    
>>>        if (excl) {
>>> -             fence_set_priority(excl, prio);
>>> +             fence_set_priority(excl, prio, timeout);
>>>                dma_fence_put(excl);
>>>        }
>>>        return 0;
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index 4c30c7c04f9c..830f2d4e540f 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -12786,7 +12786,23 @@ intel_prepare_plane_fb(struct drm_plane *plane,
>>>    
>>>        ret = intel_plane_pin_fb(to_intel_plane_state(new_state));
>>>    
>>> -     i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
>>> +     /*
>>> +      * Reschedule our dependencies, and ensure we run within a timeout.
>>> +      *
>>> +      * Note that if the timeout is exceeded, then whoever was running that
>>> +      * prevented us from acquiring the GPU is declared rogue and reset. An
>>> +      * unresponsive process will then be banned in order to preserve
>>> +      * interactivity. Since this can be seen as a bit heavy-handed, we
>>> +      * select a timeout for when the dropped frames start to become a
>>> +      * noticeable nuisance for the user (20 ms, i.e. preemption was blocked
>>> +      * for more than a frame). Note, this is only a timeout for a delay in
>>> +      * preempting the current request in order to run our dependency chain,
>>> +      * our dependency chain may itself take a long time to run to completion
>>> +      * before we can present the framebuffer.
>>> +      */
>>> +     i915_gem_object_wait_priority(obj, 0,
>>> +                                   I915_PRIORITY_DISPLAY,
>>> +                                   I915_PREEMPTION_TIMEOUT_DISPLAY);
>>
>> API signature changes to allow timeouts are fine, but I think this hunk
>> should be separate patch at the end of the series. (Since it has the
>> potential to make things which used to work, albeit stutteringly (?),
>> start crashing.
> 
> It is at the end as a separate patch. What am I missing?
> (The only thing after it is exposing a param to userspace.)

My bad, I assumed that last one depends on API signature changes from 
this one.

Regards,

Tvrtko





More information about the Intel-gfx mailing list