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
|
* The datastructure uses the iopt_pages to optimize the storage of the PFNs
|
||||||
* between the domains and xarray.
|
* between the domains and xarray.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/dma-buf.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/file.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)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct iopt_pages *pages;
|
struct iopt_pages *pages;
|
||||||
struct file *file;
|
struct dma_buf *dmabuf;
|
||||||
|
unsigned long start_byte;
|
||||||
|
unsigned long last;
|
||||||
|
|
||||||
file = fget(fd);
|
if (!length)
|
||||||
if (!file)
|
return -EINVAL;
|
||||||
return -EBADF;
|
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,
|
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 {
|
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,
|
struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
|
||||||
unsigned long length, bool writable);
|
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);
|
unsigned long length, bool writable);
|
||||||
struct iopt_pages *iopt_alloc_dmabuf_pages(struct iommufd_ctx *ictx,
|
struct iopt_pages *iopt_alloc_dmabuf_pages(struct iommufd_ctx *ictx,
|
||||||
struct dma_buf *dmabuf,
|
struct dma_buf *dmabuf,
|
||||||
|
|
|
||||||
|
|
@ -1413,22 +1413,19 @@ struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
|
||||||
return pages;
|
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)
|
unsigned long length, bool writable)
|
||||||
|
|
||||||
{
|
{
|
||||||
struct iopt_pages *pages;
|
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))
|
pages = iopt_alloc_pages(start_byte, length, writable);
|
||||||
return ERR_PTR(-EOVERFLOW);
|
|
||||||
|
|
||||||
pages = iopt_alloc_pages(start - start_down, length, writable);
|
|
||||||
if (IS_ERR(pages))
|
if (IS_ERR(pages))
|
||||||
return pages;
|
return pages;
|
||||||
pages->file = get_file(file);
|
pages->file = get_file(file);
|
||||||
pages->start = start_down;
|
pages->start = start - start_byte;
|
||||||
pages->type = IOPT_ADDRESS_FILE;
|
pages->type = IOPT_ADDRESS_FILE;
|
||||||
return pages;
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue