minigbm: i915: use explicit cache flush to maintain coherency

The Intel last level cache (LLC) acts a coherency controller on
hardware that has it. Use I915_PARAM_HAS_LLC to determine if the
hardware has LLC.

We can maintain coherency by doing a clflush on non-LLC platforms, like the
Vulkan driver in Mesa does.

BUG=none
TEST=gbmtest on Cyan, Chrome boots, Android boots, mmap_test -g, 5-10 CTS
tests. No regressions.

CQ-DEPEND=CL:425716

Change-Id: I054e69c23016cd3336c2de1d07b49bb2c3709389
Reviewed-on: https://chromium-review.googlesource.com/454105
Commit-Ready: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
diff --git a/i915.c b/i915.c
index 97fa200..efdeda6 100644
--- a/i915.c
+++ b/i915.c
@@ -17,6 +17,9 @@
 #include "helpers.h"
 #include "util.h"
 
+#define I915_CACHELINE_SIZE 64
+#define I915_CACHELINE_MASK (I915_CACHELINE_SIZE - 1)
+
 static const uint32_t tileable_formats[] = { DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR8888,
 					     DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565,
 					     DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB1555,
@@ -27,10 +30,11 @@
 						DRM_FORMAT_YVU420_ANDROID };
 
 struct i915_device {
-	int gen;
+	uint32_t gen;
+	int32_t has_llc;
 };
 
-static int get_gen(int device_id)
+static uint32_t i915_get_gen(int device_id)
 {
 	const uint16_t gen3_ids[] = { 0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE,
 				      0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011 };
@@ -175,6 +179,18 @@
 	return 0;
 }
 
+static void i915_clflush(void *start, size_t size)
+{
+	void *p = (void *)(((uintptr_t)start) & ~I915_CACHELINE_MASK);
+	void *end = (void *)((uintptr_t)start + size);
+
+	__builtin_ia32_mfence();
+	while (p < end) {
+		__builtin_ia32_clflush(p);
+		p = (void *)((uintptr_t)p + I915_CACHELINE_SIZE);
+	}
+}
+
 static int i915_init(struct driver *drv)
 {
 	int ret;
@@ -191,12 +207,23 @@
 	get_param.value = &device_id;
 	ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
 	if (ret) {
-		fprintf(stderr, "drv: DRM_IOCTL_I915_GETPARAM failed\n");
+		fprintf(stderr, "drv: Failed to get I915_PARAM_CHIPSET_ID\n");
 		free(i915);
 		return -EINVAL;
 	}
 
-	i915->gen = get_gen(device_id);
+	i915->gen = i915_get_gen(device_id);
+
+	memset(&get_param, 0, sizeof(get_param));
+	get_param.param = I915_PARAM_HAS_LLC;
+	get_param.value = &i915->has_llc;
+	ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
+	if (ret) {
+		fprintf(stderr, "drv: Failed to get I915_PARAM_HAS_LLC\n");
+		free(i915);
+		return -EINVAL;
+	}
+
 	drv->priv = i915;
 
 	return i915_add_combinations(drv);
@@ -357,18 +384,9 @@
 
 static int i915_bo_unmap(struct bo *bo, struct map_info *data)
 {
-	if (bo->tiling == I915_TILING_NONE) {
-		int ret;
-		struct drm_i915_gem_sw_finish sw_finish;
-		memset(&sw_finish, 0, sizeof(sw_finish));
-
-		sw_finish.handle = bo->handles[0].u32;
-		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SW_FINISH, &sw_finish);
-		if (ret) {
-			fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_SW_FINISH failed\n");
-			return ret;
-		}
-	}
+	struct i915_device *i915 = bo->drv->priv;
+	if (!i915->has_llc && bo->tiling == I915_TILING_NONE)
+		i915_clflush(data->addr, data->length);
 
 	return munmap(data->addr, data->length);
 }