Handle pending scanout update in drmmode_crtc_scanout_free

We have to wait for a pending scanout flip or abort a pending scanout
update, otherwise the corresponding event handler will likely crash
after drmmode_crtc_scanout_free cleaned up the data structures.

Fixes crash after VT switch while dedicated scanout pixmaps are enabled
for any CRTC.

Acked-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Michel Dänzer
2018-09-20 17:35:40 +02:00
committed by Michel Dänzer
parent ac5b6f96e9
commit 0cd2c337d2
3 changed files with 18 additions and 11 deletions

View File

@@ -2080,7 +2080,7 @@ void AMDGPULeaveVT_KMS(ScrnInfoPtr pScrn)
pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap,
None, pAMDGPUEnt);
} else {
drmmode_crtc_scanout_free(drmmode_crtc);
drmmode_crtc_scanout_free(crtc);
}
}
}

View File

@@ -448,8 +448,17 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
}
void
drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
drmmode_crtc_scanout_free(xf86CrtcPtr crtc)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
if (drmmode_crtc->scanout_update_pending) {
amdgpu_drm_wait_pending_flip(crtc);
amdgpu_drm_abort_entry(drmmode_crtc->scanout_update_pending);
drmmode_crtc->scanout_update_pending = 0;
amdgpu_drm_queue_handle_deferred(crtc);
}
drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
&drmmode_crtc->scanout[0]);
drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
@@ -1410,9 +1419,7 @@ done:
if (drmmode_crtc->scanout[scanout_id].pixmap &&
fb != amdgpu_pixmap_get_fb(drmmode_crtc->
scanout[scanout_id].pixmap)) {
amdgpu_drm_abort_entry(drmmode_crtc->scanout_update_pending);
drmmode_crtc->scanout_update_pending = 0;
drmmode_crtc_scanout_free(drmmode_crtc);
drmmode_crtc_scanout_free(crtc);
} else if (!drmmode_crtc->tear_free) {
drmmode_crtc_scanout_destroy(drmmode,
&drmmode_crtc->scanout[1]);
@@ -1737,7 +1744,7 @@ static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
}
}
drmmode_crtc_scanout_free(drmmode_crtc);
drmmode_crtc_scanout_free(crtc);
drmmode_crtc->prime_scanout_pixmap = NULL;
if (!ppix)
@@ -1752,7 +1759,7 @@ static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
ppix->drawable.width,
ppix->drawable.height)) {
drmmode_crtc_scanout_free(drmmode_crtc);
drmmode_crtc_scanout_free(crtc);
return FALSE;
}
@@ -3345,6 +3352,9 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
if (!info->drmmode_inited)
return;
for (c = 0; c < config->num_crtc; c++)
drmmode_crtc_scanout_free(config->crtc[c]);
if (pAMDGPUEnt->fd_wakeup_registered == serverGeneration &&
!--pAMDGPUEnt->fd_wakeup_ref) {
#if HAVE_NOTIFY_FD
@@ -3355,9 +3365,6 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
drm_wakeup_handler, drmmode);
#endif
}
for (c = 0; c < config->num_crtc; c++)
drmmode_crtc_scanout_free(config->crtc[c]->driver_private);
}
static void drmmode_sprite_do_set_cursor(struct amdgpu_device_priv *device_priv,

View File

@@ -234,7 +234,7 @@ extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
extern void drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
struct drmmode_scanout *scanout);
void drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc);
void drmmode_crtc_scanout_free(xf86CrtcPtr crtc);
PixmapPtr drmmode_crtc_scanout_create(xf86CrtcPtr crtc,
struct drmmode_scanout *scanout,
int width, int height);