#define DMA_ERROR_CODE         (~(dma_addr_t)0x0)
 
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
 /* Some dma direct funcs must be visible for use in other dma_ops */
 extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
                                       dma_addr_t *dma_handle, gfp_t flag);
  */
 #ifdef CONFIG_PPC64
 extern struct dma_map_ops dma_iommu_ops;
+extern u64 dma_iommu_get_required_mask(struct device *dev);
 #endif
 extern struct dma_map_ops dma_direct_ops;
 
 
        void            (*pci_dma_dev_setup)(struct pci_dev *dev);
        void            (*pci_dma_bus_setup)(struct pci_bus *bus);
 
-       /* Platform set_dma_mask override */
+       /* Platform set_dma_mask and dma_get_required_mask overrides */
        int             (*dma_set_mask)(struct device *dev, u64 dma_mask);
+       u64             (*dma_get_required_mask)(struct device *dev);
 
        int             (*probe)(void);
        void            (*setup_arch)(void); /* Optional, may be NULL */
 
                return 1;
 }
 
+u64 dma_iommu_get_required_mask(struct device *dev)
+{
+       struct iommu_table *tbl = get_iommu_table_base(dev);
+       u64 mask;
+       if (!tbl)
+               return 0;
+
+       mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
+       mask += mask - 1;
+
+       return mask;
+}
+
 struct dma_map_ops dma_iommu_ops = {
        .alloc_coherent = dma_iommu_alloc_coherent,
        .free_coherent  = dma_iommu_free_coherent,
 
 }
 EXPORT_SYMBOL(dma_set_mask);
 
+u64 dma_get_required_mask(struct device *dev)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+       u64 mask, end = 0;
+
+       if (ppc_md.dma_get_required_mask)
+               return ppc_md.dma_get_required_mask(dev);
+
+       if (unlikely(dma_ops == NULL))
+               return 0;
+
+#ifdef CONFIG_PPC64
+       else if (dma_ops == &dma_iommu_ops)
+               return dma_iommu_get_required_mask(dev);
+#endif
+#ifdef CONFIG_SWIOTLB
+       else if (dma_ops == &swiotlb_dma_ops) {
+               u64 max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
+
+               end = memblock_end_of_DRAM();
+               if (max_direct_dma_addr && end > max_direct_dma_addr)
+                       end = max_direct_dma_addr;
+               end += get_dma_offset(dev);
+       }
+#endif
+       else if (dma_ops == &dma_direct_ops)
+               end = memblock_end_of_DRAM() + get_dma_offset(dev);
+       else {
+               WARN_ONCE(1, "%s: unknown ops %p\n", __func__, dma_ops);
+               end = memblock_end_of_DRAM();
+       }
+
+       mask = 1ULL << (fls64(end) - 1);
+       mask += mask - 1;
+
+       return mask;
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+
 static int __init dma_init(void)
 {
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
 
 }
 __setup("iommu_fixed=", setup_iommu_fixed);
 
+static u64 cell_dma_get_required_mask(struct device *dev)
+{
+       if (!dev->dma_mask)
+               return 0;
+
+       if (iommu_fixed_disabled && get_dma_ops(dev) == &dma_iommu_ops)
+               return dma_iommu_get_required_mask(dev);
+
+       return DMA_BIT_MASK(64);
+}
+
 static int __init cell_iommu_init(void)
 {
        struct device_node *np;
 
        /* Setup various ppc_md. callbacks */
        ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
+       ppc_md.dma_get_required_mask = cell_dma_get_required_mask;
        ppc_md.tce_build = tce_build_cell;
        ppc_md.tce_free = tce_free_cell;
 
 
        return 0;
 }
 
+static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
+{
+       if (!dev->dma_mask)
+               return 0;
+
+       if (!disable_ddw && dev_is_pci(dev)) {
+               struct pci_dev *pdev = to_pci_dev(dev);
+               struct device_node *dn;
+
+               dn = pci_device_to_OF_node(pdev);
+
+               /* search upwards for ibm,dma-window */
+               for (; dn && PCI_DN(dn) && !PCI_DN(dn)->iommu_table;
+                               dn = dn->parent)
+                       if (of_get_property(dn, "ibm,dma-window", NULL))
+                               break;
+               /* if there is a ibm,ddw-applicable property require 64 bits */
+               if (dn && PCI_DN(dn) &&
+                               of_get_property(dn, "ibm,ddw-applicable", NULL))
+                       return DMA_BIT_MASK(64);
+       }
+
+       return dma_iommu_get_required_mask(dev);
+}
+
 #else  /* CONFIG_PCI */
 #define pci_dma_bus_setup_pSeries      NULL
 #define pci_dma_dev_setup_pSeries      NULL
 #define pci_dma_bus_setup_pSeriesLP    NULL
 #define pci_dma_dev_setup_pSeriesLP    NULL
 #define dma_set_mask_pSeriesLP         NULL
+#define dma_get_required_mask_pSeriesLP        NULL
 #endif /* !CONFIG_PCI */
 
 static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
                ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
                ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
+               ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
        } else {
                ppc_md.tce_build = tce_build_pSeries;
                ppc_md.tce_free  = tce_free_pSeries;