[Nouveau] [PATCH v3 4/4] drm/nouveau: Move PBN and VCPI allocation into nv50_head_atom
Ben Skeggs
skeggsb at gmail.com
Tue Feb 5 01:37:26 UTC 2019
On Sat, 2 Feb 2019 at 10:20, Lyude Paul <lyude at redhat.com> wrote:
>
> Atomic checks should never modify anything outside of the state that
> they're passed in. Unfortunately this appears to be exactly what we're
> doing in nv50_msto_atomic_check() where we update mstc->pbn every time
> the function is called. This hasn't caused any bugs yet, but it needs to
> be fixed in order to ensure that when committing an artificially
> duplicated state (like during system resume), that we reuse the PBN of
> that state to perform VCPI allocations and don't recalculate a different
> value from the drm connector's reported bpc.
>
> Also, move the VCPI slot allocations while we're at it as well. With
> this, removing a topology in suspend while using nouveau no longer
> causes the new atomic VCPI helpers to complain.
>
> Signed-off-by: Lyude Paul <lyude at redhat.com>
> Fixes: eceae1472467 ("drm/dp_mst: Start tracking per-port VCPI allocations")
> Cc: Daniel Vetter <daniel at ffwll.ch>
Reviewed-by: Ben Skeggs <bskeggs at redhat.com>
> ---
> drivers/gpu/drm/nouveau/dispnv50/atom.h | 6 ++++++
> drivers/gpu/drm/nouveau/dispnv50/disp.c | 28 +++++++++++++++----------
> drivers/gpu/drm/nouveau/dispnv50/head.c | 1 +
> 3 files changed, 24 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h
> index a194990d2b0d..b5fae5ab3fa8 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/atom.h
> +++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h
> @@ -116,6 +116,12 @@ struct nv50_head_atom {
> u8 depth:4;
> } or;
>
> + /* Currently only used for MST */
> + struct {
> + int pbn;
> + u8 tu:6;
> + } dp;
> +
> union nv50_head_atom_mask {
> struct {
> bool olut:1;
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> index 60d858c2f2ce..e8bb35f6d015 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> @@ -659,8 +659,6 @@ struct nv50_mstc {
>
> struct drm_display_mode *native;
> struct edid *edid;
> -
> - int pbn;
> };
>
> struct nv50_msto {
> @@ -765,17 +763,26 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
> struct drm_connector *connector = conn_state->connector;
> struct nv50_mstc *mstc = nv50_mstc(connector);
> struct nv50_mstm *mstm = mstc->mstm;
> - int bpp = connector->display_info.bpc * 3;
> + struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
> int slots;
>
> - mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
> - bpp);
> + /* When restoring duplicated states, we need to make sure that the
> + * bw remains the same and avoid recalculating it, as the connector's
> + * bpc may have changed after the state was duplicated
> + */
> + if (!state->duplicated)
> + asyh->dp.pbn =
> + drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
> + connector->display_info.bpc * 3);
>
> if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
> - mstc->port, mstc->pbn);
> + mstc->port,
> + asyh->dp.pbn);
> if (slots < 0)
> return slots;
> +
> + asyh->dp.tu = slots;
> }
>
> return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
> @@ -786,13 +793,13 @@ static void
> nv50_msto_enable(struct drm_encoder *encoder)
> {
> struct nv50_head *head = nv50_head(encoder->crtc);
> + struct nv50_head_atom *armh = nv50_head_atom(head->base.base.state);
> struct nv50_msto *msto = nv50_msto(encoder);
> struct nv50_mstc *mstc = NULL;
> struct nv50_mstm *mstm = NULL;
> struct drm_connector *connector;
> struct drm_connector_list_iter conn_iter;
> u8 proto, depth;
> - int slots;
> bool r;
>
> drm_connector_list_iter_begin(encoder->dev, &conn_iter);
> @@ -808,8 +815,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
> if (WARN_ON(!mstc))
> return;
>
> - slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn);
> - r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, slots);
> + r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, armh->dp.pbn,
> + armh->dp.tu);
> WARN_ON(!r);
>
> if (!mstm->links++)
> @@ -827,8 +834,7 @@ nv50_msto_enable(struct drm_encoder *encoder)
> default: depth = 0x6; break;
> }
>
> - mstm->outp->update(mstm->outp, head->base.index,
> - nv50_head_atom(head->base.base.state), proto, depth);
> + mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
>
> msto->head = head;
> msto->mstc = mstc;
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
> index ac97ebce5b35..2e7a0c347ddb 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/head.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
> @@ -413,6 +413,7 @@ nv50_head_atomic_duplicate_state(struct drm_crtc *crtc)
> asyh->ovly = armh->ovly;
> asyh->dither = armh->dither;
> asyh->procamp = armh->procamp;
> + asyh->dp = armh->dp;
> asyh->clr.mask = 0;
> asyh->set.mask = 0;
> return &asyh->state;
> --
> 2.20.1
>
> _______________________________________________
> Nouveau mailing list
> Nouveau at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/nouveau
More information about the dri-devel
mailing list