From 21e29e95265331f8a33cd676c2d3124007643135 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 2 Jul 2013 15:25:46 +0100 Subject: [PATCH] sna: Simplify validation of active CRTCs Atter a modeset or KMS takeover, we do a quick readback of the kernel state in order to verify that it matches our expectations. If we find that a foreign framebuffer is attached, or no mode if set on the output, we then turn off that connection and release any resources associated with that pipe. This patch tries to reduce the number of superfluous requests to turn off a connection. Signed-off-by: Chris Wilson --- src/sna/sna.h | 1 - src/sna/sna_display.c | 62 +++++++++++++++++-------------------------- src/sna/sna_driver.c | 3 +-- 3 files changed, 25 insertions(+), 41 deletions(-) diff --git a/src/sna/sna.h b/src/sna/sna.h index 2f14fad5..17cae7e2 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -321,7 +321,6 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna); bool sna_mode_fake_init(struct sna *sna); void sna_mode_adjust_frame(struct sna *sna, int x, int y); extern void sna_mode_update(struct sna *sna); -extern void sna_mode_disable_unused(struct sna *sna); extern void sna_mode_wakeup(struct sna *sna); extern void sna_mode_redisplay(struct sna *sna); extern void sna_mode_close(struct sna *sna); diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 39d7db58..eaf54e98 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -726,24 +726,6 @@ mode_to_kmode(struct drm_mode_modeinfo *kmode, DisplayModePtr mode) kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; } -static bool sna_crtc_is_bound(struct sna *sna, xf86CrtcPtr crtc) -{ - struct sna_crtc *sna_crtc = to_sna_crtc(crtc); - struct drm_mode_crtc mode; - - if (!sna_crtc->bo) - return false; - - VG_CLEAR(mode); - mode.crtc_id = sna_crtc->id; - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode)) - return false; - - DBG(("%s: crtc=%d, mode valid?=%d, fb attached?=%d\n", __FUNCTION__, - mode.crtc_id, mode.mode_valid, fb_id(sna_crtc->bo) == mode.fb_id)); - return mode.mode_valid && fb_id(sna_crtc->bo) == mode.fb_id; -} - static void sna_crtc_force_outputs_on(xf86CrtcPtr crtc) { @@ -973,22 +955,6 @@ static void update_flush_interval(struct sna *sna) max_vrefresh, sna->vblank_interval)); } -void sna_mode_disable_unused(struct sna *sna) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn); - int i; - - DBG(("%s\n", __FUNCTION__)); - - /* Force consistency between kernel and ourselves */ - for (i = 0; i < xf86_config->num_crtc; i++) { - if (!xf86_config->crtc[i]->enabled) - sna_crtc_disable(xf86_config->crtc[i]); - } - - sna_mode_update(sna); -} - static struct kgem_bo *sna_create_bo_for_fbcon(struct sna *sna, const struct drm_mode_fb_cmd *fbcon) { @@ -1507,6 +1473,9 @@ sna_crtc_dpms(xf86CrtcPtr crtc, int mode) DBG(("%s(pipe %d, dpms mode -> %d):= active=%d\n", __FUNCTION__, priv->pipe, mode, mode == DPMSModeOn)); + if (priv->dpms_mode == mode) + return; + if (mode == DPMSModeOn) { if (priv->bo == NULL && !sna_crtc_set_mode_major(crtc, @@ -3157,7 +3126,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna) mode->kmode = drmModeGetResources(sna->kgem.fd); if (mode->kmode) { xf86CrtcConfigInit(scrn, &sna_mode_funcs); - XF86_CRTC_CONFIG_PTR(sna->scrn)->xf86_crtc_notify = sna_crtc_config_notify; + XF86_CRTC_CONFIG_PTR(scrn)->xf86_crtc_notify = sna_crtc_config_notify; for (i = 0; i < mode->kmode->count_crtcs; i++) if (!sna_crtc_init(scrn, mode, i)) @@ -3570,13 +3539,30 @@ void sna_mode_update(struct sna *sna) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn); int i; - /* Validate CRTC attachments */ + /* Validate CRTC attachments and force consistency upon the kernel */ for (i = 0; i < xf86_config->num_crtc; i++) { xf86CrtcPtr crtc = xf86_config->crtc[i]; - if (to_sna_crtc(crtc) == NULL) + struct sna_crtc *sna_crtc = to_sna_crtc(crtc); + struct drm_mode_crtc mode; + uint32_t expected; + + if (sna_crtc == NULL) continue; - if (!crtc->active || !sna_crtc_is_bound(sna, crtc)) + assert(sna_crtc->bo == NULL || crtc->active); + expected = sna_crtc->bo ? fb_id(sna_crtc->bo) : 0; + + VG_CLEAR(mode); + mode.crtc_id = sna_crtc->id; + if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode)) + continue; + + DBG(("%s: crtc=%d, valid?=%d, fb attached?=%d, expected=%d\n", + __FUNCTION__, + mode.crtc_id, mode.mode_valid, + mode.fb_id, fb_id, expected)); + + if (mode.fb_id != expected) sna_crtc_disable(crtc); } diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c index ca41e7e7..503d1e51 100644 --- a/src/sna/sna_driver.c +++ b/src/sna/sna_driver.c @@ -206,7 +206,7 @@ static Bool sna_become_master(struct sna *sna) sna_set_fallback_mode(scrn); } - sna_mode_disable_unused(sna); + sna_mode_update(sna); return TRUE; } @@ -998,7 +998,6 @@ static Bool sna_enter_vt(VT_FUNC_ARGS_DECL) return FALSE; if (sna->flags & SNA_REPROBE) { - sna_mode_update(sna); RRGetInfo(xf86ScrnToScreen(scrn), TRUE); sna->flags &= ~SNA_REPROBE; }