]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - lib/swiotlb.c
cgroup: fix sparse warning of shadow symbol in cgroup.c
[mv-sheeva.git] / lib / swiotlb.c
index 1a8050ade86159877fd6eb4486954c7719bfc28d..3c95922e51e7caaf4bb7a5014d58fba4778580df 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/iommu-helper.h>
 
 #define OFFSET(val,align) ((unsigned long)     \
                           ( (val) & ( (align) - 1)))
@@ -292,6 +293,18 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
        char *dma_addr;
        unsigned int nslots, stride, index, wrap;
        int i;
+       unsigned long start_dma_addr;
+       unsigned long mask;
+       unsigned long offset_slots;
+       unsigned long max_slots;
+
+       mask = dma_get_seg_boundary(hwdev);
+       start_dma_addr = virt_to_bus(io_tlb_start) & mask;
+
+       offset_slots = ALIGN(start_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+       max_slots = mask + 1
+                   ? ALIGN(mask + 1, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT
+                   : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
 
        /*
         * For mappings greater than a page, we limit the stride (and
@@ -310,46 +323,53 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
         * request and allocate a buffer from that IO TLB pool.
         */
        spin_lock_irqsave(&io_tlb_lock, flags);
-       {
-               wrap = index = ALIGN(io_tlb_index, stride);
+       index = ALIGN(io_tlb_index, stride);
+       if (index >= io_tlb_nslabs)
+               index = 0;
+       wrap = index;
+
+       do {
+               while (iommu_is_span_boundary(index, nslots, offset_slots,
+                                             max_slots)) {
+                       index += stride;
+                       if (index >= io_tlb_nslabs)
+                               index = 0;
+                       if (index == wrap)
+                               goto not_found;
+               }
 
-               if (index >= io_tlb_nslabs)
-                       wrap = index = 0;
+               /*
+                * If we find a slot that indicates we have 'nslots' number of
+                * contiguous buffers, we allocate the buffers from that slot
+                * and mark the entries as '0' indicating unavailable.
+                */
+               if (io_tlb_list[index] >= nslots) {
+                       int count = 0;
+
+                       for (i = index; i < (int) (index + nslots); i++)
+                               io_tlb_list[i] = 0;
+                       for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
+                               io_tlb_list[i] = ++count;
+                       dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
 
-               do {
                        /*
-                        * If we find a slot that indicates we have 'nslots'
-                        * number of contiguous buffers, we allocate the
-                        * buffers from that slot and mark the entries as '0'
-                        * indicating unavailable.
+                        * Update the indices to avoid searching in the next
+                        * round.
                         */
-                       if (io_tlb_list[index] >= nslots) {
-                               int count = 0;
-
-                               for (i = index; i < (int) (index + nslots); i++)
-                                       io_tlb_list[i] = 0;
-                               for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1) && io_tlb_list[i]; i--)
-                                       io_tlb_list[i] = ++count;
-                               dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
-
-                               /*
-                                * Update the indices to avoid searching in
-                                * the next round.
-                                */
-                               io_tlb_index = ((index + nslots) < io_tlb_nslabs
-                                               ? (index + nslots) : 0);
-
-                               goto found;
-                       }
-                       index += stride;
-                       if (index >= io_tlb_nslabs)
-                               index = 0;
-               } while (index != wrap);
+                       io_tlb_index = ((index + nslots) < io_tlb_nslabs
+                                       ? (index + nslots) : 0);
 
-               spin_unlock_irqrestore(&io_tlb_lock, flags);
-               return NULL;
-       }
-  found:
+                       goto found;
+               }
+               index += stride;
+               if (index >= io_tlb_nslabs)
+                       index = 0;
+       } while (index != wrap);
+
+not_found:
+       spin_unlock_irqrestore(&io_tlb_lock, flags);
+       return NULL;
+found:
        spin_unlock_irqrestore(&io_tlb_lock, flags);
 
        /*