summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/vio.c
diff options
context:
space:
mode:
authorRobert Jennings <rcj@linux.vnet.ibm.com>2009-01-22 10:40:00 +0100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-01-28 07:15:52 +0100
commit69b052e828b5ff32df7f96d6d3268a069910c663 (patch)
treee2d013ded81fb9d8ad31a14b6ba4d8761727bd8b /arch/powerpc/kernel/vio.c
parentpowerpc: More printing warning fixes for the l64 to ll64 conversion (diff)
downloadlinux-69b052e828b5ff32df7f96d6d3268a069910c663.tar.xz
linux-69b052e828b5ff32df7f96d6d3268a069910c663.zip
powerpc/pseries: Correct VIO bus accounting problem in CMO env.
In the VIO bus code the wrappers for dma alloc_coherent and free_coherent calls are rounding to IOMMU_PAGE_SIZE. Taking a look at the underlying calls, the actual mapping is promoted to PAGE_SIZE. Changing the rounding in these two functions fixes under-reporting the entitlement used by the system. Without this change, the system could run out of entitlement before it believes it has and incur mapping failures at the firmware level. Also in the VIO bus code, the wrapper for dma map_sg is not exiting in an error path where it should. Rather than fall through to code for the success case, this patch adds the return that is needed in the error path. Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/vio.c')
-rw-r--r--arch/powerpc/kernel/vio.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 94aa7b011b27..d3694498f3af 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -492,14 +492,14 @@ static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
struct vio_dev *viodev = to_vio_dev(dev);
void *ret;
- if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE))) {
+ if (vio_cmo_alloc(viodev, roundup(size, PAGE_SIZE))) {
atomic_inc(&viodev->cmo.allocs_failed);
return NULL;
}
ret = dma_iommu_ops.alloc_coherent(dev, size, dma_handle, flag);
if (unlikely(ret == NULL)) {
- vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+ vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
atomic_inc(&viodev->cmo.allocs_failed);
}
@@ -513,7 +513,7 @@ static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
dma_iommu_ops.free_coherent(dev, size, vaddr, dma_handle);
- vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+ vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
}
static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
@@ -572,6 +572,7 @@ static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
if (unlikely(!ret)) {
vio_cmo_dealloc(viodev, alloc_size);
atomic_inc(&viodev->cmo.allocs_failed);
+ return ret;
}
for (sgl = sglist, count = 0; count < ret; count++, sgl++)