mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 04:34:11 +08:00
drm/nouveau/kms/nv50-: ensure window updates are submitted when flushing mst disables
It was possible for this to be skipped when shutting down MST streams, and leaving the core channel interlocked with a wndw channel update that never happens - leading to a hung display. Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Tested-By: Lyude Paul <lyude@redhat.com>
This commit is contained in:
parent
1264f8325e
commit
df0c97e2c7
@ -1585,8 +1585,9 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
|
||||
*****************************************************************************/
|
||||
|
||||
static void
|
||||
nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock)
|
||||
nv50_disp_atomic_commit_core(struct drm_atomic_state *state, u32 *interlock)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(state->dev);
|
||||
struct nv50_disp *disp = nv50_disp(drm->dev);
|
||||
struct nv50_core *core = disp->core;
|
||||
struct nv50_mstm *mstm;
|
||||
@ -1617,6 +1618,22 @@ nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_disp_atomic_commit_wndw(struct drm_atomic_state *state, u32 *interlock)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state;
|
||||
struct drm_plane *plane;
|
||||
int i;
|
||||
|
||||
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
||||
struct nv50_wndw *wndw = nv50_wndw(plane);
|
||||
if (interlock[wndw->interlock.type] & wndw->interlock.data) {
|
||||
if (wndw->func->update)
|
||||
wndw->func->update(wndw, interlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
{
|
||||
@ -1684,7 +1701,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
help->disable(encoder);
|
||||
interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
|
||||
if (outp->flush_disable) {
|
||||
nv50_disp_atomic_commit_core(drm, interlock);
|
||||
nv50_disp_atomic_commit_wndw(state, interlock);
|
||||
nv50_disp_atomic_commit_core(state, interlock);
|
||||
memset(interlock, 0x00, sizeof(interlock));
|
||||
}
|
||||
}
|
||||
@ -1693,15 +1711,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
/* Flush disable. */
|
||||
if (interlock[NV50_DISP_INTERLOCK_CORE]) {
|
||||
if (atom->flush_disable) {
|
||||
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
||||
struct nv50_wndw *wndw = nv50_wndw(plane);
|
||||
if (interlock[wndw->interlock.type] & wndw->interlock.data) {
|
||||
if (wndw->func->update)
|
||||
wndw->func->update(wndw, interlock);
|
||||
}
|
||||
}
|
||||
|
||||
nv50_disp_atomic_commit_core(drm, interlock);
|
||||
nv50_disp_atomic_commit_wndw(state, interlock);
|
||||
nv50_disp_atomic_commit_core(state, interlock);
|
||||
memset(interlock, 0x00, sizeof(interlock));
|
||||
}
|
||||
}
|
||||
@ -1762,18 +1773,14 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
}
|
||||
|
||||
/* Flush update. */
|
||||
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
||||
struct nv50_wndw *wndw = nv50_wndw(plane);
|
||||
if (interlock[wndw->interlock.type] & wndw->interlock.data) {
|
||||
if (wndw->func->update)
|
||||
wndw->func->update(wndw, interlock);
|
||||
}
|
||||
}
|
||||
nv50_disp_atomic_commit_wndw(state, interlock);
|
||||
|
||||
if (interlock[NV50_DISP_INTERLOCK_CORE]) {
|
||||
if (interlock[NV50_DISP_INTERLOCK_BASE] ||
|
||||
interlock[NV50_DISP_INTERLOCK_OVLY] ||
|
||||
interlock[NV50_DISP_INTERLOCK_WNDW] ||
|
||||
!atom->state.legacy_cursor_update)
|
||||
nv50_disp_atomic_commit_core(drm, interlock);
|
||||
nv50_disp_atomic_commit_core(state, interlock);
|
||||
else
|
||||
disp->core->func->update(disp->core, interlock, false);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user