aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/hp/common/sba_iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/hp/common/sba_iommu.c')
-rw-r--r--arch/ia64/hp/common/sba_iommu.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 523eae6d3e49..9409de5c9441 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -35,6 +35,7 @@
35#include <linux/nodemask.h> 35#include <linux/nodemask.h>
36#include <linux/bitops.h> /* hweight64() */ 36#include <linux/bitops.h> /* hweight64() */
37#include <linux/crash_dump.h> 37#include <linux/crash_dump.h>
38#include <linux/iommu-helper.h>
38 39
39#include <asm/delay.h> /* ia64_get_itc() */ 40#include <asm/delay.h> /* ia64_get_itc() */
40#include <asm/io.h> 41#include <asm/io.h>
@@ -460,6 +461,13 @@ get_iovp_order (unsigned long size)
460 return order; 461 return order;
461} 462}
462 463
464static unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr,
465 unsigned int bitshiftcnt)
466{
467 return (((unsigned long)res_ptr - (unsigned long)ioc->res_map) << 3)
468 + bitshiftcnt;
469}
470
463/** 471/**
464 * sba_search_bitmap - find free space in IO PDIR resource bitmap 472 * sba_search_bitmap - find free space in IO PDIR resource bitmap
465 * @ioc: IO MMU structure which owns the pdir we are interested in. 473 * @ioc: IO MMU structure which owns the pdir we are interested in.
@@ -471,15 +479,25 @@ get_iovp_order (unsigned long size)
471 * Cool perf optimization: search for log2(size) bits at a time. 479 * Cool perf optimization: search for log2(size) bits at a time.
472 */ 480 */
473static SBA_INLINE unsigned long 481static SBA_INLINE unsigned long
474sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint) 482sba_search_bitmap(struct ioc *ioc, struct device *dev,
483 unsigned long bits_wanted, int use_hint)
475{ 484{
476 unsigned long *res_ptr; 485 unsigned long *res_ptr;
477 unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]); 486 unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
478 unsigned long flags, pide = ~0UL; 487 unsigned long flags, pide = ~0UL, tpide;
488 unsigned long boundary_size;
489 unsigned long shift;
490 int ret;
479 491
480 ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0); 492 ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
481 ASSERT(res_ptr < res_end); 493 ASSERT(res_ptr < res_end);
482 494
495 boundary_size = (unsigned long long)dma_get_seg_boundary(dev) + 1;
496 boundary_size = ALIGN(boundary_size, 1ULL << iovp_shift) >> iovp_shift;
497
498 BUG_ON(ioc->ibase & ~iovp_mask);
499 shift = ioc->ibase >> iovp_shift;
500
483 spin_lock_irqsave(&ioc->res_lock, flags); 501 spin_lock_irqsave(&ioc->res_lock, flags);
484 502
485 /* Allow caller to force a search through the entire resource space */ 503 /* Allow caller to force a search through the entire resource space */
@@ -504,9 +522,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
504 if (likely(*res_ptr != ~0UL)) { 522 if (likely(*res_ptr != ~0UL)) {
505 bitshiftcnt = ffz(*res_ptr); 523 bitshiftcnt = ffz(*res_ptr);
506 *res_ptr |= (1UL << bitshiftcnt); 524 *res_ptr |= (1UL << bitshiftcnt);
507 pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); 525 pide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
508 pide <<= 3; /* convert to bit address */
509 pide += bitshiftcnt;
510 ioc->res_bitshift = bitshiftcnt + bits_wanted; 526 ioc->res_bitshift = bitshiftcnt + bits_wanted;
511 goto found_it; 527 goto found_it;
512 } 528 }
@@ -535,11 +551,13 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
535 DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); 551 DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr);
536 ASSERT(0 != mask); 552 ASSERT(0 != mask);
537 for (; mask ; mask <<= o, bitshiftcnt += o) { 553 for (; mask ; mask <<= o, bitshiftcnt += o) {
538 if(0 == ((*res_ptr) & mask)) { 554 tpide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
555 ret = iommu_is_span_boundary(tpide, bits_wanted,
556 shift,
557 boundary_size);
558 if ((0 == ((*res_ptr) & mask)) && !ret) {
539 *res_ptr |= mask; /* mark resources busy! */ 559 *res_ptr |= mask; /* mark resources busy! */
540 pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); 560 pide = tpide;
541 pide <<= 3; /* convert to bit address */
542 pide += bitshiftcnt;
543 ioc->res_bitshift = bitshiftcnt + bits_wanted; 561 ioc->res_bitshift = bitshiftcnt + bits_wanted;
544 goto found_it; 562 goto found_it;
545 } 563 }
@@ -560,6 +578,11 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
560 end = res_end - qwords; 578 end = res_end - qwords;
561 579
562 for (; res_ptr < end; res_ptr++) { 580 for (; res_ptr < end; res_ptr++) {
581 tpide = ptr_to_pide(ioc, res_ptr, 0);
582 ret = iommu_is_span_boundary(tpide, bits_wanted,
583 shift, boundary_size);
584 if (ret)
585 goto next_ptr;
563 for (i = 0 ; i < qwords ; i++) { 586 for (i = 0 ; i < qwords ; i++) {
564 if (res_ptr[i] != 0) 587 if (res_ptr[i] != 0)
565 goto next_ptr; 588 goto next_ptr;
@@ -572,8 +595,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
572 res_ptr[i] = ~0UL; 595 res_ptr[i] = ~0UL;
573 res_ptr[i] |= RESMAP_MASK(bits); 596 res_ptr[i] |= RESMAP_MASK(bits);
574 597
575 pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); 598 pide = tpide;
576 pide <<= 3; /* convert to bit address */
577 res_ptr += qwords; 599 res_ptr += qwords;
578 ioc->res_bitshift = bits; 600 ioc->res_bitshift = bits;
579 goto found_it; 601 goto found_it;
@@ -605,7 +627,7 @@ found_it:
605 * resource bit map. 627 * resource bit map.
606 */ 628 */
607static int 629static int
608sba_alloc_range(struct ioc *ioc, size_t size) 630sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
609{ 631{
610 unsigned int pages_needed = size >> iovp_shift; 632 unsigned int pages_needed = size >> iovp_shift;
611#ifdef PDIR_SEARCH_TIMING 633#ifdef PDIR_SEARCH_TIMING
@@ -622,9 +644,9 @@ sba_alloc_range(struct ioc *ioc, size_t size)
622 /* 644 /*
623 ** "seek and ye shall find"...praying never hurts either... 645 ** "seek and ye shall find"...praying never hurts either...
624 */ 646 */
625 pide = sba_search_bitmap(ioc, pages_needed, 1); 647 pide = sba_search_bitmap(ioc, dev, pages_needed, 1);
626 if (unlikely(pide >= (ioc->res_size << 3))) { 648 if (unlikely(pide >= (ioc->res_size << 3))) {
627 pide = sba_search_bitmap(ioc, pages_needed, 0); 649 pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
628 if (unlikely(pide >= (ioc->res_size << 3))) { 650 if (unlikely(pide >= (ioc->res_size << 3))) {
629#if DELAYED_RESOURCE_CNT > 0 651#if DELAYED_RESOURCE_CNT > 0
630 unsigned long flags; 652 unsigned long flags;
@@ -653,7 +675,7 @@ sba_alloc_range(struct ioc *ioc, size_t size)
653 } 675 }
654 spin_unlock_irqrestore(&ioc->saved_lock, flags); 676 spin_unlock_irqrestore(&ioc->saved_lock, flags);
655 677
656 pide = sba_search_bitmap(ioc, pages_needed, 0); 678 pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
657 if (unlikely(pide >= (ioc->res_size << 3))) 679 if (unlikely(pide >= (ioc->res_size << 3)))
658 panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", 680 panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
659 ioc->ioc_hpa); 681 ioc->ioc_hpa);
@@ -936,7 +958,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
936 spin_unlock_irqrestore(&ioc->res_lock, flags); 958 spin_unlock_irqrestore(&ioc->res_lock, flags);
937#endif 959#endif
938 960
939 pide = sba_alloc_range(ioc, size); 961 pide = sba_alloc_range(ioc, dev, size);
940 962
941 iovp = (dma_addr_t) pide << iovp_shift; 963 iovp = (dma_addr_t) pide << iovp_shift;
942 964
@@ -1373,7 +1395,7 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
1373 dma_len = (dma_len + dma_offset + ~iovp_mask) & iovp_mask; 1395 dma_len = (dma_len + dma_offset + ~iovp_mask) & iovp_mask;
1374 ASSERT(dma_len <= DMA_CHUNK_SIZE); 1396 ASSERT(dma_len <= DMA_CHUNK_SIZE);
1375 dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG 1397 dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG
1376 | (sba_alloc_range(ioc, dma_len) << iovp_shift) 1398 | (sba_alloc_range(ioc, dev, dma_len) << iovp_shift)
1377 | dma_offset); 1399 | dma_offset);
1378 n_mappings++; 1400 n_mappings++;
1379 } 1401 }