Skip to content

Commit 88ec89a

Browse files
committed
drm/nouveau: Move PBN and VCPI allocation into nv50_head_atom
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@redhat.com> Fixes: eceae14 ("drm/dp_mst: Start tracking per-port VCPI allocations") Cc: Daniel Vetter <daniel@ffwll.ch> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190202002023.29665-5-lyude@redhat.com
1 parent 022deba commit 88ec89a

File tree

3 files changed

+24
-11
lines changed

3 files changed

+24
-11
lines changed

drivers/gpu/drm/nouveau/dispnv50/atom.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ struct nv50_head_atom {
116116
u8 depth:4;
117117
} or;
118118

119+
/* Currently only used for MST */
120+
struct {
121+
int pbn;
122+
u8 tu:6;
123+
} dp;
124+
119125
union nv50_head_atom_mask {
120126
struct {
121127
bool olut:1;

drivers/gpu/drm/nouveau/dispnv50/disp.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -659,8 +659,6 @@ struct nv50_mstc {
659659

660660
struct drm_display_mode *native;
661661
struct edid *edid;
662-
663-
int pbn;
664662
};
665663

666664
struct nv50_msto {
@@ -765,17 +763,26 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
765763
struct drm_connector *connector = conn_state->connector;
766764
struct nv50_mstc *mstc = nv50_mstc(connector);
767765
struct nv50_mstm *mstm = mstc->mstm;
768-
int bpp = connector->display_info.bpc * 3;
766+
struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
769767
int slots;
770768

771-
mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
772-
bpp);
769+
/* When restoring duplicated states, we need to make sure that the
770+
* bw remains the same and avoid recalculating it, as the connector's
771+
* bpc may have changed after the state was duplicated
772+
*/
773+
if (!state->duplicated)
774+
asyh->dp.pbn =
775+
drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
776+
connector->display_info.bpc * 3);
773777

774778
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
775779
slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
776-
mstc->port, mstc->pbn);
780+
mstc->port,
781+
asyh->dp.pbn);
777782
if (slots < 0)
778783
return slots;
784+
785+
asyh->dp.tu = slots;
779786
}
780787

781788
return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
@@ -786,13 +793,13 @@ static void
786793
nv50_msto_enable(struct drm_encoder *encoder)
787794
{
788795
struct nv50_head *head = nv50_head(encoder->crtc);
796+
struct nv50_head_atom *armh = nv50_head_atom(head->base.base.state);
789797
struct nv50_msto *msto = nv50_msto(encoder);
790798
struct nv50_mstc *mstc = NULL;
791799
struct nv50_mstm *mstm = NULL;
792800
struct drm_connector *connector;
793801
struct drm_connector_list_iter conn_iter;
794802
u8 proto, depth;
795-
int slots;
796803
bool r;
797804

798805
drm_connector_list_iter_begin(encoder->dev, &conn_iter);
@@ -808,8 +815,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
808815
if (WARN_ON(!mstc))
809816
return;
810817

811-
slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn);
812-
r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, slots);
818+
r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, armh->dp.pbn,
819+
armh->dp.tu);
813820
WARN_ON(!r);
814821

815822
if (!mstm->links++)
@@ -827,8 +834,7 @@ nv50_msto_enable(struct drm_encoder *encoder)
827834
default: depth = 0x6; break;
828835
}
829836

830-
mstm->outp->update(mstm->outp, head->base.index,
831-
nv50_head_atom(head->base.base.state), proto, depth);
837+
mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
832838

833839
msto->head = head;
834840
msto->mstc = mstc;

drivers/gpu/drm/nouveau/dispnv50/head.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ nv50_head_atomic_duplicate_state(struct drm_crtc *crtc)
413413
asyh->ovly = armh->ovly;
414414
asyh->dither = armh->dither;
415415
asyh->procamp = armh->procamp;
416+
asyh->dp = armh->dp;
416417
asyh->clr.mask = 0;
417418
asyh->set.mask = 0;
418419
return &asyh->state;

0 commit comments

Comments
 (0)