diff options
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; |