Merge drm/drm-next into drm-misc-next
[sfrench/cifs-2.6.git] / drivers / dma-buf / dma-buf.c
index 844967f98866a5749bf54367f98131c7df9d5370..556f62e8b1960d49354f6b0d323c4298bf78cbeb 100644 (file)
@@ -851,6 +851,9 @@ EXPORT_SYMBOL_GPL(dma_buf_unpin);
  * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
  * on error. May return -EINTR if it is interrupted by a signal.
  *
+ * On success, the DMA addresses and lengths in the returned scatterlist are
+ * PAGE_SIZE aligned.
+ *
  * A mapping must be unmapped by using dma_buf_unmap_attachment(). Note that
  * the underlying backing storage is pinned for as long as a mapping exists,
  * therefore users/importers should not hold onto a mapping for undue amounts of
@@ -904,6 +907,24 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
                attach->dir = direction;
        }
 
+#ifdef CONFIG_DMA_API_DEBUG
+       {
+               struct scatterlist *sg;
+               u64 addr;
+               int len;
+               int i;
+
+               for_each_sgtable_dma_sg(sg_table, sg, i) {
+                       addr = sg_dma_address(sg);
+                       len = sg_dma_len(sg);
+                       if (!PAGE_ALIGNED(addr) || !PAGE_ALIGNED(len)) {
+                               pr_debug("%s: addr %llx or len %x is not page aligned!\n",
+                                        __func__, addr, len);
+                       }
+               }
+       }
+#endif /* CONFIG_DMA_API_DEBUG */
+
        return sg_table;
 }
 EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
@@ -1188,68 +1209,72 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap);
  * dma_buf_vmap - Create virtual mapping for the buffer object into kernel
  * address space. Same restrictions as for vmap and friends apply.
  * @dmabuf:    [in]    buffer to vmap
+ * @map:       [out]   returns the vmap pointer
  *
  * This call may fail due to lack of virtual mapping address space.
  * These calls are optional in drivers. The intended use for them
  * is for mapping objects linear in kernel space for high use objects.
  * Please attempt to use kmap/kunmap before thinking about these interfaces.
  *
- * Returns NULL on error.
+ * Returns 0 on success, or a negative errno code otherwise.
  */
-void *dma_buf_vmap(struct dma_buf *dmabuf)
+int dma_buf_vmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
 {
-       void *ptr;
+       struct dma_buf_map ptr;
+       int ret = 0;
+
+       dma_buf_map_clear(map);
 
        if (WARN_ON(!dmabuf))
-               return NULL;
+               return -EINVAL;
 
        if (!dmabuf->ops->vmap)
-               return NULL;
+               return -EINVAL;
 
        mutex_lock(&dmabuf->lock);
        if (dmabuf->vmapping_counter) {
                dmabuf->vmapping_counter++;
-               BUG_ON(!dmabuf->vmap_ptr);
-               ptr = dmabuf->vmap_ptr;
+               BUG_ON(dma_buf_map_is_null(&dmabuf->vmap_ptr));
+               *map = dmabuf->vmap_ptr;
                goto out_unlock;
        }
 
-       BUG_ON(dmabuf->vmap_ptr);
+       BUG_ON(dma_buf_map_is_set(&dmabuf->vmap_ptr));
 
-       ptr = dmabuf->ops->vmap(dmabuf);
-       if (WARN_ON_ONCE(IS_ERR(ptr)))
-               ptr = NULL;
-       if (!ptr)
+       ret = dmabuf->ops->vmap(dmabuf, &ptr);
+       if (WARN_ON_ONCE(ret))
                goto out_unlock;
 
        dmabuf->vmap_ptr = ptr;
        dmabuf->vmapping_counter = 1;
 
+       *map = dmabuf->vmap_ptr;
+
 out_unlock:
        mutex_unlock(&dmabuf->lock);
-       return ptr;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(dma_buf_vmap);
 
 /**
  * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.
  * @dmabuf:    [in]    buffer to vunmap
- * @vaddr:     [in]    vmap to vunmap
+ * @map:       [in]    vmap pointer to vunmap
  */
-void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
+void dma_buf_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
 {
        if (WARN_ON(!dmabuf))
                return;
 
-       BUG_ON(!dmabuf->vmap_ptr);
+       BUG_ON(dma_buf_map_is_null(&dmabuf->vmap_ptr));
        BUG_ON(dmabuf->vmapping_counter == 0);
-       BUG_ON(dmabuf->vmap_ptr != vaddr);
+       BUG_ON(!dma_buf_map_is_equal(&dmabuf->vmap_ptr, map));
 
        mutex_lock(&dmabuf->lock);
        if (--dmabuf->vmapping_counter == 0) {
                if (dmabuf->ops->vunmap)
-                       dmabuf->ops->vunmap(dmabuf, vaddr);
-               dmabuf->vmap_ptr = NULL;
+                       dmabuf->ops->vunmap(dmabuf, map);
+               dma_buf_map_clear(&dmabuf->vmap_ptr);
        }
        mutex_unlock(&dmabuf->lock);
 }