[PATCH] x86_64: GART DMA merging fix
authorAndi Kleen <ak@suse.de>
Sun, 12 Feb 2006 22:34:59 +0000 (14:34 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 13 Feb 2006 00:10:47 +0000 (16:10 -0800)
Don't touch the non DMA members in the sg list in dma_map_sg in the IOMMU

Some drivers (in particular ST) ran into problems because they reused the sg
lists after passing them to pci_map_sg().  The merging procedure in the K8
GART IOMMU corrupted the state.  This patch changes it to only touch the dma*
entries during merging, but not the other fields.  Approach suggested by Dave
Miller.

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/x86_64/kernel/pci-gart.c

index 2fe23a6..dd0718d 100644 (file)
@@ -310,7 +310,7 @@ void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int di
 
        for (i = 0; i < nents; i++) {
                struct scatterlist *s = &sg[i];
-               if (!s->dma_length || !s->length)
+               if (!s->dma_length)
                        break;
                dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
        }
@@ -364,7 +364,6 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
                
                BUG_ON(i > start && s->offset);
                if (i == start) {
-                       *sout = *s; 
                        sout->dma_address = iommu_bus_base;
                        sout->dma_address += iommu_page*PAGE_SIZE + s->offset;
                        sout->dma_length = s->length;
@@ -379,7 +378,7 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
                        SET_LEAK(iommu_page);
                        addr += PAGE_SIZE;
                        iommu_page++;
-       } 
+               }
        } 
        BUG_ON(iommu_page - iommu_start != pages);      
        return 0;
@@ -391,7 +390,6 @@ static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat,
 {
        if (!need) { 
                BUG_ON(stopat - start != 1);
-               *sout = sg[start]; 
                sout->dma_length = sg[start].length; 
                return 0;
        }