mirror of
https://github.com/X11Libre/xf86-video-ati.git
synced 2026-03-24 01:24:43 +00:00
Wait for pending flips to complete before turning off an output or CRTC
At least with older kernels, the flip may never complete otherwise, which can result in us hanging in drmmode_set_mode_major. Fixes: https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-ati/+bug/1577170 Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Michel Dänzer
parent
9a1afbf61f
commit
9090309e05
@@ -307,9 +307,15 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
|
||||
CARD64 ust;
|
||||
int ret;
|
||||
|
||||
drmmode_crtc->pending_dpms_mode = mode;
|
||||
|
||||
if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
|
||||
drmVBlank vbl;
|
||||
|
||||
/* Wait for any pending flip to finish */
|
||||
if (drmmode_crtc->flip_pending)
|
||||
return;
|
||||
|
||||
/*
|
||||
* On->Off transition: record the last vblank time,
|
||||
* sequence number and frame period.
|
||||
@@ -367,10 +373,14 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
|
||||
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
||||
|
||||
/* Disable unused CRTCs */
|
||||
if (!crtc->enabled || mode != DPMSModeOn)
|
||||
if (!crtc->enabled || mode != DPMSModeOn) {
|
||||
/* Wait for any pending flip to finish */
|
||||
if (drmmode_crtc->flip_pending)
|
||||
return;
|
||||
|
||||
drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
||||
0, 0, 0, NULL, 0, NULL);
|
||||
else if (drmmode_crtc->dpms_mode != DPMSModeOn)
|
||||
} else if (drmmode_crtc->dpms_mode != DPMSModeOn)
|
||||
crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
|
||||
crtc->x, crtc->y);
|
||||
}
|
||||
@@ -1232,6 +1242,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
|
||||
drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]);
|
||||
drmmode_crtc->drmmode = drmmode;
|
||||
drmmode_crtc->dpms_mode = DPMSModeOff;
|
||||
drmmode_crtc->pending_dpms_mode = DPMSModeOff;
|
||||
crtc->driver_private = drmmode_crtc;
|
||||
drmmode_crtc_hw_id(crtc);
|
||||
|
||||
@@ -1357,9 +1368,16 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
|
||||
if (!koutput)
|
||||
return;
|
||||
|
||||
if (mode != DPMSModeOn && crtc)
|
||||
if (mode != DPMSModeOn && crtc) {
|
||||
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
||||
|
||||
drmmode_do_crtc_dpms(crtc, mode);
|
||||
|
||||
/* Wait for any pending flip to finish */
|
||||
if (drmmode_crtc->flip_pending)
|
||||
return;
|
||||
}
|
||||
|
||||
drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
|
||||
drmmode_output->dpms_enum_id, mode);
|
||||
|
||||
@@ -2190,9 +2208,32 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
|
||||
};
|
||||
|
||||
static void
|
||||
drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
|
||||
drmmode_clear_pending_flip(xf86CrtcPtr crtc)
|
||||
{
|
||||
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
||||
|
||||
drmmode_crtc->flip_pending = FALSE;
|
||||
|
||||
if (drmmode_crtc->pending_dpms_mode != DPMSModeOn &&
|
||||
drmmode_crtc->dpms_mode != drmmode_crtc->pending_dpms_mode) {
|
||||
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
|
||||
int o;
|
||||
|
||||
for (o = 0; o < xf86_config->num_output; o++) {
|
||||
xf86OutputPtr output = xf86_config->output[o];
|
||||
|
||||
if (output->crtc != crtc)
|
||||
continue;
|
||||
|
||||
drmmode_output_dpms(output, drmmode_crtc->pending_dpms_mode);
|
||||
drmmode_crtc_dpms(crtc, drmmode_crtc->pending_dpms_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
|
||||
{
|
||||
drmmode_flipdata_ptr flipdata = event_data;
|
||||
|
||||
if (--flipdata->flip_count == 0) {
|
||||
@@ -2202,13 +2243,12 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
|
||||
free(flipdata);
|
||||
}
|
||||
|
||||
drmmode_crtc->flip_pending = FALSE;
|
||||
drmmode_clear_pending_flip(crtc);
|
||||
}
|
||||
|
||||
static void
|
||||
drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data)
|
||||
{
|
||||
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
||||
RADEONInfoPtr info = RADEONPTR(crtc->scrn);
|
||||
drmmode_flipdata_ptr flipdata = event_data;
|
||||
|
||||
@@ -2232,7 +2272,7 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
|
||||
free(flipdata);
|
||||
}
|
||||
|
||||
drmmode_crtc->flip_pending = FALSE;
|
||||
drmmode_clear_pending_flip(crtc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ typedef struct {
|
||||
unsigned scanout_id;
|
||||
Bool scanout_update_pending;
|
||||
int dpms_mode;
|
||||
/* For when a flip is pending when DPMS off requested */
|
||||
int pending_dpms_mode;
|
||||
CARD64 dpms_last_ust;
|
||||
uint32_t dpms_last_seq;
|
||||
int dpms_last_fps;
|
||||
|
||||
@@ -430,7 +430,7 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
|
||||
Bool force;
|
||||
|
||||
if (!xf86_crtc->enabled ||
|
||||
drmmode_crtc->dpms_mode != DPMSModeOn ||
|
||||
drmmode_crtc->pending_dpms_mode != DPMSModeOn ||
|
||||
!drmmode_crtc->scanout[scanout_id].pixmap)
|
||||
return FALSE;
|
||||
|
||||
@@ -564,7 +564,7 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
|
||||
if (!xf86_crtc->enabled ||
|
||||
drmmode_crtc->scanout_update_pending ||
|
||||
!drmmode_crtc->scanout[0].pixmap ||
|
||||
drmmode_crtc->dpms_mode != DPMSModeOn)
|
||||
drmmode_crtc->pending_dpms_mode != DPMSModeOn)
|
||||
return;
|
||||
|
||||
pDamage = drmmode_crtc->scanout[0].damage;
|
||||
|
||||
@@ -268,7 +268,7 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
|
||||
if (!drmmode_crtc || drmmode_crtc->rotate.bo != NULL)
|
||||
return FALSE;
|
||||
|
||||
if (drmmode_crtc->dpms_mode == DPMSModeOn)
|
||||
if (drmmode_crtc->pending_dpms_mode == DPMSModeOn)
|
||||
num_crtcs_on++;
|
||||
}
|
||||
|
||||
@@ -396,7 +396,7 @@ modeset:
|
||||
if (!crtc->enabled)
|
||||
continue;
|
||||
|
||||
if (drmmode_crtc->dpms_mode == DPMSModeOn)
|
||||
if (drmmode_crtc->pending_dpms_mode == DPMSModeOn)
|
||||
crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
|
||||
crtc->x, crtc->y);
|
||||
else
|
||||
|
||||
@@ -71,7 +71,7 @@ radeon_box_area(BoxPtr box)
|
||||
Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc)
|
||||
{
|
||||
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
||||
return drmmode_crtc->dpms_mode == DPMSModeOn;
|
||||
return drmmode_crtc->pending_dpms_mode == DPMSModeOn;
|
||||
}
|
||||
|
||||
xf86CrtcPtr
|
||||
|
||||
Reference in New Issue
Block a user