drm: move pinning/unpinning to buffer attach
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / gpu / drm / drm_prime.c
index 83cc31c..4eb519d 100644 (file)
@@ -62,28 +62,30 @@ struct drm_prime_member {
        struct dma_buf *dma_buf;
        uint32_t handle;
 };
+static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
 
-bool drm_prime_check_dmabuf_valid(struct dma_buf *dmabuf)
+static int drm_gem_map_attach(struct dma_buf *dma_buf,
+                             struct device *target_dev,
+                             struct dma_buf_attachment *attach)
 {
-       struct file *file = dmabuf->file;
-
-       /*
-        * There could be a race when drm_gem_prime_handle_to_fd() is requested
-        * during __fput() is executed with same dmabuf.
-        * Let's suppose that there are process A and B. A creates a gem obj
-        * and exports it to dmabuf, B opens gem name which comes from A.
-        * And A is closing dmabuf and B tries to import dmabuf at that time.
-        * In this case, the dmabuf is in obj->export_dma_buf cache, because
-        * gem obj is still valid, and B could get dmabuf from this cache,
-        * but this dmabuf is invalid already, so B has to get a new dmabuf
-        * directly.
-        */
-       if (!atomic_long_read(&file->f_count))
-               return false;
+       struct drm_gem_object *obj = dma_buf->priv;
+       struct drm_device *dev = obj->dev;
 
-       return true;
+       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);
 }
-EXPORT_SYMBOL(drm_prime_check_dmabuf_valid);
 
 static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
                enum dma_data_direction dir)
@@ -167,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,
@@ -206,11 +210,6 @@ 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)
 {
-       if (dev->driver->gem_prime_pin) {
-               int ret = dev->driver->gem_prime_pin(obj);
-               if (ret)
-                       return ERR_PTR(ret);
-       }
        return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size, flags);
 }
 EXPORT_SYMBOL(drm_gem_prime_export);
@@ -513,7 +512,7 @@ void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
 }
 EXPORT_SYMBOL(drm_prime_destroy_file_private);
 
-int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
+static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
 {
        struct drm_prime_member *member;
 
@@ -527,7 +526,6 @@ int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct
        list_add(&member->entry, &prime_fpriv->head);
        return 0;
 }
-EXPORT_SYMBOL(drm_prime_add_buf_handle);
 
 int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
 {