LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH -mm 0/4] fix iommu segment boundary problems (alpha)
@ 2008-02-23  6:13 FUJITA Tomonori
  2008-02-23  6:13 ` [PATCH -mm 1/4] alpha: convert IOMMU to use ALIGN() FUJITA Tomonori
  0 siblings, 1 reply; 5+ messages in thread
From: FUJITA Tomonori @ 2008-02-23  6:13 UTC (permalink / raw)
  To: linux-kernel; +Cc: tomof, Richard Henderson, Ivan Kokshaysky, Andrew Morton


This patchset is another sequel to my patchset to fix iommu segment
boundary problems, IOMMUs allocate memory areas without considering a
low level driver's segment boundary limits:

http://www.mail-archive.com/linux-scsi@vger.kernel.org/msg11919.html

This patchset fixes the Alpha IOMMU code.

There are four patches in this patchset. The first two patches are
preparation for the third patch, which fixes the IOMMU segment
boundary problem. The fourth patch just a cleanup, which removes an
unused code.

This is against 2.6.25-rc2-mm1.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH -mm 1/4] alpha: convert IOMMU to use ALIGN()
  2008-02-23  6:13 [PATCH -mm 0/4] fix iommu segment boundary problems (alpha) FUJITA Tomonori
@ 2008-02-23  6:13 ` FUJITA Tomonori
  2008-02-23  6:13   ` [PATCH -mm 2/4] alpha: IOMMU had better access to the free space bitmap at only one place FUJITA Tomonori
  0 siblings, 1 reply; 5+ messages in thread
From: FUJITA Tomonori @ 2008-02-23  6:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: tomof, FUJITA Tomonori, Richard Henderson, Ivan Kokshaysky,
	Andrew Morton

This patch is preparation for modifications to fix the IOMMU segment
boundary problem.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 arch/alpha/kernel/pci_iommu.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 26d3789..bbf9990 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -136,11 +136,11 @@ iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask)
 	/* Search forward for the first mask-aligned sequence of N free ptes */
 	ptes = arena->ptes;
 	nent = arena->size >> PAGE_SHIFT;
-	p = (arena->next_entry + mask) & ~mask;
+	p = ALIGN(arena->next_entry, mask + 1);
 	i = 0;
 	while (i < n && p+i < nent) {
 		if (ptes[p+i])
-			p = (p + i + 1 + mask) & ~mask, i = 0;
+			p = ALIGN(p + i + 1, mask + 1), i = 0;
 		else
 			i = i + 1;
 	}
@@ -153,7 +153,7 @@ iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask)
 		p = 0, i = 0;
 		while (i < n && p+i < nent) {
 			if (ptes[p+i])
-				p = (p + i + 1 + mask) & ~mask, i = 0;
+				p = ALIGN(p + i + 1, mask + 1), i = 0;
 			else
 				i = i + 1;
 		}
-- 
1.5.3.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH -mm 2/4] alpha: IOMMU had better access to the free space bitmap at only one place
  2008-02-23  6:13 ` [PATCH -mm 1/4] alpha: convert IOMMU to use ALIGN() FUJITA Tomonori
@ 2008-02-23  6:13   ` FUJITA Tomonori
  2008-02-23  6:13     ` [PATCH -mm 3/4] alpha: make IOMMU respect the segment boundary limits FUJITA Tomonori
  0 siblings, 1 reply; 5+ messages in thread
From: FUJITA Tomonori @ 2008-02-23  6:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: tomof, FUJITA Tomonori, Richard Henderson, Ivan Kokshaysky,
	Andrew Morton

iommu_arena_find_pages duplicates the code to access to the bitmap for
free space management. This patch convert the IOMMU code to have only
one place to access the bitmap, in the popular way that other IOMMUs
(e.g. POWER and SPARC) do.

