From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
To: "Zanoni, Paulo R" <paulo.r.zanoni@intel.com>,
"intel-gfx@lists.freedesktop.org"
<intel-gfx@lists.freedesktop.org>
Subject: Re: [PATCH v4 3/8] drm/i915: Kill off intel_crtc->atomic.wait_vblank, v4.
Date: Thu, 18 Feb 2016 15:46:02 +0100 [thread overview]
Message-ID: <56C5D92A.6060403@linux.intel.com> (raw)
In-Reply-To: <1455804871.2576.51.camel@intel.com>
Op 18-02-16 om 15:14 schreef Zanoni, Paulo R:
> Em Qui, 2016-02-18 às 14:22 +0100, Maarten Lankhorst escreveu:
>> Op 17-02-16 om 22:20 schreef Zanoni, Paulo R:
>>> Em Qua, 2016-02-10 às 13:49 +0100, Maarten Lankhorst escreveu:
>>>> Currently we perform our own wait in post_plane_update,
>>>> but the atomic core performs another one in wait_for_vblanks.
>>>> This means that 2 vblanks are done when a fb is changed,
>>>> which is a bit overkill.
>>>>
>>>> Merge them by creating a helper function that takes a crtc mask
>>>> for the planes to wait on.
>>>>
>>>> The broadwell vblank workaround may look gone entirely but this
>>>> is
>>>> not the case. pipe_config->wm_changed is set to true
>>>> when any plane is turned on, which forces a vblank wait.
>>>>
>>>> Changes since v1:
>>>> - Removing the double vblank wait on broadwell moved to its own
>>>> commit.
>>>> Changes since v2:
>>>> - Move out POWER_DOMAIN_MODESET handling to its own commit.
>>>> Changes since v3:
>>>> - Do not wait for vblank on legacy cursor updates. (Ville)
>>>> - Move broadwell vblank workaround comment to page_flip_finished.
>>>> (Ville)
>>>> Changes since v4:
>>>> - Compile fix, legacy_cursor_flip -> *_update.
>>>>
>>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.c
>>>> om>
>>>> ---
>>>> drivers/gpu/drm/i915/intel_atomic.c | 1 +
>>>> drivers/gpu/drm/i915/intel_display.c | 86
>>>> +++++++++++++++++++++++++++---------
>>>> drivers/gpu/drm/i915/intel_drv.h | 2 +-
>>>> 3 files changed, 67 insertions(+), 22 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/intel_atomic.c
>>>> b/drivers/gpu/drm/i915/intel_atomic.c
>>>> index 4625f8a9ba12..8e579a8505ac 100644
>>>> --- a/drivers/gpu/drm/i915/intel_atomic.c
>>>> +++ b/drivers/gpu/drm/i915/intel_atomic.c
>>>> @@ -97,6 +97,7 @@ intel_crtc_duplicate_state(struct drm_crtc
>>>> *crtc)
>>>> crtc_state->disable_lp_wm = false;
>>>> crtc_state->disable_cxsr = false;
>>>> crtc_state->wm_changed = false;
>>>> + crtc_state->fb_changed = false;
>>>>
>>>> return &crtc_state->base;
>>>> }
>>>> diff --git a/drivers/gpu/drm/i915/intel_display.c
>>>> b/drivers/gpu/drm/i915/intel_display.c
>>>> index 804f2c6f260d..4d4dddc1f970 100644
>>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>>> @@ -4785,9 +4785,6 @@ static void intel_post_plane_update(struct
>>>> intel_crtc *crtc)
>>>> to_intel_crtc_state(crtc->base.state);
>>>> struct drm_device *dev = crtc->base.dev;
>>>>
>>>> - if (atomic->wait_vblank)
>>>> - intel_wait_for_vblank(dev, crtc->pipe);
>>>> -
>>>> intel_frontbuffer_flip(dev, atomic->fb_bits);
>>>>
>>>> crtc->wm.cxsr_allowed = true;
>>>> @@ -10902,6 +10899,12 @@ static bool page_flip_finished(struct
>>>> intel_crtc *crtc)
>>>> return true;
>>>>
>>>> /*
>>>> + * BDW signals flip done immediately if the plane
>>>> + * is disabled, even if the plane enable is already
>>>> + * armed to occur at the next vblank :(
>>>> + */
>>> Having this comment here is just... weird. I think it removes a lot
>>> of
>>> the context that was present before.
>>>
>>>> +
>>>> + /*
>>>> * A DSPSURFLIVE check isn't enough in case the mmio and
>>>> CS
>>>> flips
>>>> * used the same base address. In that case the mmio
>>>> flip
>>>> might
>>>> * have completed, but the CS hasn't even executed the
>>>> flip
>>>> yet.
>>>> @@ -11778,6 +11781,9 @@ int
>>>> intel_plane_atomic_calc_changes(struct
>>>> drm_crtc_state *crtc_state,
>>>> if (!was_visible && !visible)
>>>> return 0;
>>>>
>>>> + if (fb != old_plane_state->base.fb)
>>>> + pipe_config->fb_changed = true;
>>>> +
>>>> turn_off = was_visible && (!visible || mode_changed);
>>>> turn_on = visible && (!was_visible || mode_changed);
>>>>
>>>> @@ -11793,8 +11799,6 @@ int
>>>> intel_plane_atomic_calc_changes(struct
>>>> drm_crtc_state *crtc_state,
>>>>
>>>> /* must disable cxsr around plane enable/disable
>>>> */
>>>> if (plane->type != DRM_PLANE_TYPE_CURSOR) {
>>>> - if (is_crtc_enabled)
>>>> - intel_crtc->atomic.wait_vblank =
>>>> true;
>>>> pipe_config->disable_cxsr = true;
>>>> }
>>> We could have killed the brackets here :)
>> Indeed, will do so in next version.
>>>> } else if (intel_wm_need_update(plane, plane_state)) {
>>>> @@ -11810,14 +11814,6 @@ int
>>>> intel_plane_atomic_calc_changes(struct
>>>> drm_crtc_state *crtc_state,
>>>> intel_crtc->atomic.post_enable_primary =
>>>> turn_on;
>>>> intel_crtc->atomic.update_fbc = true;
>>>>
>>>> - /*
>>>> - * BDW signals flip done immediately if the
>>>> plane
>>>> - * is disabled, even if the plane enable is
>>>> already
>>>> - * armed to occur at the next vblank :(
>>>> - */
>>>> - if (turn_on && IS_BROADWELL(dev))
>>>> - intel_crtc->atomic.wait_vblank = true;
>>>> -
>>>> break;
>>>> case DRM_PLANE_TYPE_CURSOR:
>>>> break;
>>>> @@ -11831,12 +11827,10 @@ int
>>>> intel_plane_atomic_calc_changes(struct
>>>> drm_crtc_state *crtc_state,
>>>> if (IS_IVYBRIDGE(dev) &&
>>>> needs_scaling(to_intel_plane_state(plane_sta
>>>> te))
>>>> &&
>>>> !needs_scaling(old_plane_state)) {
>>>> - to_intel_crtc_state(crtc_state)-
>>>>> disable_lp_wm = true;
>>>> - } else if (turn_off && !mode_changed) {
>>>> - intel_crtc->atomic.wait_vblank = true;
>>>> + pipe_config->disable_lp_wm = true;
>>>> + } else if (turn_off && !mode_changed)
>>>> intel_crtc-
>>>>> atomic.update_sprite_watermarks
>>>>> =
>>>> 1 << i;
>>>> - }
>>> Weird brackets here. Either kill on both sides of the if statement
>>> (the
>>> preferred way), or none.
>>>
>>> Also, shouldn't we introduce pipe_config->sprite_changed? What's
>>> guaranteeing that we're going to definitely wait for a vblank
>>> during
>>> sprite updates? I like explicit dumb-proof code instead of
>>> implications
>>> such as "we're doing waits during sprite updates because whenever
>>> we
>>> update sprites, a specific unrelated variable that's used for a
>>> different purpose gets set to true, and we check for this
>>> variable".
>> sprite_changed would be same as fb_changed + wm_changed, and
>> update_sprite_watermarks gets removed in this series
>> because nothing uses it.
> Hmmm, right. For some reason, I was interpreting fb_changed as being
> only valid for the primary fb, not for spr/cur. My bad. So fb_changed
> means "if any of pri/cur/spr changed" I guess. Maybe planes_changed
> could be a better name, or fbs_changed (plural), since we're talking
> about more then one possible plane here. Not a requirement, just
> throwing the idea.
planes_changed is already used, it means that any plane_state is being updated for this crtc.
fbs_changed could work though, most other *_changed are plural.
>>>>
>>>> break;
>>>> }
>>>> @@ -13370,6 +13364,48 @@ static int
>>>> intel_atomic_prepare_commit(struct drm_device *dev,
>>>> return ret;
>>>> }
>>>>
>>>> +static void intel_atomic_wait_for_vblanks(struct drm_device
>>>> *dev,
>>>> + struct
>>>> drm_i915_private
>>>> *dev_priv,
>>>> + unsigned crtc_mask)
>>>> +{
>>>> + unsigned last_vblank_count[I915_MAX_PIPES];
>>>> + enum pipe pipe;
>>>> + int ret;
>>>> +
>>>> + if (!crtc_mask)
>>>> + return;
>>>> +
>>>> + for_each_pipe(dev_priv, pipe) {
>>>> + struct drm_crtc *crtc = dev_priv-
>>>>> pipe_to_crtc_mapping[pipe];
>>>> +
>>>> + if (!((1 << pipe) & crtc_mask))
>>>> + continue;
>>>> +
>>>> + ret = drm_crtc_vblank_get(crtc);
>>>> + if (ret != 0) {
>>>> + crtc_mask &= ~(1 << pipe);
>>>> + continue;
>>> Shouldn't we DRM_ERROR here?
>> WARN_ON is enough, this shouldn't ever happen.
> Even better :)
>
>>>> + }
>>>> +
>>>> + last_vblank_count[pipe] =
>>>> drm_crtc_vblank_count(crtc);
>>>> + }
>>>> +
>>>> + for_each_pipe(dev_priv, pipe) {
>>>> + struct drm_crtc *crtc = dev_priv-
>>>>> pipe_to_crtc_mapping[pipe];
>>>> +
>>>> + if (!((1 << pipe) & crtc_mask))
>>>> + continue;
>>>> +
>>>> + wait_event_timeout(dev->vblank[pipe].queue,
>>>> + last_vblank_count[pipe] !=
>>>> + drm_crtc_vblank_count(cr
>>>> tc),
>>>> + msecs_to_jiffies(50));
>>> Also maybe DRM_ERROR in case we hit the timeout?
>>>
>>> I know the original code doesn't have this, but now that we're
>>> doing or
>>> own thing, we may scream in unexpected cases.
>> I'll make it a WARN_ON, shouldn't happen.
>>>> +
>>>> + drm_crtc_vblank_put(crtc);
>>>> + }
>>>> +}
>>>> +
>>>> +
>>> Two newlines :)
>> Indeed!
>>>> /**
>>>> * intel_atomic_commit - commit validated state object
>>>> * @dev: DRM device
>>>> @@ -13397,6 +13433,7 @@ static int intel_atomic_commit(struct
>>>> drm_device *dev,
>>>> int ret = 0, i;
>>>> bool hw_check = intel_state->modeset;
>>>> unsigned long put_domains[I915_MAX_PIPES] = {};
>>>> + unsigned crtc_vblank_mask = 0;
>>>>
>>>> ret = intel_atomic_prepare_commit(dev, state, async);
>>>> if (ret) {
>>>> @@ -13470,8 +13507,9 @@ static int intel_atomic_commit(struct
>>>> drm_device *dev,
>>>> for_each_crtc_in_state(state, crtc, crtc_state, i) {
>>>> struct intel_crtc *intel_crtc =
>>>> to_intel_crtc(crtc);
>>>> bool modeset = needs_modeset(crtc->state);
>>>> - bool update_pipe = !modeset &&
>>>> - to_intel_crtc_state(crtc->state)-
>>>>> update_pipe;
>>>> + struct intel_crtc_state *pipe_config =
>>>> + to_intel_crtc_state(crtc->state);
>>>> + bool update_pipe = !modeset && pipe_config-
>>>>> update_pipe;
>>>>
>>>> if (modeset && crtc->state->active) {
>>>> update_scanline_offset(to_intel_crtc(crt
>>>> c));
>>>> @@ -13488,14 +13526,20 @@ static int intel_atomic_commit(struct
>>>> drm_device *dev,
>>>> (crtc->state->planes_changed ||
>>>> update_pipe))
>>>> drm_atomic_helper_commit_planes_on_crtc(
>>>> crtc
>>>> _state);
>>>>
>>>> - intel_post_plane_update(intel_crtc);
>>>> + if (pipe_config->base.active &&
>>>> + (pipe_config->wm_changed || pipe_config-
>>>>> disable_cxsr ||
>>>> + pipe_config->fb_changed))
>>> So the wm_changed is just for the BDW workaround + sprites? What
>>> about
>>> this disable_cxsr, why is it here? Also see my comment above about
>>> sprite_changed. Maybe we need some comments here to explain the
>>> complex
>>> checks.
>> No it's waiting for a vblank for post_plane_update so all optimized
>> wm values
>> can get written, it's not just for the BDW workaround.
>> It just happens to be that the BDW w/a gets applied too as a side
>> effect.
> So maybe some comment regarding the BDW WA could be here.
>
> What about disable_cxsr? Why is this here?
That's what matches the current code, see the calc_changes hunk which had a vblank_wait = true.
>>>> + crtc_vblank_mask |= 1 << i;
>>>> }
>>>>
>>>> /* FIXME: add subpixel order */
>>>>
>>>> - drm_atomic_helper_wait_for_vblanks(dev, state);
>>>> + if (!state->legacy_cursor_update)
>>>> + intel_atomic_wait_for_vblanks(dev, dev_priv,
>>>> crtc_vblank_mask);
>>>>
>>>> for_each_crtc_in_state(state, crtc, crtc_state, i) {
>>>> + intel_post_plane_update(to_intel_crtc(crtc));
>>>> +
>>>> if (put_domains[i])
>>>> modeset_put_power_domains(dev_priv,
>>>> put_domains[i]);
>>>> }
>>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h
>>>> b/drivers/gpu/drm/i915/intel_drv.h
>>>> index 335e6b24b0bc..e911c86f873b 100644
>>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>>> @@ -379,6 +379,7 @@ struct intel_crtc_state {
>>>> bool update_pipe; /* can a fast modeset be performed? */
>>>> bool disable_cxsr;
>>>> bool wm_changed; /* watermarks are updated */
>>>> + bool fb_changed; /* fb on any of the planes is changed
>>>> */
>>>>
>>>> /* Pipe source size (ie. panel fitter input size)
>>>> * All planes will be positioned inside this space,
>>>> @@ -547,7 +548,6 @@ struct intel_crtc_atomic_commit {
>>>>
>>>> /* Sleepable operations to perform after commit */
>>>> unsigned fb_bits;
>>>> - bool wait_vblank;
>>> One of the things that I like about the code without this patch is
>>> that
>>> it's very explicit on when we need to wait for vblanks (except for
>>> the
>>> problem where we wait twice). The new code is not as easy to
>>> read/understand as the old one. This comment is similar to the one
>>> I
>>> made in patch 6: I'm not sure if sacrificing readability is worth
>>> it.
>>>
>>> I wonder that maybe the cleanest fix to the "we're waiting 2
>>> vblanks"
>>> problem is to just remove the call to
>>> drm_atomic_helper_wait_for_vblanks(), which would be a first patch.
>>> Then we'd have a second patch introducing
>>> intel_atomic_wait_for_vblanks() for the "wait for all vblanks at
>>> the
>>> same time" optimization, and then a last commit possibly replacing
>>> commit->wait_vblank for state->fb_changed. Just an idea, not a
>>> request.
>> There were cases in which the atomic helper would wait for vblanks
>> which
>> wouldn't trigger any of the other changes, so it can't be blindly
>> removed. Mostly when
>> updating a plane with a same sized fb.
> Those could be specifically addressed on their own patches, then :)
It would break things though.
I think what might make the most sense is adding a inline function for needs_vblank,
with comments why certain flags require a vblank wait.
>> Wait for vblank is required for unpinning, it would be bad if the
>> current fb is unpinned.
>>
>>> I'll wait for your answers before reaching any conclusions of what
>>> I
>>> think should be done, since I may be misunderstanding something.
>> I want to call all post flip work scheduled later on so it happens
>> after the next vblank.
>> That will remove all confusion on when a vblank is required, because
>> all post_plane_update
>> and unpin will always wait until next vblank.
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2016-02-18 14:46 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-10 12:49 [PATCH v4 0/8] Kill off intel_crtc->atomic! Maarten Lankhorst
2016-02-10 12:49 ` [PATCH v4 1/8] drm/i915: Pass crtc state to modeset_get_crtc_power_domains Maarten Lankhorst
2016-02-17 17:54 ` Zanoni, Paulo R
2016-02-18 9:51 ` Maarten Lankhorst
2016-02-18 13:08 ` Zanoni, Paulo R
2016-02-18 13:21 ` Maarten Lankhorst
2016-02-10 12:49 ` [PATCH v4 2/8] drm/i915: Unify power domain handling Maarten Lankhorst
2016-02-17 19:54 ` Zanoni, Paulo R
2016-02-10 12:49 ` [PATCH v4 3/8] drm/i915: Kill off intel_crtc->atomic.wait_vblank, v4 Maarten Lankhorst
2016-02-17 21:20 ` Zanoni, Paulo R
2016-02-18 13:22 ` Maarten Lankhorst
2016-02-18 14:14 ` Zanoni, Paulo R
2016-02-18 14:46 ` Maarten Lankhorst [this message]
2016-02-18 17:02 ` Zanoni, Paulo R
2016-02-24 10:24 ` [PATCH v6 3/8] drm/i915: Kill off intel_crtc->atomic.wait_vblank, v6 Maarten Lankhorst
2016-02-24 14:50 ` Zanoni, Paulo R
2016-02-10 12:49 ` [PATCH v4 4/8] drm/i915: Remove update_sprite_watermarks Maarten Lankhorst
2016-02-10 12:49 ` [PATCH v4 5/8] drm/i915: Remove some post-commit members from intel_crtc->atomic, v2 Maarten Lankhorst
2016-02-10 12:49 ` [PATCH v4 6/8] drm/i915: Nuke fbc " Maarten Lankhorst
2016-02-12 13:56 ` Zanoni, Paulo R
2016-02-15 14:31 ` Maarten Lankhorst
2016-02-18 17:17 ` Zanoni, Paulo R
2016-02-29 9:58 ` [PATCH v4.1 6/8] drm/i915: Nuke fbc members from intel_crtc->atomic, v3 Maarten Lankhorst
2016-02-29 21:06 ` Zanoni, Paulo R
2016-03-01 8:27 ` Maarten Lankhorst
2016-02-10 12:49 ` [PATCH v4 7/8] drm/i915: Do not compute watermarks on a noop Maarten Lankhorst
2016-02-18 20:51 ` Zanoni, Paulo R
2016-03-01 10:11 ` Maarten Lankhorst
2016-02-10 12:49 ` [PATCH v4 8/8] drm/i915: Remove vblank wait from hsw_enable_ips Maarten Lankhorst
2016-02-12 12:06 ` Zanoni, Paulo R
2016-02-16 10:32 ` Maarten Lankhorst
2016-03-23 13:33 ` [PATCH v5 8/8] drm/i915: Remove vblank wait from hsw_enable_ips, v2 Maarten Lankhorst
2016-03-23 14:43 ` Zanoni, Paulo R
2016-02-15 13:35 ` ✗ Fi.CI.BAT: failure for Kill off intel_crtc->atomic! (rev8) Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56C5D92A.6060403@linux.intel.com \
--to=maarten.lankhorst@linux.intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=paulo.r.zanoni@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.