From 7a9d3fc77f87e7b4a4aa27980790c5f111d8129a Mon Sep 17 00:00:00 2001 From: Stepan Moskovchenko Date: Thu, 11 Aug 2011 19:32:27 -0700 Subject: [PATCH] drivers: iommu: Add map/unmap range ops Add IOMMU ops functions to allow mapping and unmapping whole ranges of address space based on a scatterlist. Signed-off-by: Stepan Moskovchenko --- drivers/iommu/iommu.c | 25 +++++++++++++++++++++++++ include/linux/iommu.h | 22 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 2198b2dbbcd..52e42f54934 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -26,6 +26,7 @@ #include #include #include +#include static ssize_t show_iommu_group(struct device *dev, struct device_attribute *attr, char *buf) @@ -333,6 +334,30 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) } EXPORT_SYMBOL_GPL(iommu_unmap); +int iommu_map_range(struct iommu_domain *domain, unsigned int iova, + struct scatterlist *sg, unsigned int len, int prot) +{ + if (unlikely(domain->ops->map_range == NULL)) + return -ENODEV; + + BUG_ON(iova & (~PAGE_MASK)); + + return domain->ops->map_range(domain, iova, sg, len, prot); +} +EXPORT_SYMBOL_GPL(iommu_map_range); + +int iommu_unmap_range(struct iommu_domain *domain, unsigned int iova, + unsigned int len) +{ + if (unlikely(domain->ops->unmap_range == NULL)) + return -ENODEV; + + BUG_ON(iova & (~PAGE_MASK)); + + return domain->ops->unmap_range(domain, iova, len); +} +EXPORT_SYMBOL_GPL(iommu_unmap_range); + int iommu_device_group(struct device *dev, unsigned int *groupid) { if (iommu_present(dev->bus) && dev->bus->iommu_ops->device_group) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index d937580417b..15350f2d78c 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -20,6 +20,7 @@ #define __LINUX_IOMMU_H #include +#include #define IOMMU_READ (1) #define IOMMU_WRITE (2) @@ -70,6 +71,10 @@ struct iommu_ops { phys_addr_t paddr, size_t size, int prot); size_t (*unmap)(struct iommu_domain *domain, unsigned long iova, size_t size); + int (*map_range)(struct iommu_domain *domain, unsigned int iova, + struct scatterlist *sg, unsigned int len, int prot); + int (*unmap_range)(struct iommu_domain *domain, unsigned int iova, + unsigned int len); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, unsigned long iova); int (*domain_has_cap)(struct iommu_domain *domain, @@ -90,6 +95,10 @@ extern int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot); extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size); +extern int iommu_map_range(struct iommu_domain *domain, unsigned int iova, + struct scatterlist *sg, unsigned int len, int prot); +extern int iommu_unmap_range(struct iommu_domain *domain, unsigned int iova, + unsigned int len); extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, unsigned long iova); extern int iommu_domain_has_cap(struct iommu_domain *domain, @@ -178,6 +187,19 @@ static inline int iommu_unmap(struct iommu_domain *domain, unsigned long iova, return -ENODEV; } +static inline int iommu_map_range(struct iommu_domain *domain, + unsigned int iova, struct scatterlist *sg, + unsigned int len, int prot) +{ + return -ENODEV; +} + +static inline int iommu_unmap_range(struct iommu_domain *domain, + unsigned int iova, unsigned int len) +{ + return -ENODEV; +} + static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, unsigned long iova) {