Merge tag 'iommu-updates-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / powerpc / kernel / iommu.c
index 48d58d1dcac2d30e38d29884b51a368b45e52294..33bbd59cff792a8a981ef3775095e4a081e39aeb 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/fadump.h>
 #include <asm/vio.h>
 #include <asm/tce.h>
+#include <asm/mmu_context.h>
 
 #define DBG(...)
 
@@ -197,11 +198,11 @@ static unsigned long iommu_range_alloc(struct device *dev,
        if (unlikely(npages == 0)) {
                if (printk_ratelimit())
                        WARN_ON(1);
-               return IOMMU_MAPPING_ERROR;
+               return DMA_MAPPING_ERROR;
        }
 
        if (should_fail_iommu(dev))
-               return IOMMU_MAPPING_ERROR;
+               return DMA_MAPPING_ERROR;
 
        /*
         * We don't need to disable preemption here because any CPU can
@@ -277,7 +278,7 @@ again:
                } else {
                        /* Give up */
                        spin_unlock_irqrestore(&(pool->lock), flags);
-                       return IOMMU_MAPPING_ERROR;
+                       return DMA_MAPPING_ERROR;
                }
        }
 
@@ -309,13 +310,13 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
                              unsigned long attrs)
 {
        unsigned long entry;
-       dma_addr_t ret = IOMMU_MAPPING_ERROR;
+       dma_addr_t ret = DMA_MAPPING_ERROR;
        int build_fail;
 
        entry = iommu_range_alloc(dev, tbl, npages, NULL, mask, align_order);
 
-       if (unlikely(entry == IOMMU_MAPPING_ERROR))
-               return IOMMU_MAPPING_ERROR;
+       if (unlikely(entry == DMA_MAPPING_ERROR))
+               return DMA_MAPPING_ERROR;
 
        entry += tbl->it_offset;        /* Offset into real TCE table */
        ret = entry << tbl->it_page_shift;      /* Set the return dma address */
@@ -327,12 +328,12 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
 
        /* tbl->it_ops->set() only returns non-zero for transient errors.
         * Clean up the table bitmap in this case and return
-        * IOMMU_MAPPING_ERROR. For all other errors the functionality is
+        * DMA_MAPPING_ERROR. For all other errors the functionality is
         * not altered.
         */
        if (unlikely(build_fail)) {
                __iommu_free(tbl, ret, npages);
-               return IOMMU_MAPPING_ERROR;
+               return DMA_MAPPING_ERROR;
        }
 
        /* Flush/invalidate TLB caches if necessary */
@@ -477,7 +478,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                DBG("  - vaddr: %lx, size: %lx\n", vaddr, slen);
 
                /* Handle failure */
-               if (unlikely(entry == IOMMU_MAPPING_ERROR)) {
+               if (unlikely(entry == DMA_MAPPING_ERROR)) {
                        if (!(attrs & DMA_ATTR_NO_WARN) &&
                            printk_ratelimit())
                                dev_info(dev, "iommu_alloc failed, tbl %p "
@@ -544,7 +545,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
         */
        if (outcount < incount) {
                outs = sg_next(outs);
-               outs->dma_address = IOMMU_MAPPING_ERROR;
+               outs->dma_address = DMA_MAPPING_ERROR;
                outs->dma_length = 0;
        }
 
@@ -562,7 +563,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                        npages = iommu_num_pages(s->dma_address, s->dma_length,
                                                 IOMMU_PAGE_SIZE(tbl));
                        __iommu_free(tbl, vaddr, npages);
-                       s->dma_address = IOMMU_MAPPING_ERROR;
+                       s->dma_address = DMA_MAPPING_ERROR;
                        s->dma_length = 0;
                }
                if (s == outs)
@@ -776,7 +777,7 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
                          unsigned long mask, enum dma_data_direction direction,
                          unsigned long attrs)
 {
-       dma_addr_t dma_handle = IOMMU_MAPPING_ERROR;
+       dma_addr_t dma_handle = DMA_MAPPING_ERROR;
        void *vaddr;
        unsigned long uaddr;
        unsigned int npages, align;
@@ -796,7 +797,7 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
                dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
                                         mask >> tbl->it_page_shift, align,
                                         attrs);
-               if (dma_handle == IOMMU_MAPPING_ERROR) {
+               if (dma_handle == DMA_MAPPING_ERROR) {
                        if (!(attrs & DMA_ATTR_NO_WARN) &&
                            printk_ratelimit())  {
                                dev_info(dev, "iommu_alloc failed, tbl %p "
@@ -868,7 +869,7 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
        io_order = get_iommu_order(size, tbl);
        mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
                              mask >> tbl->it_page_shift, io_order, 0);
-       if (mapping == IOMMU_MAPPING_ERROR) {
+       if (mapping == DMA_MAPPING_ERROR) {
                free_pages((unsigned long)ret, order);
                return NULL;
        }
@@ -993,15 +994,19 @@ int iommu_tce_check_gpa(unsigned long page_shift, unsigned long gpa)
 }
 EXPORT_SYMBOL_GPL(iommu_tce_check_gpa);
 
-long iommu_tce_xchg(struct iommu_table *tbl, unsigned long entry,
-               unsigned long *hpa, enum dma_data_direction *direction)
+long iommu_tce_xchg(struct mm_struct *mm, struct iommu_table *tbl,
+               unsigned long entry, unsigned long *hpa,
+               enum dma_data_direction *direction)
 {
        long ret;
+       unsigned long size = 0;
 
        ret = tbl->it_ops->exchange(tbl, entry, hpa, direction);
 
        if (!ret && ((*direction == DMA_FROM_DEVICE) ||
-                       (*direction == DMA_BIDIRECTIONAL)))
+                       (*direction == DMA_BIDIRECTIONAL)) &&
+                       !mm_iommu_is_devmem(mm, *hpa, tbl->it_page_shift,
+                                       &size))
                SetPageDirty(pfn_to_page(*hpa >> PAGE_SHIFT));
 
        /* if (unlikely(ret))
@@ -1073,11 +1078,8 @@ void iommu_release_ownership(struct iommu_table *tbl)
 }
 EXPORT_SYMBOL_GPL(iommu_release_ownership);
 
-int iommu_add_device(struct device *dev)
+int iommu_add_device(struct iommu_table_group *table_group, struct device *dev)
 {
-       struct iommu_table *tbl;
-       struct iommu_table_group_link *tgl;
-
        /*
         * The sysfs entries should be populated before
         * binding IOMMU group. If sysfs entries isn't
@@ -1093,32 +1095,10 @@ int iommu_add_device(struct device *dev)
                return -EBUSY;
        }
 
-       tbl = get_iommu_table_base(dev);
-       if (!tbl) {
-               pr_debug("%s: Skipping device %s with no tbl\n",
-                        __func__, dev_name(dev));
-               return 0;
-       }
-
-       tgl = list_first_entry_or_null(&tbl->it_group_list,
-                       struct iommu_table_group_link, next);
-       if (!tgl) {
-               pr_debug("%s: Skipping device %s with no group\n",
-                        __func__, dev_name(dev));
-               return 0;
-       }
        pr_debug("%s: Adding %s to iommu group %d\n",
-                __func__, dev_name(dev),
-                iommu_group_id(tgl->table_group->group));
-
-       if (PAGE_SIZE < IOMMU_PAGE_SIZE(tbl)) {
-               pr_err("%s: Invalid IOMMU page size %lx (%lx) on %s\n",
-                      __func__, IOMMU_PAGE_SIZE(tbl),
-                      PAGE_SIZE, dev_name(dev));
-               return -EINVAL;
-       }
+                __func__, dev_name(dev),  iommu_group_id(table_group->group));
 
-       return iommu_group_add_device(tgl->table_group->group, dev);
+       return iommu_group_add_device(table_group->group, dev);
 }
 EXPORT_SYMBOL_GPL(iommu_add_device);
 
@@ -1138,31 +1118,4 @@ void iommu_del_device(struct device *dev)
        iommu_group_remove_device(dev);
 }
 EXPORT_SYMBOL_GPL(iommu_del_device);
-
-static int tce_iommu_bus_notifier(struct notifier_block *nb,
-                unsigned long action, void *data)
-{
-        struct device *dev = data;
-
-        switch (action) {
-        case BUS_NOTIFY_ADD_DEVICE:
-                return iommu_add_device(dev);
-        case BUS_NOTIFY_DEL_DEVICE:
-                if (device_iommu_mapped(dev))
-                        iommu_del_device(dev);
-                return 0;
-        default:
-                return 0;
-        }
-}
-
-static struct notifier_block tce_iommu_bus_nb = {
-        .notifier_call = tce_iommu_bus_notifier,
-};
-
-int __init tce_iommu_bus_notifier_init(void)
-{
-        bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
-        return 0;
-}
 #endif /* CONFIG_IOMMU_API */