Commit f626b52d authored by Ohad Ben-Cohen's avatar Ohad Ben-Cohen Committed by Joerg Roedel

omap: iommu: migrate to the generic IOMMU API

Migrate OMAP's iommu driver to the generic IOMMU API, so users can stay
generic, and any generic IOMMU functionality can be developed once
in the generic framework.

Migrate omap's iovmm (virtual memory manager) to the generic IOMMU API,
and adapt omap3isp as needed, so the latter won't break.

The plan is to eventually remove iovmm completely by replacing it
with the (upcoming) IOMMU-based DMA-API.

Tested on OMAP3 (with omap3isp) and OMAP4 (with rpmsg/remoteproc).
Signed-off-by: default avatarOhad Ben-Cohen <ohad@wizery.com>
Acked-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: default avatarHiroshi DOYU <Hiroshi.DOYU@nokia.com>
Acked-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent fcb8ce5c
...@@ -132,8 +132,10 @@ config OMAP_MBOX_KFIFO_SIZE ...@@ -132,8 +132,10 @@ config OMAP_MBOX_KFIFO_SIZE
This can also be changed at runtime (via the mbox_kfifo_size This can also be changed at runtime (via the mbox_kfifo_size
module parameter). module parameter).
#can't be tristate; iommu api doesn't support un-registration
config OMAP_IOMMU config OMAP_IOMMU
tristate bool
select IOMMU_API
config OMAP_IOMMU_DEBUG config OMAP_IOMMU_DEBUG
tristate "Export OMAP IOMMU internals in DebugFS" tristate "Export OMAP IOMMU internals in DebugFS"
......
...@@ -34,7 +34,7 @@ struct iommu { ...@@ -34,7 +34,7 @@ struct iommu {
void *isr_priv; void *isr_priv;
unsigned int refcount; unsigned int refcount;
struct mutex iommu_lock; /* global for this whole object */ spinlock_t iommu_lock; /* global for this whole object */
/* /*
* We don't change iopgd for a situation like pgd for a task, * We don't change iopgd for a situation like pgd for a task,
...@@ -167,8 +167,6 @@ extern void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, ...@@ -167,8 +167,6 @@ extern void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd,
extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova); 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 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);
extern int iommu_set_isr(const char *name, extern int iommu_set_isr(const char *name,
int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
void *priv), void *priv),
...@@ -185,5 +183,6 @@ extern int foreach_iommu_device(void *data, ...@@ -185,5 +183,6 @@ extern int foreach_iommu_device(void *data,
extern ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len); extern ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len);
extern size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t len); extern size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t len);
struct device *omap_find_iommu_device(const char *name);
#endif /* __MACH_IOMMU_H */ #endif /* __MACH_IOMMU_H */
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#ifndef __IOMMU_MMAP_H #ifndef __IOMMU_MMAP_H
#define __IOMMU_MMAP_H #define __IOMMU_MMAP_H
#include <linux/iommu.h>
struct iovm_struct { struct iovm_struct {
struct iommu *iommu; /* iommu object which this belongs to */ struct iommu *iommu; /* iommu object which this belongs to */
u32 da_start; /* area definition */ u32 da_start; /* area definition */
...@@ -71,18 +73,21 @@ struct iovm_struct { ...@@ -71,18 +73,21 @@ struct iovm_struct {
extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da); extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da);
extern u32 iommu_vmap(struct iommu *obj, u32 da, extern u32 iommu_vmap(struct iommu_domain *domain, struct iommu *obj, u32 da,
const struct sg_table *sgt, u32 flags); const struct sg_table *sgt, u32 flags);
extern struct sg_table *iommu_vunmap(struct iommu *obj, u32 da); extern struct sg_table *iommu_vunmap(struct iommu_domain *domain,
extern u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, struct iommu *obj, u32 da);
u32 flags); extern u32 iommu_vmalloc(struct iommu_domain *domain, struct iommu *obj,
extern void iommu_vfree(struct iommu *obj, const u32 da); u32 da, size_t bytes, u32 flags);
extern u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes, extern void iommu_vfree(struct iommu_domain *domain, struct iommu *obj,
u32 flags); const u32 da);
extern void iommu_kunmap(struct iommu *obj, u32 da); extern u32 iommu_kmap(struct iommu_domain *domain, struct iommu *obj, u32 da,
extern u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 pa, size_t bytes, u32 flags);
u32 flags); extern void iommu_kunmap(struct iommu_domain *domain, struct iommu *obj,
extern void iommu_kfree(struct iommu *obj, u32 da); u32 da);
extern u32 iommu_kmalloc(struct iommu_domain *domain, struct iommu *obj,
u32 da, size_t bytes, u32 flags);
extern void iommu_kfree(struct iommu_domain *domain, struct iommu *obj, u32 da);
extern void *da_to_va(struct iommu *obj, u32 da); extern void *da_to_va(struct iommu *obj, u32 da);
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/iommu.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
...@@ -30,6 +33,19 @@ ...@@ -30,6 +33,19 @@
(__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \ (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \
__i++) __i++)
/**
* struct omap_iommu_domain - omap iommu domain
* @pgtable: the page table
* @iommu_dev: an omap iommu device attached to this domain. only a single
* iommu device can be attached for now.
* @lock: domain lock, should be taken when attaching/detaching
*/
struct omap_iommu_domain {
u32 *pgtable;
struct iommu *iommu_dev;
spinlock_t lock;
};
/* accommodate the difference between omap1 and omap2/3 */ /* accommodate the difference between omap1 and omap2/3 */
static const struct iommu_functions *arch_iommu; static const struct iommu_functions *arch_iommu;
...@@ -852,35 +868,55 @@ int iommu_set_da_range(struct iommu *obj, u32 start, u32 end) ...@@ -852,35 +868,55 @@ int iommu_set_da_range(struct iommu *obj, u32 start, u32 end)
EXPORT_SYMBOL_GPL(iommu_set_da_range); EXPORT_SYMBOL_GPL(iommu_set_da_range);
/** /**
* iommu_get - Get iommu handler * omap_find_iommu_device() - find an omap iommu device by name
* @name: target iommu name * @name: name of the iommu device
*
* The generic iommu API requires the caller to provide the device
* he wishes to attach to a certain iommu domain.
*
* Drivers generally should not bother with this as it should just
* be taken care of by the DMA-API using dev_archdata.
*
* This function is provided as an interim solution until the latter
* materializes, and omap3isp is fully migrated to the DMA-API.
*/
struct device *omap_find_iommu_device(const char *name)
{
return driver_find_device(&omap_iommu_driver.driver, NULL,
(void *)name,
device_match_by_alias);
}
EXPORT_SYMBOL_GPL(omap_find_iommu_device);
/**
* omap_iommu_attach() - attach iommu device to an iommu domain
* @dev: target omap iommu device
* @iopgd: page table
**/ **/
struct iommu *iommu_get(const char *name) static struct iommu *omap_iommu_attach(struct device *dev, u32 *iopgd)
{ {
int err = -ENOMEM; int err = -ENOMEM;
struct device *dev; struct iommu *obj = to_iommu(dev);
struct iommu *obj;
dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
device_match_by_alias);
if (!dev)
return ERR_PTR(-ENODEV);
obj = to_iommu(dev);
mutex_lock(&obj->iommu_lock); spin_lock(&obj->iommu_lock);
if (obj->refcount++ == 0) { /* an iommu device can only be attached once */
err = iommu_enable(obj); if (++obj->refcount > 1) {
if (err) dev_err(dev, "%s: already attached!\n", obj->name);
goto err_enable; err = -EBUSY;
flush_iotlb_all(obj); goto err_enable;
} }
obj->iopgd = iopgd;
err = iommu_enable(obj);
if (err)
goto err_enable;
flush_iotlb_all(obj);
if (!try_module_get(obj->owner)) if (!try_module_get(obj->owner))
goto err_module; goto err_module;
mutex_unlock(&obj->iommu_lock); spin_unlock(&obj->iommu_lock);
dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
return obj; return obj;
...@@ -890,32 +926,32 @@ struct iommu *iommu_get(const char *name) ...@@ -890,32 +926,32 @@ struct iommu *iommu_get(const char *name)
iommu_disable(obj); iommu_disable(obj);
err_enable: err_enable:
obj->refcount--; obj->refcount--;
mutex_unlock(&obj->iommu_lock); spin_unlock(&obj->iommu_lock);
return ERR_PTR(err); return ERR_PTR(err);
} }
EXPORT_SYMBOL_GPL(iommu_get);
/** /**
* iommu_put - Put back iommu handler * omap_iommu_detach - release iommu device
* @obj: target iommu * @obj: target iommu
**/ **/
void iommu_put(struct iommu *obj) static void omap_iommu_detach(struct iommu *obj)
{ {
if (!obj || IS_ERR(obj)) if (!obj || IS_ERR(obj))
return; return;
mutex_lock(&obj->iommu_lock); spin_lock(&obj->iommu_lock);
if (--obj->refcount == 0) if (--obj->refcount == 0)
iommu_disable(obj); iommu_disable(obj);
module_put(obj->owner); module_put(obj->owner);
mutex_unlock(&obj->iommu_lock); obj->iopgd = NULL;
spin_unlock(&obj->iommu_lock);
dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
} }
EXPORT_SYMBOL_GPL(iommu_put);
int iommu_set_isr(const char *name, int iommu_set_isr(const char *name,
int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
...@@ -950,7 +986,6 @@ EXPORT_SYMBOL_GPL(iommu_set_isr); ...@@ -950,7 +986,6 @@ EXPORT_SYMBOL_GPL(iommu_set_isr);
static int __devinit omap_iommu_probe(struct platform_device *pdev) static int __devinit omap_iommu_probe(struct platform_device *pdev)
{ {
int err = -ENODEV; int err = -ENODEV;
void *p;
int irq; int irq;
struct iommu *obj; struct iommu *obj;
struct resource *res; struct resource *res;
...@@ -974,7 +1009,7 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) ...@@ -974,7 +1009,7 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
obj->da_start = pdata->da_start; obj->da_start = pdata->da_start;
obj->da_end = pdata->da_end; obj->da_end = pdata->da_end;
mutex_init(&obj->iommu_lock); spin_lock_init(&obj->iommu_lock);
mutex_init(&obj->mmap_lock); mutex_init(&obj->mmap_lock);
spin_lock_init(&obj->page_table_lock); spin_lock_init(&obj->page_table_lock);
INIT_LIST_HEAD(&obj->mmap); INIT_LIST_HEAD(&obj->mmap);
...@@ -1009,22 +1044,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) ...@@ -1009,22 +1044,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
goto err_irq; goto err_irq;
platform_set_drvdata(pdev, obj); platform_set_drvdata(pdev, obj);
p = (void *)__get_free_pages(GFP_KERNEL, get_order(IOPGD_TABLE_SIZE));
if (!p) {
err = -ENOMEM;
goto err_pgd;
}
memset(p, 0, IOPGD_TABLE_SIZE);
clean_dcache_area(p, IOPGD_TABLE_SIZE);
obj->iopgd = p;
BUG_ON(!IS_ALIGNED((unsigned long)obj->iopgd, IOPGD_TABLE_SIZE));
dev_info(&pdev->dev, "%s registered\n", obj->name); dev_info(&pdev->dev, "%s registered\n", obj->name);
return 0; return 0;
err_pgd:
free_irq(irq, obj);
err_irq: err_irq:
iounmap(obj->regbase); iounmap(obj->regbase);
err_ioremap: err_ioremap:
...@@ -1045,7 +1067,6 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev) ...@@ -1045,7 +1067,6 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
iopgtable_clear_entry_all(obj); iopgtable_clear_entry_all(obj);
free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE));
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
free_irq(irq, obj); free_irq(irq, obj);
...@@ -1072,6 +1093,207 @@ static void iopte_cachep_ctor(void *iopte) ...@@ -1072,6 +1093,207 @@ static void iopte_cachep_ctor(void *iopte)
clean_dcache_area(iopte, IOPTE_TABLE_SIZE); clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
} }
static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
phys_addr_t pa, int order, int prot)
{
struct omap_iommu_domain *omap_domain = domain->priv;
struct iommu *oiommu = omap_domain->iommu_dev;
struct device *dev = oiommu->dev;
size_t bytes = PAGE_SIZE << order;
struct iotlb_entry e;
int omap_pgsz;
u32 ret, flags;
/* we only support mapping a single iommu page for now */
omap_pgsz = bytes_to_iopgsz(bytes);
if (omap_pgsz < 0) {
dev_err(dev, "invalid size to map: %d\n", bytes);
return -EINVAL;
}
dev_dbg(dev, "mapping da 0x%lx to pa 0x%x size 0x%x\n", da, pa, bytes);
flags = omap_pgsz | prot;
iotlb_init_entry(&e, da, pa, flags);
ret = iopgtable_store_entry(oiommu, &e);
if (ret) {
dev_err(dev, "iopgtable_store_entry failed: %d\n", ret);
return ret;
}
return 0;
}
static int omap_iommu_unmap(struct iommu_domain *domain, unsigned long da,
int order)
{
struct omap_iommu_domain *omap_domain = domain->priv;
struct iommu *oiommu = omap_domain->iommu_dev;
struct device *dev = oiommu->dev;
size_t bytes = PAGE_SIZE << order;
size_t ret;
dev_dbg(dev, "unmapping da 0x%lx size 0x%x\n", da, bytes);
ret = iopgtable_clear_entry(oiommu, da);
if (ret != bytes) {
dev_err(dev, "entry @ 0x%lx was %d; not %d\n", da, ret, bytes);
return -EINVAL;
}
return 0;
}
static int
omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
{
struct omap_iommu_domain *omap_domain = domain->priv;
struct iommu *oiommu;
int ret = 0;
spin_lock(&omap_domain->lock);
/* only a single device is supported per domain for now */
if (omap_domain->iommu_dev) {
dev_err(dev, "iommu domain is already attached\n");
ret = -EBUSY;
goto out;
}
/* get a handle to and enable the omap iommu */
oiommu = omap_iommu_attach(dev, omap_domain->pgtable);
if (IS_ERR(oiommu)) {
ret = PTR_ERR(oiommu);
dev_err(dev, "can't get omap iommu: %d\n", ret);
goto out;
}
omap_domain->iommu_dev = oiommu;
out:
spin_unlock(&omap_domain->lock);
return ret;
}
static void omap_iommu_detach_dev(struct iommu_domain *domain,
struct device *dev)
{
struct omap_iommu_domain *omap_domain = domain->priv;
struct iommu *oiommu = to_iommu(dev);
spin_lock(&omap_domain->lock);
/* only a single device is supported per domain for now */
if (omap_domain->iommu_dev != oiommu) {
dev_err(dev, "invalid iommu device\n");
goto out;
}
iopgtable_clear_entry_all(oiommu);
omap_iommu_detach(oiommu);
omap_domain->iommu_dev = NULL;
out:
spin_unlock(&omap_domain->lock);
}
static int omap_iommu_domain_init(struct iommu_domain *domain)
{
struct omap_iommu_domain *omap_domain;
omap_domain = kzalloc(sizeof(*omap_domain), GFP_KERNEL);
if (!omap_domain) {
pr_err("kzalloc failed\n");
goto out;
}
omap_domain->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_KERNEL);
if (!omap_domain->pgtable) {
pr_err("kzalloc failed\n");
goto fail_nomem;
}
/*
* should never fail, but please keep this around to ensure
* we keep the hardware happy
*/
BUG_ON(!IS_ALIGNED((long)omap_domain->pgtable, IOPGD_TABLE_SIZE));
clean_dcache_area(omap_domain->pgtable, IOPGD_TABLE_SIZE);
spin_lock_init(&omap_domain->lock);
domain->priv = omap_domain;
return 0;
fail_nomem:
kfree(omap_domain);
out:
return -ENOMEM;
}
/* assume device was already detached */
static void omap_iommu_domain_destroy(struct iommu_domain *domain)
{
struct omap_iommu_domain *omap_domain = domain->priv;
domain->priv = NULL;
kfree(omap_domain->pgtable);
kfree(omap_domain);
}
static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long da)
{
struct omap_iommu_domain *omap_domain = domain->priv;
struct iommu *oiommu = omap_domain->iommu_dev;
struct device *dev = oiommu->dev;
u32 *pgd, *pte;
phys_addr_t ret = 0;
iopgtable_lookup_entry(oiommu, da, &pgd, &pte);
if (pte) {
if (iopte_is_small(*pte))
ret = omap_iommu_translate(*pte, da, IOPTE_MASK);
else if (iopte_is_large(*pte))
ret = omap_iommu_translate(*pte, da, IOLARGE_MASK);
else
dev_err(dev, "bogus pte 0x%x", *pte);
} else {
if (iopgd_is_section(*pgd))
ret = omap_iommu_translate(*pgd, da, IOSECTION_MASK);
else if (iopgd_is_super(*pgd))
ret = omap_iommu_translate(*pgd, da, IOSUPER_MASK);
else
dev_err(dev, "bogus pgd 0x%x", *pgd);
}
return ret;
}
static int omap_iommu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap)
{
return 0;
}
static struct iommu_ops omap_iommu_ops = {
.domain_init = omap_iommu_domain_init,
.domain_destroy = omap_iommu_domain_destroy,
.attach_dev = omap_iommu_attach_dev,
.detach_dev = omap_iommu_detach_dev,
.map = omap_iommu_map,
.unmap = omap_iommu_unmap,
.iova_to_phys = omap_iommu_iova_to_phys,
.domain_has_cap = omap_iommu_domain_has_cap,
};
static int __init omap_iommu_init(void) static int __init omap_iommu_init(void)
{ {
struct kmem_cache *p; struct kmem_cache *p;
...@@ -1084,6 +1306,8 @@ static int __init omap_iommu_init(void) ...@@ -1084,6 +1306,8 @@ static int __init omap_iommu_init(void)
return -ENOMEM; return -ENOMEM;
iopte_cachep = p; iopte_cachep = p;
register_iommu(&omap_iommu_ops);
return platform_driver_register(&omap_iommu_driver); return platform_driver_register(&omap_iommu_driver);
} }
module_init(omap_iommu_init); module_init(omap_iommu_init);
......
...@@ -56,6 +56,19 @@ ...@@ -56,6 +56,19 @@
#define IOPAGE_MASK IOPTE_MASK #define IOPAGE_MASK IOPTE_MASK
/**
* omap_iommu_translate() - va to pa translation
* @d: omap iommu descriptor
* @va: virtual address
* @mask: omap iommu descriptor mask
*
* va to pa translation
*/
static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
{
return (d & mask) | (va & (~mask));
}
/* /*
* some descriptor attributes. * some descriptor attributes.
*/ */
...@@ -64,10 +77,15 @@ ...@@ -64,10 +77,15 @@
#define IOPGD_SUPER (1 << 18 | 2 << 0) #define IOPGD_SUPER (1 << 18 | 2 << 0)
#define iopgd_is_table(x) (((x) & 3) == IOPGD_TABLE) #define iopgd_is_table(x) (((x) & 3) == IOPGD_TABLE)
#define iopgd_is_section(x) (((x) & (1 << 18 | 3)) == IOPGD_SECTION)
#define iopgd_is_super(x) (((x) & (1 << 18 | 3)) == IOPGD_SUPER)
#define IOPTE_SMALL (2 << 0) #define IOPTE_SMALL (2 << 0)
#define IOPTE_LARGE (1 << 0) #define IOPTE_LARGE (1 << 0)
#define iopte_is_small(x) (((x) & 2) == IOPTE_SMALL)
#define iopte_is_large(x) (((x) & 3) == IOPTE_LARGE)
/* to find an entry in a page-table-directory */ /* to find an entry in a page-table-directory */
#define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1)) #define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
#define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da)) #define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da))
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/iommu.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -453,39 +454,38 @@ static inline void sgtable_drain_kmalloc(struct sg_table *sgt) ...@@ -453,39 +454,38 @@ static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
} }
/* create 'da' <-> 'pa' mapping from 'sgt' */ /* create 'da' <-> 'pa' mapping from 'sgt' */
static int map_iovm_area(struct iommu *obj, struct iovm_struct *new, static int map_iovm_area(struct iommu_domain *domain, struct iovm_struct *new,
const struct sg_table *sgt, u32 flags) const struct sg_table *sgt, u32 flags)
{ {
int err; int err;
unsigned int i, j; unsigned int i, j;
struct scatterlist *sg; struct scatterlist *sg;
u32 da = new->da_start; u32 da = new->da_start;
int order;
if (!obj || !sgt) if (!domain || !sgt)
return -EINVAL; return -EINVAL;
BUG_ON(!sgtable_ok(sgt)); BUG_ON(!sgtable_ok(sgt));
for_each_sg(sgt->sgl, sg, sgt->nents, i) { for_each_sg(sgt->sgl, sg, sgt->nents, i) {
u32 pa; u32 pa;
int pgsz;
size_t bytes; size_t bytes;
struct iotlb_entry e;
pa = sg_phys(sg); pa = sg_phys(sg);
bytes = sg->length; bytes = sg->length;
flags &= ~IOVMF_PGSZ_MASK; flags &= ~IOVMF_PGSZ_MASK;
pgsz = bytes_to_iopgsz(bytes);
if (pgsz < 0) if (bytes_to_iopgsz(bytes) < 0)
goto err_out; goto err_out;
flags |= pgsz;
order = get_order(bytes);
pr_debug("%s: [%d] %08x %08x(%x)\n", __func__, pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
i, da, pa, bytes); i, da, pa, bytes);
iotlb_init_entry(&e, da, pa, flags); err = iommu_map(domain, da, pa, order, flags);
err = iopgtable_store_entry(obj, &e);
if (err) if (err)
goto err_out; goto err_out;
...@@ -499,9 +499,11 @@ static int map_iovm_area(struct iommu *obj, struct iovm_struct *new, ...@@ -499,9 +499,11 @@ static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
for_each_sg(sgt->sgl, sg, i, j) { for_each_sg(sgt->sgl, sg, i, j) {
size_t bytes; size_t bytes;
bytes = iopgtable_clear_entry(obj, da); bytes = sg->length;
order = get_order(bytes);
BUG_ON(!iopgsz_ok(bytes)); /* ignore failures.. we're already handling one */
iommu_unmap(domain, da, order);
da += bytes; da += bytes;
} }
...@@ -509,22 +511,31 @@ static int map_iovm_area(struct iommu *obj, struct iovm_struct *new, ...@@ -509,22 +511,31 @@ static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
} }
/* release 'da' <-> 'pa' mapping */ /* release 'da' <-> 'pa' mapping */
static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area) static void unmap_iovm_area(struct iommu_domain *domain, struct iommu *obj,
struct iovm_struct *area)
{ {
u32 start; u32 start;
size_t total = area->da_end - area->da_start; size_t total = area->da_end - area->da_start;
const struct sg_table *sgt = area->sgt;
struct scatterlist *sg;
int i, err;
BUG_ON(!sgtable_ok(sgt));
BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE)); BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
start = area->da_start; start = area->da_start;
while (total > 0) { for_each_sg(sgt->sgl, sg, sgt->nents, i) {
size_t bytes; size_t bytes;
int order;
bytes = sg->length;
order = get_order(bytes);
err = iommu_unmap(domain, start, order);
if (err)
break;
bytes = iopgtable_clear_entry(obj, start); dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
if (bytes == 0)
bytes = PAGE_SIZE;
else
dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
__func__, start, bytes, area->flags); __func__, start, bytes, area->flags);
BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE)); BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
...@@ -536,7 +547,8 @@ static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area) ...@@ -536,7 +547,8 @@ static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area)
} }
/* template function for all unmapping */ /* template function for all unmapping */
static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da, static struct sg_table *unmap_vm_area(struct iommu_domain *domain,
struct iommu *obj, const u32 da,
void (*fn)(const void *), u32 flags) void (*fn)(const void *), u32 flags)
{ {
struct sg_table *sgt = NULL; struct sg_table *sgt = NULL;
...@@ -562,7 +574,7 @@ static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da, ...@@ -562,7 +574,7 @@ static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
} }
sgt = (struct sg_table *)area->sgt; sgt = (struct sg_table *)area->sgt;
unmap_iovm_area(obj, area); unmap_iovm_area(domain, obj, area);
fn(area->va); fn(area->va);
...@@ -577,8 +589,9 @@ static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da, ...@@ -577,8 +589,9 @@ static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
return sgt; return sgt;
} }
static u32 map_iommu_region(struct iommu *obj, u32 da, static u32 map_iommu_region(struct iommu_domain *domain, struct iommu *obj,
const struct sg_table *sgt, void *va, size_t bytes, u32 flags) u32 da, const struct sg_table *sgt, void *va,
size_t bytes, u32 flags)
{ {
int err = -ENOMEM; int err = -ENOMEM;
struct iovm_struct *new; struct iovm_struct *new;
...@@ -593,7 +606,7 @@ static u32 map_iommu_region(struct iommu *obj, u32 da, ...@@ -593,7 +606,7 @@ static u32 map_iommu_region(struct iommu *obj, u32 da,
new->va = va; new->va = va;
new->sgt = sgt; new->sgt = sgt;
if (map_iovm_area(obj, new, sgt, new->flags)) if (map_iovm_area(domain, new, sgt, new->flags))
goto err_map; goto err_map;
mutex_unlock(&obj->mmap_lock); mutex_unlock(&obj->mmap_lock);
...@@ -610,10 +623,11 @@ static u32 map_iommu_region(struct iommu *obj, u32 da, ...@@ -610,10 +623,11 @@ static u32 map_iommu_region(struct iommu *obj, u32 da,
return err; return err;
} }
static inline u32 __iommu_vmap(struct iommu *obj, u32 da, static inline u32 __iommu_vmap(struct iommu_domain *domain, struct iommu *obj,
const struct sg_table *sgt, void *va, size_t bytes, u32 flags) u32 da, const struct sg_table *sgt,
void *va, size_t bytes, u32 flags)
{ {
return map_iommu_region(obj, da, sgt, va, bytes, flags); return map_iommu_region(domain, obj, da, sgt, va, bytes, flags);
} }
/** /**
...@@ -625,8 +639,8 @@ static inline u32 __iommu_vmap(struct iommu *obj, u32 da, ...@@ -625,8 +639,8 @@ static inline u32 __iommu_vmap(struct iommu *obj, u32 da,
* Creates 1-n-1 mapping with given @sgt and returns @da. * Creates 1-n-1 mapping with given @sgt and returns @da.
* All @sgt element must be io page size aligned. * All @sgt element must be io page size aligned.
*/ */
u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt, u32 iommu_vmap(struct iommu_domain *domain, struct iommu *obj, u32 da,
u32 flags) const struct sg_table *sgt, u32 flags)
{ {
size_t bytes; size_t bytes;
void *va = NULL; void *va = NULL;
...@@ -648,7 +662,7 @@ u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt, ...@@ -648,7 +662,7 @@ u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
flags |= IOVMF_DISCONT; flags |= IOVMF_DISCONT;
flags |= IOVMF_MMIO; flags |= IOVMF_MMIO;
da = __iommu_vmap(obj, da, sgt, va, bytes, flags); da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
if (IS_ERR_VALUE(da)) if (IS_ERR_VALUE(da))
vunmap_sg(va); vunmap_sg(va);
...@@ -664,14 +678,16 @@ EXPORT_SYMBOL_GPL(iommu_vmap); ...@@ -664,14 +678,16 @@ EXPORT_SYMBOL_GPL(iommu_vmap);
* Free the iommu virtually contiguous memory area starting at * Free the iommu virtually contiguous memory area starting at
* @da, which was returned by 'iommu_vmap()'. * @da, which was returned by 'iommu_vmap()'.
*/ */
struct sg_table *iommu_vunmap(struct iommu *obj, u32 da) struct sg_table *
iommu_vunmap(struct iommu_domain *domain, struct iommu *obj, u32 da)
{ {
struct sg_table *sgt; struct sg_table *sgt;
/* /*
* 'sgt' is allocated before 'iommu_vmalloc()' is called. * 'sgt' is allocated before 'iommu_vmalloc()' is called.
* Just returns 'sgt' to the caller to free * Just returns 'sgt' to the caller to free
*/ */
sgt = unmap_vm_area(obj, da, vunmap_sg, IOVMF_DISCONT | IOVMF_MMIO); sgt = unmap_vm_area(domain, obj, da, vunmap_sg,
IOVMF_DISCONT | IOVMF_MMIO);
if (!sgt) if (!sgt)
dev_dbg(obj->dev, "%s: No sgt\n", __func__); dev_dbg(obj->dev, "%s: No sgt\n", __func__);
return sgt; return sgt;
...@@ -688,7 +704,8 @@ EXPORT_SYMBOL_GPL(iommu_vunmap); ...@@ -688,7 +704,8 @@ EXPORT_SYMBOL_GPL(iommu_vunmap);
* Allocate @bytes linearly and creates 1-n-1 mapping and returns * Allocate @bytes linearly and creates 1-n-1 mapping and returns
* @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set. * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
*/ */
u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) u32 iommu_vmalloc(struct iommu_domain *domain, struct iommu *obj, u32 da,
size_t bytes, u32 flags)
{ {
void *va; void *va;
struct sg_table *sgt; struct sg_table *sgt;
...@@ -712,7 +729,7 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) ...@@ -712,7 +729,7 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
} }
sgtable_fill_vmalloc(sgt, va); sgtable_fill_vmalloc(sgt, va);
da = __iommu_vmap(obj, da, sgt, va, bytes, flags); da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
if (IS_ERR_VALUE(da)) if (IS_ERR_VALUE(da))
goto err_iommu_vmap; goto err_iommu_vmap;
...@@ -735,19 +752,20 @@ EXPORT_SYMBOL_GPL(iommu_vmalloc); ...@@ -735,19 +752,20 @@ EXPORT_SYMBOL_GPL(iommu_vmalloc);
* Frees the iommu virtually continuous memory area starting at * Frees the iommu virtually continuous memory area starting at
* @da, as obtained from 'iommu_vmalloc()'. * @da, as obtained from 'iommu_vmalloc()'.
*/ */
void iommu_vfree(struct iommu *obj, const u32 da) void iommu_vfree(struct iommu_domain *domain, struct iommu *obj, const u32 da)
{ {
struct sg_table *sgt; struct sg_table *sgt;
sgt = unmap_vm_area(obj, da, vfree, IOVMF_DISCONT | IOVMF_ALLOC); sgt = unmap_vm_area(domain, obj, da, vfree,
IOVMF_DISCONT | IOVMF_ALLOC);
if (!sgt) if (!sgt)
dev_dbg(obj->dev, "%s: No sgt\n", __func__); dev_dbg(obj->dev, "%s: No sgt\n", __func__);
sgtable_free(sgt); sgtable_free(sgt);
} }
EXPORT_SYMBOL_GPL(iommu_vfree); EXPORT_SYMBOL_GPL(iommu_vfree);
static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va, static u32 __iommu_kmap(struct iommu_domain *domain, struct iommu *obj,
size_t bytes, u32 flags) u32 da, u32 pa, void *va, size_t bytes, u32 flags)
{ {
struct sg_table *sgt; struct sg_table *sgt;
...@@ -757,7 +775,7 @@ static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va, ...@@ -757,7 +775,7 @@ static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
sgtable_fill_kmalloc(sgt, pa, da, bytes); sgtable_fill_kmalloc(sgt, pa, da, bytes);
da = map_iommu_region(obj, da, sgt, va, bytes, flags); da = map_iommu_region(domain, obj, da, sgt, va, bytes, flags);
if (IS_ERR_VALUE(da)) { if (IS_ERR_VALUE(da)) {
sgtable_drain_kmalloc(sgt); sgtable_drain_kmalloc(sgt);
sgtable_free(sgt); sgtable_free(sgt);
...@@ -776,8 +794,8 @@ static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va, ...@@ -776,8 +794,8 @@ static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
* Creates 1-1-1 mapping and returns @da again, which can be * Creates 1-1-1 mapping and returns @da again, which can be
* adjusted if 'IOVMF_DA_FIXED' is not set. * adjusted if 'IOVMF_DA_FIXED' is not set.
*/ */
u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes, u32 iommu_kmap(struct iommu_domain *domain, struct iommu *obj, u32 da, u32 pa,
u32 flags) size_t bytes, u32 flags)
{ {
void *va; void *va;
...@@ -793,7 +811,7 @@ u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes, ...@@ -793,7 +811,7 @@ u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
flags |= IOVMF_LINEAR; flags |= IOVMF_LINEAR;
flags |= IOVMF_MMIO; flags |= IOVMF_MMIO;
da = __iommu_kmap(obj, da, pa, va, bytes, flags); da = __iommu_kmap(domain, obj, da, pa, va, bytes, flags);
if (IS_ERR_VALUE(da)) if (IS_ERR_VALUE(da))
iounmap(va); iounmap(va);
...@@ -809,12 +827,12 @@ EXPORT_SYMBOL_GPL(iommu_kmap); ...@@ -809,12 +827,12 @@ EXPORT_SYMBOL_GPL(iommu_kmap);
* Frees the iommu virtually contiguous memory area starting at * Frees the iommu virtually contiguous memory area starting at
* @da, which was passed to and was returned by'iommu_kmap()'. * @da, which was passed to and was returned by'iommu_kmap()'.
*/ */
void iommu_kunmap(struct iommu *obj, u32 da) void iommu_kunmap(struct iommu_domain *domain, struct iommu *obj, u32 da)
{ {
struct sg_table *sgt; struct sg_table *sgt;
typedef void (*func_t)(const void *); typedef void (*func_t)(const void *);
sgt = unmap_vm_area(obj, da, (func_t)iounmap, sgt = unmap_vm_area(domain, obj, da, (func_t)iounmap,
IOVMF_LINEAR | IOVMF_MMIO); IOVMF_LINEAR | IOVMF_MMIO);
if (!sgt) if (!sgt)
dev_dbg(obj->dev, "%s: No sgt\n", __func__); dev_dbg(obj->dev, "%s: No sgt\n", __func__);
...@@ -832,7 +850,8 @@ EXPORT_SYMBOL_GPL(iommu_kunmap); ...@@ -832,7 +850,8 @@ EXPORT_SYMBOL_GPL(iommu_kunmap);
* Allocate @bytes linearly and creates 1-1-1 mapping and returns * Allocate @bytes linearly and creates 1-1-1 mapping and returns
* @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set. * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
*/ */
u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) u32 iommu_kmalloc(struct iommu_domain *domain, struct iommu *obj, u32 da,
size_t bytes, u32 flags)
{ {
void *va; void *va;
u32 pa; u32 pa;
...@@ -850,7 +869,7 @@ u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) ...@@ -850,7 +869,7 @@ u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
flags |= IOVMF_LINEAR; flags |= IOVMF_LINEAR;
flags |= IOVMF_ALLOC; flags |= IOVMF_ALLOC;
da = __iommu_kmap(obj, da, pa, va, bytes, flags); da = __iommu_kmap(domain, obj, da, pa, va, bytes, flags);
if (IS_ERR_VALUE(da)) if (IS_ERR_VALUE(da))
kfree(va); kfree(va);
...@@ -866,11 +885,11 @@ EXPORT_SYMBOL_GPL(iommu_kmalloc); ...@@ -866,11 +885,11 @@ EXPORT_SYMBOL_GPL(iommu_kmalloc);
* Frees the iommu virtually contiguous memory area starting at * Frees the iommu virtually contiguous memory area starting at
* @da, which was passed to and was returned by'iommu_kmalloc()'. * @da, which was passed to and was returned by'iommu_kmalloc()'.
*/ */
void iommu_kfree(struct iommu *obj, u32 da) void iommu_kfree(struct iommu_domain *domain, struct iommu *obj, u32 da)
{ {
struct sg_table *sgt; struct sg_table *sgt;
sgt = unmap_vm_area(obj, da, kfree, IOVMF_LINEAR | IOVMF_ALLOC); sgt = unmap_vm_area(domain, obj, da, kfree, IOVMF_LINEAR | IOVMF_ALLOC);
if (!sgt) if (!sgt)
dev_dbg(obj->dev, "%s: No sgt\n", __func__); dev_dbg(obj->dev, "%s: No sgt\n", __func__);
sgtable_free(sgt); sgtable_free(sgt);
......
...@@ -80,6 +80,13 @@ ...@@ -80,6 +80,13 @@
#include "isph3a.h" #include "isph3a.h"
#include "isphist.h" #include "isphist.h"
/*
* this is provided as an interim solution until omap3isp doesn't need
* any omap-specific iommu API
*/
#define to_iommu(dev) \
(struct iommu *)platform_get_drvdata(to_platform_device(dev))
static unsigned int autoidle; static unsigned int autoidle;
module_param(autoidle, int, 0444); module_param(autoidle, int, 0444);
MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support"); MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
...@@ -1975,7 +1982,8 @@ static int isp_remove(struct platform_device *pdev) ...@@ -1975,7 +1982,8 @@ static int isp_remove(struct platform_device *pdev)
isp_cleanup_modules(isp); isp_cleanup_modules(isp);
omap3isp_get(isp); omap3isp_get(isp);
iommu_put(isp->iommu); iommu_detach_device(isp->domain, isp->iommu_dev);
iommu_domain_free(isp->domain);
omap3isp_put(isp); omap3isp_put(isp);
free_irq(isp->irq_num, isp); free_irq(isp->irq_num, isp);
...@@ -2123,25 +2131,41 @@ static int isp_probe(struct platform_device *pdev) ...@@ -2123,25 +2131,41 @@ static int isp_probe(struct platform_device *pdev)
} }
/* IOMMU */ /* IOMMU */
isp->iommu = iommu_get("isp"); isp->iommu_dev = omap_find_iommu_device("isp");
if (IS_ERR_OR_NULL(isp->iommu)) { if (!isp->iommu_dev) {
isp->iommu = NULL; dev_err(isp->dev, "omap_find_iommu_device failed\n");
ret = -ENODEV; ret = -ENODEV;
goto error_isp; goto error_isp;
} }
/* to be removed once iommu migration is complete */
isp->iommu = to_iommu(isp->iommu_dev);
isp->domain = iommu_domain_alloc();
if (!isp->domain) {
dev_err(isp->dev, "can't alloc iommu domain\n");
ret = -ENOMEM;
goto error_isp;
}
ret = iommu_attach_device(isp->domain, isp->iommu_dev);
if (ret) {
dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
goto free_domain;
}
/* Interrupt */ /* Interrupt */
isp->irq_num = platform_get_irq(pdev, 0); isp->irq_num = platform_get_irq(pdev, 0);
if (isp->irq_num <= 0) { if (isp->irq_num <= 0) {
dev_err(isp->dev, "No IRQ resource\n"); dev_err(isp->dev, "No IRQ resource\n");
ret = -ENODEV; ret = -ENODEV;
goto error_isp; goto detach_dev;
} }
if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) { if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) {
dev_err(isp->dev, "Unable to request IRQ\n"); dev_err(isp->dev, "Unable to request IRQ\n");
ret = -EINVAL; ret = -EINVAL;
goto error_isp; goto detach_dev;
} }
/* Entities */ /* Entities */
...@@ -2162,8 +2186,11 @@ static int isp_probe(struct platform_device *pdev) ...@@ -2162,8 +2186,11 @@ static int isp_probe(struct platform_device *pdev)
isp_cleanup_modules(isp); isp_cleanup_modules(isp);
error_irq: error_irq:
free_irq(isp->irq_num, isp); free_irq(isp->irq_num, isp);
detach_dev:
iommu_detach_device(isp->domain, isp->iommu_dev);
free_domain:
iommu_domain_free(isp->domain);
error_isp: error_isp:
iommu_put(isp->iommu);
omap3isp_put(isp); omap3isp_put(isp);
error: error:
isp_put_clocks(isp); isp_put_clocks(isp);
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/iommu.h>
#include <plat/iommu.h> #include <plat/iommu.h>
#include <plat/iovmm.h> #include <plat/iovmm.h>
...@@ -295,6 +296,8 @@ struct isp_device { ...@@ -295,6 +296,8 @@ struct isp_device {
unsigned int subclk_resources; unsigned int subclk_resources;
struct iommu *iommu; struct iommu *iommu;
struct iommu_domain *domain;
struct device *iommu_dev;
struct isp_platform_callback platform_cb; struct isp_platform_callback platform_cb;
}; };
......
...@@ -365,7 +365,7 @@ static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc, ...@@ -365,7 +365,7 @@ static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
dma_unmap_sg(isp->dev, req->iovm->sgt->sgl, dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
req->iovm->sgt->nents, DMA_TO_DEVICE); req->iovm->sgt->nents, DMA_TO_DEVICE);
if (req->table) if (req->table)
iommu_vfree(isp->iommu, req->table); iommu_vfree(isp->domain, isp->iommu, req->table);
kfree(req); kfree(req);
} }
...@@ -437,8 +437,8 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc, ...@@ -437,8 +437,8 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
req->enable = 1; req->enable = 1;
req->table = iommu_vmalloc(isp->iommu, 0, req->config.size, req->table = iommu_vmalloc(isp->domain, isp->iommu, 0,
IOMMU_FLAG); req->config.size, IOMMU_FLAG);
if (IS_ERR_VALUE(req->table)) { if (IS_ERR_VALUE(req->table)) {
req->table = 0; req->table = 0;
ret = -ENOMEM; ret = -ENOMEM;
...@@ -733,15 +733,15 @@ static int ccdc_config(struct isp_ccdc_device *ccdc, ...@@ -733,15 +733,15 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
* already done by iommu_vmalloc(). * already done by iommu_vmalloc().
*/ */
size = ccdc->fpc.fpnum * 4; size = ccdc->fpc.fpnum * 4;
table_new = iommu_vmalloc(isp->iommu, 0, size, table_new = iommu_vmalloc(isp->domain, isp->iommu, 0,
IOMMU_FLAG); size, IOMMU_FLAG);
if (IS_ERR_VALUE(table_new)) if (IS_ERR_VALUE(table_new))
return -ENOMEM; return -ENOMEM;
if (copy_from_user(da_to_va(isp->iommu, table_new), if (copy_from_user(da_to_va(isp->iommu, table_new),
(__force void __user *) (__force void __user *)
ccdc->fpc.fpcaddr, size)) { ccdc->fpc.fpcaddr, size)) {
iommu_vfree(isp->iommu, table_new); iommu_vfree(isp->domain, isp->iommu, table_new);
return -EFAULT; return -EFAULT;
} }
...@@ -751,7 +751,7 @@ static int ccdc_config(struct isp_ccdc_device *ccdc, ...@@ -751,7 +751,7 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
ccdc_configure_fpc(ccdc); ccdc_configure_fpc(ccdc);
if (table_old != 0) if (table_old != 0)
iommu_vfree(isp->iommu, table_old); iommu_vfree(isp->domain, isp->iommu, table_old);
} }
return ccdc_lsc_config(ccdc, ccdc_struct); return ccdc_lsc_config(ccdc, ccdc_struct);
...@@ -2286,5 +2286,5 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp) ...@@ -2286,5 +2286,5 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp)
ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue); ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
if (ccdc->fpc.fpcaddr != 0) if (ccdc->fpc.fpcaddr != 0)
iommu_vfree(isp->iommu, ccdc->fpc.fpcaddr); iommu_vfree(isp->domain, isp->iommu, ccdc->fpc.fpcaddr);
} }
...@@ -366,7 +366,7 @@ static void isp_stat_bufs_free(struct ispstat *stat) ...@@ -366,7 +366,7 @@ static void isp_stat_bufs_free(struct ispstat *stat)
dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl, dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
buf->iovm->sgt->nents, buf->iovm->sgt->nents,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
iommu_vfree(isp->iommu, buf->iommu_addr); iommu_vfree(isp->domain, isp->iommu, buf->iommu_addr);
} else { } else {
if (!buf->virt_addr) if (!buf->virt_addr)
continue; continue;
...@@ -399,8 +399,8 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size) ...@@ -399,8 +399,8 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
struct iovm_struct *iovm; struct iovm_struct *iovm;
WARN_ON(buf->dma_addr); WARN_ON(buf->dma_addr);
buf->iommu_addr = iommu_vmalloc(isp->iommu, 0, size, buf->iommu_addr = iommu_vmalloc(isp->domain, isp->iommu, 0,
IOMMU_FLAG); size, IOMMU_FLAG);
if (IS_ERR((void *)buf->iommu_addr)) { if (IS_ERR((void *)buf->iommu_addr)) {
dev_err(stat->isp->dev, dev_err(stat->isp->dev,
"%s: Can't acquire memory for " "%s: Can't acquire memory for "
......
...@@ -446,7 +446,7 @@ ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen) ...@@ -446,7 +446,7 @@ ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
sgt->nents = sglen; sgt->nents = sglen;
sgt->orig_nents = sglen; sgt->orig_nents = sglen;
da = iommu_vmap(isp->iommu, 0, sgt, IOMMU_FLAG); da = iommu_vmap(isp->domain, isp->iommu, 0, sgt, IOMMU_FLAG);
if (IS_ERR_VALUE(da)) if (IS_ERR_VALUE(da))
kfree(sgt); kfree(sgt);
...@@ -462,7 +462,7 @@ static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da) ...@@ -462,7 +462,7 @@ static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
{ {
struct sg_table *sgt; struct sg_table *sgt;
sgt = iommu_vunmap(isp->iommu, (u32)da); sgt = iommu_vunmap(isp->domain, isp->iommu, (u32)da);
kfree(sgt); kfree(sgt);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment