configure.ac | 2 debian/changelog | 6 src/compat-api.h | 10 src/intel_device.c | 21 src/intel_driver.h | 1 src/intel_module.c | 19 src/legacy/i810/i810_video.c | 44 + src/sna/blt.c | 1258 ++++++++++++++++++++----------------------- src/sna/fb/fbimage.c | 12 src/sna/gen2_render.c | 330 ++++++++++- src/sna/gen9_render.c | 31 - src/sna/kgem.c | 37 - src/sna/kgem.h | 13 src/sna/sna.h | 39 + src/sna/sna_accel.c | 183 ++++-- src/sna/sna_acpi.c | 11 src/sna/sna_blt.c | 5 src/sna/sna_composite.c | 3 src/sna/sna_display.c | 308 +++++++++- src/sna/sna_dri2.c | 57 - src/sna/sna_dri3.c | 4 src/sna/sna_driver.c | 71 ++ src/sna/sna_present.c | 64 +- src/sna/sna_render.c | 10 src/sna/sna_video_textured.c | 16 src/uxa/intel.h | 2 src/uxa/intel_display.c | 17 src/uxa/intel_driver.c | 27 test/Makefile.am | 1 test/dri2-race.c | 15 test/present-speed.c | 414 ++++++++++++-- 31 files changed, 2139 insertions(+), 892 deletions(-)
New commits: commit f90aee9362a6de168344e7f52567bd81f5572211 Author: Timo Aaltonen <tjaal...@debian.org> Date: Wed Nov 9 11:56:37 2016 +0200 update changelog diff --git a/debian/changelog b/debian/changelog index 1260292..3a8adae 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +xserver-xorg-video-intel (2:2.99.917+git20161105-1) UNRELEASED; urgency=medium + + * New upstream snapshot. + + -- Timo Aaltonen <tjaal...@debian.org> Wed, 09 Nov 2016 11:55:29 +0200 + xserver-xorg-video-intel (2:2.99.917+git20160706-1) unstable; urgency=medium * New upstream snapshot. commit 6c8fc4434330ee37a290b6cf466af3282d09a8b3 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Sat Nov 5 23:40:28 2016 +0000 sna: Mark up CPU writes for scanout flush When we flip to a bo, the kernel will flush it from the CPU write domain and so afterwards we need to do a new set-domain to mark up a subsequent CPU write (and flush before another flip). References: https://bugs.freedesktop.org/show_bug.cgi?id=95414 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/kgem.c b/src/sna/kgem.c index c57624c..f0d171a 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -6179,9 +6179,7 @@ void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo) /* Whatever actually happens, we can regard the GTT write domain * as being flushed. */ - bo->gtt_dirty = false; - bo->needs_flush = false; - bo->domain = DOMAIN_NONE; + __kgem_bo_clear_dirty(bo); } inline static bool nearly_idle(struct kgem *kgem) @@ -7107,6 +7105,7 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo) bo->needs_flush = false; kgem_bo_retire(kgem, bo); bo->domain = DOMAIN_CPU; + bo->gtt_dirty = true; } } @@ -7147,10 +7146,11 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write) DBG(("%s: sync: GPU hang detected\n", __FUNCTION__)); kgem_throttle(kgem); } + bo->needs_flush = false; if (write) { - bo->needs_flush = false; kgem_bo_retire(kgem, bo); bo->domain = DOMAIN_CPU; + bo->gtt_dirty = true; } else { if (bo->exec == NULL) kgem_bo_maybe_retire(kgem, bo); diff --git a/src/sna/kgem.h b/src/sna/kgem.h index ded8f78..08b4eb2 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -638,17 +638,24 @@ static inline void kgem_bo_mark_busy(struct kgem *kgem, struct kgem_bo *bo, int } } -inline static void __kgem_bo_clear_busy(struct kgem_bo *bo) +static inline void __kgem_bo_clear_dirty(struct kgem_bo *bo) { DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle)); - bo->rq = NULL; - list_del(&bo->request); bo->domain = DOMAIN_NONE; bo->needs_flush = false; bo->gtt_dirty = false; } +inline static void __kgem_bo_clear_busy(struct kgem_bo *bo) +{ + DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle)); + bo->rq = NULL; + list_del(&bo->request); + + __kgem_bo_clear_dirty(bo); +} + static inline bool kgem_bo_is_busy(struct kgem_bo *bo) { DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__, diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 66c3147..59ecfd3 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -3037,8 +3037,10 @@ retry: /* Attach per-crtc pixmap or direct */ } /* Prevent recursion when enabling outputs during execbuffer */ - if (bo->exec && RQ(bo->rq)->bo == NULL) + if (bo->exec && RQ(bo->rq)->bo == NULL) { _kgem_submit(&sna->kgem); + __kgem_bo_clear_dirty(bo); + } sna_crtc->bo = bo; ret = sna_crtc_apply(crtc); @@ -6716,6 +6718,7 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x, return false; crtc->offset = y << 16 | x; + __kgem_bo_clear_dirty(bo); return true; } @@ -6798,6 +6801,7 @@ sna_page_flip(struct sna *sna, return 0; kgem_bo_submit(&sna->kgem, bo); + __kgem_bo_clear_dirty(bo); sigio = sigio_block(); for (i = 0; i < sna->mode.num_real_crtc; i++) { @@ -8988,6 +8992,7 @@ void sna_mode_redisplay(struct sna *sna) sna_crtc_redisplay(crtc, &damage, bo); kgem_bo_submit(&sna->kgem, bo); + __kgem_bo_clear_dirty(bo); assert_crtc_fb(sna, sna_crtc); arg.crtc_id = __sna_crtc_id(sna_crtc); @@ -9092,6 +9097,7 @@ disable1: arg.reserved = 0; kgem_bo_submit(&sna->kgem, new); + __kgem_bo_clear_dirty(new); sigio = sigio_block(); for (i = 0; i < sna->mode.num_real_crtc; i++) { commit bf7316a4539afdf7a742d2b2ccbbaa5f27918255 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Thu Nov 3 10:38:19 2016 +0000 sna/dri2: Don't request a signal following a dead flip completion If we do flip to restore the bo after the current Window is destroyed, we should not request that we send an event back to the client. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 22a6f6c..697a729 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -2846,7 +2846,7 @@ sna_dri2_flip_continue(struct sna_dri2_event *info) info->flip_continue = 0; assert(!info->signal); - info->signal = info->type == FLIP_THROTTLE; + info->signal = info->type == FLIP_THROTTLE && info->draw; if (info->sna->mode.front_active == 0) return false; commit 40e3be34367141c952678f456f0e0d4632b6c266 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Thu Nov 3 10:18:32 2016 +0000 sna/dri2: Complete the final flip in a chain after the window is destroyed When the pending flip is queued, we update all the Windows to use the next bo as their rendering target. However, that bo is not yet the scanout until the future flip is performed. If the current fullscreen Window is destroyed, we still must allow that flip to proceed or else the old bo is left on the scanout. And yes, this is indeed a fix to one of the debug patches that intended to detect the error causing #93844. Irony. Fixes: 7817949314a2 ("sna/dri2: Avoiding marking a pending-signal on a dead Drawable") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93844 Reported-by: Diego Viola <diego.vi...@gmail.com> Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 72cb128..22a6f6c 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -2845,9 +2845,6 @@ sna_dri2_flip_continue(struct sna_dri2_event *info) info->type = info->flip_continue; info->flip_continue = 0; - if (info->draw == NULL) - return false; - assert(!info->signal); info->signal = info->type == FLIP_THROTTLE; @@ -2866,7 +2863,6 @@ sna_dri2_flip_continue(struct sna_dri2_event *info) info->sna->dri2.flip_pending == info); info->sna->dri2.flip_pending = info; info->queued = true; - assert(info->draw); return true; } commit 47da17fe745efeef61a6f5106f5b888fd7abfb06 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Thu Oct 27 18:13:31 2016 +0100 sna: Load DRI3 if try to load DRI2 and fail As a backup in case DRI2 is disabled due to the presence of vgaarb, make sure we have DRI3 loaded. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna.h b/src/sna/sna.h index 4f9fc89..072c34f 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -362,8 +362,9 @@ struct sna { } cursor; struct sna_dri2 { - bool available; - bool open; + bool available : 1; + bool enable : 1; + bool open : 1; #if HAVE_DRI2 void *flip_pending; @@ -372,8 +373,11 @@ struct sna { } dri2; struct sna_dri3 { - bool available; - bool open; + bool available :1; + bool override : 1; + bool enable : 1; + bool open :1; + #if HAVE_DRI3 SyncScreenCreateFenceFunc create_fence; struct list pixmaps; diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c index aa637c0..5170439 100644 --- a/src/sna/sna_driver.c +++ b/src/sna/sna_driver.c @@ -433,16 +433,24 @@ static void setup_dri(struct sna *sna) unsigned level; sna->dri2.available = false; + sna->dri2.enable = false; sna->dri3.available = false; + sna->dri3.enable = false; + sna->dri3.override = false; level = intel_option_cast_to_unsigned(sna->Options, OPTION_DRI, DEFAULT_DRI_LEVEL); #if HAVE_DRI3 + sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3"); + sna->dri3.override = + !sna->dri3.available || + xf86IsOptionSet(sna->Options, OPTION_DRI); if (level >= 3 && sna->kgem.gen >= 040) - sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3"); + sna->dri3.enable = sna->dri3.available; #endif #if HAVE_DRI2 + sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2"); if (level >= 2) - sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2"); + sna->dri2.enable = sna->dri2.available; #endif } @@ -1059,12 +1067,13 @@ static void sna_dri_init(struct sna *sna, ScreenPtr screen) { char str[128] = ""; - if (sna->dri2.available) + if (sna->dri2.enable) sna->dri2.open = sna_dri2_open(sna, screen); if (sna->dri2.open) strcat(str, "DRI2 "); - if (sna->dri3.available) + /* Load DRI3 in case DRI2 doesn't work, e.g. vgaarb */ + if (sna->dri3.enable || (!sna->dri2.open && !sna->dri3.override)) sna->dri3.open = sna_dri3_open(sna, screen); if (sna->dri3.open) strcat(str, "DRI3 "); commit 714052fb32a3c521efb295f2c400a673d515fb77 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Mon Oct 24 22:22:44 2016 +0100 sna: Keep the backlight iface name on the heap When finding the per-connector backlight interface, we have to take a copy of the interface name for later use, as in this case it is not constant. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 28a2ee8..66c3147 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -1008,7 +1008,7 @@ static const char * const sysfs_connector_types[] = { /* DRM_MODE_CONNECTOR_DPI */ "DPI" }; -static char *has_connector_backlight(xf86OutputPtr output, char *buf) +static char *has_connector_backlight(xf86OutputPtr output) { struct sna_output *sna_output = output->driver_private; struct sna *sna = to_sna(output->scrn); @@ -1016,7 +1016,7 @@ static char *has_connector_backlight(xf86OutputPtr output, char *buf) DIR *dir; struct dirent *de; int minor, len; - char *ret = NULL; + char *str = NULL; if (sna_output->connector_type >= ARRAY_SIZE(sysfs_connector_types)) return NULL; @@ -1052,14 +1052,13 @@ static char *has_connector_backlight(xf86OutputPtr output, char *buf) __FUNCTION__, de->d_name)); if (backlight_exists(de->d_name)) { - snprintf(buf, 128, "%s", de->d_name); - ret = buf; + str = strdup(de->d_name); /* leak! */ break; } } closedir(dir); - return ret; + return str; } static void @@ -1067,7 +1066,6 @@ sna_output_backlight_init(xf86OutputPtr output) { struct sna_output *sna_output = output->driver_private; struct pci_device *pci; - char buf[128]; MessageType from; char *best_iface; @@ -1082,7 +1080,7 @@ sna_output_backlight_init(xf86OutputPtr output) goto done; } - best_iface = has_connector_backlight(output, buf); + best_iface = has_connector_backlight(output); if (best_iface) goto done; commit 325570e731b5819e28ce6bae72242914bb2d7f8e Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Mon Oct 24 15:23:33 2016 +0100 sna: Check for the per-connector backlight sysfs interface Modern kernels include a link from the sysfs connector directory to the backlight interface on that connector. Try to find that link first as this should allow us to enable backlight interfaces on connectors other than the presumed solitary panel. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index db2bd14..28a2ee8 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -39,6 +39,7 @@ #include <errno.h> #include <poll.h> #include <ctype.h> +#include <dirent.h> #if HAVE_ALLOCA_H #include <alloca.h> @@ -253,6 +254,8 @@ struct sna_output { unsigned int is_panel : 1; unsigned int add_default_modes : 1; + int connector_type; + int connector_type_id; uint32_t edid_idx; uint32_t edid_blob_id; @@ -974,11 +977,97 @@ has_user_backlight_override(xf86OutputPtr output) return strdup(str); } +static int get_device_minor(int fd) +{ + struct stat st; + + if (fstat(fd, &st) || !S_ISCHR(st.st_mode)) + return -1; + + return st.st_rdev & 0x63; +} + +static const char * const sysfs_connector_types[] = { + /* DRM_MODE_CONNECTOR_Unknown */ "Unknown", + /* DRM_MODE_CONNECTOR_VGA */ "VGA", + /* DRM_MODE_CONNECTOR_DVII */ "DVI-I", + /* DRM_MODE_CONNECTOR_DVID */ "DVI-D", + /* DRM_MODE_CONNECTOR_DVIA */ "DVI-A", + /* DRM_MODE_CONNECTOR_Composite */ "Composite", + /* DRM_MODE_CONNECTOR_SVIDEO */ "SVIDEO", + /* DRM_MODE_CONNECTOR_LVDS */ "LVDS", + /* DRM_MODE_CONNECTOR_Component */ "Component", + /* DRM_MODE_CONNECTOR_9PinDIN */ "DIN", + /* DRM_MODE_CONNECTOR_DisplayPort */ "DP", + /* DRM_MODE_CONNECTOR_HDMIA */ "HDMI-A", + /* DRM_MODE_CONNECTOR_HDMIB */ "HDMI-B", + /* DRM_MODE_CONNECTOR_TV */ "TV", + /* DRM_MODE_CONNECTOR_eDP */ "eDP", + /* DRM_MODE_CONNECTOR_VIRTUAL */ "Virtual", + /* DRM_MODE_CONNECTOR_DSI */ "DSI", + /* DRM_MODE_CONNECTOR_DPI */ "DPI" +}; + +static char *has_connector_backlight(xf86OutputPtr output, char *buf) +{ + struct sna_output *sna_output = output->driver_private; + struct sna *sna = to_sna(output->scrn); + char path[1024]; + DIR *dir; + struct dirent *de; + int minor, len; + char *ret = NULL; + + if (sna_output->connector_type >= ARRAY_SIZE(sysfs_connector_types)) + return NULL; + + minor = get_device_minor(sna->kgem.fd); + if (minor < 0) + return NULL; + + len = snprintf(path, sizeof(path), + "/sys/class/drm/card%d-%s-%d", + minor, + sysfs_connector_types[sna_output->connector_type], + sna_output->connector_type_id); + DBG(("%s: lookup %s\n", __FUNCTION__, path)); + + dir = opendir(path); + while ((de = readdir(dir))) { + struct stat st; + + if (*de->d_name == '.') + continue; + + snprintf(path + len, sizeof(path) - len, + "/%s", de->d_name); + + if (stat(path, &st)) + continue; + + if (!S_ISDIR(st.st_mode)) + continue; + + DBG(("%s: testing %s as backlight\n", + __FUNCTION__, de->d_name)); + + if (backlight_exists(de->d_name)) { + snprintf(buf, 128, "%s", de->d_name); + ret = buf; + break; + } + } + + closedir(dir); + return ret; +} + static void sna_output_backlight_init(xf86OutputPtr output) { struct sna_output *sna_output = output->driver_private; struct pci_device *pci; + char buf[128]; MessageType from; char *best_iface; @@ -986,11 +1075,20 @@ sna_output_backlight_init(xf86OutputPtr output) return; #endif - from = X_CONFIG; - best_iface = has_user_backlight_override(output); + if (sna_output->is_panel) { + from = X_CONFIG; + best_iface = has_user_backlight_override(output); + if (best_iface) + goto done; + } + + best_iface = has_connector_backlight(output, buf); if (best_iface) goto done; + if (!sna_output->is_panel) + return; + /* XXX detect right backlight for multi-GPU/panels */ from = X_PROBED; pci = xf86GetPciInfoForEntity(to_sna(output->scrn)->pEnt->index); @@ -4487,7 +4585,8 @@ static const char * const output_names[] = { /* DRM_MODE_CONNECTOR_TV */ "TV", /* DRM_MODE_CONNECTOR_eDP */ "eDP", /* DRM_MODE_CONNECTOR_VIRTUAL */ "Virtual", - /* DRM_MODE_CONNECTOR_DSI */ "DSI" + /* DRM_MODE_CONNECTOR_DSI */ "DSI", + /* DRM_MODE_CONNECTOR_DPI */ "DPI" }; static bool @@ -4911,6 +5010,8 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial) if (!sna_output) return -1; + sna_output->connector_type = compat_conn.conn.connector_type; + sna_output->connector_type_id = compat_conn.conn.connector_type_id; sna_output->num_props = compat_conn.conn.count_props; sna_output->prop_ids = malloc(sizeof(uint32_t)*compat_conn.conn.count_props); sna_output->prop_values = malloc(sizeof(uint64_t)*compat_conn.conn.count_props); @@ -5040,8 +5141,7 @@ reset: sna_output->base = output; backlight_init(&sna_output->backlight); - if (sna_output->is_panel) - sna_output_backlight_init(output); + sna_output_backlight_init(output); output->possible_crtcs = possible_crtcs & count_to_mask(sna->mode.num_real_crtc); output->interlaceAllowed = TRUE; commit 388fd4a65411f4984768132eab380b9a67f14e3c Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Sun Oct 23 20:52:55 2016 +0100 sna: Check current fb id before flip as well as after More debug sanity checks that pageflips work. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/kgem.c b/src/sna/kgem.c index 20ca9b9..c57624c 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -5353,7 +5353,7 @@ bool kgem_bo_is_fenced(struct kgem *kgem, struct kgem_bo *bo) VG_CLEAR(tiling); tiling.handle = bo->handle; - tiling.tiling_mode = 0; + tiling.tiling_mode = bo->tiling; (void)do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_TILING, &tiling); return tiling.tiling_mode == bo->tiling; /* assume pitch is fine! */ } diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index caa238e..db2bd14 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -564,6 +564,15 @@ static void assert_scanout(struct kgem *kgem, struct kgem_bo *bo, #define assert_scanout(k, b, w, h) #endif +static void assert_crtc_fb(struct sna *sna, struct sna_crtc *crtc) +{ +#ifndef NDEBUG + struct drm_mode_crtc mode = { .crtc_id = __sna_crtc_id(crtc) }; + drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode); + assert(mode.fb_id == fb_id(crtc->bo)); +#endif +} + static unsigned get_fb(struct sna *sna, struct kgem_bo *bo, int width, int height) { @@ -6709,6 +6718,7 @@ sna_page_flip(struct sna *sna, assert(crtc->bo->refcnt >= crtc->bo->active_scanout); assert(crtc->flip_bo == NULL); + assert_crtc_fb(sna, crtc); if (data == NULL && crtc->bo == bo) goto next_crtc; @@ -8881,6 +8891,7 @@ void sna_mode_redisplay(struct sna *sna) sna_crtc_redisplay(crtc, &damage, bo); kgem_bo_submit(&sna->kgem, bo); + assert_crtc_fb(sna, sna_crtc); arg.crtc_id = __sna_crtc_id(sna_crtc); arg.fb_id = get_fb(sna, bo, crtc->mode.HDisplay, @@ -8998,6 +9009,7 @@ disable1: assert(config->crtc[i]->enabled); assert(crtc->flip_bo == NULL); + assert_crtc_fb(sna, crtc); arg.crtc_id = __sna_crtc_id(crtc); arg.user_data = (uintptr_t)crtc; @@ -9213,14 +9225,6 @@ again: assert(crtc->bo->active_scanout); assert(crtc->bo->refcnt >= crtc->bo->active_scanout); -#ifndef NDEBUG - { - struct drm_mode_crtc mode = { .crtc_id = __sna_crtc_id(crtc) }; - drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode); - assert(mode.fb_id == fb_id(crtc->flip_bo)); - } -#endif - crtc->bo->active_scanout--; kgem_bo_destroy(&sna->kgem, crtc->bo); @@ -9231,6 +9235,8 @@ again: crtc->bo = crtc->flip_bo; crtc->flip_bo = NULL; + + assert_crtc_fb(sna, crtc); } else { crtc->flip_bo->active_scanout--; kgem_bo_destroy(&sna->kgem, crtc->flip_bo); commit 90172d81ea762eeca4cfb3796fab83cff9f0acaa Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Sat Oct 22 21:06:11 2016 +0100 sna: Allow Option DPMS to switch on (but not off) We start off the system with the screens blanked, waiting the first dixSaveScreen unblank, where we then apply the accumulated modesets. This means we have to allow that even if Option DPMS off, and so we restrict the Option to only enable DPMS (then once enabled they will not turn off). References: https://bugs.freedesktop.org/show_bug.cgi?id=98375 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c index 3e9cf86..aa637c0 100644 --- a/src/sna/sna_driver.c +++ b/src/sna/sna_driver.c @@ -296,7 +296,7 @@ static void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags) DBG(("%s(mode=%d, flags=%d), vtSema=%d => off?=%d\n", __FUNCTION__, mode, flags, scrn->vtSema, mode!=DPMSModeOn)); - if (!scrn->vtSema || sna->flags & SNA_NO_DPMS) + if (!scrn->vtSema) return; /* Opencoded version of xf86DPMSSet(). @@ -308,7 +308,7 @@ static void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags) * back on. */ if (mode != DPMSModeOn) { - if (sna->mode.hidden == 0) { + if (sna->mode.hidden == 0 && !(sna->flags & SNA_NO_DPMS)) { DBG(("%s: hiding %d outputs\n", __FUNCTION__, config->num_output)); for (i = 0; i < config->num_output; i++) { commit b7d6f695ddab02b7afef0f1ca3ae132f4fdbfd43 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Fri Oct 21 23:11:42 2016 +0100 sna: Disable screen saver if Option "DPMS" is specified The defacto standard is that the screensaver only blanks the screen but keeps the outputs alive. We differ by actually disabling the CRTC when the screen saver kicks in (to save power), however this circumvents Option "DPMS". Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98375 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna.h b/src/sna/sna.h index 09f57cc..4f9fc89 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -264,6 +264,7 @@ struct sna { #define SNA_FLUSH_GTT 0x800 #define SNA_PERFORMANCE 0x1000 #define SNA_POWERSAVE 0x2000 +#define SNA_NO_DPMS 0x4000 #define SNA_HAS_FLIP 0x10000 #define SNA_HAS_ASYNC_FLIP 0x20000 #define SNA_LINEAR_FB 0x40000 diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c index c731e58..3e9cf86 100644 --- a/src/sna/sna_driver.c +++ b/src/sna/sna_driver.c @@ -296,7 +296,7 @@ static void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags) DBG(("%s(mode=%d, flags=%d), vtSema=%d => off?=%d\n", __FUNCTION__, mode, flags, scrn->vtSema, mode!=DPMSModeOn)); - if (!scrn->vtSema) + if (!scrn->vtSema || sna->flags & SNA_NO_DPMS) return; /* Opencoded version of xf86DPMSSet(). @@ -1209,6 +1209,8 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL) CMAP_PALETTED_TRUECOLOR)) return FALSE; + if (!xf86CheckBoolOption(scrn->options, "dpms", TRUE)) + sna->flags |= SNA_NO_DPMS; xf86DPMSInit(screen, sna_dpms_set, 0); sna_uevent_init(sna); commit f18c7620cfba8412b0d141748fbb195670984ad2 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Sun Oct 16 13:31:42 2016 +0100 sna: Only apply the CRTC fixup when attempting to turn DPMS off If we were attempting to switch DPMS leave the state as is if the kernel reports an error. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 9d60d9a..caa238e 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -4126,7 +4126,7 @@ __sna_output_dpms(xf86OutputPtr output, int dpms, int fixup) dpms)) { DBG(("%s(%s:%d): failed to set DPMS to %d (fixup? %d)\n", __FUNCTION__, output->name, sna_output->id, dpms, fixup)); - if (fixup) { + if (fixup && dpms != DPMSModeOn) { sna_crtc_disable(output->crtc, false); return; } commit b9cebe59f9ddc1b38e47514e04a37b6de4efe2df Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Fri Oct 21 09:52:18 2016 +0100 sna: Ignore the current CRTC mode following a hotplug event If we detect a change in the output status, ignore the residual mode on the CRTC. We use this CRTC mode during inheritance to provide continuity and to make xrandr look neat we ensure that the mode is included in the output list. However, following a hotplug event the current mode may now be invalid and needs to be pruned. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 5e8c50a..9d60d9a 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -272,6 +272,7 @@ struct sna_output { uint32_t last_detect; uint32_t status; + unsigned int hotplug_count; bool update_properties; bool reprobe; @@ -3971,7 +3972,7 @@ sna_output_get_modes(xf86OutputPtr output) sna_output_attach_tile(output); current = NULL; - if (output->crtc) { + if (output->crtc && !sna_output->hotplug_count) { struct drm_mode_crtc mode; VG_CLEAR(mode); @@ -5302,6 +5303,7 @@ void sna_mode_discover(struct sna *sna, bool tell) } else { DBG(("%s: output %s (id=%d), changed state, reprobing\n", __FUNCTION__, output->name, sna_output->id)); + sna_output->hotplug_count++; sna_output->last_detect = 0; changed |= 4; } commit 6a2e5bca4214a3785f20fa8ba3dce5325ef75a27 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Fri Oct 21 09:46:23 2016 +0100 sna: Force a reprobe for the specified hotplug connector If the kernel can provide us with the exact connector that needs reprobing following a hotplug event, use it. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna.h b/src/sna/sna.h index fb5c007..09f57cc 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -470,6 +470,7 @@ extern void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc); extern bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv, const RegionRec *region); extern void sna_mode_set_primary(struct sna *sna); +extern bool sna_mode_find_hotplug_connector(struct sna *sna, unsigned id); extern void sna_mode_close(struct sna *sna); extern void sna_mode_fini(struct sna *sna); diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index ea7e287..5e8c50a 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -273,6 +273,7 @@ struct sna_output { uint32_t last_detect; uint32_t status; bool update_properties; + bool reprobe; int num_modes; struct drm_mode_modeinfo *modes; @@ -3548,6 +3549,7 @@ sna_output_detect(xf86OutputPtr output) DBG(("%s(%s): found %d modes, connection status=%d\n", __FUNCTION__, output->name, sna_output->num_modes, compat_conn.conn.connection)); + sna_output->reprobe = false; sna_output->last_detect = now; switch (compat_conn.conn.connection) { case DRM_MODE_CONNECTED: @@ -5147,6 +5149,22 @@ static bool disable_unused_crtc(struct sna *sna) return update; } +bool sna_mode_find_hotplug_connector(struct sna *sna, unsigned id) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn); + int i; + + for (i = 0; i < sna->mode.num_real_output; i++) { + struct sna_output *output = to_sna_output(config->output[i]); + if (output->id == id) { + output->reprobe = true; + return true; + } + } + + return false; +} + static bool output_check_status(struct sna *sna, struct sna_output *output) { @@ -5156,6 +5174,9 @@ output_check_status(struct sna *sna, struct sna_output *output) xf86OutputStatus status; char *edid; + if (output->reprobe) + return false; + VG_CLEAR(compat_conn); compat_conn.conn.connection = -1; @@ -5237,7 +5258,7 @@ void sna_mode_discover(struct sna *sna, bool tell) res.count_connectors, sna->mode.num_real_output, res.count_encoders, res.count_crtcs)); if (res.count_connectors > 32) - return; + res.count_connectors = 32; assert(sna->mode.num_real_crtc == res.count_crtcs || is_zaphod(sna->scrn)); assert(sna->mode.max_crtc_width == res.max_width); diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c index 57562b2..c731e58 100644 --- a/src/sna/sna_driver.c +++ b/src/sna/sna_driver.c @@ -796,8 +796,13 @@ sna_handle_uevents(int fd, void *closure) const char *str; str = udev_device_get_property_value(dev, "HOTPLUG"); - if (str && atoi(str) == 1) - hotplug = true; + if (str && atoi(str) == 1) { + str = udev_device_get_property_value(dev, "CONNECTOR"); + if (str) + hotplug |= sna_mode_find_hotplug_connector(sna, atoi(str)); + else + hotplug = true; + } } udev_device_unref(dev); commit a43455d4a317a13fe422c92b86083ed8a4fbeab9 Author: Manasi Navare <manasi.d.nav...@intel.com> Date: Mon Oct 17 15:31:24 2016 -0700 sna: Reprobe if kernel updates the connector mode list Output_check_status() should return a false if it detects that the connector mode list has changed so that sna_mode_discover can reprobe. Fixes: eb01cc549d4d (sna: Refresh mode list if the kernel updates) Signed-off-by: Manasi Navare <manasi.d.nav...@intel.com> Cc: Chris Wilson <ch...@chris-wilson.co.uk> Cc: Ville Syrjala <ville.syrj...@linux.intel.com> diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 15be27c..ea7e287 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -5191,7 +5191,7 @@ output_check_status(struct sna *sna, struct sna_output *output) return true; if (output->num_modes != compat_conn.conn.count_modes) - return true; + return false; if (output->edid_len == 0) return false; commit eb01cc549d4d5544833ff6da4d79bc63587fd5ca Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Wed Oct 12 17:35:37 2016 +0100 sna: Refresh mode list if the kernel updates If the kernel changes its list of modes, make sure we update. (This is a losing battle since X will add whatever modes it finds from the EDID despite what the kernel is telling it.) Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 39c07b3..15be27c 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -5190,6 +5190,9 @@ output_check_status(struct sna *sna, struct sna_output *output) if (status != XF86OutputStatusConnected) return true;