aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/dart_iommu.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-08-30 15:24:18 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-09-02 00:07:32 -0400
commit8fb07c0444c37caa39a8df7c70a694c6211f2f57 (patch)
tree1a8d1d5c3d30098822e9ca7f1931a136334641da /arch/powerpc/sysdev/dart_iommu.c
parent5b6e9ff6deb703b95fb355bb66d86096c1a2df09 (diff)
powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe
The PCI-Express bus off the U4/CPC945 bridge supports direct DMA to all of memory, bypassing the DART iommu, for 64-bit capable devices. This adds support for it on Bimini and Apple Quad G5's in order to improve DMA performances of cards using that slot (the x16 graphics slot). Tested with an Intel ixgbe 10GE card. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev/dart_iommu.c')
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c74
1 files changed, 64 insertions, 10 deletions
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 559db2b846a9..17cf15ec38be 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -70,6 +70,8 @@ static int iommu_table_dart_inited;
70static int dart_dirty; 70static int dart_dirty;
71static int dart_is_u4; 71static int dart_is_u4;
72 72
73#define DART_U4_BYPASS_BASE 0x8000000000ull
74
73#define DBG(...) 75#define DBG(...)
74 76
75static inline void dart_tlb_invalidate_all(void) 77static inline void dart_tlb_invalidate_all(void)
@@ -292,12 +294,20 @@ static void iommu_table_dart_setup(void)
292 set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map); 294 set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
293} 295}
294 296
295static void pci_dma_dev_setup_dart(struct pci_dev *dev) 297static void dma_dev_setup_dart(struct device *dev)
296{ 298{
297 /* We only have one iommu table on the mac for now, which makes 299 /* We only have one iommu table on the mac for now, which makes
298 * things simple. Setup all PCI devices to point to this table 300 * things simple. Setup all PCI devices to point to this table
299 */ 301 */
300 set_iommu_table_base(&dev->dev, &iommu_table_dart); 302 if (get_dma_ops(dev) == &dma_direct_ops)
303 set_dma_offset(dev, DART_U4_BYPASS_BASE);
304 else
305 set_iommu_table_base(dev, &iommu_table_dart);
306}
307
308static void pci_dma_dev_setup_dart(struct pci_dev *dev)
309{
310 dma_dev_setup_dart(&dev->dev);
301} 311}
302 312
303static void pci_dma_bus_setup_dart(struct pci_bus *bus) 313static void pci_dma_bus_setup_dart(struct pci_bus *bus)
@@ -315,6 +325,45 @@ static void pci_dma_bus_setup_dart(struct pci_bus *bus)
315 PCI_DN(dn)->iommu_table = &iommu_table_dart; 325 PCI_DN(dn)->iommu_table = &iommu_table_dart;
316} 326}
317 327
328static bool dart_device_on_pcie(struct device *dev)
329{
330 struct device_node *np = of_node_get(dev->of_node);
331
332 while(np) {
333 if (of_device_is_compatible(np, "U4-pcie") ||
334 of_device_is_compatible(np, "u4-pcie")) {
335 of_node_put(np);
336 return true;
337 }
338 np = of_get_next_parent(np);
339 }
340 return false;
341}
342
343static int dart_dma_set_mask(struct device *dev, u64 dma_mask)
344{
345 if (!dev->dma_mask || !dma_supported(dev, dma_mask))
346 return -EIO;
347
348 /* U4 supports a DART bypass, we use it for 64-bit capable
349 * devices to improve performances. However, that only works
350 * for devices connected to U4 own PCIe interface, not bridged
351 * through hypertransport. We need the device to support at
352 * least 40 bits of addresses.
353 */
354 if (dart_device_on_pcie(dev) && dma_mask >= DMA_BIT_MASK(40)) {
355 dev_info(dev, "Using 64-bit DMA iommu bypass\n");
356 set_dma_ops(dev, &dma_direct_ops);
357 } else {
358 dev_info(dev, "Using 32-bit DMA via iommu\n");
359 set_dma_ops(dev, &dma_iommu_ops);
360 }
361 dma_dev_setup_dart(dev);
362
363 *dev->dma_mask = dma_mask;
364 return 0;
365}
366
318void __init iommu_init_early_dart(void) 367void __init iommu_init_early_dart(void)
319{ 368{
320 struct device_node *dn; 369 struct device_node *dn;
@@ -328,20 +377,25 @@ void __init iommu_init_early_dart(void)
328 dart_is_u4 = 1; 377 dart_is_u4 = 1;
329 } 378 }
330 379
380 /* Initialize the DART HW */
381 if (dart_init(dn) != 0)
382 goto bail;
383
331 /* Setup low level TCE operations for the core IOMMU code */ 384 /* Setup low level TCE operations for the core IOMMU code */
332 ppc_md.tce_build = dart_build; 385 ppc_md.tce_build = dart_build;
333 ppc_md.tce_free = dart_free; 386 ppc_md.tce_free = dart_free;
334 ppc_md.tce_flush = dart_flush; 387 ppc_md.tce_flush = dart_flush;
335 388
336 /* Initialize the DART HW */ 389 /* Setup bypass if supported */
337 if (dart_init(dn) == 0) { 390 if (dart_is_u4)
338 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart; 391 ppc_md.dma_set_mask = dart_dma_set_mask;
339 ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
340 392
341 /* Setup pci_dma ops */ 393 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart;
342 set_pci_dma_ops(&dma_iommu_ops); 394 ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
343 return; 395
344 } 396 /* Setup pci_dma ops */
397 set_pci_dma_ops(&dma_iommu_ops);
398 return;
345 399
346 bail: 400 bail:
347 /* If init failed, use direct iommu and null setup functions */ 401 /* If init failed, use direct iommu and null setup functions */