[Intel-gfx] [PATCH 4/6] intel: write only map support

Ben Widawsky ben at bwidawsk.net
Tue Sep 20 06:25:04 CEST 2011


Support the kernel write only interface. Also add an interface to ease user
flushing for non LLC coherent architectures.

Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
 include/drm/i915_drm.h   |    5 ++
 intel/intel_bufmgr.h     |    9 ++++
 intel/intel_bufmgr_gem.c |  105 ++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index adc2392..576d419 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -189,6 +189,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_OVERLAY_PUT_IMAGE	0x27
 #define DRM_I915_OVERLAY_ATTRS	0x28
 #define DRM_I915_GEM_EXECBUFFER2	0x29
+#define DRM_I915_GEM_FLUSH	0x2a
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -230,6 +231,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_MADVISE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
 #define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE	DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image)
 #define DRM_IOCTL_I915_OVERLAY_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
+#define DRM_IOCTL_I915_GEM_FLUSH	DRM_IOW  (DRM_COMMAND_BASE + DRM_I915_GEM_FLUSH , struct drm_i915_gem_flush)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -835,4 +837,7 @@ struct drm_intel_overlay_attrs {
 	__u32 gamma5;
 };
 
+struct drm_i915_gem_flush {
+	__u32 bo_handle;
+};
 #endif				/* _I915_DRM_H_ */
diff --git a/intel/intel_bufmgr.h b/intel/intel_bufmgr.h
index 889ef46..c6fd907 100644
--- a/intel/intel_bufmgr.h
+++ b/intel/intel_bufmgr.h
@@ -81,6 +81,9 @@ struct _drm_intel_bo {
 	 * MM-specific handle for accessing object
 	 */
 	int handle;
+
+	/** Buffer is only writable from CPU */
+	int write_only;
 };
 
 #define BO_ALLOC_FOR_RENDER (1<<0)
@@ -145,6 +148,12 @@ drm_intel_bo *drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr,
 						unsigned int handle);
 void drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr);
 void drm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr);
+int drm_intel_gem_bo_flush(drm_intel_bo *bo, uint32_t offset, size_t size);
+#define drm_intel_gem_bo_flush_obj(bo) drm_intel_gem_bo_flush(bo, 0, bo->size);
+int drm_intel_gem_bo_map_wo(drm_intel_bo *bo);
+int drm_intel_gem_bo_map_gtt_wo(drm_intel_bo *bo,
+				uint32_t prefault_offset,
+				int prefault_pages);
 int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo);
 int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo);
 void drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable);
diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
index 4f4de92..b9e8936 100644
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
@@ -998,7 +998,7 @@ static void drm_intel_gem_bo_unreference(drm_intel_bo *bo)
 	}
 }
 
-static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
+static int do_bo_map(drm_intel_bo *bo, int read_enable, int write_enable)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
@@ -1036,6 +1036,9 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
 	    bo_gem->mem_virtual);
 	bo->virtual = bo_gem->mem_virtual;
 
+	if (read_enable == 0 && bo->write_only)
+		goto map_done;
+
 	set_domain.handle = bo_gem->gem_handle;
 	set_domain.read_domains = I915_GEM_DOMAIN_CPU;
 	if (write_enable)
@@ -1050,13 +1053,73 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
 		    __FILE__, __LINE__, bo_gem->gem_handle,
 		    strerror(errno));
 	}
+	if (read_enable == 0)
+		bo->write_only = 1;
 
+map_done:
 	pthread_mutex_unlock(&bufmgr_gem->lock);
 
 	return 0;
 }
 
-int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
+static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
+{
+	return do_bo_map(bo, 1, write_enable);
+}
+
+static int
+get_cacheline_size(void)
+{
+	int ret = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
+	if (ret == -1)
+		ret = 64;
+
+	return ret;
+}
+
+int drm_intel_gem_bo_flush(drm_intel_bo *bo, uint32_t offset, size_t size)
+{
+	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+	const int cacheline_size = get_cacheline_size();
+	int num_cachelines;
+	struct drm_i915_gem_flush args;
+	int i;
+
+	if (bufmgr_gem->gen >= 6)
+		return 0;
+
+	if (bo_gem->mem_virtual == NULL)
+		return -1;
+
+	/* round offset down to cacheline size */
+	offset &= ~(cacheline_size - 1);
+
+	num_cachelines = (bo->size - offset) / size;
+	if (num_cachelines <= 0)
+		return 0;
+
+	if ((offset + size) > bo->size)
+		return -1;
+
+	for(i = 0; i < num_cachelines; i++) {
+		void *addr = ((uint8_t *)bo_gem->mem_virtual) + (i * cacheline_size);
+		asm volatile("clflush (%0)" :: "r" (addr));
+	}
+
+	args.bo_handle = 0;
+	return ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_FLUSH, &args);
+}
+
+/**
+ * Any buffers mapped write only must use the flush interface
+ */
+int drm_intel_gem_bo_map_wo(drm_intel_bo *bo)
+{
+	return do_bo_map(bo, 0, 1);
+}
+
+static int do_bo_map_gtt(drm_intel_bo *bo, int read, int write)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
@@ -1112,8 +1175,8 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
 
 	/* Now move it to the GTT domain so that the CPU caches are flushed */
 	set_domain.handle = bo_gem->gem_handle;
-	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
-	set_domain.write_domain = I915_GEM_DOMAIN_GTT;
+	set_domain.read_domains = read;
+	set_domain.write_domain = write;
 	ret = drmIoctl(bufmgr_gem->fd,
 		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
 		       &set_domain);
@@ -1128,6 +1191,40 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
 	return 0;
 }
 
+int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
+{
+	return do_bo_map_gtt(bo, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+}
+
+int drm_intel_gem_bo_map_gtt_wo(drm_intel_bo *bo,
+				uint32_t prefault_offset,
+				int prefault_pages)
+{
+	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+	volatile uint8_t *faultin_start;
+	int ret, i;
+
+	prefault_offset &= ~(4096 - 1);
+
+	if (prefault_offset + (prefault_pages * 4096) > bo->size)
+		return -EINVAL;
+
+	ret = do_bo_map_gtt(bo, 0, I915_GEM_DOMAIN_GTT);
+	if (ret)
+		return ret;
+
+	if (prefault_pages <= 0)
+		return 0;
+
+	faultin_start = ((uint8_t *)bo_gem->gtt_virtual) + prefault_offset;
+	for (i = 0; i < prefault_pages; i+=4096) {
+		volatile uint8_t *bar = (uint8_t *)(faultin_start + i);
+		*bar;
+	}
+
+	return ret;
+}
+
 int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
-- 
1.7.6.1




More information about the Intel-gfx mailing list