aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/dma-mapping.h3
-rw-r--r--arch/powerpc/include/asm/machdep.h3
-rw-r--r--arch/powerpc/kernel/dma-iommu.c13
-rw-r--r--arch/powerpc/kernel/dma.c39
-rw-r--r--arch/powerpc/platforms/cell/iommu.c12
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c27
6 files changed, 96 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index dd70fac57ec8..8135e66a4bb9 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -20,6 +20,8 @@
20 20
21#define DMA_ERROR_CODE (~(dma_addr_t)0x0) 21#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
22 22
23#define ARCH_HAS_DMA_GET_REQUIRED_MASK
24
23/* Some dma direct funcs must be visible for use in other dma_ops */ 25/* Some dma direct funcs must be visible for use in other dma_ops */
24extern void *dma_direct_alloc_coherent(struct device *dev, size_t size, 26extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
25 dma_addr_t *dma_handle, gfp_t flag); 27 dma_addr_t *dma_handle, gfp_t flag);
@@ -69,6 +71,7 @@ static inline unsigned long device_to_mask(struct device *dev)
69 */ 71 */
70#ifdef CONFIG_PPC64 72#ifdef CONFIG_PPC64
71extern struct dma_map_ops dma_iommu_ops; 73extern struct dma_map_ops dma_iommu_ops;
74extern u64 dma_iommu_get_required_mask(struct device *dev);
72#endif 75#endif
73extern struct dma_map_ops dma_direct_ops; 76extern struct dma_map_ops dma_direct_ops;
74 77
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 47cacddb14cf..58fc21623014 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -85,8 +85,9 @@ struct machdep_calls {
85 void (*pci_dma_dev_setup)(struct pci_dev *dev); 85 void (*pci_dma_dev_setup)(struct pci_dev *dev);
86 void (*pci_dma_bus_setup)(struct pci_bus *bus); 86 void (*pci_dma_bus_setup)(struct pci_bus *bus);
87 87
88 /* Platform set_dma_mask override */ 88 /* Platform set_dma_mask and dma_get_required_mask overrides */
89 int (*dma_set_mask)(struct device *dev, u64 dma_mask); 89 int (*dma_set_mask)(struct device *dev, u64 dma_mask);
90 u64 (*dma_get_required_mask)(struct device *dev);
90 91
91 int (*probe)(void); 92 int (*probe)(void);
92 void (*setup_arch)(void); /* Optional, may be NULL */ 93 void (*setup_arch)(void); /* Optional, may be NULL */
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index e7554154a6de..1f2a711a261e 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -90,6 +90,19 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
90 return 1; 90 return 1;
91} 91}
92 92
93u64 dma_iommu_get_required_mask(struct device *dev)
94{
95 struct iommu_table *tbl = get_iommu_table_base(dev);
96 u64 mask;
97 if (!tbl)
98 return 0;
99
100 mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
101 mask += mask - 1;
102
103 return mask;
104}
105
93struct dma_map_ops dma_iommu_ops = { 106struct dma_map_ops dma_iommu_ops = {
94 .alloc_coherent = dma_iommu_alloc_coherent, 107 .alloc_coherent = dma_iommu_alloc_coherent,
95 .free_coherent = dma_iommu_free_coherent, 108 .free_coherent = dma_iommu_free_coherent,
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 4f0959fbfbee..503093efa202 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -170,6 +170,45 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
170} 170}
171EXPORT_SYMBOL(dma_set_mask); 171EXPORT_SYMBOL(dma_set_mask);
172 172
173u64 dma_get_required_mask(struct device *dev)
174{
175 struct dma_map_ops *dma_ops = get_dma_ops(dev);
176 u64 mask, end = 0;
177
178 if (ppc_md.dma_get_required_mask)
179 return ppc_md.dma_get_required_mask(dev);
180
181 if (unlikely(dma_ops == NULL))
182 return 0;
183
184#ifdef CONFIG_PPC64
185 else if (dma_ops == &dma_iommu_ops)
186 return dma_iommu_get_required_mask(dev);
187#endif
188#ifdef CONFIG_SWIOTLB
189 else if (dma_ops == &swiotlb_dma_ops) {
190 u64 max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
191
192 end = memblock_end_of_DRAM();
193 if (max_direct_dma_addr && end > max_direct_dma_addr)
194 end = max_direct_dma_addr;
195 end += get_dma_offset(dev);
196 }
197#endif
198 else if (dma_ops == &dma_direct_ops)
199 end = memblock_end_of_DRAM() + get_dma_offset(dev);
200 else {
201 WARN_ONCE(1, "%s: unknown ops %p\n", __func__, dma_ops);
202 end = memblock_end_of_DRAM();
203 }
204
205 mask = 1ULL << (fls64(end) - 1);
206 mask += mask - 1;
207
208 return mask;
209}
210EXPORT_SYMBOL_GPL(dma_get_required_mask);
211
173static int __init dma_init(void) 212static int __init dma_init(void)
174{ 213{
175 dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); 214 dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 26a067122a54..5ef55f3b0987 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -1159,6 +1159,17 @@ static int __init setup_iommu_fixed(char *str)
1159} 1159}
1160__setup("iommu_fixed=", setup_iommu_fixed); 1160__setup("iommu_fixed=", setup_iommu_fixed);
1161 1161
1162static u64 cell_dma_get_required_mask(struct device *dev)
1163{
1164 if (!dev->dma_mask)
1165 return 0;
1166
1167 if (iommu_fixed_disabled && get_dma_ops(dev) == &dma_iommu_ops)
1168 return dma_iommu_get_required_mask(dev);
1169
1170 return DMA_BIT_MASK(64);
1171}
1172
1162static int __init cell_iommu_init(void) 1173static int __init cell_iommu_init(void)
1163{ 1174{
1164 struct device_node *np; 1175 struct device_node *np;
@@ -1175,6 +1186,7 @@ static int __init cell_iommu_init(void)
1175 1186
1176 /* Setup various ppc_md. callbacks */ 1187 /* Setup various ppc_md. callbacks */
1177 ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup; 1188 ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
1189 ppc_md.dma_get_required_mask = cell_dma_get_required_mask;
1178 ppc_md.tce_build = tce_build_cell; 1190 ppc_md.tce_build = tce_build_cell;
1179 ppc_md.tce_free = tce_free_cell; 1191 ppc_md.tce_free = tce_free_cell;
1180 1192
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 01faab9456ca..fe5ededf0d60 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1077,12 +1077,38 @@ check_mask:
1077 return 0; 1077 return 0;
1078} 1078}
1079 1079
1080static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
1081{
1082 if (!dev->dma_mask)
1083 return 0;
1084
1085 if (!disable_ddw && dev_is_pci(dev)) {
1086 struct pci_dev *pdev = to_pci_dev(dev);
1087 struct device_node *dn;
1088
1089 dn = pci_device_to_OF_node(pdev);
1090
1091 /* search upwards for ibm,dma-window */
1092 for (; dn && PCI_DN(dn) && !PCI_DN(dn)->iommu_table;
1093 dn = dn->parent)
1094 if (of_get_property(dn, "ibm,dma-window", NULL))
1095 break;
1096 /* if there is a ibm,ddw-applicable property require 64 bits */
1097 if (dn && PCI_DN(dn) &&
1098 of_get_property(dn, "ibm,ddw-applicable", NULL))
1099 return DMA_BIT_MASK(64);
1100 }
1101
1102 return dma_iommu_get_required_mask(dev);
1103}
1104
1080#else /* CONFIG_PCI */ 1105#else /* CONFIG_PCI */
1081#define pci_dma_bus_setup_pSeries NULL 1106#define pci_dma_bus_setup_pSeries NULL
1082#define pci_dma_dev_setup_pSeries NULL 1107#define pci_dma_dev_setup_pSeries NULL
1083#define pci_dma_bus_setup_pSeriesLP NULL 1108#define pci_dma_bus_setup_pSeriesLP NULL
1084#define pci_dma_dev_setup_pSeriesLP NULL 1109#define pci_dma_dev_setup_pSeriesLP NULL
1085#define dma_set_mask_pSeriesLP NULL 1110#define dma_set_mask_pSeriesLP NULL
1111#define dma_get_required_mask_pSeriesLP NULL
1086#endif /* !CONFIG_PCI */ 1112#endif /* !CONFIG_PCI */
1087 1113
1088static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action, 1114static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
@@ -1186,6 +1212,7 @@ void iommu_init_early_pSeries(void)
1186 ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP; 1212 ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
1187 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP; 1213 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
1188 ppc_md.dma_set_mask = dma_set_mask_pSeriesLP; 1214 ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
1215 ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
1189 } else { 1216 } else {
1190 ppc_md.tce_build = tce_build_pSeries; 1217 ppc_md.tce_build = tce_build_pSeries;
1191 ppc_md.tce_free = tce_free_pSeries; 1218 ppc_md.tce_free = tce_free_pSeries;