aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/parisc/sba_iommu.c
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-03-04 17:29:28 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-03-04 19:35:17 -0500
commit466634488e80968f12e73dd1fe6af5c37a1fbfe2 (patch)
treed738011402f57e5366c42bd4b2a525637ffdbcd1 /drivers/parisc/sba_iommu.c
parent7c8cda625acd9b704100994626fb6d2fb4ffb9c2 (diff)
iommu: parisc: make the IOMMUs respect the segment boundary limits
Make PARISC's two IOMMU implementations not allocate a memory area spanning LLD's segment boundary. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: Kyle McMartin <kyle@parisc-linux.org> Cc: Matthew Wilcox <matthew@wil.cx> Cc: Grant Grundler <grundler@parisc-linux.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/parisc/sba_iommu.c')
-rw-r--r--drivers/parisc/sba_iommu.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 7d58bd2019b9..e834127a8505 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -29,6 +29,7 @@
29#include <linux/string.h> 29#include <linux/string.h>
30#include <linux/pci.h> 30#include <linux/pci.h>
31#include <linux/scatterlist.h> 31#include <linux/scatterlist.h>
32#include <linux/iommu-helper.h>
32 33
33#include <asm/byteorder.h> 34#include <asm/byteorder.h>
34#include <asm/io.h> 35#include <asm/io.h>
@@ -313,6 +314,12 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
313#define RESMAP_MASK(n) (~0UL << (BITS_PER_LONG - (n))) 314#define RESMAP_MASK(n) (~0UL << (BITS_PER_LONG - (n)))
314#define RESMAP_IDX_MASK (sizeof(unsigned long) - 1) 315#define RESMAP_IDX_MASK (sizeof(unsigned long) - 1)
315 316
317unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr,
318 unsigned int bitshiftcnt)
319{
320 return (((unsigned long)res_ptr - (unsigned long)ioc->res_map) << 3)
321 + bitshiftcnt;
322}
316 323
317/** 324/**
318 * sba_search_bitmap - find free space in IO PDIR resource bitmap 325 * sba_search_bitmap - find free space in IO PDIR resource bitmap
@@ -324,19 +331,36 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
324 * Cool perf optimization: search for log2(size) bits at a time. 331 * Cool perf optimization: search for log2(size) bits at a time.
325 */ 332 */
326static SBA_INLINE unsigned long 333static SBA_INLINE unsigned long
327sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted) 334sba_search_bitmap(struct ioc *ioc, struct device *dev,
335 unsigned long bits_wanted)
328{ 336{
329 unsigned long *res_ptr = ioc->res_hint; 337 unsigned long *res_ptr = ioc->res_hint;
330 unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]); 338 unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
331 unsigned long pide = ~0UL; 339 unsigned long pide = ~0UL, tpide;
340 unsigned long boundary_size;
341 unsigned long shift;
342 int ret;
343
344 boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, 1 << IOVP_SHIFT);
345 boundary_size >>= IOVP_SHIFT;
346
347#if defined(ZX1_SUPPORT)
348 BUG_ON(ioc->ibase & ~IOVP_MASK);
349 shift = ioc->ibase >> IOVP_SHIFT;
350#else
351 shift = 0;
352#endif
332 353
333 if (bits_wanted > (BITS_PER_LONG/2)) { 354 if (bits_wanted > (BITS_PER_LONG/2)) {
334 /* Search word at a time - no mask needed */ 355 /* Search word at a time - no mask needed */
335 for(; res_ptr < res_end; ++res_ptr) { 356 for(; res_ptr < res_end; ++res_ptr) {
336 if (*res_ptr == 0) { 357 tpide = ptr_to_pide(ioc, res_ptr, 0);
358 ret = iommu_is_span_boundary(tpide, bits_wanted,
359 shift,
360 boundary_size);
361 if ((*res_ptr == 0) && !ret) {
337 *res_ptr = RESMAP_MASK(bits_wanted); 362 *res_ptr = RESMAP_MASK(bits_wanted);
338 pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); 363 pide = tpide;
339 pide <<= 3; /* convert to bit address */
340 break; 364 break;
341 } 365 }
342 } 366 }
@@ -365,11 +389,13 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
365 { 389 {
366 DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); 390 DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr);
367 WARN_ON(mask == 0); 391 WARN_ON(mask == 0);
368 if(((*res_ptr) & mask) == 0) { 392 tpide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
393 ret = iommu_is_span_boundary(tpide, bits_wanted,
394 shift,
395 boundary_size);
396 if ((((*res_ptr) & mask) == 0) && !ret) {
369 *res_ptr |= mask; /* mark resources busy! */ 397 *res_ptr |= mask; /* mark resources busy! */
370 pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); 398 pide = tpide;
371 pide <<= 3; /* convert to bit address */
372 pide += bitshiftcnt;
373 break; 399 break;
374 } 400 }
375 mask >>= o; 401 mask >>= o;
@@ -412,9 +438,9 @@ sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
412#endif 438#endif
413 unsigned long pide; 439 unsigned long pide;
414 440
415 pide = sba_search_bitmap(ioc, pages_needed); 441 pide = sba_search_bitmap(ioc, dev, pages_needed);
416 if (pide >= (ioc->res_size << 3)) { 442 if (pide >= (ioc->res_size << 3)) {
417 pide = sba_search_bitmap(ioc, pages_needed); 443 pide = sba_search_bitmap(ioc, dev, pages_needed);
418 if (pide >= (ioc->res_size << 3)) 444 if (pide >= (ioc->res_size << 3))
419 panic("%s: I/O MMU @ %p is out of mapping resources\n", 445 panic("%s: I/O MMU @ %p is out of mapping resources\n",
420 __FILE__, ioc->ioc_hpa); 446 __FILE__, ioc->ioc_hpa);