[Intel-gfx] [PATCH 1/3] drm: Defer disabling the vblank IRQ until the next interrupt (for instant-off)
Mario Kleiner
mario.kleiner.de at gmail.com
Wed Mar 22 15:06:32 UTC 2017
On 03/15/2017 10:00 PM, Ville Syrjälä wrote:
> On Wed, Mar 15, 2017 at 08:40:25PM +0000, Chris Wilson wrote:
>> On vblank instant-off systems, we can get into a situation where the cost
>> of enabling and disabling the vblank IRQ around a drmWaitVblank query
>> dominates. And with the advent of even deeper hardware sleep state,
>> touching registers becomes ever more expensive. However, we know that if
>> the user wants the current vblank counter, they are also very likely to
>> immediately queue a vblank wait and so we can keep the interrupt around
>> and only turn it off if we have no further vblank requests queued within
>> the interrupt interval.
>>
>> After vblank event delivery, this patch adds a shadow of one vblank where
>> the interrupt is kept alive for the user to query and queue another vblank
>> event. Similarly, if the user is using blocking drmWaitVblanks, the
>> interrupt will be disabled on the IRQ following the wait completion.
>> However, if the user is simply querying the current vblank counter and
>> timestamp, the interrupt will be disabled after every IRQ and the user
>> will enabled it again on the first query following the IRQ.
>>
>> v2: Mario Kleiner -
>> After testing this, one more thing that would make sense is to move
>> the disable block at the end of drm_handle_vblank() instead of at the
>> top.
>>
>> Turns out that if high precision timestaming is disabled or doesn't
>> work for some reason (as can be simulated by echo 0 >
>> /sys/module/drm/parameters/timestamp_precision_usec), then with your
>> delayed disable code at its current place, the vblank counter won't
>> increment anymore at all for instant queries, ie. with your other
>> "instant query" patches. Clients which repeatedly query the counter
>> and wait for it to progress will simply hang, spinning in an endless
>> query loop. There's that comment in vblank_disable_and_save:
>>
>> "* Skip this step if there isn't any high precision timestamp
>> * available. In that case we can't account for this and just
>> * hope for the best.
>> */
>>
>> With the disable happening after leading edge of vblank (== hw counter
>> increment already happened) but before the vblank counter/timestamp
>> handling in drm_handle_vblank, that step is needed to keep the counter
>> progressing, so skipping it is bad.
>>
>> Now without high precision timestamping support, a kms driver must not
>> set dev->vblank_disable_immediate = true, as this would cause problems
>> for clients, so this shouldn't matter, but it would be good to still
>> make this robust against a future kms driver which might have
>> unreliable high precision timestamping, e.g., high precision
>> timestamping that intermittently doesn't work.
>>
>> v3: Patch before coffee needs extra coffee.
>>
>> Testcase: igt/kms_vblank
>> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
>> Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
>> Cc: Daniel Vetter <daniel at ffwll.ch>
>> Cc: Michel Dänzer <michel at daenzer.net>
>> Cc: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>> Cc: Dave Airlie <airlied at redhat.com>,
>> Cc: Mario Kleiner <mario.kleiner.de at gmail.com>
>
> Yep. This seems like a good idea to me. I just neglected to review it
> last time around (and maybe even before that?) for some reason. Locks
> seem to be taken in the right order, so it at least looks safe to me.
>
> Reviewed-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
>
Hi,
as a followup to this one, maybe we should move the
drm_handle_vblank_events(dev, pipe); down, immediately after Chris new
delayed disable code?
The idea was to avoid lots of redundant enable->disable->enable... calls
by having some 1 frame delay before disable. This works for pure vblank
count/ts queries.
But both DRI2 and DRI3/Present use vblank events to trigger a
pageflip-ioctl at the right target vblank. With the current ordering we
may dispatch the vblank swap trigger event to the X-Server and drop the
vblank refcount to zero due to the vblank_put inside
drm_handle_vblank_events for the dispatched event, then detect in this
patch that refcount == 0 and disable vblanks, but a few microseconds
later the server will queue a pageflip ioctl which bumps the refcount
and reenables vblank irqs, so we have a redundant disable->enable.
Also many kms drivers now use drm_crtc_arm_vblank_event() for pageflip
completion handling at vblank, the pageflip completion events are also
dispatched via drm_handle_vblank_events(). After a pageflip completes,
it makes sense to have this "swap shadow" of 1 full frame, as animations
would likely queue a new vblank query/event immediately for the next
animation frame.
-mario
>> ---
>> drivers/gpu/drm/drm_irq.c | 14 ++++++++++++--
>> 1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
>> index 9bdca69f754c..e64b05ea95ea 100644
>> --- a/drivers/gpu/drm/drm_irq.c
>> +++ b/drivers/gpu/drm/drm_irq.c
>> @@ -1198,9 +1198,9 @@ static void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
>> if (atomic_dec_and_test(&vblank->refcount)) {
>> if (drm_vblank_offdelay == 0)
>> return;
>> - else if (dev->vblank_disable_immediate || drm_vblank_offdelay < 0)
>> + else if (drm_vblank_offdelay < 0)
>> vblank_disable_fn((unsigned long)vblank);
>> - else
>> + else if (!dev->vblank_disable_immediate)
>> mod_timer(&vblank->disable_timer,
>> jiffies + ((drm_vblank_offdelay * HZ)/1000));
>> }
>> @@ -1734,6 +1734,16 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
>> wake_up(&vblank->queue);
>> drm_handle_vblank_events(dev, pipe);
>>
>> + /* With instant-off, we defer disabling the interrupt until after
>> + * we finish processing the following vblank. The disable has to
>> + * be last (after drm_handle_vblank_events) so that the timestamp
>> + * is always accurate.
>> + */
>> + if (dev->vblank_disable_immediate &&
>> + drm_vblank_offdelay > 0 &&
>> + !atomic_read(&vblank->refcount))
>> + vblank_disable_fn((unsigned long)vblank);
>> +
>> spin_unlock_irqrestore(&dev->event_lock, irqflags);
>>
>> return true;
>> --
>> 2.11.0
>
More information about the Intel-gfx
mailing list