return ret;
 }
 
+static int copy_property(void *fdt, int node_offset, const struct device_node *dn,
+                        const char *propname)
+{
+       const void *prop, *fdtprop;
+       int len = 0, fdtlen = 0, ret;
+
+       prop = of_get_property(dn, propname, &len);
+       fdtprop = fdt_getprop(fdt, node_offset, propname, &fdtlen);
+
+       if (fdtprop && !prop)
+               ret = fdt_delprop(fdt, node_offset, propname);
+       else if (prop)
+               ret = fdt_setprop(fdt, node_offset, propname, prop, len);
+
+       return ret;
+}
+
+static int update_pci_dma_nodes(void *fdt, const char *dmapropname)
+{
+       struct device_node *dn;
+       int pci_offset, root_offset, ret = 0;
+
+       if (!firmware_has_feature(FW_FEATURE_LPAR))
+               return 0;
+
+       root_offset = fdt_path_offset(fdt, "/");
+       for_each_node_with_property(dn, dmapropname) {
+               pci_offset = fdt_subnode_offset(fdt, root_offset, of_node_full_name(dn));
+               if (pci_offset < 0)
+                       continue;
+
+               ret = copy_property(fdt, pci_offset, dn, "ibm,dma-window");
+               if (ret < 0)
+                       break;
+               ret = copy_property(fdt, pci_offset, dn, dmapropname);
+               if (ret < 0)
+                       break;
+       }
+
+       return ret;
+}
+
 /**
  * setup_new_fdt_ppc64 - Update the flattend device-tree of the kernel
  *                       being loaded.
        if (ret < 0)
                goto out;
 
+#define DIRECT64_PROPNAME "linux,direct64-ddr-window-info"
+#define DMA64_PROPNAME "linux,dma64-ddr-window-info"
+       ret = update_pci_dma_nodes(fdt, DIRECT64_PROPNAME);
+       if (ret < 0)
+               goto out;
+
+       ret = update_pci_dma_nodes(fdt, DMA64_PROPNAME);
+       if (ret < 0)
+               goto out;
+#undef DMA64_PROPNAME
+#undef DIRECT64_PROPNAME
+
        /* Update memory reserve map */
        ret = get_reserved_memory_ranges(&rmem);
        if (ret)
 
        .get = tce_get_pSeriesLP
 };
 
+/*
+ * Find nearest ibm,dma-window (default DMA window) or direct DMA window or
+ * dynamic 64bit DMA window, walking up the device tree.
+ */
+static struct device_node *pci_dma_find(struct device_node *dn,
+                                       const __be32 **dma_window)
+{
+       const __be32 *dw = NULL;
+
+       for ( ; dn && PCI_DN(dn); dn = dn->parent) {
+               dw = of_get_property(dn, "ibm,dma-window", NULL);
+               if (dw) {
+                       if (dma_window)
+                               *dma_window = dw;
+                       return dn;
+               }
+               dw = of_get_property(dn, DIRECT64_PROPNAME, NULL);
+               if (dw)
+                       return dn;
+               dw = of_get_property(dn, DMA64_PROPNAME, NULL);
+               if (dw)
+                       return dn;
+       }
+
+       return NULL;
+}
+
 static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
 {
        struct iommu_table *tbl;
        pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %pOF\n",
                 dn);
 
-       /*
-        * Find nearest ibm,dma-window (default DMA window), walking up the
-        * device tree
-        */
-       for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
-               dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
-               if (dma_window != NULL)
-                       break;
-       }
+       pdn = pci_dma_find(dn, &dma_window);
 
-       if (dma_window == NULL) {
+       if (dma_window == NULL)
                pr_debug("  no ibm,dma-window property !\n");
-               return;
-       }
 
        ppci = PCI_DN(pdn);
 
        if (!ppci->table_group) {
                ppci->table_group = iommu_pseries_alloc_group(ppci->phb->node);
                tbl = ppci->table_group->tables[0];
-               iommu_table_setparms_lpar(ppci->phb, pdn, tbl,
-                               ppci->table_group, dma_window);
+               if (dma_window) {
+                       iommu_table_setparms_lpar(ppci->phb, pdn, tbl,
+                                                 ppci->table_group, dma_window);
 
-               if (!iommu_init_table(tbl, ppci->phb->node, 0, 0))
-                       panic("Failed to initialize iommu table");
+                       if (!iommu_init_table(tbl, ppci->phb->node, 0, 0))
+                               panic("Failed to initialize iommu table");
+               }
                iommu_register_group(ppci->table_group,
                                pci_domain_nr(bus), 0);
                pr_debug("  created table: %p\n", ppci->table_group);
        bool default_win_removed = false, direct_mapping = false;
        bool pmem_present;
        struct pci_dn *pci = PCI_DN(pdn);
-       struct iommu_table *tbl = pci->table_group->tables[0];
+       struct property *default_win = NULL;
 
        dn = of_find_node_by_type(NULL, "ibm,pmemory");
        pmem_present = dn != NULL;
         * for extensions presence.
         */
        if (query.windows_available == 0) {
-               struct property *default_win;
                int reset_win_ext;
 
                /* DDW + IOMMU on single window may fail if there is any allocation */
-               if (iommu_table_in_use(tbl)) {
+               if (iommu_table_in_use(pci->table_group->tables[0])) {
                        dev_warn(&dev->dev, "current IOMMU table in use, can't be replaced.\n");
                        goto out_failed;
                }
 
                pci->table_group->tables[1] = newtbl;
 
-               /* Keep default DMA window struct if removed */
-               if (default_win_removed) {
-                       tbl->it_size = 0;
-                       vfree(tbl->it_map);
-                       tbl->it_map = NULL;
-               }
-
                set_iommu_table_base(&dev->dev, newtbl);
        }
 
+       if (default_win_removed) {
+               iommu_tce_table_put(pci->table_group->tables[0]);
+               pci->table_group->tables[0] = NULL;
+
+               /* default_win is valid here because default_win_removed == true */
+               of_remove_property(pdn, default_win);
+               dev_info(&dev->dev, "Removed default DMA window for %pOF\n", pdn);
+       }
+
        spin_lock(&dma_win_list_lock);
        list_add(&window->list, &dma_win_list);
        spin_unlock(&dma_win_list_lock);
        dn = pci_device_to_OF_node(dev);
        pr_debug("  node is %pOF\n", dn);
 
-       for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->table_group;
-            pdn = pdn->parent) {
-               dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
-               if (dma_window)
-                       break;
-       }
-
+       pdn = pci_dma_find(dn, &dma_window);
        if (!pdn || !PCI_DN(pdn)) {
                printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "
                       "no DMA window found for pci dev=%s dn=%pOF\n",
 static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask)
 {
        struct device_node *dn = pci_device_to_OF_node(pdev), *pdn;
-       const __be32 *dma_window = NULL;
 
        /* only attempt to use a new window if 64-bit DMA is requested */
        if (dma_mask < DMA_BIT_MASK(64))
         * search upwards in the tree until we either hit a dma-window
         * property, OR find a parent with a table already allocated.
         */
-       for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->table_group;
-                       pdn = pdn->parent) {
-               dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
-               if (dma_window)
-                       break;
-       }
-
+       pdn = pci_dma_find(dn, NULL);
        if (pdn && PCI_DN(pdn))
                return enable_ddw(pdev, pdn);