#include <asm/vio.h>
 #include <asm/bug.h>
 #include <asm/machdep.h>
+#include <asm/swiotlb.h>
 
 /*
  * Generic direct DMA implementation
  * default the offset is PCI_DRAM_OFFSET.
  */
 
+static u64 __maybe_unused get_pfn_limit(struct device *dev)
+{
+       u64 pfn = (dev->coherent_dma_mask >> PAGE_SHIFT) + 1;
+       struct dev_archdata __maybe_unused *sd = &dev->archdata;
+
+#ifdef CONFIG_SWIOTLB
+       if (sd->max_direct_dma_addr && sd->dma_ops == &swiotlb_dma_ops)
+               pfn = min_t(u64, pfn, sd->max_direct_dma_addr >> PAGE_SHIFT);
+#endif
+
+       return pfn;
+}
 
 void *dma_direct_alloc_coherent(struct device *dev, size_t size,
                                dma_addr_t *dma_handle, gfp_t flag,
 #else
        struct page *page;
        int node = dev_to_node(dev);
-       u64 pfn = (dev->coherent_dma_mask >> PAGE_SHIFT) + 1;
+       u64 pfn = get_pfn_limit(dev);
        int zone;
 
        zone = dma_pfn_limit_to_zone(pfn);