[PATCH RFC 072/111] staging: etnaviv: "better" DMA API usage

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Russell King <rmk+kernel@xxxxxxxxxxxxxxxx>

The DMA API usage by etnaviv is really not up to scratch.  It does not
respect the buffer ownership rules, which are vitally necessary when
using DMA_BIDIRECTIONAL, as mapping /only/ cleans the cache lines,
causing dirty data to be written back to RAM and an unmap /only/
invalidates them, causing any data in the cache to be discarded.  Given
the length of time which these objects remain mapped, we can't hold
them in the mapped state while hoping that no other CPU accesses to the
buffer occur.

This has lead to visible pixmap corruption in the X server.  Work around
this by mapping and then immediately unmapping the buffers.  This causes
data in the buffers to be written back and then purged from the caches.

Signed-off-by: Russell King <rmk+kernel@xxxxxxxxxxxxxxxx>
---
 drivers/staging/etnaviv/etnaviv_gem.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c b/drivers/staging/etnaviv/etnaviv_gem.c
index 8eeafcafb4e9..56e4ff5dd048 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -26,14 +26,15 @@
 static void etnaviv_gem_scatter_map(struct etnaviv_gem_object *etnaviv_obj)
 {
 	struct drm_device *dev = etnaviv_obj->base.dev;
+	struct sg_table *sgt = etnaviv_obj->sgt;
 
 	/*
 	 * For non-cached buffers, ensure the new pages are clean
 	 * because display controller, GPU, etc. are not coherent.
 	 */
 	if (etnaviv_obj->flags & (ETNA_BO_WC|ETNA_BO_CACHED)) {
-		dma_map_sg(dev->dev, etnaviv_obj->sgt->sgl,
-			   etnaviv_obj->sgt->nents, DMA_BIDIRECTIONAL);
+		dma_map_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+		dma_unmap_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
 	} else {
 		struct scatterlist *sg;
 		unsigned int i;
@@ -50,6 +51,7 @@ static void etnaviv_gem_scatter_map(struct etnaviv_gem_object *etnaviv_obj)
 static void etnaviv_gem_scatterlist_unmap(struct etnaviv_gem_object *etnaviv_obj)
 {
 	struct drm_device *dev = etnaviv_obj->base.dev;
+	struct sg_table *sgt = etnaviv_obj->sgt;
 
 	/*
 	 * For non-cached buffers, ensure the new pages are clean
@@ -66,10 +68,10 @@ static void etnaviv_gem_scatterlist_unmap(struct etnaviv_gem_object *etnaviv_obj
 	 * written into the remainder of the region, this can
 	 * discard those writes.
 	 */
-	if (etnaviv_obj->flags & (ETNA_BO_WC|ETNA_BO_CACHED))
-		dma_unmap_sg(dev->dev, etnaviv_obj->sgt->sgl,
-			     etnaviv_obj->sgt->nents,
-			     DMA_BIDIRECTIONAL);
+	if (etnaviv_obj->flags & (ETNA_BO_WC|ETNA_BO_CACHED)) {
+		dma_map_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+		dma_unmap_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+	}
 }
 
 /* called with dev->struct_mutex held */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel





[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux