summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2018-10-24 18:14:02 +0200
committerMichel Dänzer <michel.daenzer@amd.com>2018-10-24 18:14:02 +0200
commit86fe8d27b9a3f043e5288ce50eaf1f5fffd24516 (patch)
treed29c4745bf8bd82cdd940b4ba134af88470597d7
parentf892d3791219d1041e0cbb1b866e15774004aa18 (diff)
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. (Ported from amdgpu commit 0cd2c337d2c02b8ec2bd994d6124b4aaaad10741)
-rw-r--r--src/drmmode_display.c25
-rw-r--r--src/drmmode_display.h2
-rw-r--r--src/radeon_kms.c2
3 files changed, 18 insertions, 11 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 8445ef2a..7493d636 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -508,8 +508,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) {
+ radeon_drm_wait_pending_flip(crtc);
+ radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending);
+ drmmode_crtc->scanout_update_pending = 0;
+ radeon_drm_queue_handle_deferred(crtc);
+ }
+
drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
&drmmode_crtc->scanout[0]);
drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
@@ -967,9 +976,7 @@ done:
if (drmmode_crtc->scanout[scanout_id].pixmap &&
fb != radeon_pixmap_get_fb(drmmode_crtc->
scanout[scanout_id].pixmap)) {
- radeon_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]);
@@ -1265,7 +1272,7 @@ 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)
@@ -1280,7 +1287,7 @@ 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;
}
@@ -2770,6 +2777,9 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
if (info->dri2.pKernelDRMVersion->version_minor < 4 || !info->drmmode_inited)
return;
+ for (c = 0; c < config->num_crtc; c++)
+ drmmode_crtc_scanout_free(config->crtc[c]);
+
if (pRADEONEnt->fd_wakeup_registered == serverGeneration &&
!--pRADEONEnt->fd_wakeup_ref) {
#if HAVE_NOTIFY_FD
@@ -2780,9 +2790,6 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
drm_wakeup_handler, pScrn);
#endif
}
-
- for (c = 0; c < config->num_crtc; c++)
- drmmode_crtc_scanout_free(config->crtc[c]->driver_private);
}
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index bc66eda6..bfc13010 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -215,7 +215,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);
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index ae69f335..50c7137c 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -2614,7 +2614,7 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn)
pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap,
None, pRADEONEnt);
} else {
- drmmode_crtc_scanout_free(drmmode_crtc);
+ drmmode_crtc_scanout_free(crtc);
}
}
}