Browse Source

i915: add dma-buf vmap support for exporting vmapped buffer

This is used to export a vmapping to the udl driver so that
i915 and udl can share the udl scanout.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Dave Airlie 13 years ago
parent
commit
9a70cc2a78
2 changed files with 58 additions and 0 deletions
  1. 3 0
      drivers/gpu/drm/i915/i915_drv.h
  2. 55 0
      drivers/gpu/drm/i915/i915_gem_dmabuf.c

+ 3 - 0
drivers/gpu/drm/i915/i915_drv.h

@@ -942,6 +942,9 @@ struct drm_i915_gem_object {
 
 	/* prime dma-buf support */
 	struct sg_table *sg_table;
+	void *dma_buf_vmapping;
+	int vmapping_count;
+
 	/**
 	 * Used for performing relocations during execbuffer insertion.
 	 */

+ 55 - 0
drivers/gpu/drm/i915/i915_gem_dmabuf.c

@@ -74,6 +74,59 @@ static void i915_gem_dmabuf_release(struct dma_buf *dma_buf)
 	}
 }
 
+static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
+{
+	struct drm_i915_gem_object *obj = dma_buf->priv;
+	struct drm_device *dev = obj->base.dev;
+	int ret;
+
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	if (obj->dma_buf_vmapping) {
+		obj->vmapping_count++;
+		goto out_unlock;
+	}
+
+	if (!obj->pages) {
+		ret = i915_gem_object_get_pages_gtt(obj, __GFP_NORETRY | __GFP_NOWARN);
+		if (ret) {
+			mutex_unlock(&dev->struct_mutex);
+			return ERR_PTR(ret);
+		}
+	}
+
+	obj->dma_buf_vmapping = vmap(obj->pages, obj->base.size / PAGE_SIZE, 0, PAGE_KERNEL);
+	if (!obj->dma_buf_vmapping) {
+		DRM_ERROR("failed to vmap object\n");
+		goto out_unlock;
+	}
+
+	obj->vmapping_count = 1;
+out_unlock:
+	mutex_unlock(&dev->struct_mutex);
+	return obj->dma_buf_vmapping;
+}
+
+static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
+{
+	struct drm_i915_gem_object *obj = dma_buf->priv;
+	struct drm_device *dev = obj->base.dev;
+	int ret;
+
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		return;
+
+	--obj->vmapping_count;
+	if (obj->vmapping_count == 0) {
+		vunmap(obj->dma_buf_vmapping);
+		obj->dma_buf_vmapping = NULL;
+	}
+	mutex_unlock(&dev->struct_mutex);
+}
+
 static void *i915_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num)
 {
 	return NULL;
@@ -107,6 +160,8 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
 	.kunmap = i915_gem_dmabuf_kunmap,
 	.kunmap_atomic = i915_gem_dmabuf_kunmap_atomic,
 	.mmap = i915_gem_dmabuf_mmap,
+	.vmap = i915_gem_dmabuf_vmap,
+	.vunmap = i915_gem_dmabuf_vunmap,
 };
 
 struct dma_buf *i915_gem_prime_export(struct drm_device *dev,