diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/iommu.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/iommu.c | 35 |
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 | ||
962 | out_free_window: | ||
963 | kfree(window); | ||
964 | |||
961 | out_clear_window: | 965 | out_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 | ||
1084 | static 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 | ||
1088 | static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action, | 1118 | static 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; |