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)
|
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
|
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
|
3. Finish access
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,8 @@ static int dma_buf_release(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
dmabuf = file->private_data;
|
dmabuf = file->private_data;
|
||||||
|
|
||||||
|
BUG_ON(dmabuf->vmapping_counter);
|
||||||
|
|
||||||
dmabuf->ops->release(dmabuf);
|
dmabuf->ops->release(dmabuf);
|
||||||
kfree(dmabuf);
|
kfree(dmabuf);
|
||||||
return 0;
|
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,
|
int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
|
||||||
unsigned long pgoff)
|
unsigned long pgoff)
|
||||||
{
|
{
|
||||||
|
struct file *oldfile;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (WARN_ON(!dmabuf || !vma))
|
if (WARN_ON(!dmabuf || !vma))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -458,14 +463,22 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* readjust the vma */
|
/* readjust the vma */
|
||||||
if (vma->vm_file)
|
get_file(dmabuf->file);
|
||||||
fput(vma->vm_file);
|
oldfile = vma->vm_file;
|
||||||
|
vma->vm_file = dmabuf->file;
|
||||||
vma->vm_file = get_file(dmabuf->file);
|
|
||||||
|
|
||||||
vma->vm_pgoff = pgoff;
|
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);
|
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 *dma_buf_vmap(struct dma_buf *dmabuf)
|
||||||
{
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
if (WARN_ON(!dmabuf))
|
if (WARN_ON(!dmabuf))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (dmabuf->ops->vmap)
|
if (!dmabuf->ops->vmap)
|
||||||
return dmabuf->ops->vmap(dmabuf);
|
return NULL;
|
||||||
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);
|
EXPORT_SYMBOL_GPL(dma_buf_vmap);
|
||||||
|
|
||||||
|
@ -500,7 +535,16 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
|
||||||
if (WARN_ON(!dmabuf))
|
if (WARN_ON(!dmabuf))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dmabuf->ops->vunmap)
|
BUG_ON(!dmabuf->vmap_ptr);
|
||||||
dmabuf->ops->vunmap(dmabuf, vaddr);
|
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);
|
EXPORT_SYMBOL_GPL(dma_buf_vunmap);
|
||||||
|
|
|
@ -119,8 +119,10 @@ struct dma_buf {
|
||||||
struct file *file;
|
struct file *file;
|
||||||
struct list_head attachments;
|
struct list_head attachments;
|
||||||
const struct dma_buf_ops *ops;
|
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;
|
struct mutex lock;
|
||||||
|
unsigned vmapping_counter;
|
||||||
|
void *vmap_ptr;
|
||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue