aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-14 23:34:37 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-14 23:34:37 -0500
commiteda670c626a4f53eb8ac5f20d8c10d3f0b54c583 (patch)
treee8b31fdeddd520b0fc56483f0a33c0501ee3b692 /arch/arm/include
parentb746f9c7941f227ad582b4f0bc981f3adcbc46b2 (diff)
parent18c51e1a3fabb455ff1f5cd610097d89f577b8f7 (diff)
Merge tag 'stable/for-linus-3.13-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull Xen updates from Konrad Rzeszutek Wilk: "This has tons of fixes and two major features which are concentrated around the Xen SWIOTLB library. The short <blurb> is that the tracing facility (just one function) has been added to SWIOTLB to make it easier to track I/O progress. Additionally under Xen and ARM (32 & 64) the Xen-SWIOTLB driver "is used to translate physical to machine and machine to physical addresses of foreign[guest] pages for DMA operations" (Stefano) when booting under hardware without proper IOMMU. There are also bug-fixes, cleanups, compile warning fixes, etc. The commit times for some of the commits is a bit fresh - that is b/c we wanted to make sure we have the Ack's from the ARM folks - which with the string of back-to-back conferences took a bit of time. Rest assured - the code has been stewing in #linux-next for some time. Features: - SWIOTLB has tracing added when doing bounce buffer. - Xen ARM/ARM64 can use Xen-SWIOTLB. This work allows Linux to safely program real devices for DMA operations when running as a guest on Xen on ARM, without IOMMU support. [*1] - xen_raw_printk works with PVHVM guests if needed. Bug-fixes: - Make memory ballooning work under HVM with large MMIO region. - Inform hypervisor of MCFG regions found in ACPI DSDT. - Remove deprecated IRQF_DISABLED. - Remove deprecated __cpuinit. [*1]: "On arm and arm64 all Xen guests, including dom0, run with second stage translation enabled. As a consequence when dom0 programs a device for a DMA operation is going to use (pseudo) physical addresses instead machine addresses. This work introduces two trees to track physical to machine and machine to physical mappings of foreign pages. Local pages are assumed mapped 1:1 (physical address == machine address). It enables the SWIOTLB-Xen driver on ARM and ARM64, so that Linux can translate physical addresses to machine addresses for dma operations when necessary. " (Stefano)" * tag 'stable/for-linus-3.13-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: (32 commits) xen/arm: pfn_to_mfn and mfn_to_pfn return the argument if nothing is in the p2m arm,arm64/include/asm/io.h: define struct bio_vec swiotlb-xen: missing include dma-direction.h pci-swiotlb-xen: call pci_request_acs only ifdef CONFIG_PCI arm: make SWIOTLB available xen: delete new instances of added __cpuinit xen/balloon: Set balloon's initial state to number of existing RAM pages xen/mcfg: Call PHYSDEVOP_pci_mmcfg_reserved for MCFG areas. xen: remove deprecated IRQF_DISABLED x86/xen: remove deprecated IRQF_DISABLED swiotlb-xen: fix error code returned by xen_swiotlb_map_sg_attrs swiotlb-xen: static inline xen_phys_to_bus, xen_bus_to_phys, xen_virt_to_bus and range_straddles_page_boundary grant-table: call set_phys_to_machine after mapping grant refs arm,arm64: do not always merge biovec if we are running on Xen swiotlb: print a warning when the swiotlb is full swiotlb-xen: use xen_dma_map/unmap_page, xen_dma_sync_single_for_cpu/device xen: introduce xen_dma_map/unmap_page and xen_dma_sync_single_for_cpu/device tracing/events: Fix swiotlb tracepoint creation swiotlb-xen: use xen_alloc/free_coherent_pages xen: introduce xen_alloc/free_coherent_pages ...
Diffstat (limited to 'arch/arm/include')
-rw-r--r--arch/arm/include/asm/dma-mapping.h46
-rw-r--r--arch/arm/include/asm/io.h9
-rw-r--r--arch/arm/include/asm/xen/hypervisor.h2
-rw-r--r--arch/arm/include/asm/xen/page-coherent.h50
-rw-r--r--arch/arm/include/asm/xen/page.h44
5 files changed, 143 insertions, 8 deletions
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)
15extern struct dma_map_ops arm_dma_ops; 18extern struct dma_map_ops arm_dma_ops;
16extern struct dma_map_ops arm_coherent_dma_ops; 19extern struct dma_map_ops arm_coherent_dma_ops;
17 20
18static inline struct dma_map_ops *get_dma_ops(struct device *dev) 21static 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
28static 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
25static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) 36static 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
108static 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
114static 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
120static 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
139static 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
377struct bio_vec;
378extern 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
377extern int valid_phys_addr_range(phys_addr_t addr, size_t size); 386extern 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 paravirt_lazy_mode paravirt_get_lazy_mode(void)
16 return PARAVIRT_LAZY_NONE; 16 return PARAVIRT_LAZY_NONE;
17} 17}
18 18
19extern struct dma_map_ops *xen_dma_ops;
20
19#endif /* _ASM_ARM_XEN_HYPERVISOR_H */ 21#endif /* _ASM_ARM_XEN_HYPERVISOR_H */
diff --git a/arch/arm/include/asm/xen/page-coherent.h b/arch/arm/include/asm/xen/page-coherent.h
new file mode 100644
index 000000000000..1109017499e5
--- /dev/null
+++ b/arch/arm/include/asm/xen/page-coherent.h
@@ -0,0 +1,50 @@
1#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
2#define _ASM_ARM_XEN_PAGE_COHERENT_H
3
4#include <asm/page.h>
5#include <linux/dma-attrs.h>
6#include <linux/dma-mapping.h>
7
8static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
9 dma_addr_t *dma_handle, gfp_t flags,
10 struct dma_attrs *attrs)
11{
12 return __generic_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
13}
14
15static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
16 void *cpu_addr, dma_addr_t dma_handle,
17 struct dma_attrs *attrs)
18{
19 __generic_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
20}
21
22static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
23 unsigned long offset, size_t size, enum dma_data_direction dir,
24 struct dma_attrs *attrs)
25{
26 __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
27}
28
29static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
30 size_t size, enum dma_data_direction dir,
31 struct dma_attrs *attrs)
32{
33 if (__generic_dma_ops(hwdev)->unmap_page)
34 __generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
35}
36
37static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
38 dma_addr_t handle, size_t size, enum dma_data_direction dir)
39{
40 if (__generic_dma_ops(hwdev)->sync_single_for_cpu)
41 __generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
42}
43
44static inline void xen_dma_sync_single_for_device(struct device *hwdev,
45 dma_addr_t handle, size_t size, enum dma_data_direction dir)
46{
47 if (__generic_dma_ops(hwdev)->sync_single_for_device)
48 __generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
49}
50#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h
index 359a7b50b158..75579a9d6f76 100644
--- a/arch/arm/include/asm/xen/page.h
+++ b/arch/arm/include/asm/xen/page.h
@@ -6,12 +6,12 @@
6 6
7#include <linux/pfn.h> 7#include <linux/pfn.h>
8#include <linux/types.h> 8#include <linux/types.h>
9#include <linux/dma-mapping.h>
9 10
11#include <xen/xen.h>
10#include <xen/interface/grant_table.h> 12#include <xen/interface/grant_table.h>
11 13
12#define pfn_to_mfn(pfn) (pfn)
13#define phys_to_machine_mapping_valid(pfn) (1) 14#define phys_to_machine_mapping_valid(pfn) (1)
14#define mfn_to_pfn(mfn) (mfn)
15#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) 15#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
16 16
17#define pte_mfn pte_pfn 17#define pte_mfn pte_pfn
@@ -32,6 +32,38 @@ typedef struct xpaddr {
32 32
33#define INVALID_P2M_ENTRY (~0UL) 33#define INVALID_P2M_ENTRY (~0UL)
34 34
35unsigned long __pfn_to_mfn(unsigned long pfn);
36unsigned long __mfn_to_pfn(unsigned long mfn);
37extern struct rb_root phys_to_mach;
38
39static inline unsigned long pfn_to_mfn(unsigned long pfn)
40{
41 unsigned long mfn;
42
43 if (phys_to_mach.rb_node != NULL) {
44 mfn = __pfn_to_mfn(pfn);
45 if (mfn != INVALID_P2M_ENTRY)
46 return mfn;
47 }
48
49 return pfn;
50}
51
52static inline unsigned long mfn_to_pfn(unsigned long mfn)
53{
54 unsigned long pfn;
55
56 if (phys_to_mach.rb_node != NULL) {
57 pfn = __mfn_to_pfn(mfn);
58 if (pfn != INVALID_P2M_ENTRY)
59 return pfn;
60 }
61
62 return mfn;
63}
64
65#define mfn_to_local_pfn(mfn) mfn_to_pfn(mfn)
66
35static inline xmaddr_t phys_to_machine(xpaddr_t phys) 67static inline xmaddr_t phys_to_machine(xpaddr_t phys)
36{ 68{
37 unsigned offset = phys.paddr & ~PAGE_MASK; 69 unsigned offset = phys.paddr & ~PAGE_MASK;
@@ -76,11 +108,9 @@ static inline int m2p_remove_override(struct page *page, bool clear_pte)
76 return 0; 108 return 0;
77} 109}
78 110
79static inline bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) 111bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
80{ 112bool __set_phys_to_machine_multi(unsigned long pfn, unsigned long mfn,
81 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); 113 unsigned long nr_pages);
82 return true;
83}
84 114
85static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) 115static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
86{ 116{