mirror of https://github.com/torvalds/linux.git
iommufd: Accept a DMABUF through IOMMU_IOAS_MAP_FILE
Finally call iopt_alloc_dmabuf_pages() if the user passed in a DMABUF through IOMMU_IOAS_MAP_FILE. This makes the feature visible to userspace. Link: https://patch.msgid.link/r/8-v2-b2c110338e3f+5c2-iommufd_dmabuf_jgg@nvidia.com Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Tested-by: Shuai Xue <xueshuai@linux.alibaba.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
217725f0b2
commit
44ebaa1744
|
|
@ -8,6 +8,7 @@
|
|||
* The datastructure uses the iopt_pages to optimize the storage of the PFNs
|
||||
* between the domains and xarray.
|
||||
*/
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/file.h>
|
||||
|
|
@ -484,19 +485,41 @@ int iopt_map_file_pages(struct iommufd_ctx *ictx, struct io_pagetable *iopt,
|
|||
unsigned int flags)
|
||||
{
|
||||
struct iopt_pages *pages;
|
||||
struct file *file;
|
||||
struct dma_buf *dmabuf;
|
||||
unsigned long start_byte;
|
||||
unsigned long last;
|
||||
|
||||
file = fget(fd);
|
||||
if (!file)
|
||||
return -EBADF;
|
||||
if (!length)
|
||||
return -EINVAL;
|
||||
if (check_add_overflow(start, length - 1, &last))
|
||||
return -EOVERFLOW;
|
||||
|
||||
start_byte = start - ALIGN_DOWN(start, PAGE_SIZE);
|
||||
dmabuf = dma_buf_get(fd);
|
||||
if (!IS_ERR(dmabuf)) {
|
||||
pages = iopt_alloc_dmabuf_pages(ictx, dmabuf, start_byte, start,
|
||||
length,
|
||||
iommu_prot & IOMMU_WRITE);
|
||||
if (IS_ERR(pages)) {
|
||||
dma_buf_put(dmabuf);
|
||||
return PTR_ERR(pages);
|
||||
}
|
||||
} else {
|
||||
struct file *file;
|
||||
|
||||
file = fget(fd);
|
||||
if (!file)
|
||||
return -EBADF;
|
||||
|
||||
pages = iopt_alloc_file_pages(file, start_byte, start, length,
|
||||
iommu_prot & IOMMU_WRITE);
|
||||
fput(file);
|
||||
if (IS_ERR(pages))
|
||||
return PTR_ERR(pages);
|
||||
}
|
||||
|
||||
pages = iopt_alloc_file_pages(file, start, length,
|
||||
iommu_prot & IOMMU_WRITE);
|
||||
fput(file);
|
||||
if (IS_ERR(pages))
|
||||
return PTR_ERR(pages);
|
||||
return iopt_map_common(ictx, iopt, pages, iova, length,
|
||||
start - pages->start, iommu_prot, flags);
|
||||
start_byte, iommu_prot, flags);
|
||||
}
|
||||
|
||||
struct iova_bitmap_fn_arg {
|
||||
|
|
|
|||
|
|
@ -265,7 +265,9 @@ static inline bool iopt_dmabuf_revoked(struct iopt_pages *pages)
|
|||
|
||||
struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
|
||||
unsigned long length, bool writable);
|
||||
struct iopt_pages *iopt_alloc_file_pages(struct file *file, unsigned long start,
|
||||
struct iopt_pages *iopt_alloc_file_pages(struct file *file,
|
||||
unsigned long start_byte,
|
||||
unsigned long start,
|
||||
unsigned long length, bool writable);
|
||||
struct iopt_pages *iopt_alloc_dmabuf_pages(struct iommufd_ctx *ictx,
|
||||
struct dma_buf *dmabuf,
|
||||
|
|
|
|||
|
|
@ -1413,22 +1413,19 @@ struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
|
|||
return pages;
|
||||
}
|
||||
|
||||
struct iopt_pages *iopt_alloc_file_pages(struct file *file, unsigned long start,
|
||||
struct iopt_pages *iopt_alloc_file_pages(struct file *file,
|
||||
unsigned long start_byte,
|
||||
unsigned long start,
|
||||
unsigned long length, bool writable)
|
||||
|
||||
{
|
||||
struct iopt_pages *pages;
|
||||
unsigned long start_down = ALIGN_DOWN(start, PAGE_SIZE);
|
||||
unsigned long end;
|
||||
|
||||
if (length && check_add_overflow(start, length - 1, &end))
|
||||
return ERR_PTR(-EOVERFLOW);
|
||||
|
||||
pages = iopt_alloc_pages(start - start_down, length, writable);
|
||||
pages = iopt_alloc_pages(start_byte, length, writable);
|
||||
if (IS_ERR(pages))
|
||||
return pages;
|
||||
pages->file = get_file(file);
|
||||
pages->start = start_down;
|
||||
pages->start = start - start_byte;
|
||||
pages->type = IOPT_ADDRESS_FILE;
|
||||
return pages;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue