[POWERPC] DMA 4GB boundary protection

2007-04-30 Thread Linux Kernel Mailing List
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 = 0xl;
+   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


[POWERPC] DMA 4GB boundary protection

2007-04-30 Thread Linux Kernel Mailing List
Gitweb: 
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=569975591c5530fdc9c7a3c45122e5e46f075a74
Commit: 569975591c5530fdc9c7a3c45122e5e46f075a74
Parent: 1f9209cfe06be715b82075e79c9aab3c5b714010
Author: Jake Moilanen [EMAIL PROTECTED]
AuthorDate: Thu Mar 29 08:44:02 2007 -0500
Committer:  Paul Mackerras [EMAIL PROTECTED]
CommitDate: Fri Apr 13 03:55:13 2007 +1000

[POWERPC] DMA 4GB boundary protection

There are many adapters which cannot handle DMAing across any 4 GB
boundary.  For instance, the latest Emulex adapters.

This normally is not an issue as firmware gives dma-windows under
4gigs.  However, some of the new System-P boxes have dma-windows above
4gigs, and this present a problem.

During initialization of the IOMMU tables, the last entry at each 4GB
boundary is marked as used.  Thus no mappings can cross the boundary.
If a table ends at a 4GB boundary, the entry is not marked as used.

A boot option to remove this 4GB protection is given w/ protect4gb=off.
This exposes the potential issue for driver and hardware development
purposes.

Signed-off-by: Jake Moilanen [EMAIL PROTECTED]
Acked-by: Olof Johansson [EMAIL PROTECTED]
Signed-off-by: Paul Mackerras [EMAIL PROTECTED]
---
 arch/powerpc/kernel/iommu.c |   35 ++-
 1 files changed, 34 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index c50d707..d2598e2 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -47,6 +47,8 @@ static int novmerge = 0;
 static int novmerge = 1;
 #endif
 
+static int protect4gb = 1;
+
 static inline unsigned long iommu_num_pages(unsigned long vaddr,
unsigned long slen)
 {
@@ -58,6 +60,16 @@ static inline unsigned long iommu_num_pages(unsigned long 
vaddr,
return npages;
 }
 
+static int __init setup_protect4gb(char *str)
+{
+   if (strcmp(str, on) == 0)
+   protect4gb = 1;
+   else if (strcmp(str, off) == 0)
+   protect4gb = 0;
+
+   return 1;
+}
+
 static int __init setup_iommu(char *str)
 {
if (!strcmp(str, novmerge))
@@ -67,6 +79,7 @@ static int __init setup_iommu(char *str)
return 1;
 }
 
+__setup(protect4gb=, setup_protect4gb);
 __setup(iommu=, setup_iommu);
 
 static unsigned long iommu_range_alloc(struct iommu_table *tbl,
@@ -439,6 +452,9 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct 
scatterlist *sglist,
 struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
 {
unsigned long sz;
+   unsigned long start_index, end_index;
+   unsigned long entries_per_4g;
+   unsigned long index;
static int welcomed = 0;
struct page *page;
 
@@ -460,7 +476,7 @@ struct iommu_table *iommu_init_table(struct iommu_table 
*tbl, int nid)
 
 #ifdef CONFIG_CRASH_DUMP
if (ppc_md.tce_get) {
-   unsigned long index, tceval;
+   unsigned long tceval;
unsigned long tcecount = 0;
 
/*
@@ -490,6 +506,23 @@ struct iommu_table *iommu_init_table(struct iommu_table 
*tbl, int nid)
ppc_md.tce_free(tbl, tbl-it_offset, tbl-it_size);
 #endif
 
+   /*
+* DMA cannot cross 4 GB boundary.  Mark last entry of each 4
+* GB chunk as reserved.
+*/
+   if (protect4gb) {
+   entries_per_4g = 0x1l  IOMMU_PAGE_SHIFT;
+
+   /* Mark the last bit before a 4GB boundary as used */
+   start_index = tbl-it_offset | (entries_per_4g - 1);
+   start_index -= tbl-it_offset;
+
+   end_index = tbl-it_size;
+
+   for (index = start_index; index  end_index - 1; index += 
entries_per_4g)
+   __set_bit(index, tbl-it_map);
+   }
+
if (!welcomed) {
printk(KERN_INFO IOMMU table initialized, virtual merging 
%s\n,
   novmerge ? disabled : enabled);
-
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


Revert [POWERPC] DMA 4GB boundary protection

2007-04-30 Thread Linux Kernel Mailing List
Gitweb: 
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0999ed7f57728c1919b131207e47d9b311cfbd74
Commit: 0999ed7f57728c1919b131207e47d9b311cfbd74
Parent: c78f830547087aa4143affd3404a854995603544
Author: Paul Mackerras [EMAIL PROTECTED]
AuthorDate: Thu Apr 26 17:01:04 2007 +1000
Committer:  Paul Mackerras [EMAIL PROTECTED]
CommitDate: Thu Apr 26 19:48:15 2007 +1000

Revert [POWERPC] DMA 4GB boundary protection

This reverts commit 618d3adc351a24c4c48437c767befb88ca2d199d, because
it is superseded by 569975591c5530fdc9c7a3c45122e5e46f075a74.
---
 arch/powerpc/kernel/iommu.c |   10 --
 1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index d2598e2..c08ceca 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -89,7 +89,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 +159,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 = 0xl;
-   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