summaryrefslogtreecommitdiff
path: root/drivers/parisc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/parisc')
-rw-r--r--drivers/parisc/Kconfig5
-rw-r--r--drivers/parisc/ccio-dma.c27
-rw-r--r--drivers/parisc/iommu-helpers.h6
-rw-r--r--drivers/parisc/pdc_stable.c6
-rw-r--r--drivers/parisc/sba_iommu.c52
5 files changed, 68 insertions, 28 deletions
diff --git a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig
index 1d3b84b..553a990 100644
--- a/drivers/parisc/Kconfig
+++ b/drivers/parisc/Kconfig
@@ -103,6 +103,11 @@ config IOMMU_SBA
depends on PCI_LBA
default PCI_LBA
+config IOMMU_HELPER
+ bool
+ depends on IOMMU_SBA || IOMMU_CCIO
+ default y
+
#config PCI_EPIC
# bool "EPIC/SAGA PCI support"
# depends on PCI
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index d08b284..62db3c3 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -43,6 +43,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/scatterlist.h>
+#include <linux/iommu-helper.h>
#include <asm/byteorder.h>
#include <asm/cache.h> /* for L1_CACHE_BYTES */
@@ -302,13 +303,17 @@ static int ioc_count;
*/
#define CCIO_SEARCH_LOOP(ioc, res_idx, mask, size) \
for(; res_ptr < res_end; ++res_ptr) { \
- if(0 == (*res_ptr & mask)) { \
- *res_ptr |= mask; \
- res_idx = (unsigned int)((unsigned long)res_ptr - (unsigned long)ioc->res_map); \
- ioc->res_hint = res_idx + (size >> 3); \
- goto resource_found; \
- } \
- }
+ int ret;\
+ unsigned int idx;\
+ idx = (unsigned int)((unsigned long)res_ptr - (unsigned long)ioc->res_map); \
+ ret = iommu_is_span_boundary(idx << 3, pages_needed, 0, boundary_size);\
+ if ((0 == (*res_ptr & mask)) && !ret) { \
+ *res_ptr |= mask; \
+ res_idx = idx;\
+ ioc->res_hint = res_idx + (size >> 3); \
+ goto resource_found; \
+ } \
+ }
#define CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, size) \
u##size *res_ptr = (u##size *)&((ioc)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \
@@ -341,10 +346,11 @@ static int ioc_count;
* of available pages for the requested size.
*/
static int
-ccio_alloc_range(struct ioc *ioc, size_t size)
+ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
{
unsigned int pages_needed = size >> IOVP_SHIFT;
unsigned int res_idx;
+ unsigned long boundary_size;
#ifdef CCIO_SEARCH_TIME
unsigned long cr_start = mfctl(16);
#endif
@@ -360,6 +366,9 @@ ccio_alloc_range(struct ioc *ioc, size_t size)
** ggg sacrifices another 710 to the computer gods.
*/
+ boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1,
+ 1ULL << IOVP_SHIFT) >> IOVP_SHIFT;
+
if (pages_needed <= 8) {
/*
* LAN traffic will not thrash the TLB IFF the same NIC
@@ -760,7 +769,7 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
ioc->msingle_pages += size >> IOVP_SHIFT;
#endif
- idx = ccio_alloc_range(ioc, size);
+ idx = ccio_alloc_range(ioc, dev, size);
iovp = (dma_addr_t)MKIOVP(idx);
pdir_start = &(ioc->pdir_base[idx]);
diff --git a/drivers/parisc/iommu-helpers.h b/drivers/parisc/iommu-helpers.h
index 97ba828..a9c46cc 100644
--- a/drivers/parisc/iommu-helpers.h
+++ b/drivers/parisc/iommu-helpers.h
@@ -96,8 +96,8 @@ iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
static inline unsigned int
iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
- struct scatterlist *startsg, int nents,
- int (*iommu_alloc_range)(struct ioc *, size_t))
+ struct scatterlist *startsg, int nents,
+ int (*iommu_alloc_range)(struct ioc *, struct device *, size_t))
{
struct scatterlist *contig_sg; /* contig chunk head */
unsigned long dma_offset, dma_len; /* start/len of DMA stream */
@@ -166,7 +166,7 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE);
sg_dma_address(contig_sg) =
PIDE_FLAG
- | (iommu_alloc_range(ioc, dma_len) << IOVP_SHIFT)
+ | (iommu_alloc_range(ioc, dev, dma_len) << IOVP_SHIFT)
| dma_offset;
n_mappings++;
}
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index de34aa9..f9f9a5f 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -829,7 +829,7 @@ static ssize_t pdcs_autoboot_write(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
- return pdcs_auto_write(kset, attr, buf, count, PF_AUTOBOOT);
+ return pdcs_auto_write(kobj, attr, buf, count, PF_AUTOBOOT);
}
/**
@@ -845,7 +845,7 @@ static ssize_t pdcs_autosearch_write(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
- return pdcs_auto_write(kset, attr, buf, count, PF_AUTOSEARCH);
+ return pdcs_auto_write(kobj, attr, buf, count, PF_AUTOSEARCH);
}
/**
@@ -1066,7 +1066,7 @@ pdc_stable_init(void)
}
/* Don't forget the root entries */
- error = sysfs_create_group(stable_kobj, pdcs_attr_group);
+ error = sysfs_create_group(stable_kobj, &pdcs_attr_group);
/* register the paths kset as a child of the stable kset */
paths_kset = kset_create_and_add("paths", NULL, stable_kobj);
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index d06627c..8c4d2c1 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -29,6 +29,7 @@
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/scatterlist.h>
+#include <linux/iommu-helper.h>
#include <asm/byteorder.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_IDX_MASK (sizeof(unsigned long) - 1)
+static 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
@@ -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.
*/
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_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((unsigned long long)dma_get_seg_boundary(dev) + 1,
+ 1ULL << IOVP_SHIFT) >> 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)) {
/* Search word at a time - no mask needed */
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);
- pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
- pide <<= 3; /* convert to bit address */
+ pide = tpide;
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);
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! */
- pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
- pide <<= 3; /* convert to bit address */
- pide += bitshiftcnt;
+ pide = tpide;
break;
}
mask >>= o;
@@ -404,7 +430,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
* resource bit map.
*/
static int
-sba_alloc_range(struct ioc *ioc, size_t size)
+sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
{
unsigned int pages_needed = size >> IOVP_SHIFT;
#ifdef SBA_COLLECT_STATS
@@ -412,9 +438,9 @@ sba_alloc_range(struct ioc *ioc, size_t size)
#endif
unsigned long pide;
- pide = sba_search_bitmap(ioc, pages_needed);
+ pide = sba_search_bitmap(ioc, dev, pages_needed);
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))
panic("%s: I/O MMU @ %p is out of mapping resources\n",
__FILE__, ioc->ioc_hpa);
@@ -710,7 +736,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
ioc->msingle_calls++;
ioc->msingle_pages += size >> IOVP_SHIFT;
#endif
- pide = sba_alloc_range(ioc, size);
+ pide = sba_alloc_range(ioc, dev, size);
iovp = (dma_addr_t) pide << IOVP_SHIFT;
DBG_RUN("%s() 0x%p -> 0x%lx\n",