aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/iommu.c')
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 01faab9456c..b719d970973 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -29,6 +29,7 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/mm.h> 30#include <linux/mm.h>
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <linux/sched.h> /* for show_stack */
32#include <linux/string.h> 33#include <linux/string.h>
33#include <linux/pci.h> 34#include <linux/pci.h>
34#include <linux/dma-mapping.h> 35#include <linux/dma-mapping.h>
@@ -939,14 +940,14 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
939 if (ret) { 940 if (ret) {
940 dev_info(&dev->dev, "failed to map direct window for %s: %d\n", 941 dev_info(&dev->dev, "failed to map direct window for %s: %d\n",
941 dn->full_name, ret); 942 dn->full_name, ret);
942 goto out_clear_window; 943 goto out_free_window;
943 } 944 }
944 945
945 ret = prom_add_property(pdn, win64); 946 ret = prom_add_property(pdn, win64);
946 if (ret) { 947 if (ret) {
947 dev_err(&dev->dev, "unable to add dma window property for %s: %d", 948 dev_err(&dev->dev, "unable to add dma window property for %s: %d",
948 pdn->full_name, ret); 949 pdn->full_name, ret);
949 goto out_clear_window; 950 goto out_free_window;
950 } 951 }
951 952
952 window->device = pdn; 953 window->device = pdn;
@@ -958,6 +959,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
958 dma_addr = of_read_number(&create.addr_hi, 2); 959 dma_addr = of_read_number(&create.addr_hi, 2);
959 goto out_unlock; 960 goto out_unlock;
960 961
962out_free_window:
963 kfree(window);
964
961out_clear_window: 965out_clear_window:
962 remove_ddw(pdn); 966 remove_ddw(pdn);
963 967
@@ -1077,12 +1081,38 @@ check_mask:
1077 return 0; 1081 return 0;
1078} 1082}
1079 1083
1084static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
1085{
1086 if (!dev->dma_mask)
1087 return 0;
1088
1089 if (!disable_ddw && dev_is_pci(dev)) {
1090 struct pci_dev *pdev = to_pci_dev(dev);
1091 struct device_node *dn;
1092
1093 dn = pci_device_to_OF_node(pdev);
1094
1095 /* search upwards for ibm,dma-window */
1096 for (; dn && PCI_DN(dn) && !PCI_DN(dn)->iommu_table;
1097 dn = dn->parent)
1098 if (of_get_property(dn, "ibm,dma-window", NULL))
1099 break;
1100 /* if there is a ibm,ddw-applicable property require 64 bits */
1101 if (dn && PCI_DN(dn) &&
1102 of_get_property(dn, "ibm,ddw-applicable", NULL))
1103 return DMA_BIT_MASK(64);
1104 }
1105
1106 return dma_iommu_ops.get_required_mask(dev);
1107}
1108
1080#else /* CONFIG_PCI */ 1109#else /* CONFIG_PCI */
1081#define pci_dma_bus_setup_pSeries NULL 1110#define pci_dma_bus_setup_pSeries NULL
1082#define pci_dma_dev_setup_pSeries NULL 1111#define pci_dma_dev_setup_pSeries NULL
1083#define pci_dma_bus_setup_pSeriesLP NULL 1112#define pci_dma_bus_setup_pSeriesLP NULL
1084#define pci_dma_dev_setup_pSeriesLP NULL 1113#define pci_dma_dev_setup_pSeriesLP NULL
1085#define dma_set_mask_pSeriesLP NULL 1114#define dma_set_mask_pSeriesLP NULL
1115#define dma_get_required_mask_pSeriesLP NULL
1086#endif /* !CONFIG_PCI */ 1116#endif /* !CONFIG_PCI */
1087 1117
1088static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action, 1118static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
@@ -1186,6 +1216,7 @@ void iommu_init_early_pSeries(void)
1186 ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP; 1216 ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
1187 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP; 1217 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
1188 ppc_md.dma_set_mask = dma_set_mask_pSeriesLP; 1218 ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
1219 ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
1189 } else { 1220 } else {
1190 ppc_md.tce_build = tce_build_pSeries; 1221 ppc_md.tce_build = tce_build_pSeries;
1191 ppc_md.tce_free = tce_free_pSeries; 1222 ppc_md.tce_free = tce_free_pSeries;