drm: move pinning/unpinning to buffer attach
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>
Tue, 9 Apr 2013 07:52:54 +0000 (09:52 +0200)
committerDave Airlie <airlied@redhat.com>
Mon, 10 Jun 2013 21:54:21 +0000 (07:54 +1000)
This allows importing bo's to own device to work without requiring that the buffer is pinned in GART.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/drm_prime.c

index 1a36b0c2273222937e9ea1ef4f62b668863445d9..58ac6770a8c6441652b5756683585833809a991c 100644 (file)
@@ -64,6 +64,29 @@ struct drm_prime_member {
 };
 static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
 
+static int drm_gem_map_attach(struct dma_buf *dma_buf,
+                             struct device *target_dev,
+                             struct dma_buf_attachment *attach)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+       struct drm_device *dev = obj->dev;
+
+       if (!dev->driver->gem_prime_pin)
+               return 0;
+
+       return dev->driver->gem_prime_pin(obj);
+}
+
+static void drm_gem_map_detach(struct dma_buf *dma_buf,
+                              struct dma_buf_attachment *attach)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+       struct drm_device *dev = obj->dev;
+
+       if (dev->driver->gem_prime_unpin)
+               dev->driver->gem_prime_unpin(obj);
+}
+
 static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
                enum dma_data_direction dir)
 {
@@ -92,13 +115,10 @@ static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
 static void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
 {
        struct drm_gem_object *obj = dma_buf->priv;
-       struct drm_device *dev = obj->dev;
 
        if (obj->export_dma_buf == dma_buf) {
                /* drop the reference on the export fd holds */
                obj->export_dma_buf = NULL;
-               if (dev->driver->gem_prime_unpin)
-                       dev->driver->gem_prime_unpin(obj);
                drm_gem_object_unreference_unlocked(obj);
        }
 }
@@ -149,6 +169,8 @@ static int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf,
 }
 
 static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
+       .attach = drm_gem_map_attach,
+       .detach = drm_gem_map_detach,
        .map_dma_buf = drm_gem_map_dma_buf,
        .unmap_dma_buf = drm_gem_unmap_dma_buf,
        .release = drm_gem_dmabuf_release,
@@ -188,19 +210,8 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
 struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
                                     struct drm_gem_object *obj, int flags)
 {
-       struct dma_buf *buf;
-
-       if (dev->driver->gem_prime_pin) {
-               int ret = dev->driver->gem_prime_pin(obj);
-               if (ret)
-                       return ERR_PTR(ret);
-       }
-       buf = dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size,
+       return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size,
                             0600);
-
-       if (IS_ERR(buf) && dev->driver->gem_prime_unpin)
-               dev->driver->gem_prime_unpin(obj);
-       return buf;
 }
 EXPORT_SYMBOL(drm_gem_prime_export);