]> err.no Git - linux-2.6/blobdiff - arch/powerpc/kernel/iommu.c
x86: printk kernel version in WARN_ON and other dump_stack users
[linux-2.6] / arch / powerpc / kernel / iommu.c
index d2598e2e7bbef78d8157b6477bdf129e9a9f17ed..2d0c9ef555e9e4578d9df93ff91e025697069c4e 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/dma-mapping.h>
-#include <linux/init.h>
 #include <linux/bitops.h>
 #include <asm/io.h>
 #include <asm/prom.h>
@@ -89,7 +88,6 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
                                        unsigned int align_order)
 { 
        unsigned long n, end, i, start;
-       unsigned long start_addr, end_addr;
        unsigned long limit;
        int largealloc = npages > 15;
        int pass = 0;
@@ -160,15 +158,6 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
                }
        }
 
-       /* DMA cannot cross 4 GB boundary */
-       start_addr = (n + tbl->it_offset) << PAGE_SHIFT;
-       end_addr = (end + tbl->it_offset) << PAGE_SHIFT;
-       if ((start_addr >> 32) != (end_addr >> 32)) {
-               end_addr &= 0xffffffff00000000l;
-               start = (end_addr >> PAGE_SHIFT) - tbl->it_offset;
-               goto again;
-       }
-
        for (i = n; i < end; i++)
                if (test_bit(i, tbl->it_map)) {
                        start = i+1;
@@ -288,7 +277,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
        dma_addr_t dma_next = 0, dma_addr;
        unsigned long flags;
        struct scatterlist *s, *outs, *segstart;
-       int outcount, incount;
+       int outcount, incount, i;
        unsigned long handle;
 
        BUG_ON(direction == DMA_NONE);
@@ -308,7 +297,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
 
        spin_lock_irqsave(&(tbl->it_lock), flags);
 
-       for (s = outs; nelems; nelems--, s++) {
+       for_each_sg(sglist, s, nelems, i) {
                unsigned long vaddr, npages, entry, slen;
 
                slen = s->length;
@@ -318,7 +307,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
                        continue;
                }
                /* Allocate iommu entries for that segment */
-               vaddr = (unsigned long)page_address(s->page) + s->offset;
+               vaddr = (unsigned long) sg_virt(s);
                npages = iommu_num_pages(vaddr, slen);
                entry = iommu_range_alloc(tbl, npages, &handle, mask >> IOMMU_PAGE_SHIFT, 0);
 
@@ -352,7 +341,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
                        if (novmerge || (dma_addr != dma_next)) {
                                /* Can't merge: create a new segment */
                                segstart = s;
-                               outcount++; outs++;
+                               outcount++;
+                               outs = sg_next(outs);
                                DBG("    can't merge, new segment.\n");
                        } else {
                                outs->dma_length += s->length;
@@ -385,7 +375,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
         * next entry of the sglist if we didn't fill the list completely
         */
        if (outcount < incount) {
-               outs++;
+               outs = sg_next(outs);
                outs->dma_address = DMA_ERROR_CODE;
                outs->dma_length = 0;
        }
@@ -396,7 +386,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
        return outcount;
 
  failure:
-       for (s = &sglist[0]; s <= outs; s++) {
+       for_each_sg(sglist, s, nelems, i) {
                if (s->dma_length != 0) {
                        unsigned long vaddr, npages;
 
@@ -406,6 +396,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
                        s->dma_address = DMA_ERROR_CODE;
                        s->dma_length = 0;
                }
+               if (s == outs)
+                       break;
        }
        spin_unlock_irqrestore(&(tbl->it_lock), flags);
        return 0;
@@ -415,6 +407,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
 void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
                int nelems, enum dma_data_direction direction)
 {
+       struct scatterlist *sg;
        unsigned long flags;
 
        BUG_ON(direction == DMA_NONE);
@@ -424,15 +417,16 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
 
        spin_lock_irqsave(&(tbl->it_lock), flags);
 
+       sg = sglist;
        while (nelems--) {
                unsigned int npages;
-               dma_addr_t dma_handle = sglist->dma_address;
+               dma_addr_t dma_handle = sg->dma_address;
 
-               if (sglist->dma_length == 0)
+               if (sg->dma_length == 0)
                        break;
-               npages = iommu_num_pages(dma_handle,sglist->dma_length);
+               npages = iommu_num_pages(dma_handle, sg->dma_length);
                __iommu_free(tbl, dma_handle, npages);
-               sglist++;
+               sg = sg_next(sg);
        }
 
        /* Flush/invalidate TLBs if necessary. As for iommu_free(), we