drm/i915: implement dma buf begin_cpu_access (v2)
authorDave Airlie <airlied@redhat.com>
Thu, 16 Aug 2012 00:15:34 +0000 (10:15 +1000)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 17 Aug 2012 08:10:06 +0000 (10:10 +0200)
In order for udl vmap to work properly, we need to push the object
into the CPU domain before we start copying the data to the USB device.

This along with the udl change avoids userspace explicit mapping to
be used.

v2: add a flag for userspace to query to know if Intel kernel driver can
deal with the vmap flushing properly. In theory udl would need a flag also,
but I intend to push the patches very close to each other and other drivers
should do the right thing from the start.

I've added a test to my intel-gpu-tools prime branch, however testing
this is a bit messy since the only way to get udl to vmap is to rendering
something. I've tested this with real code as well to make sure it works.

Signed-off-by: Dave Airlie <airlied@redhat.com>
[danvet: resolved conflict, which required reallocating the PARAM
number to 21.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
include/drm/i915_drm.h

index 2285ae31717a7b96a583668be8148e2330c48ad7..2cba7b4a04eddaa4a83d796249af533ba7acf9be 100644 (file)
@@ -1012,6 +1012,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_SEMAPHORES:
                value = i915_semaphore_is_enabled(dev);
                break;
+       case I915_PARAM_HAS_PRIME_VMAP_FLUSH:
+               value = 1;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                 param->param);
index aa308e1337db7c8bacbf73d00dc80badecb617a2..ceaad5af01a468ef4c3655391e936ad7798eae6f 100644 (file)
@@ -151,6 +151,22 @@ static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *
        return -EINVAL;
 }
 
+static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, size_t start, size_t length, enum dma_data_direction direction)
+{
+       struct drm_i915_gem_object *obj = dma_buf->priv;
+       struct drm_device *dev = obj->base.dev;
+       int ret;
+       bool write = (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE);
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ret;
+
+       ret = i915_gem_object_set_to_cpu_domain(obj, write);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
 static const struct dma_buf_ops i915_dmabuf_ops =  {
        .map_dma_buf = i915_gem_map_dma_buf,
        .unmap_dma_buf = i915_gem_unmap_dma_buf,
@@ -162,6 +178,7 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
        .mmap = i915_gem_dmabuf_mmap,
        .vmap = i915_gem_dmabuf_vmap,
        .vunmap = i915_gem_dmabuf_vunmap,
+       .begin_cpu_access = i915_gem_begin_cpu_access,
 };
 
 struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
index d8a79bf59ae74c17f6e6c796da3c110247fa63fc..05e24d31f32981bb1ee3615ae7052932b7ca182f 100644 (file)
@@ -312,6 +312,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_ALIASING_PPGTT   18
 #define I915_PARAM_HAS_WAIT_TIMEOUT     19
 #define I915_PARAM_HAS_SEMAPHORES       20
+#define I915_PARAM_HAS_PRIME_VMAP_FLUSH         21
 
 typedef struct drm_i915_getparam {
        int param;