Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2004 Hewlett-Packard Development Company, L.P. |
| 3 | * Contributed by David Mosberger-Tang <davidm@hpl.hp.com> |
| 4 | * |
| 5 | * This is a pseudo I/O MMU which dispatches to the hardware I/O MMU |
| 6 | * whenever possible. We assume that the hardware I/O MMU requires |
| 7 | * full 32-bit addressability, as is the case, e.g., for HP zx1-based |
| 8 | * systems (there, the I/O MMU window is mapped at 3-4GB). If a |
| 9 | * device doesn't provide full 32-bit addressability, we fall back on |
| 10 | * the sw I/O TLB. This is good enough to let us support broken |
| 11 | * hardware such as soundcards which have a DMA engine that can |
| 12 | * address only 28 bits. |
| 13 | */ |
| 14 | |
| 15 | #include <linux/device.h> |
FUJITA Tomonori | 917f69b | 2009-01-05 23:36:08 +0900 | [diff] [blame] | 16 | #include <linux/dma-mapping.h> |
Joerg Roedel | 9979aa7 | 2008-10-29 14:17:59 -0700 | [diff] [blame] | 17 | #include <linux/swiotlb.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 18 | #include <asm/machvec.h> |
| 19 | |
FUJITA Tomonori | 160c1d8 | 2009-01-05 23:59:02 +0900 | [diff] [blame] | 20 | extern struct dma_map_ops sba_dma_ops, swiotlb_dma_ops; |
FUJITA Tomonori | c7b3aee | 2009-01-05 23:36:17 +0900 | [diff] [blame] | 21 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 22 | /* swiotlb declarations & definitions: */ |
Alex Williamson | 0b9afed | 2005-09-06 11:20:49 -0600 | [diff] [blame] | 23 | extern int swiotlb_late_init_with_default_size (size_t size); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 24 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 25 | /* |
| 26 | * Note: we need to make the determination of whether or not to use |
| 27 | * the sw I/O TLB based purely on the device structure. Anything else |
| 28 | * would be unreliable or would be too intrusive. |
| 29 | */ |
FUJITA Tomonori | c7b3aee | 2009-01-05 23:36:17 +0900 | [diff] [blame] | 30 | static inline int use_swiotlb(struct device *dev) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 31 | { |
FUJITA Tomonori | c7b3aee | 2009-01-05 23:36:17 +0900 | [diff] [blame] | 32 | return dev && dev->dma_mask && |
FUJITA Tomonori | 160c1d8 | 2009-01-05 23:59:02 +0900 | [diff] [blame] | 33 | !sba_dma_ops.dma_supported(dev, *dev->dma_mask); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 34 | } |
| 35 | |
FUJITA Tomonori | 160c1d8 | 2009-01-05 23:59:02 +0900 | [diff] [blame] | 36 | struct dma_map_ops *hwsw_dma_get_ops(struct device *dev) |
FUJITA Tomonori | c7b3aee | 2009-01-05 23:36:17 +0900 | [diff] [blame] | 37 | { |
| 38 | if (use_swiotlb(dev)) |
| 39 | return &swiotlb_dma_ops; |
| 40 | return &sba_dma_ops; |
| 41 | } |
| 42 | EXPORT_SYMBOL(hwsw_dma_get_ops); |
FUJITA Tomonori | 4d9b977 | 2009-01-05 23:36:12 +0900 | [diff] [blame] | 43 | |
Tony Luck | 9a86bbb | 2007-05-10 11:57:58 -0700 | [diff] [blame] | 44 | void __init |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 45 | hwsw_init (void) |
| 46 | { |
| 47 | /* default to a smallish 2MB sw I/O TLB */ |
Alex Williamson | 0b9afed | 2005-09-06 11:20:49 -0600 | [diff] [blame] | 48 | if (swiotlb_late_init_with_default_size (2 * (1<<20)) != 0) { |
| 49 | #ifdef CONFIG_IA64_GENERIC |
| 50 | /* Better to have normal DMA than panic */ |
| 51 | printk(KERN_WARNING "%s: Failed to initialize software I/O TLB," |
Harvey Harrison | d4ed808 | 2008-03-04 15:15:00 -0800 | [diff] [blame] | 52 | " reverting to hpzx1 platform vector\n", __func__); |
Alex Williamson | 0b9afed | 2005-09-06 11:20:49 -0600 | [diff] [blame] | 53 | machvec_init("hpzx1"); |
| 54 | #else |
| 55 | panic("Unable to initialize software I/O TLB services"); |
| 56 | #endif |
| 57 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 58 | } |