OMAP: iommu: create new api to set valid da range
authorGuzman Lugo, Fernando <x0095840@ti.com>
Wed, 15 Dec 2010 00:54:03 +0000 (00:54 +0000)
committerHari Kanigeri <h-kanigeri2@ti.com>
Wed, 15 Dec 2010 17:29:10 +0000 (11:29 -0600)
Some IOMMUs cannot use the whole 0x0 - 0xFFFFFFFF range.
With this new API the valid range can be set.

Signed-off-by: Fernando Guzman Lugo <x0095840@ti.com>
Acked-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
arch/arm/mach-omap2/omap-iommu.c
arch/arm/plat-omap/include/plat/iommu.h
arch/arm/plat-omap/iommu.c
arch/arm/plat-omap/iovmm.c

index f5a1aad..6be548c 100644 (file)
@@ -33,6 +33,8 @@ static struct iommu_device omap3_devices[] = {
                        .name = "isp",
                        .nr_tlb_entries = 8,
                        .clk_name = "cam_ick",
+                       .da_start = 0x0,
+                       .da_end = 0xFFFFF000,
                },
        },
 #if defined(CONFIG_MPU_BRIDGE_IOMMU)
@@ -43,6 +45,8 @@ static struct iommu_device omap3_devices[] = {
                        .name = "iva2",
                        .nr_tlb_entries = 32,
                        .clk_name = "iva2_ck",
+                       .da_start = 0x11000000,
+                       .da_end = 0xFFFFF000,
                },
        },
 #endif
@@ -64,6 +68,8 @@ static struct iommu_device omap4_devices[] = {
                        .name = "ducati",
                        .nr_tlb_entries = 32,
                        .clk_name = "ducati_ick",
+                       .da_start = 0x0,
+                       .da_end = 0xFFFFF000,
                },
        },
 #if defined(CONFIG_MPU_TESLA_IOMMU)
@@ -74,6 +80,8 @@ static struct iommu_device omap4_devices[] = {
                        .name = "tesla",
                        .nr_tlb_entries = 32,
                        .clk_name = "tesla_ick",
+                       .da_start = 0x0,
+                       .da_end = 0xFFFFF000,
                },
        },
 #endif
index 33c7d41..69230d6 100644 (file)
@@ -50,6 +50,8 @@ struct iommu {
        int (*isr)(struct iommu *obj);
 
        void *ctx; /* iommu context: registres saved area */
+       u32 da_start;
+       u32 da_end;
 };
 
 struct cr_regs {
@@ -103,6 +105,8 @@ struct iommu_platform_data {
        const char *name;
        const char *clk_name;
        const int nr_tlb_entries;
+       u32 da_start;
+       u32 da_end;
 };
 
 #if defined(CONFIG_ARCH_OMAP1)
@@ -152,6 +156,7 @@ extern void flush_iotlb_all(struct iommu *obj);
 extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
 extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
 
+extern int iommu_set_da_range(struct iommu *obj, u32 start, u32 end);
 extern struct iommu *iommu_get(const char *name);
 extern void iommu_put(struct iommu *obj);
 
index 6cd151b..b1107c0 100644 (file)
@@ -830,6 +830,28 @@ static int device_match_by_alias(struct device *dev, void *data)
 }
 
 /**
+ * iommu_set_da_range - Set a valid device address range
+ * @obj:               target iommu
+ * @start              Start of valid range
+ * @end                        End of valid range
+ **/
+int iommu_set_da_range(struct iommu *obj, u32 start, u32 end)
+{
+
+       if (!obj)
+               return -EFAULT;
+
+       if (end < start || !PAGE_ALIGN(start | end))
+               return -EINVAL;
+
+       obj->da_start = start;
+       obj->da_end = end;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_set_da_range);
+
+/**
  * iommu_get - Get iommu handler
  * @name:      target iommu name
  **/
@@ -922,6 +944,8 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
        obj->name = pdata->name;
        obj->dev = &pdev->dev;
        obj->ctx = (void *)obj + sizeof(*obj);
+       obj->da_start = pdata->da_start;
+       obj->da_end = pdata->da_end;
 
        mutex_init(&obj->iommu_lock);
        mutex_init(&obj->mmap_lock);
index fa6e643..6dc1296 100644 (file)
@@ -280,13 +280,14 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
        alignement = PAGE_SIZE;
 
        if (flags & IOVMF_DA_ANON) {
-               /*
-                * Reserve the first page for NULL
-                */
-               start = PAGE_SIZE;
+               start = obj->da_start;
+
                if (flags & IOVMF_LINEAR)
                        alignement = iopgsz_max(bytes);
                start = roundup(start, alignement);
+       } else if (start < obj->da_start || start > obj->da_end ||
+                                       obj->da_end - start < bytes) {
+               return ERR_PTR(-EINVAL);
        }
 
        tmp = NULL;
@@ -299,16 +300,16 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
                if (prev_end > start)
                        break;
 
-               if (start + bytes <= tmp->da_start)
+               if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
                        goto found;
 
-               if (flags & IOVMF_DA_ANON)
+               if (tmp->da_end >= start && flags & IOVMF_DA_ANON)
                        start = roundup(tmp->da_end + 1, alignement);
 
                prev_end = tmp->da_end;
        }
 
-       if ((start >= prev_end) && (ULONG_MAX - start + 1 >= bytes))
+       if ((start >= prev_end) && (obj->da_end - start >= bytes))
                goto found;
 
        dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",