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