diff options
author | Andi Kleen <ak@suse.de> | 2006-02-12 17:34:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-12 19:10:47 -0500 |
commit | 0d541064e8f58858e11cd34d81b6e83617f6eb4a (patch) | |
tree | 2118bef73c46aa505eb54cdbbfe80e0c7ab93738 /arch/x86_64 | |
parent | a65d17c9d27a85782cfe1bbc36c747ffa1f81814 (diff) |
[PATCH] x86_64: GART DMA merging fix
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>
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/kernel/pci-gart.c | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 2fe23a6c361b..dd0718dc178b 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c | |||
@@ -310,7 +310,7 @@ void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int di | |||
310 | 310 | ||
311 | for (i = 0; i < nents; i++) { | 311 | for (i = 0; i < nents; i++) { |
312 | struct scatterlist *s = &sg[i]; | 312 | struct scatterlist *s = &sg[i]; |
313 | if (!s->dma_length || !s->length) | 313 | if (!s->dma_length) |
314 | break; | 314 | break; |
315 | dma_unmap_single(dev, s->dma_address, s->dma_length, dir); | 315 | dma_unmap_single(dev, s->dma_address, s->dma_length, dir); |
316 | } | 316 | } |
@@ -364,7 +364,6 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat, | |||
364 | 364 | ||
365 | BUG_ON(i > start && s->offset); | 365 | BUG_ON(i > start && s->offset); |
366 | if (i == start) { | 366 | if (i == start) { |
367 | *sout = *s; | ||
368 | sout->dma_address = iommu_bus_base; | 367 | sout->dma_address = iommu_bus_base; |
369 | sout->dma_address += iommu_page*PAGE_SIZE + s->offset; | 368 | sout->dma_address += iommu_page*PAGE_SIZE + s->offset; |
370 | sout->dma_length = s->length; | 369 | sout->dma_length = s->length; |
@@ -379,7 +378,7 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat, | |||
379 | SET_LEAK(iommu_page); | 378 | SET_LEAK(iommu_page); |
380 | addr += PAGE_SIZE; | 379 | addr += PAGE_SIZE; |
381 | iommu_page++; | 380 | iommu_page++; |
382 | } | 381 | } |
383 | } | 382 | } |
384 | BUG_ON(iommu_page - iommu_start != pages); | 383 | BUG_ON(iommu_page - iommu_start != pages); |
385 | return 0; | 384 | return 0; |
@@ -391,7 +390,6 @@ static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat, | |||
391 | { | 390 | { |
392 | if (!need) { | 391 | if (!need) { |
393 | BUG_ON(stopat - start != 1); | 392 | BUG_ON(stopat - start != 1); |
394 | *sout = sg[start]; | ||
395 | sout->dma_length = sg[start].length; | 393 | sout->dma_length = sg[start].length; |
396 | return 0; | 394 | return 0; |
397 | } | 395 | } |