ia64: round iommu allocations to power-of-two sizes.

Linux Kernel Mailing List <[email protected]> Fri, 02 Jul 2004 21:41:59 +0000
Newsgroups gmane.linux.kernel.commits.2-4
Message-ID <[email protected]>
ChangeSet 1.1451, 2004/07/02 15:41:59-06:00, [email protected]

	ia64: round iommu allocations to power-of-two sizes.
	
	Round IOVA allocations to power-of-two sizes to avoid
	REO/Grande defect AR2305.



 sba_iommu.c |    9 +++++++++
 1 files changed, 9 insertions(+)


diff -Nru a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
--- a/arch/ia64/hp/common/sba_iommu.c	2005-03-24 09:03:41 -08:00
+++ b/arch/ia64/hp/common/sba_iommu.c	2005-03-24 09:03:41 -08:00
@@ -447,6 +447,14 @@
 
 	ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
 	ASSERT(res_ptr < res_end);
+
+	/*
+	 * N.B.  REO/Grande defect AR2305 can cause TLB fetch timeouts
+	 * if a TLB entry is purged while in use.  sba_mark_invalid()
+	 * purges IOTLB entries in power-of-two sizes, so we also
+	 * allocate IOVA space in power-of-two sizes.
+	 */
+	bits_wanted = 1UL << get_iovp_order(bits_wanted << PAGE_SHIFT);
 	if (bits_wanted > (BITS_PER_LONG/2)) {
 		/* Search word at a time - no mask needed */
 		for(; res_ptr < res_end; ++res_ptr) {
@@ -583,6 +591,7 @@
 	unsigned long *res_ptr = (unsigned long *) &((ioc)->res_map[ridx & ~RESMAP_IDX_MASK]);
 
 	int bits_not_wanted = size >> iovp_shift;
+	bits_not_wanted = 1UL << get_iovp_order(bits_not_wanted << PAGE_SHIFT);
 
 	/* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */
 	unsigned long m = RESMAP_MASK(bits_not_wanted) << (pide & (BITS_PER_LONG - 1));