Commit 9da44c98 authored by Olof Johansson's avatar Olof Johansson Committed by Linus Torvalds

[PATCH] ppc64: Make pci_alloc_consistent() conform to API docs

Documentation/DMA-mapping.txt says that pci_alloc_consistent() needs to
return a mapping that is aligned by the closest larger order of two as the
allocation.

We're currently breaking this with our iommu code.  To fix this, add
align_order arguments to the relevant functions and pass it down. 
Specifying align_order of 0 gives same behaviour as previous.
Signed-off-by: default avatarOlof Johansson <olof@austin.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 65b0e657
...@@ -59,13 +59,18 @@ static int __init setup_iommu(char *str) ...@@ -59,13 +59,18 @@ static int __init setup_iommu(char *str)
__setup("iommu=", setup_iommu); __setup("iommu=", setup_iommu);
static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long npages, static unsigned long iommu_range_alloc(struct iommu_table *tbl,
unsigned long *handle) unsigned long npages,
unsigned long *handle,
unsigned int align_order)
{ {
unsigned long n, end, i, start; unsigned long n, end, i, start;
unsigned long limit; unsigned long limit;
int largealloc = npages > 15; int largealloc = npages > 15;
int pass = 0; int pass = 0;
unsigned long align_mask;
align_mask = 0xffffffffffffffffl >> (64 - align_order);
/* This allocator was derived from x86_64's bit string search */ /* This allocator was derived from x86_64's bit string search */
...@@ -97,6 +102,10 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long np ...@@ -97,6 +102,10 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long np
again: again:
n = find_next_zero_bit(tbl->it_map, limit, start); n = find_next_zero_bit(tbl->it_map, limit, start);
/* Align allocation */
n = (n + align_mask) & ~align_mask;
end = n + npages; end = n + npages;
if (unlikely(end >= limit)) { if (unlikely(end >= limit)) {
...@@ -141,14 +150,15 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long np ...@@ -141,14 +150,15 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long np
} }
static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
unsigned int npages, enum dma_data_direction direction) unsigned int npages, enum dma_data_direction direction,
unsigned int align_order)
{ {
unsigned long entry, flags; unsigned long entry, flags;
dma_addr_t ret = DMA_ERROR_CODE; dma_addr_t ret = DMA_ERROR_CODE;
spin_lock_irqsave(&(tbl->it_lock), flags); spin_lock_irqsave(&(tbl->it_lock), flags);
entry = iommu_range_alloc(tbl, npages, NULL); entry = iommu_range_alloc(tbl, npages, NULL, align_order);
if (unlikely(entry == DMA_ERROR_CODE)) { if (unlikely(entry == DMA_ERROR_CODE)) {
spin_unlock_irqrestore(&(tbl->it_lock), flags); spin_unlock_irqrestore(&(tbl->it_lock), flags);
...@@ -264,7 +274,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, ...@@ -264,7 +274,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
vaddr = (unsigned long)page_address(s->page) + s->offset; vaddr = (unsigned long)page_address(s->page) + s->offset;
npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK); npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK);
npages >>= PAGE_SHIFT; npages >>= PAGE_SHIFT;
entry = iommu_range_alloc(tbl, npages, &handle); entry = iommu_range_alloc(tbl, npages, &handle, 0);
DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen);
...@@ -478,7 +488,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, ...@@ -478,7 +488,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
npages >>= PAGE_SHIFT; npages >>= PAGE_SHIFT;
if (tbl) { if (tbl) {
dma_handle = iommu_alloc(tbl, vaddr, npages, direction); dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 0);
if (dma_handle == DMA_ERROR_CODE) { if (dma_handle == DMA_ERROR_CODE) {
if (printk_ratelimit()) { if (printk_ratelimit()) {
printk(KERN_INFO "iommu_alloc failed, " printk(KERN_INFO "iommu_alloc failed, "
...@@ -537,7 +547,7 @@ void *iommu_alloc_consistent(struct iommu_table *tbl, size_t size, ...@@ -537,7 +547,7 @@ void *iommu_alloc_consistent(struct iommu_table *tbl, size_t size,
memset(ret, 0, size); memset(ret, 0, size);
/* Set up tces to cover the allocated range */ /* Set up tces to cover the allocated range */
mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL); mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, order);
if (mapping == DMA_ERROR_CODE) { if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order); free_pages((unsigned long)ret, order);
ret = NULL; ret = NULL;
......
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