[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-intel: Changes to 'debian-unstable'



 debian/changelog           |    6 
 src/sna/gen3_render.c      |   91 +++--
 src/sna/kgem.c             |   72 +++-
 src/sna/kgem.h             |    3 
 src/sna/sna_display.c      |   89 ++++-
 src/sna/sna_dri2.c         |    1 
 src/sna/sna_driver.c       |    8 
 src/sna/sna_video_sprite.c |    3 
 src/uxa/intel_display.c    |    8 
 test/.gitignore            |    1 
 test/Makefile.am           |    3 
 test/dri2-race.c           |  724 ++++++++++++++++++++++++++++++---------------
 test/dri2-test.c           |   44 ++
 test/present-race.c        |  484 ++++++++++++++++++++++++++++++
 14 files changed, 1224 insertions(+), 313 deletions(-)

New commits:
commit 10c054b5a66b894cbb92f857feabb861456cd3a6
Author: Timo Aaltonen <tjaalton@debian.org>
Date:   Fri Feb 19 00:08:51 2016 +0200

    release to unstable

diff --git a/debian/changelog b/debian/changelog
index 9d5b6bd..7f3362b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+xserver-xorg-video-intel (2:2.99.917+git20160218-1) unstable; urgency=medium
+
+  * New upstream snapshot.
+
+ -- Timo Aaltonen <tjaalton@debian.org>  Fri, 19 Feb 2016 00:06:43 +0200
+
 xserver-xorg-video-intel (2:2.99.917+git20160127-1) unstable; urgency=medium
 
   * New upstream snapshot.

commit 05320318fb940247d8749da8330215d19f41d84e
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Thu Feb 18 13:54:11 2016 +0000

    sna: Prefer to avoid direct rendering with FBC
    
    If FBC is enabled, avoid the overhead of tracking rendering into the
    frontbuffer by rendering into a backbuffer and flipping. Again, we have
    no actual flag to indicate when FBC is enabled, so take a guess from the
    module parameter.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index f2fca7c..a1e1ffb 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -7105,6 +7105,22 @@ sna_mode_wants_tear_free(struct sna *sna)
 	FILE *file;
 	int i;
 
+	file = fopen("/sys/module/i915/parameters/enable_fbc", "r");
+	if (file) {
+		int fbc_enabled = 0;
+		int value;
+
+		if (fscanf(file, "%d", &value) == 1)
+			fbc_enabled = value > 0;
+		fclose(file);
+
+		DBG(("%s: module parameter 'enable_fbc' enabled? %d\n",
+		     __FUNCTION__, fbc_enabled));
+
+		if (fbc_enabled)
+			return true;
+	}
+
 	for (i = 0; i < sna->mode.num_real_output; i++) {
 		struct sna_output *output = to_sna_output(config->output[i]);
 		int id = find_property(sna, output, "Panel Self-Refresh");

commit b99e8b022c4aaf586ae49e0eb597f0c34bc0e165
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Thu Feb 18 13:53:07 2016 +0000

    sna: Use dirtyfb for fallback direct rendering
    
    The preferred solution when direct rendering is too costly is to render
    into the backbuffer and flip. However, if the user insists, we need to
    tell the kernel when to flush the scanout due to direct rendering.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index aceedd4..abb9e02 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -86,6 +86,7 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
 #define DBG_NO_WC_MMAP 0
 #define DBG_NO_BLT_Y 0
 #define DBG_NO_SCANOUT_Y 0
+#define DBG_NO_DIRTYFB 0
 #define DBG_NO_DETILING 0
 #define DBG_DUMP 0
 #define DBG_NO_MALLOC_CACHE 0
@@ -1499,6 +1500,47 @@ static bool test_can_scanout_y(struct kgem *kgem)
 	return ret;
 }
 
+static bool test_has_dirtyfb(struct kgem *kgem)
+{
+	struct drm_mode_fb_cmd create;
+	bool ret = false;
+
+	if (DBG_NO_DIRTYFB)
+		return false;
+
+	VG_CLEAR(create);
+	create.width = 32;
+	create.height = 32;
+	create.pitch = 4*32;
+	create.bpp = 32;
+	create.depth = 32;
+	create.handle = gem_create(kgem->fd, 1);
+	if (create.handle == 0)
+		return false;
+
+	if (drmIoctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &create) == 0) {
+		struct drm_mode_fb_dirty_cmd dirty;
+
+		memset(&dirty, 0, sizeof(dirty));
+		dirty.fb_id = create.fb_id;
+		ret = drmIoctl(kgem->fd,
+			       DRM_IOCTL_MODE_DIRTYFB,
+			       &dirty) == 0;
+
+		/* XXX There may be multiple levels of DIRTYFB, depending on
+		 * whether the kernel thinks tracking dirty regions is
+		 * beneficial vs flagging the whole fb as dirty.
+		 */
+
+		drmIoctl(kgem->fd,
+			 DRM_IOCTL_MODE_RMFB,
+			 &create.fb_id);
+	}
+	gem_close(kgem->fd, create.handle);
+
+	return ret;
+}
+
 static bool test_has_secure_batches(struct kgem *kgem)
 {
 	if (DBG_NO_SECURE_BATCHES)
@@ -1981,6 +2023,9 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
 	DBG(("%s: can scanout Y-tiled surfaces? %d\n", __FUNCTION__,
 	     kgem->can_scanout_y));
 
+	kgem->has_dirtyfb = test_has_dirtyfb(kgem);
+	DBG(("%s: has dirty fb? %d\n", __FUNCTION__, kgem->has_dirtyfb));
+
 	kgem->has_secure_batches = test_has_secure_batches(kgem);
 	DBG(("%s: can use privileged batchbuffers? %d\n", __FUNCTION__,
 	     kgem->has_secure_batches));
@@ -6090,7 +6135,7 @@ static void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo)
 
 void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo)
 {
-	if (!bo->needs_flush)
+	if (!bo->needs_flush && !bo->gtt_dirty)
 		return;
 
 	kgem_bo_submit(kgem, bo);
@@ -6103,6 +6148,13 @@ void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo)
 	if (bo->rq)
 		__kgem_flush(kgem, bo);
 
