|
@@ -29,6 +29,7 @@
|
|
#include <linux/string.h>
|
|
#include <linux/string.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/scatterlist.h>
|
|
|
|
+#include <linux/iommu-helper.h>
|
|
|
|
|
|
#include <asm/byteorder.h>
|
|
#include <asm/byteorder.h>
|
|
#include <asm/io.h>
|
|
#include <asm/io.h>
|
|
@@ -313,6 +314,12 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
|
|
#define RESMAP_MASK(n) (~0UL << (BITS_PER_LONG - (n)))
|
|
#define RESMAP_MASK(n) (~0UL << (BITS_PER_LONG - (n)))
|
|
#define RESMAP_IDX_MASK (sizeof(unsigned long) - 1)
|
|
#define RESMAP_IDX_MASK (sizeof(unsigned long) - 1)
|
|
|
|
|
|
|
|
+unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr,
|
|
|
|
+ unsigned int bitshiftcnt)
|
|
|
|
+{
|
|
|
|
+ return (((unsigned long)res_ptr - (unsigned long)ioc->res_map) << 3)
|
|
|
|
+ + bitshiftcnt;
|
|
|
|
+}
|
|
|
|
|
|
/**
|
|
/**
|
|
* sba_search_bitmap - find free space in IO PDIR resource bitmap
|
|
* 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)
|
|
* Cool perf optimization: search for log2(size) bits at a time.
|
|
* Cool perf optimization: search for log2(size) bits at a time.
|
|
*/
|
|
*/
|
|
static SBA_INLINE unsigned long
|
|
static SBA_INLINE unsigned long
|
|
-sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
|
|
|
|
|
|
+sba_search_bitmap(struct ioc *ioc, struct device *dev,
|
|
|
|
+ unsigned long bits_wanted)
|
|
{
|
|
{
|
|
unsigned long *res_ptr = ioc->res_hint;
|
|
unsigned long *res_ptr = ioc->res_hint;
|
|
unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
|
|
unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
|
|
- unsigned long pide = ~0UL;
|
|
|
|
|
|
+ unsigned long pide = ~0UL, tpide;
|
|
|
|
+ unsigned long boundary_size;
|
|
|
|
+ unsigned long shift;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, 1 << IOVP_SHIFT);
|
|
|
|
+ boundary_size >>= IOVP_SHIFT;
|
|
|
|
+
|
|
|
|
+#if defined(ZX1_SUPPORT)
|
|
|
|
+ BUG_ON(ioc->ibase & ~IOVP_MASK);
|
|
|
|
+ shift = ioc->ibase >> IOVP_SHIFT;
|
|
|
|
+#else
|
|
|
|
+ shift = 0;
|
|
|
|
+#endif
|
|
|
|
|
|
if (bits_wanted > (BITS_PER_LONG/2)) {
|
|
if (bits_wanted > (BITS_PER_LONG/2)) {
|
|
/* Search word at a time - no mask needed */
|
|
/* Search word at a time - no mask needed */
|
|
for(; res_ptr < res_end; ++res_ptr) {
|
|
for(; res_ptr < res_end; ++res_ptr) {
|
|
- if (*res_ptr == 0) {
|
|
|
|
|
|
+ tpide = ptr_to_pide(ioc, res_ptr, 0);
|
|
|
|
+ ret = iommu_is_span_boundary(tpide, bits_wanted,
|
|
|
|
+ shift,
|
|
|
|
+ boundary_size);
|
|
|
|
+ if ((*res_ptr == 0) && !ret) {
|
|
*res_ptr = RESMAP_MASK(bits_wanted);
|
|
*res_ptr = RESMAP_MASK(bits_wanted);
|
|
- pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
|
|
|
|
- pide <<= 3; /* convert to bit address */
|
|
|
|
|
|
+ pide = tpide;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -365,11 +389,13 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
|
|
{
|
|
{
|
|
DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr);
|
|
DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr);
|
|
WARN_ON(mask == 0);
|
|
WARN_ON(mask == 0);
|
|
- if(((*res_ptr) & mask) == 0) {
|
|
|
|
|
|
+ tpide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
|
|
|
|
+ ret = iommu_is_span_boundary(tpide, bits_wanted,
|
|
|
|
+ shift,
|
|
|
|
+ boundary_size);
|
|
|
|
+ if ((((*res_ptr) & mask) == 0) && !ret) {
|
|
*res_ptr |= mask; /* mark resources busy! */
|
|
*res_ptr |= mask; /* mark resources busy! */
|
|
- pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
|
|
|
|
- pide <<= 3; /* convert to bit address */
|
|
|
|
- pide += bitshiftcnt;
|
|
|
|
|
|
+ pide = tpide;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
mask >>= o;
|
|
mask >>= o;
|
|
@@ -412,9 +438,9 @@ sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
|
|
#endif
|
|
#endif
|
|
unsigned long pide;
|
|
unsigned long pide;
|
|
|
|
|
|
- pide = sba_search_bitmap(ioc, pages_needed);
|
|
|
|
|
|
+ pide = sba_search_bitmap(ioc, dev, pages_needed);
|
|
if (pide >= (ioc->res_size << 3)) {
|
|
if (pide >= (ioc->res_size << 3)) {
|
|
- pide = sba_search_bitmap(ioc, pages_needed);
|
|
|
|
|
|
+ pide = sba_search_bitmap(ioc, dev, pages_needed);
|
|
if (pide >= (ioc->res_size << 3))
|
|
if (pide >= (ioc->res_size << 3))
|
|
panic("%s: I/O MMU @ %p is out of mapping resources\n",
|
|
panic("%s: I/O MMU @ %p is out of mapping resources\n",
|
|
__FILE__, ioc->ioc_hpa);
|
|
__FILE__, ioc->ioc_hpa);
|