Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=618d3adc351a24c4c48437c767befb88ca2d199d
Commit:     618d3adc351a24c4c48437c767befb88ca2d199d
Parent:     723ec731de880a76a004a304b62bf8d0f96435d8
Author:     Jake Moilanen <[EMAIL PROTECTED]>
AuthorDate: Fri Mar 2 15:49:43 2007 -0600
Committer:  Paul Mackerras <[EMAIL PROTECTED]>
CommitDate: Fri Mar 9 15:03:25 2007 +1100

    [POWERPC] DMA 4GB boundary protection
    
    There are many adapters which can not handle DMAing acrosss any 4 GB
    boundary.  For instance the latest Emulex adapters.
    
    This normally is not an issue as firmware gives us dma-windows under
    4gigs.  However, some of the new System-P boxes have dma-windows above
    4gigs, and this present a problem.
    
    I propose fixing it in the IOMMU allocation instead of making each
    driver protect against it as it is more efficient, and won't require
    changing every driver which has not considered this issue.
    
    This patch checks to see if the mapping spans a 4 gig boundary, and if
    it does, retries the allocation.  It tries the next allocation at the
    start of the crossed 4 gig boundary.
    
    Signed-off-by: Jake Moilanen <[EMAIL PROTECTED]>
    Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/iommu.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 95edad4..c50d707 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -76,6 +76,7 @@ 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;
@@ -146,6 +147,15 @@ 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;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to