aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/parisc/sba_iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/parisc/sba_iommu.c')
-rw-r--r--drivers/parisc/sba_iommu.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index d06627c3f353..bdbe780e21c5 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((unsigned long long)dma_get_seg_boundary(dev) + 1,
345 1ULL << IOVP_SHIFT) >> 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;
@@ -404,7 +430,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
404 * resource bit map. 430 * resource bit map.
405 */ 431 */
406static int 432static int
407sba_alloc_range(struct ioc *ioc, size_t size) 433sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
408{ 434{
409 unsigned int pages_needed = size >> IOVP_SHIFT; 435 unsigned int pages_needed = size >> IOVP_SHIFT;
410#ifdef SBA_COLLECT_STATS 436#ifdef SBA_COLLECT_STATS
@@ -412,9 +438,9 @@ sba_alloc_range(struct ioc *ioc, 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);
@@ -710,7 +736,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
710 ioc->msingle_calls++; 736 ioc->msingle_calls++;
711 ioc->msingle_pages += size >> IOVP_SHIFT; 737 ioc->msingle_pages += size >> IOVP_SHIFT;
712#endif 738#endif
713 pide = sba_alloc_range(ioc, size); 739 pide = sba_alloc_range(ioc, dev, size);
714 iovp = (dma_addr_t) pide << IOVP_SHIFT; 740 iovp = (dma_addr_t) pide << IOVP_SHIFT;
715 741
716 DBG_RUN("%s() 0x%p -> 0x%lx\n", 742 DBG_RUN("%s() 0x%p -> 0x%lx\n",