Commit ce883130 authored by Thomas Petazzoni's avatar Thomas Petazzoni Committed by Rich Felker

arch/sh: make the DMA mapping operations observe dev->dma_pfn_offset

Some devices may have a non-zero DMA offset, i.e an offset between the
DMA address and the physical address. Such an offset can be encoded
into the dma_pfn_offset field of "struct device", but the SuperH
implementation of the DMA mapping API does not observe this
information.

This commit fixes that by ensuring the DMA address is properly
calculated depending on this DMA offset.
Signed-off-by: default avatarThomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: default avatarRich Felker <dalias@libc.org>
parent bc05aa6e
...@@ -16,7 +16,8 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page, ...@@ -16,7 +16,8 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
enum dma_data_direction dir, enum dma_data_direction dir,
unsigned long attrs) unsigned long attrs)
{ {
dma_addr_t addr = page_to_phys(page) + offset; dma_addr_t addr = page_to_phys(page) + offset
- PFN_PHYS(dev->dma_pfn_offset);
WARN_ON(size == 0); WARN_ON(size == 0);
...@@ -36,12 +37,14 @@ static int nommu_map_sg(struct device *dev, struct scatterlist *sg, ...@@ -36,12 +37,14 @@ static int nommu_map_sg(struct device *dev, struct scatterlist *sg,
WARN_ON(nents == 0 || sg[0].length == 0); WARN_ON(nents == 0 || sg[0].length == 0);
for_each_sg(sg, s, nents, i) { for_each_sg(sg, s, nents, i) {
dma_addr_t offset = PFN_PHYS(dev->dma_pfn_offset);
BUG_ON(!sg_page(s)); BUG_ON(!sg_page(s));
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
sh_sync_dma_for_device(sg_virt(s), s->length, dir); sh_sync_dma_for_device(sg_virt(s), s->length, dir);
s->dma_address = sg_phys(s); s->dma_address = sg_phys(s) - offset;
s->dma_length = s->length; s->dma_length = s->length;
} }
......
...@@ -59,7 +59,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, ...@@ -59,7 +59,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
split_page(pfn_to_page(virt_to_phys(ret) >> PAGE_SHIFT), order); split_page(pfn_to_page(virt_to_phys(ret) >> PAGE_SHIFT), order);
*dma_handle = virt_to_phys(ret); *dma_handle = virt_to_phys(ret) - PFN_PHYS(dev->dma_pfn_offset);
return ret_nocache; return ret_nocache;
} }
...@@ -69,7 +69,7 @@ void dma_generic_free_coherent(struct device *dev, size_t size, ...@@ -69,7 +69,7 @@ void dma_generic_free_coherent(struct device *dev, size_t size,
unsigned long attrs) unsigned long attrs)
{ {
int order = get_order(size); int order = get_order(size);
unsigned long pfn = dma_handle >> PAGE_SHIFT; unsigned long pfn = (dma_handle >> PAGE_SHIFT) + dev->dma_pfn_offset;
int k; int k;
for (k = 0; k < (1 << order); k++) for (k = 0; k < (1 << order); k++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment