Em Qui, 2016-02-18 às 15:46 +0100, Maarten Lankhorst escreveu: > 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@xxxxxxxxx > > > > > el.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. I noticed that you fix the brackets on patch 4/8 by removing the "else" part. So feel free to keep this chunk like this, so you won't need to resend patch 4. > > > > > > > > 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_coun > > > > > t(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_c > > > > > rtc( > > > > > 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. Hmm, right. I missed that, sorry. > > > > > + 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. Ok, let's discard the idea then. > > 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. That could be good. I have no further questions/requests for this patch. In the end, it seems the changes needed are small :). I'll wait for the next version. > > > 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@xxxxxxxxxxxxxxxxxxxxx > > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx > _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx