aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-03-04 17:28:57 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-03-04 19:35:14 -0500
commit23d7e0390ab57cf15a5cfe8d6806192f0997e5a8 (patch)
tree8e812d880912e2034513cc1cdb3deb3e2cefb374 /arch/alpha
parent3c5f1def7dd50b792f56dcf7378c2684c06947f3 (diff)
alpha: IOMMU had better access to the free space bitmap at only one place
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> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/kernel/pci_iommu.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index bbf9990cd23..e54f829528c 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)
132{ 132{
133 unsigned long *ptes; 133 unsigned long *ptes;
134 long i, p, nent; 134 long i, p, nent;
135 int pass = 0;
135 136
136 /* Search forward for the first mask-aligned sequence of N free ptes */ 137 /* Search forward for the first mask-aligned sequence of N free ptes */
137 ptes = arena->ptes; 138 ptes = arena->ptes;
138 nent = arena->size >> PAGE_SHIFT; 139 nent = arena->size >> PAGE_SHIFT;
139 p = ALIGN(arena->next_entry, mask + 1); 140 p = ALIGN(arena->next_entry, mask + 1);
140 i = 0; 141 i = 0;
142
143again:
141 while (i < n && p+i < nent) { 144 while (i < n && p+i < nent) {
142 if (ptes[p+i]) 145 if (ptes[p+i])
143 p = ALIGN(p + i + 1, mask + 1), i = 0; 146 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)
146 } 149 }
147 150
148 if (i < n) { 151 if (i < n) {
149 /* Reached the end. Flush the TLB and restart the 152 if (pass < 1) {
150 search from the beginning. */ 153 /*
151 alpha_mv.mv_pci_tbi(arena->hose, 0, -1); 154 * Reached the end. Flush the TLB and restart
152 155 * the search from the beginning.
153 p = 0, i = 0; 156 */
154 while (i < n && p+i < nent) { 157 alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
155 if (ptes[p+i]) 158
156 p = ALIGN(p + i + 1, mask + 1), i = 0; 159 pass++;
157 else 160 p = 0;
158 i = i + 1; 161 i = 0;
159 } 162 goto again;
160 163 } else
161 if (i < n)
162 return -1; 164 return -1;
163 } 165 }
164 166