]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - arch/powerpc/kernel/iommu.c
powerpc/powernv/iommu: Add real mode version of iommu_table_ops::exchange()
[mirror_ubuntu-zesty-kernel.git] / arch / powerpc / kernel / iommu.c
index 37d6e741be826da51474ab50fe3027cc06400cd5..685a4767b72238e7264d13fb3f5a8b1021efb467 100644 (file)
@@ -479,7 +479,8 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 
                /* Handle failure */
                if (unlikely(entry == DMA_ERROR_CODE)) {
-                       if (printk_ratelimit())
+                       if (!(attrs & DMA_ATTR_NO_WARN) &&
+                           printk_ratelimit())
                                dev_info(dev, "iommu_alloc failed, tbl %p "
                                         "vaddr %lx npages %lu\n", tbl, vaddr,
                                         npages);
@@ -776,7 +777,8 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
                                         mask >> tbl->it_page_shift, align,
                                         attrs);
                if (dma_handle == DMA_ERROR_CODE) {
-                       if (printk_ratelimit())  {
+                       if (!(attrs & DMA_ATTR_NO_WARN) &&
+                           printk_ratelimit())  {
                                dev_info(dev, "iommu_alloc failed, tbl %p "
                                         "vaddr %p npages %d\n", tbl, vaddr,
                                         npages);
@@ -1002,6 +1004,31 @@ long iommu_tce_xchg(struct iommu_table *tbl, unsigned long entry,
 }
 EXPORT_SYMBOL_GPL(iommu_tce_xchg);
 
+#ifdef CONFIG_PPC_BOOK3S_64
+long iommu_tce_xchg_rm(struct iommu_table *tbl, unsigned long entry,
+               unsigned long *hpa, enum dma_data_direction *direction)
+{
+       long ret;
+
+       ret = tbl->it_ops->exchange_rm(tbl, entry, hpa, direction);
+
+       if (!ret && ((*direction == DMA_FROM_DEVICE) ||
+                       (*direction == DMA_BIDIRECTIONAL))) {
+               struct page *pg = realmode_pfn_to_page(*hpa >> PAGE_SHIFT);
+
+               if (likely(pg)) {
+                       SetPageDirty(pg);
+               } else {
+                       tbl->it_ops->exchange_rm(tbl, entry, hpa, direction);
+                       ret = -EFAULT;
+               }
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_tce_xchg_rm);
+#endif
+
 int iommu_take_ownership(struct iommu_table *tbl)
 {
        unsigned long flags, i, sz = (tbl->it_size + 7) >> 3;