powerpc/kernel/iommu: Use largepool as a last resort when !largealloc
[linux-2.6-microblaze.git] / arch / powerpc / kernel / iommu.c
index 560be51..57d6b85 100644 (file)
@@ -296,6 +296,15 @@ again:
                        pass++;
                        goto again;
 
+               } else if (pass == tbl->nr_pools + 1) {
+                       /* Last resort: try largepool */
+                       spin_unlock(&pool->lock);
+                       pool = &tbl->large_pool;
+                       spin_lock(&pool->lock);
+                       pool->hint = pool->start;
+                       pass++;
+                       goto again;
+
                } else {
                        /* Give up */
                        spin_unlock_irqrestore(&(pool->lock), flags);
@@ -889,6 +898,7 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
        unsigned int order;
        unsigned int nio_pages, io_order;
        struct page *page;
+       size_t size_io = size;
 
        size = PAGE_ALIGN(size);
        order = get_order(size);
@@ -915,8 +925,9 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
        memset(ret, 0, size);
 
        /* Set up tces to cover the allocated range */
-       nio_pages = size >> tbl->it_page_shift;
-       io_order = get_iommu_order(size, tbl);
+       size_io = IOMMU_PAGE_ALIGN(size_io, tbl);
+       nio_pages = size_io >> tbl->it_page_shift;
+       io_order = get_iommu_order(size_io, tbl);
        mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
                              mask >> tbl->it_page_shift, io_order, 0);
        if (mapping == DMA_MAPPING_ERROR) {
@@ -931,10 +942,9 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size,
                         void *vaddr, dma_addr_t dma_handle)
 {
        if (tbl) {
-               unsigned int nio_pages;
+               size_t size_io = IOMMU_PAGE_ALIGN(size, tbl);
+               unsigned int nio_pages = size_io >> tbl->it_page_shift;
 
-               size = PAGE_ALIGN(size);
-               nio_pages = size >> tbl->it_page_shift;
                iommu_free(tbl, dma_handle, nio_pages);
                size = PAGE_ALIGN(size);
                free_pages((unsigned long)vaddr, get_order(size));