This patch is preparation for modifications to fix the IOMMU segment
boundary problem.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 arch/alpha/kernel/pci_iommu.c |   28 +++++++++++++++-------------
 1 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index bbf9990..e54f829 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -132,12 +132,15 @@ iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask)
 {
 	unsigned long *ptes;
 	long i, p, nent;
+	int pass = 0;
 
 	/* Search forward for the first mask-aligned sequence of N free ptes */
 	ptes = arena->ptes;
 	nent = arena->size >> PAGE_SHIFT;
 	p = ALIGN(arena->next_entry, mask + 1);
 	i = 0;
+
+again:
 	while (i < n && p+i < nent) {
 		if (ptes[p+i])
 			p = ALIGN(p + i + 1, mask + 1), i = 0;
@@ -146,19 +149,18 @@ iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask)
 	}
 
 	if (i < n) {
-                /* Reached the end.  Flush the TLB and restart the
-                   search from the beginning.  */
-		alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
-
-		p = 0, i = 0;
-		while (i < n && p+i < nent) {
-			if (ptes[p+i])
-				p = ALIGN(p + i + 1, mask + 1), i = 0;
-			else
-				i = i + 1;
-		}
-
-		if (i < n)
+		if (pass < 1) {
+			/*
+			 * Reached the end.  Flush the TLB and restart
+			 * the search from the beginning.
+			*/
+			alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
+
+			pass++;
+			p = 0;
+			i = 0;
+			goto again;
+		} else
 			return -1;
 	}
 
-- 
1.5.3.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH -mm 3/4] alpha: make IOMMU respect the segment boundary limits
  2008-02-23  6:13   ` [PATCH -mm 2/4] alpha: IOMMU had better access to the free space bitmap at only one place FUJITA Tomonori
@ 2008-02-23  6:13     ` FUJITA Tomonori
  2008-02-23  6:13       ` [PATCH -mm 4/4] alpha: remove unused DEBUG_FORCEDAC define in IOMMU FUJITA Tomonori
  0 siblings, 1 reply; 5+ messages in thread
From: FUJITA Tomonori @ 2008-02-23  6:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: tomof, FUJITA Tomonori, Richard Henderson, Ivan Kokshaysky,
	Andrew Morton

This patch makes the IOMMU code not allocate a memory area spanning
LLD's segment boundary.

is_span_boundary() judges whether a memory area spans LLD's segment
boundary. If iommu_arena_find_pages() finds such a area, it tries to
find the next available memory area.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 arch/alpha/kernel/pci_iommu.c |   40 ++++++++++++++++++++++++++++++++++------
 1 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index e54f829..54540c3 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -126,13 +126,34 @@ iommu_arena_new(struct pci_controller *hose, dma_addr_t base,
 	return iommu_arena_new_node(0, hose, base, window_size, align);
 }
 
+static inline int is_span_boundary(unsigned int index, unsigned int nr,
+				   unsigned long shift,
+				   unsigned long boundary_size)
+{
+	shift = (shift + index) & (boundary_size - 1);
+	return shift + nr > boundary_size;
+}
+
 /* Must be called with the arena lock held */
 static long
-iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask)
+iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
+		       long n, long mask)
 {
 	unsigned long *ptes;
 	long i, p, nent;
 	int pass = 0;
+	unsigned long base;
+	unsigned long boundary_size;
+
+	BUG_ON(arena->dma_base & ~PAGE_MASK);
+	base = arena->dma_base >> PAGE_SHIFT;
+	if (dev)
+		boundary_size = ALIGN(dma_get_max_seg_size(dev) + 1, PAGE_SIZE)
+			>> PAGE_SHIFT;
+	else
+		boundary_size = ALIGN(1UL << 32, PAGE_SIZE) >> PAGE_SHIFT;
+
+	BUG_ON(!is_power_of_2(boundary_size));
 
 	/* Search forward for the first mask-aligned sequence of N free ptes */
 	ptes = arena->ptes;
@@ -142,6 +163,11 @@ iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask)
 
 again:
 	while (i < n && p+i < nent) {
+		if (!i && is_span_boundary(p, n, base, boundary_size)) {
+			p = ALIGN(p + 1, mask + 1);
+			goto again;
+		}
+
 		if (ptes[p+i])
 			p = ALIGN(p + i + 1, mask + 1), i = 0;
 		else
@@ -170,7 +196,8 @@ again:
 }
 
 static long
-iommu_arena_alloc(struct pci_iommu_arena *arena, long n, unsigned int align)
+iommu_arena_alloc(struct device *dev, struct pci_iommu_arena *arena, long n,
+		  unsigned int align)
 {
 	unsigned long flags;
 	unsigned long *ptes;
@@ -181,7 +208,7 @@ iommu_arena_alloc(struct pci_iommu_arena *arena, long n, unsigned int align)
 	/* Search for N empty ptes */
 	ptes = arena->ptes;
 	mask = max(align, arena->align_entry) - 1;
-	p = iommu_arena_find_pages(arena, n, mask);
+	p = iommu_arena_find_pages(dev, arena, n, mask);
 	if (p < 0) {
 		spin_unlock_irqrestore(&arena->lock, flags);
 		return -1;
@@ -231,6 +258,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
 	unsigned long paddr;
 	dma_addr_t ret;
 	unsigned int align = 0;
+	struct device *dev = pdev ? &pdev->dev : NULL;
 
 	paddr = __pa(cpu_addr);
 
@@ -278,7 +306,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
 	/* Force allocation to 64KB boundary for ISA bridges. */
 	if (pdev && pdev == isa_bridge)
 		align = 8;
-	dma_ofs = iommu_arena_alloc(arena, npages, align);
+	dma_ofs = iommu_arena_alloc(dev, arena, npages, align);
 	if (dma_ofs < 0) {
 		printk(KERN_WARNING "pci_map_single failed: "
 		       "could not allocate dma page tables\n");
@@ -565,7 +593,7 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
 
 	paddr &= ~PAGE_MASK;
 	npages = calc_npages(paddr + size);
-	dma_ofs = iommu_arena_alloc(arena, npages, 0);
+	dma_ofs = iommu_arena_alloc(dev, arena, npages, 0);
 	if (dma_ofs < 0) {
 		/* If we attempted a direct map above but failed, die.  */
 		if (leader->dma_address == 0)
@@ -832,7 +860,7 @@ iommu_reserve(struct pci_iommu_arena *arena, long pg_count, long align_mask)
 
 	/* Search for N empty ptes.  */
 	ptes = arena->ptes;
-	p = iommu_arena_find_pages(arena, pg_count, align_mask);
+	p = iommu_arena_find_pages(NULL, arena, pg_count, align_mask);
 	if (p < 0) {
 		spin_unlock_irqrestore(&arena->lock, flags);
 		return -1;
-- 
1.5.3.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH -mm 4/4] alpha: remove unused DEBUG_FORCEDAC define in IOMMU
  2008-02-23  6:13     ` [PATCH -mm 3/4] alpha: make IOMMU respect the segment boundary limits FUJITA Tomonori
