Hi,

On 1/28/21 4:01 AM, Chuck Lever wrote:
From: Isaac J. Manjarres <[email protected]>

Add support for IOMMU drivers to have their own map_sg() callbacks.
This completes the path for having iommu_map_sg() invoke an IOMMU
driver's map_sg() callback, which can then invoke the io-pgtable
map_sg() callback with the entire scatter-gather list, so that it
can be processed entirely in the io-pgtable layer.

For IOMMU drivers that do not provide a callback, the default
implementation of iterating through the scatter-gather list, while
calling iommu_map() will be used.

Signed-off-by: Isaac J. Manjarres <[email protected]>
Tested-by: Sai Prakash Ranjan <[email protected]>
[ cel: adjusted new iotlb_sync_map call site ]
Signed-off-by: Chuck Lever <[email protected]>
---
  drivers/iommu/iommu.c |   12 ++++++++++++
  include/linux/iommu.h |    5 +++++
  2 files changed, 17 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index ed879a4d7fac..bd7adbd0339b 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2551,6 +2551,18 @@ static size_t __iommu_map_sg(struct iommu_domain 
*domain, unsigned long iova,
        unsigned int i = 0;
        int ret;
+ if (ops->map_sg) {
+               ret = ops->map_sg(domain, iova, sg, nents, prot, gfp, &mapped);
+
+               if (ops->iotlb_sync_map)
+                       ops->iotlb_sync_map(domain, iova, mapped);
+
+               if (ret)
+                       goto out_err;
+
+               return mapped;
+       }
+
        while (i <= nents) {
                phys_addr_t s_phys = sg_phys(sg);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index cd5f35022a25..667edc7b034a 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -192,6 +192,8 @@ struct iommu_iotlb_gather {
   * @attach_dev: attach device to an iommu domain
   * @detach_dev: detach device from an iommu domain
   * @map: map a physically contiguous memory region to an iommu domain
+ * @map_sg: map a scatter-gather list of physically contiguous chunks to
+ *          an iommu domain.
   * @unmap: unmap a physically contiguous memory region from an iommu domain
   * @flush_iotlb_all: Synchronously flush all hardware TLBs for this domain
   * @iotlb_sync_map: Sync mappings created recently using @map to the hardware
@@ -243,6 +245,9 @@ struct iommu_ops {
        void (*detach_dev)(struct iommu_domain *domain, struct device *dev);
        int (*map)(struct iommu_domain *domain, unsigned long iova,
                   phys_addr_t paddr, size_t size, int prot, gfp_t gfp);
+       int (*map_sg)(struct iommu_domain *domain, unsigned long iova,
+                     struct scatterlist *sg, unsigned int nents, int prot,
+                     gfp_t gfp, size_t *mapped);

I might be oversensitive. But what if the vendor iommu driver uses iova
beyond the pre-allocated range? It's safer if we could pass an iova
length parameter as well, so that the iommu driver could do some sanity
check.

Best regards,
baolu

        size_t (*unmap)(struct iommu_domain *domain, unsigned long iova,
                     size_t size, struct iommu_iotlb_gather *iotlb_gather);
        void (*flush_iotlb_all)(struct iommu_domain *domain);


_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to