diff options
36 files changed, 846 insertions, 67 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 00c1ff45a158..e089e622be79 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -1862,6 +1862,12 @@ config CC_STACKPROTECTOR | |||
| 1862 | neutralized via a kernel panic. | 1862 | neutralized via a kernel panic. |
| 1863 | This feature requires gcc version 4.2 or above. | 1863 | This feature requires gcc version 4.2 or above. |
| 1864 | 1864 | ||
| 1865 | config SWIOTLB | ||
| 1866 | def_bool y | ||
| 1867 | |||
| 1868 | config IOMMU_HELPER | ||
| 1869 | def_bool SWIOTLB | ||
| 1870 | |||
| 1865 | config XEN_DOM0 | 1871 | config XEN_DOM0 |
| 1866 | def_bool y | 1872 | def_bool y |
| 1867 | depends on XEN | 1873 | depends on XEN |
| @@ -1872,6 +1878,7 @@ config XEN | |||
| 1872 | depends on CPU_V7 && !CPU_V6 | 1878 | depends on CPU_V7 && !CPU_V6 |
| 1873 | depends on !GENERIC_ATOMIC64 | 1879 | depends on !GENERIC_ATOMIC64 |
| 1874 | select ARM_PSCI | 1880 | select ARM_PSCI |
| 1881 | select SWIOTLB_XEN | ||
| 1875 | help | 1882 | help |
| 1876 | Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. | 1883 | Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. |
| 1877 | 1884 | ||
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 863cd84eb1a2..e701a4d9aa59 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
| @@ -11,17 +11,28 @@ | |||
| 11 | #include <asm-generic/dma-coherent.h> | 11 | #include <asm-generic/dma-coherent.h> |
| 12 | #include <asm/memory.h> | 12 | #include <asm/memory.h> |
| 13 | 13 | ||
| 14 | #include <xen/xen.h> | ||
| 15 | #include <asm/xen/hypervisor.h> | ||
| 16 | |||
| 14 | #define DMA_ERROR_CODE (~0) | 17 | #define DMA_ERROR_CODE (~0) |
| 15 | extern struct dma_map_ops arm_dma_ops; | 18 | extern struct dma_map_ops arm_dma_ops; |
| 16 | extern struct dma_map_ops arm_coherent_dma_ops; | 19 | extern struct dma_map_ops arm_coherent_dma_ops; |
| 17 | 20 | ||
| 18 | static inline struct dma_map_ops *get_dma_ops(struct device *dev) | 21 | static inline struct dma_map_ops *__generic_dma_ops(struct device *dev) |
| 19 | { | 22 | { |
| 20 | if (dev && dev->archdata.dma_ops) | 23 | if (dev && dev->archdata.dma_ops) |
| 21 | return dev->archdata.dma_ops; | 24 | return dev->archdata.dma_ops; |
| 22 | return &arm_dma_ops; | 25 | return &arm_dma_ops; |
| 23 | } | 26 | } |
| 24 | 27 | ||
| 28 | static inline struct dma_map_ops *get_dma_ops(struct device *dev) | ||
| 29 | { | ||
| 30 | if (xen_initial_domain()) | ||
| 31 | return xen_dma_ops; | ||
| 32 | else | ||
| 33 | return __generic_dma_ops(dev); | ||
| 34 | } | ||
| 35 | |||
| 25 | static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) | 36 | static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) |
| 26 | { | 37 | { |
| 27 | BUG_ON(!dev); | 38 | BUG_ON(!dev); |
| @@ -94,6 +105,39 @@ static inline unsigned long dma_max_pfn(struct device *dev) | |||
| 94 | } | 105 | } |
| 95 | #define dma_max_pfn(dev) dma_max_pfn(dev) | 106 | #define dma_max_pfn(dev) dma_max_pfn(dev) |
| 96 | 107 | ||
| 108 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | ||
| 109 | { | ||
| 110 | unsigned int offset = paddr & ~PAGE_MASK; | ||
| 111 | return pfn_to_dma(dev, __phys_to_pfn(paddr)) + offset; | ||
| 112 | } | ||
| 113 | |||
| 114 | static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr) | ||
| 115 | { | ||
| 116 | unsigned int offset = dev_addr & ~PAGE_MASK; | ||
| 117 | return __pfn_to_phys(dma_to_pfn(dev, dev_addr)) + offset; | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) | ||
| 121 | { | ||
| 122 | u64 limit, mask; | ||
| 123 | |||
| 124 | if (!dev->dma_mask) | ||
| 125 | return 0; | ||
| 126 | |||
| 127 | mask = *dev->dma_mask; | ||
| 128 | |||
| 129 | limit = (mask + 1) & ~mask; | ||
| 130 | if (limit && size > limit) | ||
| 131 | return 0; | ||
| 132 | |||
| 133 | if ((addr | (addr + size - 1)) & ~mask) | ||
| 134 | return 0; | ||
| 135 | |||
| 136 | return 1; | ||
| 137 | } | ||
| 138 | |||
| 139 | static inline void dma_mark_clean(void *addr, size_t size) { } | ||
| 140 | |||
| 97 | /* | 141 | /* |
| 98 | * DMA errors are defined by all-bits-set in the DMA address. | 142 | * DMA errors are defined by all-bits-set in the DMA address. |
| 99 | */ | 143 | */ |
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index d070741b2b37..3c597c222ef2 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h | |||
| @@ -24,9 +24,11 @@ | |||
| 24 | #ifdef __KERNEL__ | 24 | #ifdef __KERNEL__ |
| 25 | 25 | ||
| 26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
| 27 | #include <linux/blk_types.h> | ||
| 27 | #include <asm/byteorder.h> | 28 | #include <asm/byteorder.h> |
| 28 | #include <asm/memory.h> | 29 | #include <asm/memory.h> |
| 29 | #include <asm-generic/pci_iomap.h> | 30 | #include <asm-generic/pci_iomap.h> |
| 31 | #include <xen/xen.h> | ||
| 30 | 32 | ||
| 31 | /* | 33 | /* |
| 32 | * ISA I/O bus memory addresses are 1:1 with the physical address. | 34 | * ISA I/O bus memory addresses are 1:1 with the physical address. |
| @@ -372,6 +374,13 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr); | |||
| 372 | #define BIOVEC_MERGEABLE(vec1, vec2) \ | 374 | #define BIOVEC_MERGEABLE(vec1, vec2) \ |
| 373 | ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) | 375 | ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) |
| 374 | 376 | ||
| 377 | struct bio_vec; | ||
| 378 | extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1, | ||
| 379 | const struct bio_vec *vec2); | ||
| 380 | #define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \ | ||
| 381 | (__BIOVEC_PHYS_MERGEABLE(vec1, vec2) && \ | ||
| 382 | (!xen_domain() || xen_biovec_phys_mergeable(vec1, vec2))) | ||
| 383 | |||
| 375 | #ifdef CONFIG_MMU | 384 | #ifdef CONFIG_MMU |
| 376 | #define ARCH_HAS_VALID_PHYS_ADDR_RANGE | 385 | #define ARCH_HAS_VALID_PHYS_ADDR_RANGE |
| 377 | extern int valid_phys_addr_range(phys_addr_t addr, size_t size); | 386 | extern int valid_phys_addr_range(phys_addr_t addr, size_t size); |
diff --git a/arch/arm/include/asm/xen/hypervisor.h b/arch/arm/include/asm/xen/hypervisor.h index d7ab99a0c9eb..1317ee40f4df 100644 --- a/arch/arm/include/asm/xen/hypervisor.h +++ b/arch/arm/include/asm/xen/hypervisor.h | |||
| @@ -16,4 +16,6 @@ static inline enum | |||