@ 2008-02-23  6:13       ` FUJITA Tomonori
  0 siblings, 0 replies; 5+ messages in thread
From: FUJITA Tomonori @ 2008-02-23  6:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: tomof, FUJITA Tomonori, Richard Henderson, Ivan Kokshaysky,
	Andrew Morton

This just removes unused DEBUG_FORCEDAC define in the IOMMU code.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 arch/alpha/kernel/pci_iommu.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 54540c3..be6fa10 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -31,7 +31,6 @@
 #endif
 
 #define DEBUG_NODIRECT 0
-#define DEBUG_FORCEDAC 0
 
 #define ISA_DMA_MASK		0x00ffffff
 
-- 
1.5.3.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-02-23  6:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-23  6:13 [PATCH -mm 0/4] fix iommu segment boundary problems (alpha) FUJITA Tomonori
2008-02-23  6:13 ` [PATCH -mm 1/4] alpha: convert IOMMU to use ALIGN() FUJITA Tomonori
2008-02-23  6:13   ` [PATCH -mm 2/4] alpha: IOMMU had better access to the free space bitmap at only one place FUJITA Tomonori
2008-02-23  6:13     ` [PATCH -mm 3/4] alpha: make IOMMU respect the segment boundary limits FUJITA Tomonori
2008-02-23  6:13       ` [PATCH -mm 4/4] alpha: remove unused DEBUG_FORCEDAC define in IOMMU FUJITA Tomonori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).