summaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2017-12-04 16:09:01 +0100
committerRich Felker <dalias@libc.org>2018-04-12 19:47:53 -0400
commitce88313069c36eef80f21fd7403f16620ecd21a2 (patch)
tree6d0733fa5f58aead4d68ffbdd846038cbd306ff1 /arch/sh
parentbc05aa6e13a717e1abff6f863f7ba82b14556df4 (diff)
downloadop-kernel-dev-ce88313069c36eef80f21fd7403f16620ecd21a2.zip
op-kernel-dev-ce88313069c36eef80f21fd7403f16620ecd21a2.tar.gz
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: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Rich Felker <dalias@libc.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/kernel/dma-nommu.c7
-rw-r--r--arch/sh/mm/consistent.c4
2 files changed, 7 insertions, 4 deletions
diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c
index 62b4851..178457d 100644
--- a/arch/sh/kernel/dma-nommu.c
+++ b/arch/sh/kernel/dma-nommu.c
@@ -16,7 +16,8 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
enum dma_data_direction dir,
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);
@@ -36,12 +37,14 @@ static int nommu_map_sg(struct device *dev, struct scatterlist *sg,
WARN_ON(nents == 0 || sg[0].length == 0);
for_each_sg(sg, s, nents, i) {
+ dma_addr_t offset = PFN_PHYS(dev->dma_pfn_offset);
+
BUG_ON(!sg_page(s));
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
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;
}
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index 6ea3aab..8ce9869 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -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);
- *dma_handle = virt_to_phys(ret);
+ *dma_handle = virt_to_phys(ret) - PFN_PHYS(dev->dma_pfn_offset);
return ret_nocache;
}
@@ -69,7 +69,7 @@ void dma_generic_free_coherent(struct device *dev, size_t size,
unsigned long attrs)
{
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;
for (k = 0; k < (1 << order); k++)
OpenPOWER on IntegriCloud