3.9: dma-buf updates
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJRLdoIAAoJEAG+/NWsLn5b1bAQAOTPfhn3e7BuhzPrKADk0hfo GjMXy62wreou/Zl5FanouQOXoPKkIMX4M1wfUjljdLOTkAbWxnElOqvWaoG64L1S +PmZ9YvR8uPn8zA8vTUjCgmbjcqNymHRIKKKsOSfPnbe/s0X39zcZIYWSI0rZVnq 7s4FpWtyU6ltTPn63VvkDeaKWyYI4EW5erM1gnQ3aiBmW19UlgEQ3/quzk13lZnn hkIdkiA2eA9N81mC7uzt+nl5fQ+AzvcWIKEKw7GJBo5oweMwD9QTu569Dfuo/wBV pHQnbyifRnYLM4k1lpL5upg7Bt+D/dGX40XyW7MJysqlrWIvt8p3ahs1ZHcGzvO8 Pv43Dg/68Y3H1F9qxulNQmlmr4c7pJszdTARqRiBTEzUwEQ678Qgzw4jNPxVU5Cn YYUXDI0J0rnA7NQWbZI+xZShLO4q3gr09SaxRmIXjdvNxI6epFioo3RGm+UE3inJ EgDvGdkolBzcoQ9Mfp8Sf2ACcwAhigr+U+KesIB5Q9uSSZ4rP89N+OCtmP+Ul+Ct xI/eqrQX6zI2sJfCSRhXaomsbgiufWmUCqN8rhC5ZaOYiC56t6QRu4v6KrY7ryGv 8BQfP8FW8uDqGiv9pbK2YT+MB8dQuuGvZv5kU7O0fuPu8HoGIgzJ+KZzqjfGdhkL zfTZDHW9KSn2mz+otaYz =9Fzb -----END PGP SIGNATURE----- Merge tag 'tag-for-linus-3.9' of git://git.linaro.org/people/sumitsemwal/linux-dma-buf Pull dma-buf framework updates from Sumit Semwal: "Refcounting implemented for vmap in core dma-buf" * tag 'tag-for-linus-3.9' of git://git.linaro.org/people/sumitsemwal/linux-dma-buf: CHROMIUM: dma-buf: restore args on failure of dma_buf_mmap dma-buf: implement vmap refcounting in the interface logic
This commit is contained in:
commit
5e04f4b429
|
@ -302,7 +302,11 @@ Access to a dma_buf from the kernel context involves three steps:
|
|||
void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
|
||||
|
||||
The vmap call can fail if there is no vmap support in the exporter, or if it
|
||||
runs out of vmalloc space. Fallback to kmap should be implemented.
|
||||
runs out of vmalloc space. Fallback to kmap should be implemented. Note that
|
||||
the dma-buf layer keeps a reference count for all vmap access and calls down
|
||||
into the exporter's vmap function only when no vmapping exists, and only
|
||||
unmaps it once. Protection against concurrent vmap/vunmap calls is provided
|
||||
by taking the dma_buf->lock mutex.
|
||||
|
||||
3. Finish access
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ static int dma_buf_release(struct inode *inode, struct file *file)
|
|||
|
||||
dmabuf = file->private_data;
|
||||
|
||||
BUG_ON(dmabuf->vmapping_counter);
|
||||
|
||||
dmabuf->ops->release(dmabuf);
|
||||
kfree(dmabuf);
|
||||
return 0;
|
||||
|
@ -445,6 +447,9 @@ EXPORT_SYMBOL_GPL(dma_buf_kunmap);
|
|||
int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
|
||||
unsigned long pgoff)
|
||||
{
|
||||
struct file *oldfile;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(!dmabuf || !vma))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -458,14 +463,22 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
|
|||
return -EINVAL;
|
||||
|
||||
/* readjust the vma */
|
||||
if (vma->vm_file)
|
||||
fput(vma->vm_file);
|
||||
|
||||
vma->vm_file = get_file(dmabuf->file);
|
||||
|
||||
get_file(dmabuf->file);
|
||||
oldfile = vma->vm_file;
|
||||
vma->vm_file = dmabuf->file;
|
||||
vma->vm_pgoff = pgoff;
|
||||
|
||||
return dmabuf->ops->mmap(dmabuf, vma);
|
||||
ret = dmabuf->ops->mmap(dmabuf, vma);
|
||||
if (ret) {
|
||||
/* restore old parameters on failure */
|
||||
vma->vm_file = oldfile;
|
||||
fput(dmabuf->file);
|
||||
} else {
|
||||
if (oldfile)
|
||||
fput(oldfile);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_mmap);
|
||||
|
||||
|
@ -481,12 +494,34 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap);
|
|||
*/
|
||||
void *dma_buf_vmap(struct dma_buf *dmabuf)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (WARN_ON(!dmabuf))
|
||||
return NULL;
|
||||
|
||||
if (dmabuf->ops->vmap)
|
||||
return dmabuf->ops->vmap(dmabuf);
|
||||
return NULL;
|
||||
if (!dmabuf->ops->vmap)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&dmabuf->lock);
|
||||
if (dmabuf->vmapping_counter) {
|
||||
dmabuf->vmapping_counter++;
|
||||
BUG_ON(!dmabuf->vmap_ptr);
|
||||
ptr = dmabuf->vmap_ptr;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
BUG_ON(dmabuf->vmap_ptr);
|
||||
|
||||
ptr = dmabuf->ops->vmap(dmabuf);
|
||||
if (IS_ERR_OR_NULL(ptr))
|
||||
goto out_unlock;
|
||||
|
||||
dmabuf->vmap_ptr = ptr;
|
||||
dmabuf->vmapping_counter = 1;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&dmabuf->lock);
|
||||
return ptr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_vmap);
|
||||
|
||||
|
@ -500,7 +535,16 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
|
|||
if (WARN_ON(!dmabuf))
|
||||
return;
|
||||
|
||||
if (dmabuf->ops->vunmap)
|
||||
dmabuf->ops->vunmap(dmabuf, vaddr);
|
||||
BUG_ON(!dmabuf->vmap_ptr);
|
||||
BUG_ON(dmabuf->vmapping_counter == 0);
|
||||
BUG_ON(dmabuf->vmap_ptr != vaddr);
|
||||
|
||||
mutex_lock(&dmabuf->lock);
|
||||
if (--dmabuf->vmapping_counter == 0) {
|
||||
if (dmabuf->ops->vunmap)
|
||||
dmabuf->ops->vunmap(dmabuf, vaddr);
|
||||
dmabuf->vmap_ptr = NULL;
|
||||
}
|
||||
mutex_unlock(&dmabuf->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_vunmap);
|
||||
|
|
|
@ -119,8 +119,10 @@ struct dma_buf {
|
|||
struct file *file;
|
||||
struct list_head attachments;
|
||||
const struct dma_buf_ops *ops;
|
||||
/* mutex to serialize list manipulation and attach/detach */
|
||||
/* mutex to serialize list manipulation, attach/detach and vmap/unmap */
|
||||
struct mutex lock;
|
||||
unsigned vmapping_counter;
|
||||
void *vmap_ptr;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue