Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Kernel v2.6.25-rc7 /lib/swiotlb.c

Filename:/lib/swiotlb.c
Lines Added:34
Lines Deleted:3
Also changed in: (Previous) 2.6.25-rc6  2.6.25-rc5-git7  2.6.25-rc5-git6  2.6.25-rc5-git5  2.6.25-rc5-git4  2.6.25-rc5 
(Following) 2.6.25-rc8  2.6.25-rc9  2.6.25  2.6.25-git14  2.6.25-git15  2.6.25-git16 

Location
[  2.6.25-rc7
  [  lib
     o  swiotlb.c

Patch

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 1a8050a..0259228 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -282,6 +282,15 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr)
    return (addr & ~mask) != 0;
 }
 
+static inline unsigned int is_span_boundary(unsigned int index,
+                   unsigned int nslots,
+                   unsigned long offset_slots,
+                   unsigned long max_slots)
+{
+   unsigned long offset = (offset_slots + index) & (max_slots - 1);
+   return offset + nslots > max_slots;
+}
+
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
@@ -292,6 +301,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
@@ -311,12 +332,21 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
     */
    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)
-         wrap = index = 0;
+         index = 0;
+      wrap = index;
 
       do {
+         while (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 we find a slot that indicates we have 'nslots'
           * number of contiguous buffers, we allocate the
@@ -346,6 +376,7 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
             index = 0;
       } while (index != wrap);
 
+  not_found:
       spin_unlock_irqrestore(&io_tlb_lock, flags);
       return NULL;
    }


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.