From: Eli Billauer <eli.billauer@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: monstr@monstr.eu, Eli Billauer <eli.billauer@gmail.com>
Subject: [PATCH 3/3] microblaze: Refinements on cache flushes and invalidations (dma.c)
Date: Sun, 11 Sep 2011 22:43:08 +0300 [thread overview]
Message-ID: <1315770188-17550-3-git-send-email-eli.billauer@gmail.com> (raw)
In-Reply-To: <1315770188-17550-1-git-send-email-eli.billauer@gmail.com>
Mapping and unmapping methods' cache syncronization calls were refined to
avoid unnecessary synchronizations of the cache. Flushing of the cache is
now made even when mapping memory as DMA_FROM_DEVICE, so that a possible
dirty cache lines don't get flushed later, and overwrite data written by
device.
Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
---
arch/microblaze/kernel/dma.c | 36 ++++++++++++++++++++++++++++--------
1 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index e06ddad..2f231ee 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -76,16 +76,23 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
for_each_sg(sgl, sg, nents, i) {
sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
__dma_sync(page_to_phys(sg_page(sg)) + sg->offset,
- sg->length, direction);
+ sg->length, DMA_TO_DEVICE);
}
return nents;
}
-static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
+static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction direction,
struct dma_attrs *attrs)
{
+ struct scatterlist *sg;
+ int i;
+
+ /* FIXME this part of code is untested */
+ if (direction == DMA_FROM_DEVICE)
+ for_each_sg(sgl, sg, nents, i)
+ __dma_sync(sg->dma_address, sg->length, direction);
}
static int dma_direct_dma_supported(struct device *dev, u64 mask)
@@ -100,7 +107,16 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev,
enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- __dma_sync(page_to_phys(page) + offset, size, direction);
+ /*
+ * We're before the DMA transfer, so cache invalidation makes no
+ * sense in the case of DMA_FROM_DEVICE. Flushing is necessary
+ * in either case, or an unflushed cache line may overwrite
+ * data written by device, in the event of that line being allocated
+ * for other use. Calling __dma_sync with DMA_TO_DEVICE makes this
+ * flush.
+ */
+
+ __dma_sync(page_to_phys(page) + offset, size, DMA_TO_DEVICE);
return page_to_phys(page) + offset + get_dma_direct_offset(dev);
}
@@ -110,12 +126,16 @@ static inline void dma_direct_unmap_page(struct device *dev,
enum dma_data_direction direction,
struct dma_attrs *attrs)
{
-/* There is not necessary to do cache cleanup
- *
- * phys_to_virt is here because in __dma_sync_page is __virt_to_phys and
- * dma_address is physical address
+
+/*
+ * On a DMA to the device, the data has already been flushed and read by
+ * the device at the point unmapping is done. No point doing anything.
+ * In the other direction, unmapping may be used just before accessing the
+ * data on the CPU, so cache invalidation is necessary.
*/
- __dma_sync(dma_address, size, direction);
+
+ if (direction == DMA_FROM_DEVICE)
+ __dma_sync(dma_address, size, direction);
}
static inline void
--
1.7.2.3
next prev parent reply other threads:[~2011-09-11 19:43 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-11 19:43 [PATCH 1/3] microblaze: Moved __dma_sync() to dma-mapping.h Eli Billauer
2011-09-11 19:43 ` [PATCH 2/3] microblaze: Added DMA sync operations Eli Billauer
2011-09-13 11:26 ` Michal Simek
2011-09-11 19:43 ` Eli Billauer [this message]
2011-09-13 11:31 ` [PATCH 3/3] microblaze: Refinements on cache flushes and invalidations (dma.c) Michal Simek
2011-09-13 11:26 ` [PATCH 1/3] microblaze: Moved __dma_sync() to dma-mapping.h Michal Simek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1315770188-17550-3-git-send-email-eli.billauer@gmail.com \
--to=eli.billauer@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=monstr@monstr.eu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox