mtd: OneNAND: S5PC110: Fix wrong DMA handling when HIGHMEM
Linux-MTD Mailing List
linux-mtd at lists.infradead.org
Sun Oct 24 20:59:08 EDT 2010
Gitweb: http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=dcf08227e964a53a2cb39130b74842c7dcb6adde
Commit: dcf08227e964a53a2cb39130b74842c7dcb6adde
Parent: aa6d1c0e15948894978b342da45d91f5a2af9933
Author: Kyungmin Park <kyungmin.park at samsung.com>
AuthorDate: Tue Sep 28 19:27:10 2010 +0900
Committer: David Woodhouse <David.Woodhouse at intel.com>
CommitDate: Mon Oct 25 00:51:33 2010 +0100
mtd: OneNAND: S5PC110: Fix wrong DMA handling when HIGHMEM
When use HIGHMEM, dma_map_single doesn't get the proper DMA address.
So use the dma_map_page in this case.
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
drivers/mtd/onenand/samsung.c | 29 ++++++++++++++++++-----------
1 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 285085a..afdb4c5 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -582,7 +582,8 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
void __iomem *p;
void *buf = (void *) buffer;
dma_addr_t dma_src, dma_dst;
- int err;
+ int err, page_dma = 0;
+ struct device *dev = &onenand->pdev->dev;
p = this->base + area;
if (ONENAND_CURRENT_BUFFERRAM(this)) {
@@ -606,21 +607,27 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
page = vmalloc_to_page(buf);
if (!page)
goto normal;
- buf = page_address(page) + ((size_t) buf & ~PAGE_MASK);
- }
- /* DMA routine */
- dma_src = onenand->phys_base + (p - this->base);
- dma_dst = dma_map_single(&onenand->pdev->dev,
- buf, count, DMA_FROM_DEVICE);
- if (dma_mapping_error(&onenand->pdev->dev, dma_dst)) {
- dev_err(&onenand->pdev->dev,
- "Couldn't map a %d byte buffer for DMA\n", count);
+ page_dma = 1;
+ /* DMA routine */
+ dma_src = onenand->phys_base + (p - this->base);
+ dma_dst = dma_map_page(dev, page, 0, count, DMA_FROM_DEVICE);
+ } else {
+ /* DMA routine */
+ dma_src = onenand->phys_base + (p - this->base);
+ dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE);
+ }
+ if (dma_mapping_error(dev, dma_dst)) {
+ dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count);
goto normal;
}
err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src,
count, S5PC110_DMA_DIR_READ);
- dma_unmap_single(&onenand->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
+
+ if (page_dma)
+ dma_unmap_page(dev, dma_dst, count, DMA_FROM_DEVICE);
+ else
+ dma_unmap_single(dev, dma_dst, count, DMA_FROM_DEVICE);
if (!err)
return 0;
More information about the linux-mtd-cvs
mailing list