Merge tag 'iommu-updates-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / iommu / iommu.c
index 5a570d4..3303d70 100644 (file)
@@ -7,7 +7,9 @@
 #define pr_fmt(fmt)    "iommu: " fmt
 
 #include <linux/device.h>
+#include <linux/dma-iommu.h>
 #include <linux/kernel.h>
+#include <linux/bits.h>
 #include <linux/bug.h>
 #include <linux/types.h>
 #include <linux/init.h>
@@ -29,7 +31,7 @@ static struct kset *iommu_group_kset;
 static DEFINE_IDA(iommu_group_ida);
 
 static unsigned int iommu_def_domain_type __read_mostly;
-static bool iommu_dma_strict __read_mostly = true;
+static bool iommu_dma_strict __read_mostly = IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_STRICT);
 static u32 iommu_cmd_line __read_mostly;
 
 struct iommu_group {
@@ -113,6 +115,7 @@ static const char *iommu_domain_type_str(unsigned int t)
        case IOMMU_DOMAIN_UNMANAGED:
                return "Unmanaged";
        case IOMMU_DOMAIN_DMA:
+       case IOMMU_DOMAIN_DMA_FQ:
                return "Translated";
        default:
                return "Unknown";
@@ -133,11 +136,20 @@ static int __init iommu_subsys_init(void)
                }
        }
 
+       if (!iommu_default_passthrough() && !iommu_dma_strict)
+               iommu_def_domain_type = IOMMU_DOMAIN_DMA_FQ;
+
        pr_info("Default domain type: %s %s\n",
                iommu_domain_type_str(iommu_def_domain_type),
                (iommu_cmd_line & IOMMU_CMD_LINE_DMA_API) ?
                        "(set via kernel command line)" : "");
 
+       if (!iommu_default_passthrough())
+               pr_info("DMA domain TLB invalidation policy: %s mode %s\n",
+                       iommu_dma_strict ? "strict" : "lazy",
+                       (iommu_cmd_line & IOMMU_CMD_LINE_STRICT) ?
+                               "(set via kernel command line)" : "");
+
        return 0;
 }
 subsys_initcall(iommu_subsys_init);
@@ -273,7 +285,9 @@ int iommu_probe_device(struct device *dev)
         * support default domains, so the return value is not yet
         * checked.
         */
+       mutex_lock(&group->mutex);
        iommu_alloc_default_domain(group, dev);
+       mutex_unlock(&group->mutex);
 
        if (group->default_domain) {
                ret = __iommu_attach_device(group->default_domain, dev);
@@ -344,21 +358,13 @@ static int __init iommu_dma_setup(char *str)
 }
 early_param("iommu.strict", iommu_dma_setup);
 
-void iommu_set_dma_strict(bool strict)
+void iommu_set_dma_strict(void)
 {
-       if (strict || !(iommu_cmd_line & IOMMU_CMD_LINE_STRICT))
-               iommu_dma_strict = strict;
+       iommu_dma_strict = true;
+       if (iommu_def_domain_type == IOMMU_DOMAIN_DMA_FQ)
+               iommu_def_domain_type = IOMMU_DOMAIN_DMA;
 }
 
-bool iommu_get_dma_strict(struct iommu_domain *domain)
-{
-       /* only allow lazy flushing for DMA domains */
-       if (domain->type == IOMMU_DOMAIN_DMA)
-               return iommu_dma_strict;
-       return true;
-}
-EXPORT_SYMBOL_GPL(iommu_get_dma_strict);
-
 static ssize_t iommu_group_attr_show(struct kobject *kobj,
                                     struct attribute *__attr, char *buf)
 {
@@ -546,6 +552,9 @@ static ssize_t iommu_group_show_type(struct iommu_group *group,
                case IOMMU_DOMAIN_DMA:
                        type = "DMA\n";
                        break;
+               case IOMMU_DOMAIN_DMA_FQ:
+                       type = "DMA-FQ\n";
+                       break;
                }
        }
        mutex_unlock(&group->mutex);
@@ -759,7 +768,7 @@ static int iommu_create_device_direct_mappings(struct iommu_group *group,
        unsigned long pg_size;
        int ret = 0;
 
-       if (!domain || domain->type != IOMMU_DOMAIN_DMA)
+       if (!domain || !iommu_is_dma_domain(domain))
                return 0;
 
        BUG_ON(!domain->pgsize_bitmap);
@@ -1944,6 +1953,11 @@ static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
        /* Assume all sizes by default; the driver may override this later */
        domain->pgsize_bitmap  = bus->iommu_ops->pgsize_bitmap;
 
+       /* Temporarily avoid -EEXIST while drivers still get their own cookies */
+       if (iommu_is_dma_domain(domain) && !domain->iova_cookie && iommu_get_dma_cookie(domain)) {
+               iommu_domain_free(domain);
+               domain = NULL;
+       }
        return domain;
 }
 
@@ -1955,6 +1969,7 @@ EXPORT_SYMBOL_GPL(iommu_domain_alloc);
 
 void iommu_domain_free(struct iommu_domain *domain)
 {
+       iommu_put_dma_cookie(domain);
        domain->ops->domain_free(domain);
 }
 EXPORT_SYMBOL_GPL(iommu_domain_free);
@@ -2370,45 +2385,94 @@ EXPORT_SYMBOL_GPL(iommu_detach_group);
 
 phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
 {
-       if (unlikely(domain->ops->iova_to_phys == NULL))
+       if (domain->type == IOMMU_DOMAIN_IDENTITY)
+               return iova;
+
+       if (domain->type == IOMMU_DOMAIN_BLOCKED)
                return 0;
 
        return domain->ops->iova_to_phys(domain, iova);
 }
 EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
 
-static size_t iommu_pgsize(struct iommu_domain *domain,
-                          unsigned long addr_merge, size_t size)
+static size_t iommu_pgsize(struct iommu_domain *domain, unsigned long iova,
+                          phys_addr_t paddr, size_t size, size_t *count)
 {
-       unsigned int pgsize_idx;
-       size_t pgsize;
+       unsigned int pgsize_idx, pgsize_idx_next;
+       unsigned long pgsizes;
+       size_t offset, pgsize, pgsize_next;
+       unsigned long addr_merge = paddr | iova;
 
-       /* Max page size that still fits into 'size' */
-       pgsize_idx = __fls(size);
+       /* Page sizes supported by the hardware and small enough for @size */
+       pgsizes = domain->pgsize_bitmap & GENMASK(__fls(size), 0);
 
-       /* need to consider alignment requirements ? */
-       if (likely(addr_merge)) {
-               /* Max page size allowed by address */
-               unsigned int align_pgsize_idx = __ffs(addr_merge);
-               pgsize_idx = min(pgsize_idx, align_pgsize_idx);
-       }
+       /* Constrain the page sizes further based on the maximum alignment */
+       if (likely(addr_merge))
+               pgsizes &= GENMASK(__ffs(addr_merge), 0);
 
-       /* build a mask of acceptable page sizes */
-       pgsize = (1UL << (pgsize_idx + 1)) - 1;
+       /* Make sure we have at least one suitable page size */
+       BUG_ON(!pgsizes);
 
-       /* throw away page sizes not supported by the hardware */
-       pgsize &= domain->pgsize_bitmap;
+       /* Pick the biggest page size remaining */
+       pgsize_idx = __fls(pgsizes);
+       pgsize = BIT(pgsize_idx);
+       if (!count)
+               return pgsize;
 
-       /* make sure we're still sane */
-       BUG_ON(!pgsize);
+       /* Find the next biggest support page size, if it exists */
+       pgsizes = domain->pgsize_bitmap & ~GENMASK(pgsize_idx, 0);
+       if (!pgsizes)
+               goto out_set_count;
 
-       /* pick the biggest page */
-       pgsize_idx = __fls(pgsize);
-       pgsize = 1UL << pgsize_idx;
+       pgsize_idx_next = __ffs(pgsizes);
+       pgsize_next = BIT(pgsize_idx_next);
 
+       /*
+        * There's no point trying a bigger page size unless the virtual
+        * and physical addresses are similarly offset within the larger page.
+        */
+       if ((iova ^ paddr) & (pgsize_next - 1))
+               goto out_set_count;
+
+       /* Calculate the offset to the next page size alignment boundary */
+       offset = pgsize_next - (addr_merge & (pgsize_next - 1));
+
+       /*
+        * If size is big enough to accommodate the larger page, reduce
+        * the number of smaller pages.
+        */
+       if (offset + pgsize_next <= size)
+               size = offset;
+
+out_set_count:
+       *count = size >> pgsize_idx;
        return pgsize;
 }
 
+static int __iommu_map_pages(struct iommu_domain *domain, unsigned long iova,
+                            phys_addr_t paddr, size_t size, int prot,
+                            gfp_t gfp, size_t *mapped)
+{
+       const struct iommu_ops *ops = domain->ops;
+       size_t pgsize, count;
+       int ret;
+
+       pgsize = iommu_pgsize(domain, iova, paddr, size, &count);
+
+       pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx count %zu\n",
+                iova, &paddr, pgsize, count);
+
+       if (ops->map_pages) {
+               ret = ops->map_pages(domain, iova, paddr, pgsize, count, prot,
+                                    gfp, mapped);
+       } else {
+               ret = ops->map(domain, iova, paddr, pgsize, prot, gfp);
+               *mapped = ret ? 0 : pgsize;
+       }
+
+       return ret;
+}
+
 static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
                       phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
@@ -2419,7 +2483,7 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
        phys_addr_t orig_paddr = paddr;
        int ret = 0;
 
-       if (unlikely(ops->map == NULL ||
+       if (unlikely(!(ops->map || ops->map_pages) ||
                     domain->pgsize_bitmap == 0UL))
                return -ENODEV;
 
@@ -2443,18 +2507,21 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
        pr_debug("map: iova 0x%lx pa %pa size 0x%zx\n", iova, &paddr, size);
 
        while (size) {
-               size_t pgsize = iommu_pgsize(domain, iova | paddr, size);
+               size_t mapped = 0;
 
-               pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n",
-                        iova, &paddr, pgsize);
-               ret = ops->map(domain, iova, paddr, pgsize, prot, gfp);
+               ret = __iommu_map_pages(domain, iova, paddr, size, prot, gfp,
+                                       &mapped);
+               /*
+                * Some pages may have been mapped, even if an error occurred,
+                * so we should account for those so they can be unmapped.
+                */
+               size -= mapped;
 
                if (ret)
                        break;
 
-               iova += pgsize;
-               paddr += pgsize;
-               size -= pgsize;
+               iova += mapped;
+               paddr += mapped;
        }
 
        /* unroll mapping in case something went wrong */
@@ -2494,6 +2561,19 @@ int iommu_map_atomic(struct iommu_domain *domain, unsigned long iova,
 }
 EXPORT_SYMBOL_GPL(iommu_map_atomic);
 
+static size_t __iommu_unmap_pages(struct iommu_domain *domain,
+                                 unsigned long iova, size_t size,
+                                 struct iommu_iotlb_gather *iotlb_gather)
+{
+       const struct iommu_ops *ops = domain->ops;
+       size_t pgsize, count;
+
+       pgsize = iommu_pgsize(domain, iova, iova, size, &count);
+       return ops->unmap_pages ?
+              ops->unmap_pages(domain, iova, pgsize, count, iotlb_gather) :
+              ops->unmap(domain, iova, pgsize, iotlb_gather);
+}
+
 static size_t __iommu_unmap(struct iommu_domain *domain,
                            unsigned long iova, size_t size,
                            struct iommu_iotlb_gather *iotlb_gather)
@@ -2503,7 +2583,7 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
        unsigned long orig_iova = iova;
        unsigned int min_pagesz;
 
-       if (unlikely(ops->unmap == NULL ||
+       if (unlikely(!(ops->unmap || ops->unmap_pages) ||
                     domain->pgsize_bitmap == 0UL))
                return 0;
 
@@ -2531,9 +2611,9 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
         * or we hit an area that isn't mapped.
         */
        while (unmapped < size) {
-               size_t pgsize = iommu_pgsize(domain, iova, size - unmapped);
-
-               unmapped_page = ops->unmap(domain, iova, pgsize, iotlb_gather);
+               unmapped_page = __iommu_unmap_pages(domain, iova,
+                                                   size - unmapped,
+                                                   iotlb_gather);
                if (!unmapped_page)
                        break;
 
@@ -3128,6 +3208,14 @@ static int iommu_change_dev_def_domain(struct iommu_group *group,
                goto out;
        }
 
+       /* We can bring up a flush queue without tearing down the domain */
+       if (type == IOMMU_DOMAIN_DMA_FQ && prev_dom->type == IOMMU_DOMAIN_DMA) {
+               ret = iommu_dma_init_fq(prev_dom);
+               if (!ret)
+                       prev_dom->type = IOMMU_DOMAIN_DMA_FQ;
+               goto out;
+       }
+
        /* Sets group->default_domain to the newly allocated domain */
        ret = iommu_group_alloc_default_domain(dev->bus, group, type);
        if (ret)
@@ -3168,9 +3256,9 @@ out:
 }
 
 /*
- * Changing the default domain through sysfs requires the users to ubind the
- * drivers from the devices in the iommu group. Return failure if this doesn't
- * meet.
+ * Changing the default domain through sysfs requires the users to unbind the
+ * drivers from the devices in the iommu group, except for a DMA -> DMA-FQ
+ * transition. Return failure if this isn't met.
  *
  * We need to consider the race between this and the device release path.
  * device_lock(dev) is used here to guarantee that the device release path
@@ -3193,6 +3281,8 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
                req_type = IOMMU_DOMAIN_IDENTITY;
        else if (sysfs_streq(buf, "DMA"))
                req_type = IOMMU_DOMAIN_DMA;
+       else if (sysfs_streq(buf, "DMA-FQ"))
+               req_type = IOMMU_DOMAIN_DMA_FQ;
        else if (sysfs_streq(buf, "auto"))
                req_type = 0;
        else
@@ -3244,7 +3334,8 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 
        /* Check if the device in the group still has a driver bound to it */
        device_lock(dev);
-       if (device_is_bound(dev)) {
+       if (device_is_bound(dev) && !(req_type == IOMMU_DOMAIN_DMA_FQ &&
+           group->default_domain->type == IOMMU_DOMAIN_DMA)) {
                pr_err_ratelimited("Device is still bound to driver\n");
                ret = -EBUSY;
                goto out;