diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-17 22:34:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-17 22:34:12 -0400 |
commit | 08351fc6a75731226e1112fc7254542bd3a2912e (patch) | |
tree | 8b25bd168e0663c766f0332c8be082aa7d6ed265 /arch/tile/kernel/pci-dma.c | |
parent | 0df0914d414a504b975f3cc66ace0c16ef55b7f3 (diff) | |
parent | 0dccb0489f9a5a13a33e828ab965aa49685d12f8 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile: (27 commits)
arch/tile: support newer binutils assembler shift semantics
arch/tile: fix deadlock bugs in rwlock implementation
drivers/edac: provide support for tile architecture
tile on-chip network driver: sync up with latest fixes
arch/tile: support 4KB page size as well as 64KB
arch/tile: add some more VMSPLIT options and use consistent naming
arch/tile: fix some comments and whitespace
arch/tile: export some additional module symbols
arch/tile: enhance existing finv_buffer_remote() routine
arch/tile: fix two bugs in the backtracer code
arch/tile: use extended assembly to inline __mb_incoherent()
arch/tile: use a cleaner technique to enable interrupt for cpu_idle()
arch/tile: sync up with <arch/sim.h> and <arch/sim_def.h> changes
arch/tile: fix reversed test of strict_strtol() return value
arch/tile: avoid a simulator warning during bootup
arch/tile: export <asm/hardwall.h> to userspace
arch/tile: warn and retry if an IPI is not accepted by the target cpu
arch/tile: stop disabling INTCTRL_1 interrupts during hypervisor downcalls
arch/tile: fix __ndelay etc to work better
arch/tile: bug fix: exec'ed task thought it was still single-stepping
...
Fix up trivial conflict in arch/tile/kernel/vmlinux.lds.S (percpu
alignment vs section naming convention fix)
Diffstat (limited to 'arch/tile/kernel/pci-dma.c')
-rw-r--r-- | arch/tile/kernel/pci-dma.c | 38 |
1 files changed, 19 insertions, 19 deletions
diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c index 5ad5e13b0fa6..658752b2835e 100644 --- a/arch/tile/kernel/pci-dma.c +++ b/arch/tile/kernel/pci-dma.c | |||
@@ -86,6 +86,21 @@ EXPORT_SYMBOL(dma_free_coherent); | |||
86 | * can count on nothing having been touched. | 86 | * can count on nothing having been touched. |
87 | */ | 87 | */ |
88 | 88 | ||
89 | /* Flush a PA range from cache page by page. */ | ||
90 | static void __dma_map_pa_range(dma_addr_t dma_addr, size_t size) | ||
91 | { | ||
92 | struct page *page = pfn_to_page(PFN_DOWN(dma_addr)); | ||
93 | size_t bytesleft = PAGE_SIZE - (dma_addr & (PAGE_SIZE - 1)); | ||
94 | |||
95 | while ((ssize_t)size > 0) { | ||
96 | /* Flush the page. */ | ||
97 | homecache_flush_cache(page++, 0); | ||
98 | |||
99 | /* Figure out if we need to continue on the next page. */ | ||
100 | size -= bytesleft; | ||
101 | bytesleft = PAGE_SIZE; | ||
102 | } | ||
103 | } | ||
89 | 104 | ||
90 | /* | 105 | /* |
91 | * dma_map_single can be passed any memory address, and there appear | 106 | * dma_map_single can be passed any memory address, and there appear |
@@ -97,26 +112,12 @@ EXPORT_SYMBOL(dma_free_coherent); | |||
97 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 112 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, |
98 | enum dma_data_direction direction) | 113 | enum dma_data_direction direction) |
99 | { | 114 | { |
100 | struct page *page; | 115 | dma_addr_t dma_addr = __pa(ptr); |
101 | dma_addr_t dma_addr; | ||
102 | int thispage; | ||
103 | 116 | ||
104 | BUG_ON(!valid_dma_direction(direction)); | 117 | BUG_ON(!valid_dma_direction(direction)); |
105 | WARN_ON(size == 0); | 118 | WARN_ON(size == 0); |
106 | 119 | ||
107 | dma_addr = __pa(ptr); | 120 | __dma_map_pa_range(dma_addr, size); |
108 | |||
109 | /* We might have been handed a buffer that wraps a page boundary */ | ||
110 | while ((int)size > 0) { | ||
111 | /* The amount to flush that's on this page */ | ||
112 | thispage = PAGE_SIZE - ((unsigned long)ptr & (PAGE_SIZE - 1)); | ||
113 | thispage = min((int)thispage, (int)size); | ||
114 | /* Is this valid for any page we could be handed? */ | ||
115 | page = pfn_to_page(kaddr_to_pfn(ptr)); | ||
116 | homecache_flush_cache(page, 0); | ||
117 | ptr += thispage; | ||
118 | size -= thispage; | ||
119 | } | ||
120 | 121 | ||
121 | return dma_addr; | 122 | return dma_addr; |
122 | } | 123 | } |
@@ -140,10 +141,8 @@ int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, | |||
140 | WARN_ON(nents == 0 || sglist->length == 0); | 141 | WARN_ON(nents == 0 || sglist->length == 0); |
141 | 142 | ||
142 | for_each_sg(sglist, sg, nents, i) { | 143 | for_each_sg(sglist, sg, nents, i) { |
143 | struct page *page; | ||
144 | sg->dma_address = sg_phys(sg); | 144 | sg->dma_address = sg_phys(sg); |
145 | page = pfn_to_page(sg->dma_address >> PAGE_SHIFT); | 145 | __dma_map_pa_range(sg->dma_address, sg->length); |
146 | homecache_flush_cache(page, 0); | ||
147 | } | 146 | } |
148 | 147 | ||
149 | return nents; | 148 | return nents; |
@@ -163,6 +162,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, | |||
163 | { | 162 | { |
164 | BUG_ON(!valid_dma_direction(direction)); | 163 | BUG_ON(!valid_dma_direction(direction)); |
165 | 164 | ||
165 | BUG_ON(offset + size > PAGE_SIZE); | ||
166 | homecache_flush_cache(page, 0); | 166 | homecache_flush_cache(page, 0); |
167 | 167 | ||
168 | return page_to_pa(page) + offset; | 168 | return page_to_pa(page) + offset; |