+	if (bo->scanout && kgem->needs_dirtyfb) {
+		struct drm_mode_fb_dirty_cmd cmd;
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.fb_id = bo->delta;
+		(void)drmIoctl(kgem->fd, DRM_IOCTL_MODE_DIRTYFB, &cmd);
+	}
+
 	/* Whatever actually happens, we can regard the GTT write domain
 	 * as being flushed.
 	 */
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 6cf877c..8bea755 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -189,6 +189,7 @@ struct kgem {
 	uint32_t has_no_reloc :1;
 	uint32_t has_handle_lut :1;
 	uint32_t has_wc_mmap :1;
+	uint32_t has_dirtyfb :1;
 
 	uint32_t can_fence :1;
 	uint32_t can_blt_cpu :1;
@@ -196,6 +197,8 @@ struct kgem {
 	uint32_t can_render_y :1;
 	uint32_t can_scanout_y :1;
 
+	uint32_t needs_dirtyfb :1;
+
 	uint16_t fence_max;
 	uint16_t half_cpu_cache_pages;
 	uint32_t aperture_total, aperture_high, aperture_low, aperture_mappable, aperture_fenceable;
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 14ec2f6..b245594 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -461,13 +461,13 @@ static bool enable_tear_free(struct sna *sna)
 	return ENABLE_TEAR_FREE;
 }
 
-static void setup_tear_free(struct sna *sna)
+static bool setup_tear_free(struct sna *sna)
 {
 	MessageType from;
 	Bool enable;
 
 	if (sna->flags & SNA_LINEAR_FB)
-		return;
+		return false;
 
 	if ((sna->flags & SNA_HAS_FLIP) == 0) {
 		from = X_PROBED;
@@ -486,6 +486,7 @@ static void setup_tear_free(struct sna *sna)
 done:
 	xf86DrvMsg(sna->scrn->scrnIndex, from, "TearFree %sabled\n",
 		   sna->flags & SNA_TEAR_FREE ? "en" : "dis");
+	return sna->flags & SNA_TEAR_FREE;
 }
 
 /**
@@ -653,7 +654,8 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
 	}
 	scrn->currentMode = scrn->modes;
 
-	setup_tear_free(sna);
+	if (!setup_tear_free(sna) && sna_mode_wants_tear_free(sna))
+		sna->kgem.needs_dirtyfb = sna->kgem.has_dirtyfb;
 
 	xf86SetGamma(scrn, zeros);
 	xf86SetDpi(scrn, 0, 0);

commit c4382c5e5b28a60261986b00bf0fcb8da4b78625
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Thu Feb 18 13:51:13 2016 +0000

    sna: Check enable_psr module parameters
    
    Despite protestations over the last 2 years, PSR was enabled by default
    upstream with no way for userspace to detect the change in behaviour.
    Have a look at the module parameter and take a guess.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 9215b23..f2fca7c 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -7101,18 +7101,42 @@ bool
 sna_mode_wants_tear_free(struct sna *sna)
 {
 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	bool found = false;
+	FILE *file;
 	int i;
 
 	for (i = 0; i < sna->mode.num_real_output; i++) {
 		struct sna_output *output = to_sna_output(config->output[i]);
 		int id = find_property(sna, output, "Panel Self-Refresh");
-		if (id !=-1 && output->prop_values[id] != -1) {
+		if (id == -1)
+			continue;
+
+		found = true;
+		if (output->prop_values[id] != -1) {
 			DBG(("%s: Panel Self-Refresh detected on %s\n",
 			     __FUNCTION__, config->output[i]->name));
 			return true;
 		}
 	}
 
+	if (!found) {
+		file = fopen("/sys/module/i915/parameters/enable_psr", "r");
+		if (file) {
+			int psr_enabled = 0;
+			int value;
+
+			if (fscanf(file, "%d", &value) == 1)
+				psr_enabled = value > 0;
+			fclose(file);
+
+			DBG(("%s: module parameter 'enable_psr' enabled? %d\n",
+			     __FUNCTION__, psr_enabled));
+
+			if (psr_enabled)
+				return true;
+		}
+	}
+
 	return false;
 }
 

commit aacc3442bb8c280a6ebc1fc1e34451613a72d7c4
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Thu Feb 18 10:15:11 2016 +0000

    sna: Restrict set-domain short-circuit to readonly
    
    If we write to the bo, we do want the kernel to mark it as dirty (for
    the purposes of swap invalidation and the like), so we can't apply the
    shortcircuit.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 6112952..aceedd4 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -7012,9 +7012,6 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
 		bo = bo->proxy;
 	assert(!bo->purged);
 
-	if (bo->rq == NULL && (kgem->has_llc || bo->snoop))
-		return;
-
 	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
 		struct drm_i915_gem_set_domain set_domain;
 
@@ -7055,7 +7052,7 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
 	assert(bo->refcnt);
 	assert(!bo->purged);
 
-	if (bo->rq == NULL && (kgem->has_llc || bo->snoop))
+	if (bo->rq == NULL && (kgem->has_llc || bo->snoop) && !write)
 		return;
 
 	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
@@ -7093,9 +7090,7 @@ void kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo)
 	assert(bo->refcnt);
 	assert(bo->proxy == NULL);
 	assert_tiling(kgem, bo);
-
-	if (bo->rq == NULL)
-		return;
+	assert(!bo->snoop);
 
 	kgem_bo_submit(kgem, bo);
 

commit e41040fb55e84fc72612ae503944a99814a5c9d3
Author: Martin Peres <martin.peres@linux.intel.com>
Date:   Fri Feb 12 17:33:24 2016 +0200

    sna_video_sprite: add asserts to catch invalid pipe#
    
    Caught by Klockwork. This will be enough to catch those issues during
    bringup.
    
    Signed-off-by: Martin Peres <martin.peres@linux.intel.com>
    Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index 9e85049..ae08ef7 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -86,6 +86,7 @@ static int sna_video_sprite_stop(ddStopVideo_ARGS)
 		int pipe;
 
 		pipe = sna_crtc_pipe(crtc);
+		assert(pipe < ARRAY_SIZE(video->bo));
 		if (video->bo[pipe] == NULL)
 			continue;
 
@@ -260,6 +261,7 @@ sna_video_sprite_show(struct sna *sna,
 		video->color_key_changed &= ~(1 << pipe);
 	}
 
+	assert(pipe < ARRAY_SIZE(video->bo));
 	if (video->bo[pipe] == frame->bo)
 		return true;
 
@@ -415,6 +417,7 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
 		RegionIntersect(&reg, &reg, &clip);
 		if (RegionNil(&reg)) {
 off:
+			assert(pipe < ARRAY_SIZE(video->bo));
 			if (video->bo[pipe]) {
 				struct local_mode_set_plane s;
 				memset(&s, 0, sizeof(s));

commit 7c81719b7fcba091fe2e9cf6fb7cb62a13d4f1dd
Author: Martin Peres <martin.peres@linux.intel.com>
Date:   Thu Feb 11 12:19:13 2016 +0200

    display: prevent a NULL pointer dereference in intel_set_scanout_pixmap
    
    Caught by Klockwork.
    
    v2:
     - be less verbose on failure
    
    Signed-off-by: Martin Peres <martin.peres@linux.intel.com>

diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
index 8bf0184..fa371c6 100644
--- a/src/uxa/intel_display.c
+++ b/src/uxa/intel_display.c
@@ -688,9 +688,11 @@ intel_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
 	}
 
 	bo = intel_get_pixmap_bo(ppix);
-	if (intel->front_buffer) {
-		ErrorF("have front buffer\n");
-	}
+	if (!bo)
+		return FALSE;
+
+	if (intel->front_buffer)
+		return FALSE;
 
 	drm_intel_bo_disable_reuse(bo);
 

commit 636b52913cac10e691834a699cff10fb94d395fa
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Sat Feb 13 08:54:04 2016 +0000

    sna: Also mark imported Prime objects as unclean
    
    Since they have an external source, we cannot be sure of their busyness
    or other GPU state and so we need to treat them as unclean.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index f441396..6112952 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -4792,8 +4792,9 @@ struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name)
 
 	bo->unique_id = kgem_get_unique_id(kgem);
 	bo->tiling = tiling.tiling_mode;
-	bo->reusable = false;
 	bo->prime = true;
+	bo->reusable = false;
+	kgem_bo_unclean(kgem, bo);
 
 	debug_alloc__bo(kgem, bo);
 	return bo;
@@ -6915,7 +6916,6 @@ uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo)
 	 * party, we track the lifetime accurately.
 	 */
 	bo->reusable = false;
-
 	kgem_bo_unclean(kgem, bo);
 
 	return flink.name;

commit b2cd809fe2b06325a4572865ec7ca5cfbfcfced2
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Sat Feb 13 08:47:29 2016 +0000

    test/dri2-race: Tweak runtimes
    
    When we specify a divider we are looking for slightly different races
    that are in theory not so timing dependent (since we are using vrefresh
    windows). However, since they each take some multiple of vblanks to
    complete, they are much slower. We should be able to reduce the number
    of iterations without losing detection capability.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/test/dri2-race.c b/test/dri2-race.c
index a79ddaf..d75293b 100644
--- a/test/dri2-race.c
+++ b/test/dri2-race.c
@@ -118,8 +118,8 @@ static void race_window(Display *dpy, int width, int height,
 	 */
 	attr.override_redirect = 1;
 	for (n = 0; n < N_DIVISORS; n++) {
-		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
+		printf("DRI2SwapBuffers(divisor=%d), loop=%d", divisors[n], loop);
 		do {
 			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
 					0, 0, width, height, 0,
@@ -146,8 +146,8 @@ static void race_window(Display *dpy, int width, int height,
 	}
 
 	for (n = 0; n < N_DIVISORS; n++) {
-		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
+		printf("xcb_dri2_swap_buffers(divisor=%d), loops=%d", divisors[n], loop);
 		do {
 			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
 					0, 0, width, height, 0,
@@ -174,8 +174,8 @@ static void race_window(Display *dpy, int width, int height,
 	}
 
 	for (n = 0; n < N_DIVISORS; n++) {
-		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
+		printf("DRI2WaitMsc(divisor=%d), loop=%d", divisors[n], loop);
 		do {
 			uint64_t ignore, msc;
 			xcb_connection_t *c = XGetXCBConnection(dpy);
@@ -196,7 +196,7 @@ static void race_window(Display *dpy, int width, int height,
 						xcb_dri2_wait_msc(c, win,
 							upper_32_bits(msc),
 							lower_32_bits(msc),
-							0, 1, 0, 0).sequence);
+							0, 0, 0, 0).sequence);
 				msc += divisors[n];
 			}
 			XFlush(dpy);
@@ -229,7 +229,7 @@ static void race_manager(Display *dpy, int width, int height,
 	attr.override_redirect = 1;
 	for (n = 0; n < N_DIVISORS; n++) {
 		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
 		do {
 			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
 					0, 0, width, height, 0,
@@ -259,7 +259,7 @@ static void race_manager(Display *dpy, int width, int height,
 
 	for (n = 0; n < N_DIVISORS; n++) {
 		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
 		do {
 			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
 					0, 0, width, height, 0,
@@ -289,7 +289,7 @@ static void race_manager(Display *dpy, int width, int height,
 
 	for (n = 0; n < N_DIVISORS; n++) {
 		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
 		do {
 			uint64_t ignore, msc;
 			xcb_connection_t *c = XGetXCBConnection(dpy);
@@ -310,7 +310,7 @@ static void race_manager(Display *dpy, int width, int height,
 						xcb_dri2_wait_msc(c, win,
 							upper_32_bits(msc),
 							lower_32_bits(msc),
-							0, 1, 0, 0).sequence);
+							0, 0, 0, 0).sequence);
 				msc += divisors[n];
 			}
 			XFlush(dpy);
@@ -345,7 +345,7 @@ static void race_close(int width, int height,
 	attr.override_redirect = 1;
 	for (n = 0; n < N_DIVISORS; n++) {
 		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
 		do {
 			Display *dpy = XOpenDisplay(NULL);
 			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
@@ -373,7 +373,7 @@ static void race_close(int width, int height,
 
 	for (n = 0; n < N_DIVISORS; n++) {
 		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
 		do {
 			Display *dpy = XOpenDisplay(NULL);
 			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
@@ -401,7 +401,7 @@ static void race_close(int width, int height,
 
 	for (n = 0; n < N_DIVISORS; n++) {
 		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
 		do {
 			uint64_t ignore, msc;
 			Display *dpy = XOpenDisplay(NULL);
@@ -423,7 +423,7 @@ static void race_close(int width, int height,
 						xcb_dri2_wait_msc(c, win,
 							upper_32_bits(msc),
 							lower_32_bits(msc),
-							0, 1, 0, 0).sequence);
+							0, 0, 0, 0).sequence);
 				msc += divisors[n];
 			}
 			XFlush(dpy);
@@ -450,7 +450,7 @@ static void race_client(int width, int height,
 	attr.override_redirect = 1;
 	for (n = 0; n < N_DIVISORS; n++) {
 		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
 		do {
 			Display *dpy;
 			Window win;
@@ -492,7 +492,7 @@ static void race_client(int width, int height,
 
 	for (n = 0; n < N_DIVISORS; n++) {
 		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
 		do {
 			Display *dpy;
 			Window win;
@@ -534,7 +534,7 @@ static void race_client(int width, int height,
 
 	for (n = 0; n < N_DIVISORS; n++) {
 		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
-		loop = 100;
+		loop = 256 >> ffs(divisors[n]);
 		do {
 			uint64_t ignore, msc;
 			Display *dpy;
@@ -564,7 +564,7 @@ static void race_client(int width, int height,
 						  xcb_dri2_wait_msc(c, win,
 								    upper_32_bits(msc),
 								    lower_32_bits(msc),
-								    0, 1, 0, 0).sequence);
+								    0, 0, 0, 0).sequence);
 				msc += divisors[n];
 			}
 

commit 8f04d6721fe0ac844fa66df3167a779bac236138
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Sat Feb 13 08:46:58 2016 +0000

    sna/dri2: Initialize priv->cache_size
    
    Silence a valgrind warning, though it should have no runtime impace.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 3656d5f..f441396 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2910,6 +2910,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 	DBG(("%s: handle=%d, size=%d\n", __FUNCTION__, bo->handle, bytes(bo)));
 
 	assert(list_is_empty(&bo->list));
+	assert(list_is_empty(&bo->vma));
 	assert(bo->refcnt == 0);
 	assert(bo->proxy == NULL);
 	assert(bo->active_scanout == 0);
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 045b12d..fcfbd9d 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1519,6 +1519,7 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
 			priv->msc_delta = 0;
 			priv->chain = NULL;
 			priv->scanout = -1;
+			priv->cache_size = 0;
 			list_init(&priv->cache);
 			dri2_window_attach((WindowPtr)draw, priv);
 		}

commit 9df8119e1e8216d11a116fdc28c1b499a521ef8b
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Sat Feb 13 08:44:15 2016 +0000

    sna: Reorder busyness checks after finding the proxy's parents
    
    Due to the way request tracking on proxies work, we need to inspect the
    parent and not the proxy itself.
    
    Reported-by: Matti Hämäläinen <ccr@tnsp.org>
    References: https://bugs.freedesktop.org/show_bug.cgi?id=94125
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 8e5ec51..3656d5f 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -7003,9 +7003,6 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
 	assert(!bo->scanout);
 	assert_tiling(kgem, bo);
 
-	if (bo->rq == NULL && (kgem->has_llc || bo->snoop))
-		return;
-
 	kgem_bo_submit(kgem, bo);
 
 	/* SHM pixmaps use proxies for subpage offsets */
@@ -7014,6 +7011,9 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
 		bo = bo->proxy;
 	assert(!bo->purged);
 
+	if (bo->rq == NULL && (kgem->has_llc || bo->snoop))
+		return;
+
 	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
 		struct drm_i915_gem_set_domain set_domain;
 
@@ -7043,9 +7043,6 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
 	assert(!bo->scanout || !write);
 	assert_tiling(kgem, bo);
 
-	if (bo->rq == NULL && (kgem->has_llc || bo->snoop))
-		return;
-
 	if (write || bo->needs_flush)
 		kgem_bo_submit(kgem, bo);
 
@@ -7057,6 +7054,9 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
 	assert(bo->refcnt);
 	assert(!bo->purged);
 
+	if (bo->rq == NULL && (kgem->has_llc || bo->snoop))
+		return;
+
 	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
 		struct drm_i915_gem_set_domain set_domain;
 

commit de7407d20703615c5bf0b1d9f522e93dcc13ba82
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Feb 10 11:00:28 2016 +0000

    test/dri2-race: Add a set of races against Client death
    
    Try terminating the client using XKillClient and seeing if we can find
    any races with Client shutdown.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/test/dri2-race.c b/test/dri2-race.c
index c898562..a79ddaf 100644
--- a/test/dri2-race.c
+++ b/test/dri2-race.c
@@ -16,6 +16,7 @@
 
 #include <xf86drm.h>
 #include <drm.h>
+#include <setjmp.h>
 
 #include "dri2.h"
 
@@ -24,6 +25,30 @@
 #define N_DIVISORS 3
 static const int divisors[N_DIVISORS] = { 0, 1, 16 };
 
+static jmp_buf error_handler[4];
+static int have_error_handler;
+
+#define error_get() \
+	setjmp(error_handler[have_error_handler++])
+
+#define error_put() \
+	have_error_handler--
+
+static int (*saved_io_error)(Display *dpy);
+
+static int io_error(Display *dpy)
+{
+	if (have_error_handler)
+		longjmp(error_handler[--have_error_handler], 0);
+
+	return saved_io_error(dpy);
+}
+
+static int x_error(Display *dpy, XErrorEvent *e)
+{
+	return Success;
+}
+
 static uint32_t upper_32_bits(uint64_t val)
 {
 	return val >> 32;
@@ -305,9 +330,9 @@ static void race_manager(Display *dpy, int width, int height,
 	XCloseDisplay(mgr);
 }
 
-static void race_client(int width, int height,
-			unsigned int *attachments, int nattachments,
-			const char *name)
+static void race_close(int width, int height,
+		       unsigned int *attachments, int nattachments,
+		       const char *name)
 {
 	XSetWindowAttributes attr;
 	int count, loop, n;
@@ -409,6 +434,155 @@ static void race_client(int width, int height,
 	}
 }
 
+static void race_client(int width, int height,
+			unsigned int *attachments, int nattachments,
+			const char *name)
+{
+	Display *mgr = XOpenDisplay(NULL);
+	XSetWindowAttributes attr;
+	int count, loop, n;
+
+	printf("%s(%s)\n", __func__, name);
+
+	/* Be nasty and install a fullscreen window on top so that we
+	 * can guarantee we do not get clipped by children.
+	 */
+	attr.override_redirect = 1;
+	for (n = 0; n < N_DIVISORS; n++) {
+		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
+		loop = 100;
+		do {
+			Display *dpy;
+			Window win;
+
+			if (error_get()) {
+				printf("+"); fflush(stdout);
+				continue;
+			}
+
+			dpy = XOpenDisplay(NULL);
+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
+					    0, 0, width, height, 0,
+					    DefaultDepth(dpy, DefaultScreen(dpy)),
+					    InputOutput,
+					    DefaultVisual(dpy, DefaultScreen(dpy)),
+					    CWOverrideRedirect, &attr);
+			XMapWindow(dpy, win);
+
+			DRI2CreateDrawable(dpy, win);
+			free(DRI2GetBuffers(dpy, win, &width, &height,
+					    attachments, nattachments, &count));
+			if (count != nattachments)
+				return;
+
+			for (count = 0; count < loop; count++)
+				DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
+
+			XFlush(dpy);
+			XKillClient(mgr, win);
+			XFlush(mgr);
+
+			XCloseDisplay(dpy);
+			printf("."); fflush(stdout);
+
+			error_put();
+		} while (--loop);
+		printf("*\n");
+	}
+
+	for (n = 0; n < N_DIVISORS; n++) {
+		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
+		loop = 100;
+		do {
+			Display *dpy;
+			Window win;
+
+			if (error_get()) {
+				printf("+"); fflush(stdout);
+				continue;
+			}
+
+			dpy = XOpenDisplay(NULL);
+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
+					    0, 0, width, height, 0,
+					    DefaultDepth(dpy, DefaultScreen(dpy)),
+					    InputOutput,
+					    DefaultVisual(dpy, DefaultScreen(dpy)),
+					    CWOverrideRedirect, &attr);
+			XMapWindow(dpy, win);
+
+			DRI2CreateDrawable(dpy, win);
+			free(DRI2GetBuffers(dpy, win, &width, &height,
+					    attachments, nattachments, &count));
+			if (count != nattachments)
+				return;
+
+			for (count = 0; count < loop; count++)
+				swap_buffers(dpy, win, divisors[n], attachments, nattachments);
+
+			XFlush(dpy);
+			XKillClient(mgr, win);
+			XFlush(mgr);
+
+			XCloseDisplay(dpy);
+			printf("."); fflush(stdout);
+
+			error_put();
+		} while (--loop);
+		printf("*\n");
+	}
+
+	for (n = 0; n < N_DIVISORS; n++) {
+		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
+		loop = 100;
+		do {
+			uint64_t ignore, msc;
+			Display *dpy;
+			xcb_connection_t *c;
+			Window win;
+
+			if (error_get()) {
+				printf("+"); fflush(stdout);
+				continue;
+			}
+
+			dpy = XOpenDisplay(NULL);
+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
+					    0, 0, width, height, 0,
+					    DefaultDepth(dpy, DefaultScreen(dpy)),
+					    InputOutput,
+					    DefaultVisual(dpy, DefaultScreen(dpy)),
+					    CWOverrideRedirect, &attr);
+			XMapWindow(dpy, win);
+
+			DRI2CreateDrawable(dpy, win);
+			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
+			c = XGetXCBConnection(dpy);
+			msc++;
+			for (count = 0; count < loop; count++) {
+				xcb_discard_reply(c,
+						  xcb_dri2_wait_msc(c, win,
+								    upper_32_bits(msc),
+								    lower_32_bits(msc),
+								    0, 1, 0, 0).sequence);
+				msc += divisors[n];
+			}
+
+			XFlush(dpy);
+			XKillClient(mgr, win);
+			XFlush(mgr);
+
+			XCloseDisplay(dpy);
+			printf("."); fflush(stdout);
+
+			error_put();
+		} while (--loop);
+		printf("*\n");
+	}
+
+	XCloseDisplay(mgr);
+}
+
 int main(void)
 {
 	Display *dpy;
@@ -418,7 +592,10 @@ int main(void)
 		DRI2BufferFrontLeft,
 	};
 
-	dpy = XOpenDisplay (NULL);
+	saved_io_error = XSetIOErrorHandler(io_error);
+	XSetErrorHandler(x_error);
+
+	dpy = XOpenDisplay(NULL);
 	if (dpy == NULL)
 		return 77;
 
@@ -434,6 +611,9 @@ int main(void)
 	race_manager(dpy, width, height, attachments, 1, "fullscreen");
 	race_manager(dpy, width, height, attachments, 2, "fullscreen (with front)");
 
+	race_close(width, height, attachments, 1, "fullscreen");
+	race_close(width, height, attachments, 2, "fullscreen (with front)");
+
 	race_client(width, height, attachments, 1, "fullscreen");
 	race_client(width, height, attachments, 2, "fullscreen (with front)");
 
@@ -445,6 +625,9 @@ int main(void)
 	race_manager(dpy, width, height, attachments, 1, "windowed");
 	race_manager(dpy, width, height, attachments, 2, "windowed (with front)");
 
+	race_close(width, height, attachments, 1, "windowed");
+	race_close(width, height, attachments, 2, "windowed (with front)");
+
 	race_client(width, height, attachments, 1, "windowed");
 	race_client(width, height, attachments, 2, "windowed (with front)");
 

commit 3aab3684124a77d3dafdfdf1f234b9b68faf7025
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Feb 10 10:50:04 2016 +0000

    test/dri2-race: Use loops for iterating over divisor tests
    
    Expand the test cases slightly to check high dividers everywhere.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/test/dri2-race.c b/test/dri2-race.c
index 39e2bbd..c898562 100644
--- a/test/dri2-race.c
+++ b/test/dri2-race.c
@@ -21,6 +21,9 @@
 
 #define COUNT 60
 
+#define N_DIVISORS 3
+static const int divisors[N_DIVISORS] = { 0, 1, 16 };
+


Reply to: