diff options
author | Lyude Paul <lyude@redhat.com> | 2022-08-17 15:38:42 -0400 |
---|---|---|
committer | Lyude Paul <lyude@redhat.com> | 2022-08-23 16:53:41 -0400 |
commit | a76eb4297f90301fa9e4c888fb06749ef1be1c86 (patch) | |
tree | 6b778b892ccc89201e02e963fb1b99a2297b5ded /drivers/gpu/drm/nouveau | |
parent | 21167510605470d53c94e7162ae886c8fb67d93d (diff) |
drm/display/dp_mst: Add helpers for serializing SST <-> MST transitions
There's another kind of situation where we could potentially race with
nonblocking modesets and MST, especially if we were to only use the locking
provided by atomic modesetting:
* Display 1 begins as enabled on DP-1 in SST mode
* Display 1 switches to MST mode, exposes one sink in MST mode
* Userspace does non-blocking modeset to disable the SST display
* Userspace does non-blocking modeset to enable the MST display with a
different CRTC, but the SST display hasn't been fully taken down yet
* Execution order between the last two commits isn't guaranteed since they
share no drm resources
We can fix this however, by ensuring that we always pull in the atomic
topology state whenever a connector capable of driving an MST display
performs its atomic check - and then tracking CRTC commits happening on the
SST connector in the MST topology state. So, let's add some simple helpers
for doing that and hook them up in various drivers.
v2:
* Use intel_dp_mst_source_support() to check for MST support in i915, fixes
CI failures
Signed-off-by: Lyude Paul <lyude@redhat.com>
Cc: Wayne Lin <Wayne.Lin@amd.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Fangzhi Zuo <Jerry.Zuo@amd.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Sean Paul <sean@poorly.run>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-14-lyude@redhat.com
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/disp.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 14 |
3 files changed, 17 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 24807aa9da5f..7e9a0b50bb42 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1813,7 +1813,7 @@ nv50_sor_func = { .destroy = nv50_sor_destroy, }; -static bool nv50_has_mst(struct nouveau_drm *drm) +bool nv50_has_mst(struct nouveau_drm *drm) { struct nvkm_bios *bios = nvxx_bios(&drm->client.device); u32 data; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h b/drivers/gpu/drm/nouveau/dispnv50/disp.h index 38dec11e7dda..9d66c9c726c3 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h @@ -106,6 +106,8 @@ void nv50_dmac_destroy(struct nv50_dmac *); */ struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder); +bool nv50_has_mst(struct nouveau_drm *drm); + u32 *evo_wait(struct nv50_dmac *, int nr); void evo_kick(u32 *, struct nv50_dmac *); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index b8ee2173ca8f..1991bbb1d05c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1106,11 +1106,25 @@ nouveau_connector_best_encoder(struct drm_connector *connector) return NULL; } +static int +nouveau_connector_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) +{ + struct nouveau_connector *nv_conn = nouveau_connector(connector); + struct drm_connector_state *conn_state = + drm_atomic_get_new_connector_state(state, connector); + + if (!nv_conn->dp_encoder || !nv50_has_mst(nouveau_drm(connector->dev))) + return 0; + + return drm_dp_mst_root_conn_atomic_check(conn_state, &nv_conn->dp_encoder->dp.mstm->mgr); +} + static const struct drm_connector_helper_funcs nouveau_connector_helper_funcs = { .get_modes = nouveau_connector_get_modes, .mode_valid = nouveau_connector_mode_valid, .best_encoder = nouveau_connector_best_encoder, + .atomic_check = nouveau_connector_atomic_check, }; static const struct drm_connector_funcs |