Commit ac9af7cb authored by Brian King's avatar Brian King Committed by Linus Torvalds

[PATCH] ppc64: iommu vmerge fix

This fixes a bug in the PPC64 iommu vmerge code which results in the
potential for iommu_unmap_sg to go off unmapping more than it should.

This was found on a test system which resulted in PCI bus errors due to
PCI memory being unmapped while DMAs were still in progress.
Signed-off-by: default avatarBrian King <brking@us.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 75e8727f
...@@ -242,7 +242,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, ...@@ -242,7 +242,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
dma_addr_t dma_next = 0, dma_addr; dma_addr_t dma_next = 0, dma_addr;
unsigned long flags; unsigned long flags;
struct scatterlist *s, *outs, *segstart; struct scatterlist *s, *outs, *segstart;
int outcount; int outcount, incount;
unsigned long handle; unsigned long handle;
BUG_ON(direction == DMA_NONE); BUG_ON(direction == DMA_NONE);
...@@ -252,6 +252,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, ...@@ -252,6 +252,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
outs = s = segstart = &sglist[0]; outs = s = segstart = &sglist[0];
outcount = 1; outcount = 1;
incount = nelems;
handle = 0; handle = 0;
/* Init first segment length for backout at failure */ /* Init first segment length for backout at failure */
...@@ -338,10 +339,10 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, ...@@ -338,10 +339,10 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
DBG("mapped %d elements:\n", outcount); DBG("mapped %d elements:\n", outcount);
/* For the sake of iommu_free_sg, we clear out the length in the /* For the sake of iommu_unmap_sg, we clear out the length in the
* next entry of the sglist if we didn't fill the list completely * next entry of the sglist if we didn't fill the list completely
*/ */
if (outcount < nelems) { if (outcount < incount) {
outs++; outs++;
outs->dma_address = DMA_ERROR_CODE; outs->dma_address = DMA_ERROR_CODE;
outs->dma_length = 0; outs->dma_length = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment