Commit 1abb4ba5 authored by Joerg Roedel's avatar Joerg Roedel

Merge branches 'amd/fixes', 'debug/dma-api', 'arm/omap', 'arm/msm', 'core',...

Merge branches 'amd/fixes', 'debug/dma-api', 'arm/omap', 'arm/msm', 'core', 'iommu/fault-reporting' and 'api/iommu-ops-per-bus' into next

Conflicts:
	drivers/iommu/amd_iommu.c
	drivers/iommu/iommu.c
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0) ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0)
static void __iommu_set_twl(struct iommu *obj, bool on) static void __iommu_set_twl(struct omap_iommu *obj, bool on)
{ {
u32 l = iommu_read_reg(obj, MMU_CNTL); u32 l = iommu_read_reg(obj, MMU_CNTL);
...@@ -85,7 +85,7 @@ static void __iommu_set_twl(struct iommu *obj, bool on) ...@@ -85,7 +85,7 @@ static void __iommu_set_twl(struct iommu *obj, bool on)
} }
static int omap2_iommu_enable(struct iommu *obj) static int omap2_iommu_enable(struct omap_iommu *obj)
{ {
u32 l, pa; u32 l, pa;
unsigned long timeout; unsigned long timeout;
...@@ -127,7 +127,7 @@ static int omap2_iommu_enable(struct iommu *obj) ...@@ -127,7 +127,7 @@ static int omap2_iommu_enable(struct iommu *obj)
return 0; return 0;
} }
static void omap2_iommu_disable(struct iommu *obj) static void omap2_iommu_disable(struct omap_iommu *obj)
{ {
u32 l = iommu_read_reg(obj, MMU_CNTL); u32 l = iommu_read_reg(obj, MMU_CNTL);
...@@ -138,12 +138,12 @@ static void omap2_iommu_disable(struct iommu *obj) ...@@ -138,12 +138,12 @@ static void omap2_iommu_disable(struct iommu *obj)
dev_dbg(obj->dev, "%s is shutting down\n", obj->name); dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
} }
static void omap2_iommu_set_twl(struct iommu *obj, bool on) static void omap2_iommu_set_twl(struct omap_iommu *obj, bool on)
{ {
__iommu_set_twl(obj, false); __iommu_set_twl(obj, false);
} }
static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra) static u32 omap2_iommu_fault_isr(struct omap_iommu *obj, u32 *ra)
{ {
u32 stat, da; u32 stat, da;
u32 errs = 0; u32 errs = 0;
...@@ -173,13 +173,13 @@ static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra) ...@@ -173,13 +173,13 @@ static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
return errs; return errs;
} }
static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr) static void omap2_tlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
{ {
cr->cam = iommu_read_reg(obj, MMU_READ_CAM); cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
cr->ram = iommu_read_reg(obj, MMU_READ_RAM); cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
} }
static void omap2_tlb_load_cr(struct iommu *obj, struct cr_regs *cr) static void omap2_tlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
{ {
iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM); iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
iommu_write_reg(obj, cr->ram, MMU_RAM); iommu_write_reg(obj, cr->ram, MMU_RAM);
...@@ -193,7 +193,8 @@ static u32 omap2_cr_to_virt(struct cr_regs *cr) ...@@ -193,7 +193,8 @@ static u32 omap2_cr_to_virt(struct cr_regs *cr)
return cr->cam & mask; return cr->cam & mask;
} }
static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e) static struct cr_regs *omap2_alloc_cr(struct omap_iommu *obj,
struct iotlb_entry *e)
{ {
struct cr_regs *cr; struct cr_regs *cr;
...@@ -230,7 +231,8 @@ static u32 omap2_get_pte_attr(struct iotlb_entry *e) ...@@ -230,7 +231,8 @@ static u32 omap2_get_pte_attr(struct iotlb_entry *e)
return attr; return attr;
} }
static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf) static ssize_t
omap2_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, char *buf)
{ {
char *p = buf; char *p = buf;
...@@ -254,7 +256,8 @@ static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf) ...@@ -254,7 +256,8 @@ static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
goto out; \ goto out; \
} while (0) } while (0)
static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len) static ssize_t
omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
{ {
char *p = buf; char *p = buf;
...@@ -280,7 +283,7 @@ static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len) ...@@ -280,7 +283,7 @@ static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len)
return p - buf; return p - buf;
} }
static void omap2_iommu_save_ctx(struct iommu *obj) static void omap2_iommu_save_ctx(struct omap_iommu *obj)
{ {
int i; int i;
u32 *p = obj->ctx; u32 *p = obj->ctx;
...@@ -293,7 +296,7 @@ static void omap2_iommu_save_ctx(struct iommu *obj) ...@@ -293,7 +296,7 @@ static void omap2_iommu_save_ctx(struct iommu *obj)
BUG_ON(p[0] != IOMMU_ARCH_VERSION); BUG_ON(p[0] != IOMMU_ARCH_VERSION);
} }
static void omap2_iommu_restore_ctx(struct iommu *obj) static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
{ {
int i; int i;
u32 *p = obj->ctx; u32 *p = obj->ctx;
...@@ -343,13 +346,13 @@ static const struct iommu_functions omap2_iommu_ops = { ...@@ -343,13 +346,13 @@ static const struct iommu_functions omap2_iommu_ops = {
static int __init omap2_iommu_init(void) static int __init omap2_iommu_init(void)
{ {
return install_iommu_arch(&omap2_iommu_ops); return omap_install_iommu_arch(&omap2_iommu_ops);
} }
module_init(omap2_iommu_init); module_init(omap2_iommu_init);
static void __exit omap2_iommu_exit(void) static void __exit omap2_iommu_exit(void)
{ {
uninstall_iommu_arch(&omap2_iommu_ops); omap_uninstall_iommu_arch(&omap2_iommu_ops);
} }
module_exit(omap2_iommu_exit); module_exit(omap2_iommu_exit);
......
...@@ -132,18 +132,6 @@ config OMAP_MBOX_KFIFO_SIZE ...@@ -132,18 +132,6 @@ 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).
config OMAP_IOMMU
tristate
config OMAP_IOMMU_DEBUG
tristate "Export OMAP IOMMU internals in DebugFS"
depends on OMAP_IOMMU && DEBUG_FS
help
Select this to see extensive information about
the internal state of OMAP IOMMU in debugfs.
Say N unless you know you need this.
config OMAP_IOMMU_IVA2 config OMAP_IOMMU_IVA2
bool bool
......
...@@ -18,8 +18,6 @@ obj-$(CONFIG_ARCH_OMAP3) += omap_device.o ...@@ -18,8 +18,6 @@ obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
obj-$(CONFIG_ARCH_OMAP4) += omap_device.o obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
......
...@@ -25,16 +25,17 @@ struct iotlb_entry { ...@@ -25,16 +25,17 @@ struct iotlb_entry {
}; };
}; };
struct iommu { struct omap_iommu {
const char *name; const char *name;
struct module *owner; struct module *owner;
struct clk *clk; struct clk *clk;
void __iomem *regbase; void __iomem *regbase;
struct device *dev; struct device *dev;
void *isr_priv; void *isr_priv;
struct iommu_domain *domain;
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,
...@@ -48,8 +49,6 @@ struct iommu { ...@@ -48,8 +49,6 @@ struct iommu {
struct list_head mmap; struct list_head mmap;
struct mutex mmap_lock; /* protect mmap */ struct mutex mmap_lock; /* protect mmap */
int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, void *priv);
void *ctx; /* iommu context: registres saved area */ void *ctx; /* iommu context: registres saved area */
u32 da_start; u32 da_start;
u32 da_end; u32 da_end;
...@@ -81,25 +80,27 @@ struct iotlb_lock { ...@@ -81,25 +80,27 @@ struct iotlb_lock {
struct iommu_functions { struct iommu_functions {
unsigned long version; unsigned long version;
int (*enable)(struct iommu *obj); int (*enable)(struct omap_iommu *obj);
void (*disable)(struct iommu *obj); void (*disable)(struct omap_iommu *obj);
void (*set_twl)(struct iommu *obj, bool on); void (*set_twl)(struct omap_iommu *obj, bool on);
u32 (*fault_isr)(struct iommu *obj, u32 *ra); u32 (*fault_isr)(struct omap_iommu *obj, u32 *ra);
void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr); void (*tlb_read_cr)(struct omap_iommu *obj, struct cr_regs *cr);
void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr); void (*tlb_load_cr)(struct omap_iommu *obj, struct cr_regs *cr);
struct cr_regs *(*alloc_cr)(struct iommu *obj, struct iotlb_entry *e); struct cr_regs *(*alloc_cr)(struct omap_iommu *obj,
struct iotlb_entry *e);
int (*cr_valid)(struct cr_regs *cr); int (*cr_valid)(struct cr_regs *cr);
u32 (*cr_to_virt)(struct cr_regs *cr); u32 (*cr_to_virt)(struct cr_regs *cr);
void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e); void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
ssize_t (*dump_cr)(struct iommu *obj, struct cr_regs *cr, char *buf); ssize_t (*dump_cr)(struct omap_iommu *obj, struct cr_regs *cr,
char *buf);
u32 (*get_pte_attr)(struct iotlb_entry *e); u32 (*get_pte_attr)(struct iotlb_entry *e);
void (*save_ctx)(struct iommu *obj); void (*save_ctx)(struct omap_iommu *obj);
void (*restore_ctx)(struct iommu *obj); void (*restore_ctx)(struct omap_iommu *obj);
ssize_t (*dump_ctx)(struct iommu *obj, char *buf, ssize_t len); ssize_t (*dump_ctx)(struct omap_iommu *obj, char *buf, ssize_t len);
}; };
struct iommu_platform_data { struct iommu_platform_data {
...@@ -150,40 +151,31 @@ struct iommu_platform_data { ...@@ -150,40 +151,31 @@ struct iommu_platform_data {
/* /*
* global functions * global functions
*/ */
extern u32 iommu_arch_version(void); extern u32 omap_iommu_arch_version(void);
extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e); extern void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
extern u32 iotlb_cr_to_virt(struct cr_regs *cr);
extern int
extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e); omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
extern void iommu_set_twl(struct iommu *obj, bool on);
extern void flush_iotlb_page(struct iommu *obj, u32 da); extern int omap_iommu_set_isr(const char *name,
extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end); int (*isr)(struct omap_iommu *obj, u32 da, u32 iommu_errs,
extern void flush_iotlb_all(struct iommu *obj);
extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
extern void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd,
u32 **ppte);
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);
extern int iommu_set_isr(const char *name,
int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
void *priv), void *priv),
void *isr_priv); void *isr_priv);
extern void iommu_save_ctx(struct iommu *obj); extern void omap_iommu_save_ctx(struct omap_iommu *obj);
extern void iommu_restore_ctx(struct iommu *obj); extern void omap_iommu_restore_ctx(struct omap_iommu *obj);
extern int install_iommu_arch(const struct iommu_functions *ops); extern int omap_install_iommu_arch(const struct iommu_functions *ops);
extern void uninstall_iommu_arch(const struct iommu_functions *ops); extern void omap_uninstall_iommu_arch(const struct iommu_functions *ops);
extern int foreach_iommu_device(void *data, extern int omap_foreach_iommu_device(void *data,
int (*fn)(struct device *, void *)); int (*fn)(struct device *, void *));
extern ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len); extern ssize_t
extern size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t len); omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len);
extern size_t
omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t len);
struct device *omap_find_iommu_device(const char *name);
#endif /* __MACH_IOMMU_H */ #endif /* __MACH_IOMMU_H */
...@@ -83,12 +83,12 @@ ...@@ -83,12 +83,12 @@
/* /*
* register accessors * register accessors
*/ */
static inline u32 iommu_read_reg(struct iommu *obj, size_t offs) static inline u32 iommu_read_reg(struct omap_iommu *obj, size_t offs)
{ {
return __raw_readl(obj->regbase + offs); return __raw_readl(obj->regbase + offs);
} }
static inline void iommu_write_reg(struct iommu *obj, u32 val, size_t offs) static inline void iommu_write_reg(struct omap_iommu *obj, u32 val, size_t offs)
{ {
__raw_writel(val, obj->regbase + offs); __raw_writel(val, obj->regbase + offs);
} }
......
...@@ -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))
...@@ -97,6 +115,6 @@ static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa, ...@@ -97,6 +115,6 @@ static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
} }
#define to_iommu(dev) \ #define to_iommu(dev) \
(struct iommu *)platform_get_drvdata(to_platform_device(dev)) (struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
#endif /* __PLAT_OMAP_IOMMU_H */ #endif /* __PLAT_OMAP_IOMMU_H */
...@@ -13,8 +13,10 @@ ...@@ -13,8 +13,10 @@
#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 omap_iommu *iommu; /* iommu object which this belongs to */
u32 da_start; /* area definition */ u32 da_start; /* area definition */
u32 da_end; u32 da_end;
u32 flags; /* IOVMF_: see below */ u32 flags; /* IOVMF_: see below */
...@@ -70,20 +72,18 @@ struct iovm_struct { ...@@ -70,20 +72,18 @@ struct iovm_struct {
#define IOVMF_DA_FIXED (1 << (4 + IOVMF_SW_SHIFT)) #define IOVMF_DA_FIXED (1 << (4 + IOVMF_SW_SHIFT))
extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da); extern struct iovm_struct *omap_find_iovm_area(struct omap_iommu *obj, u32 da);
extern u32 iommu_vmap(struct iommu *obj, u32 da, extern u32
omap_iommu_vmap(struct iommu_domain *domain, struct omap_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 *omap_iommu_vunmap(struct iommu_domain *domain,
extern u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, struct omap_iommu *obj, u32 da);
u32 flags); extern u32
extern void iommu_vfree(struct iommu *obj, const u32 da); omap_iommu_vmalloc(struct iommu_domain *domain, struct omap_iommu *obj,
extern u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes, u32 da, size_t bytes, u32 flags);
u32 flags); extern void
extern void iommu_kunmap(struct iommu *obj, u32 da); omap_iommu_vfree(struct iommu_domain *domain, struct omap_iommu *obj,
extern u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, const u32 da);
u32 flags); extern void *omap_da_to_va(struct omap_iommu *obj, u32 da);
extern void iommu_kfree(struct iommu *obj, u32 da);
extern void *da_to_va(struct iommu *obj, u32 da);
#endif /* __IOMMU_MMAP_H */ #endif /* __IOMMU_MMAP_H */
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/intel-iommu.h> #include <linux/intel-iommu.h>
#include <linux/pci.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/gcc_intrin.h> #include <asm/gcc_intrin.h>
...@@ -204,7 +205,7 @@ int kvm_dev_ioctl_check_extension(long ext) ...@@ -204,7 +205,7 @@ int kvm_dev_ioctl_check_extension(long ext)
r = KVM_COALESCED_MMIO_PAGE_OFFSET; r = KVM_COALESCED_MMIO_PAGE_OFFSET;
break; break;
case KVM_CAP_IOMMU: case KVM_CAP_IOMMU:
r = iommu_found(); r = iommu_present(&pci_bus_type);
break; break;
default: default:
r = 0; r = 0;
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/hash.h> #include <linux/hash.h>
#include <linux/pci.h>
#include <trace/events/kvm.h> #include <trace/events/kvm.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
...@@ -2095,7 +2096,7 @@ int kvm_dev_ioctl_check_extension(long ext) ...@@ -2095,7 +2096,7 @@ int kvm_dev_ioctl_check_extension(long ext)
r = 0; r = 0;
break; break;
case KVM_CAP_IOMMU: case KVM_CAP_IOMMU:
r = iommu_found(); r = iommu_present(&pci_bus_type);
break; break;
case KVM_CAP_MCE: case KVM_CAP_MCE:
r = KVM_MAX_MCE_BANKS; r = KVM_MAX_MCE_BANKS;
......
...@@ -107,4 +107,23 @@ config INTR_REMAP ...@@ -107,4 +107,23 @@ config INTR_REMAP
To use x2apic mode in the CPU's which support x2APIC enhancements or To use x2apic mode in the CPU's which support x2APIC enhancements or
to support platforms with CPU's having > 8 bit APIC ID, say Y. to support platforms with CPU's having > 8 bit APIC ID, say Y.
# OMAP IOMMU support
config OMAP_IOMMU
bool "OMAP IOMMU Support"
depends on ARCH_OMAP
select IOMMU_API
config OMAP_IOVMM
tristate "OMAP IO Virtual Memory Manager Support"
depends on OMAP_IOMMU
config OMAP_IOMMU_DEBUG
tristate "Export OMAP IOMMU/IOVMM internals in DebugFS"
depends on OMAP_IOVMM && DEBUG_FS
help
Select this to see extensive information about
the internal state of OMAP IOMMU/IOVMM in debugfs.
Say N unless you know you need this.
endif # IOMMU_SUPPORT endif # IOMMU_SUPPORT
...@@ -3,3 +3,6 @@ obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o ...@@ -3,3 +3,6 @@ obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
...@@ -1283,7 +1283,7 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom, ...@@ -1283,7 +1283,7 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom,
if (!pte || !IOMMU_PTE_PRESENT(*pte)) if (!pte || !IOMMU_PTE_PRESENT(*pte))
continue; continue;
dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1); dma_ops_reserve_addresses(dma_dom, i >> PAGE_SHIFT, 1);
} }
update_domain(&dma_dom->domain); update_domain(&dma_dom->domain);
...@@ -2495,7 +2495,7 @@ static unsigned device_dma_ops_init(void) ...@@ -2495,7 +2495,7 @@ static unsigned device_dma_ops_init(void)
void __init amd_iommu_init_api(void) void __init amd_iommu_init_api(void)
{ {
register_iommu(&amd_iommu_ops); bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
} }
int __init amd_iommu_init_dma_ops(void) int __init amd_iommu_init_dma_ops(void)
......
...@@ -3486,7 +3486,7 @@ int __init intel_iommu_init(void) ...@@ -3486,7 +3486,7 @@ int __init intel_iommu_init(void)
init_iommu_pm_ops(); init_iommu_pm_ops();
register_iommu(&intel_iommu_ops); bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
bus_register_notifier(&pci_bus_type, &device_nb); bus_register_notifier(&pci_bus_type, &device_nb);
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -23,32 +25,78 @@ ...@@ -23,32 +25,78 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/iommu.h> #include <linux/iommu.h>
static struct iommu_ops *iommu_ops; static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops)
{
}
void register_iommu(struct iommu_ops *ops) /**
* bus_set_iommu - set iommu-callbacks for the bus
* @bus: bus.
* @ops: the callbacks provided by the iommu-driver
*
* This function is called by an iommu driver to set the iommu methods
* used for a particular bus. Drivers for devices on that bus can use
* the iommu-api after these ops are registered.
* This special function is needed because IOMMUs are usually devices on
* the bus itself, so the iommu drivers are not initialized when the bus
* is set up. With this function the iommu-driver can set the iommu-ops
* afterwards.
*/
int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops)
{ {
if (iommu_ops) if (bus->iommu_ops != NULL)
BUG(); return -EBUSY;
bus->iommu_ops = ops;
/* Do IOMMU specific setup for this bus-type */
iommu_bus_init(bus, ops);
iommu_ops = ops; return 0;
} }
EXPORT_SYMBOL_GPL(bus_set_iommu);
bool iommu_found(void) bool iommu_present(struct bus_type *bus)
{ {
return iommu_ops != NULL; return bus->iommu_ops != NULL;
} }
EXPORT_SYMBOL_GPL(iommu_found); EXPORT_SYMBOL_GPL(iommu_present);
struct iommu_domain *iommu_domain_alloc(void) /**
* iommu_set_fault_handler() - set a fault handler for an iommu domain
* @domain: iommu domain
* @handler: fault handler
*
* This function should be used by IOMMU users which want to be notified
* whenever an IOMMU fault happens.
*
* The fault handler itself should return 0 on success, and an appropriate
* error code otherwise.
*/
void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler)
{
BUG_ON(!domain);
domain->handler = handler;
}
EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
{ {
struct iommu_domain *domain; struct iommu_domain *domain;
int ret; int ret;
if (bus == NULL || bus->iommu_ops == NULL)
return NULL;
domain = kmalloc(sizeof(*domain), GFP_KERNEL); domain = kmalloc(sizeof(*domain), GFP_KERNEL);
if (!domain) if (!domain)
return NULL; return NULL;
ret = iommu_ops->domain_init(domain); domain->ops = bus->iommu_ops;
ret = domain->ops->domain_init(domain);
if (ret) if (ret)
goto out_free; goto out_free;
...@@ -63,62 +111,78 @@ EXPORT_SYMBOL_GPL(iommu_domain_alloc); ...@@ -63,62 +111,78 @@ EXPORT_SYMBOL_GPL(iommu_domain_alloc);
void iommu_domain_free(struct iommu_domain *domain) void iommu_domain_free(struct iommu_domain *domain)
{ {
iommu_ops->domain_destroy(domain); if (likely(domain->ops->domain_destroy != NULL))
domain->ops->domain_destroy(domain);
kfree(domain); kfree(domain);
} }
EXPORT_SYMBOL_GPL(iommu_domain_free); EXPORT_SYMBOL_GPL(iommu_domain_free);
int iommu_attach_device(struct iommu_domain *domain, struct device *dev) int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
{ {
return iommu_ops->attach_dev(domain, dev); if (unlikely(domain->ops->attach_dev == NULL))
return -ENODEV;
return domain->ops->attach_dev(domain, dev);
} }
EXPORT_SYMBOL_GPL(iommu_attach_device); EXPORT_SYMBOL_GPL(iommu_attach_device);
void iommu_detach_device(struct iommu_domain *domain, struct device *dev) void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
{ {
iommu_ops->detach_dev(domain, dev); if (unlikely(domain->ops->detach_dev == NULL))
return;
domain->ops->detach_dev(domain, dev);
} }
EXPORT_SYMBOL_GPL(iommu_detach_device); EXPORT_SYMBOL_GPL(iommu_detach_device);
phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long iova) unsigned long iova)
{ {
return iommu_ops->iova_to_phys(domain, iova); if (unlikely(domain->ops->iova_to_phys == NULL))
return 0;
return domain->ops->iova_to_phys(domain, iova);
} }
EXPORT_SYMBOL_GPL(iommu_iova_to_phys); EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
int iommu_domain_has_cap(struct iommu_domain *domain, int iommu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap) unsigned long cap)
{ {
return iommu_ops->domain_has_cap(domain, cap); if (unlikely(domain->ops->domain_has_cap == NULL))
return 0;
return domain->ops->domain_has_cap(domain, cap);
} }
EXPORT_SYMBOL_GPL(iommu_domain_has_cap); EXPORT_SYMBOL_GPL(iommu_domain_has_cap);
int iommu_map(struct iommu_domain *domain, unsigned long iova, int iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, int gfp_order, int prot) phys_addr_t paddr, int gfp_order, int prot)
{ {
unsigned long invalid_mask;
size_t size; size_t size;
size = 0x1000UL << gfp_order; if (unlikely(domain->ops->map == NULL))
invalid_mask = size - 1; return -ENODEV;
BUG_ON((iova | paddr) & invalid_mask); size = PAGE_SIZE << gfp_order;
return iommu_ops->map(domain, iova, paddr, gfp_order, prot); BUG_ON(!IS_ALIGNED(iova | paddr, size));
return domain->ops->map(domain, iova, paddr, gfp_order, prot);
} }
EXPORT_SYMBOL_GPL(iommu_map); EXPORT_SYMBOL_GPL(iommu_map);
int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order) int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)
{ {
unsigned long invalid_mask;
size_t size; size_t size;
size = 0x1000UL << gfp_order; if (unlikely(domain->ops->unmap == NULL))
invalid_mask = size - 1; return -ENODEV;
size = PAGE_SIZE << gfp_order;
BUG_ON(iova & invalid_mask); BUG_ON(!IS_ALIGNED(iova, size));
return iommu_ops->unmap(domain, iova, gfp_order); return domain->ops->unmap(domain, iova, gfp_order);
} }
EXPORT_SYMBOL_GPL(iommu_unmap); EXPORT_SYMBOL_GPL(iommu_unmap);
...@@ -543,6 +543,13 @@ static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va, ...@@ -543,6 +543,13 @@ static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
} }
ret = __flush_iotlb(domain); ret = __flush_iotlb(domain);
/*
* the IOMMU API requires us to return the order of the unmapped
* page (on success).
*/
if (!ret)
ret = order;
fail: fail:
spin_unlock_irqrestore(&msm_iommu_lock, flags); spin_unlock_irqrestore(&msm_iommu_lock, flags);
return ret; return ret;
...@@ -721,7 +728,7 @@ static void __init setup_iommu_tex_classes(void) ...@@ -721,7 +728,7 @@ static void __init setup_iommu_tex_classes(void)
static int __init msm_iommu_init(void) static int __init msm_iommu_init(void)
{ {
setup_iommu_tex_classes(); setup_iommu_tex_classes();
register_iommu(&msm_iommu_ops); bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
return 0; return 0;
} }
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <plat/iommu.h> #include <plat/iommu.h>
#include <plat/iovmm.h> #include <plat/iovmm.h>
#include "iopgtable.h" #include <plat/iopgtable.h>
#define MAXCOLUMN 100 /* for short messages */ #define MAXCOLUMN 100 /* for short messages */
...@@ -32,7 +32,7 @@ static struct dentry *iommu_debug_root; ...@@ -32,7 +32,7 @@ static struct dentry *iommu_debug_root;
static ssize_t debug_read_ver(struct file *file, char __user *userbuf, static ssize_t debug_read_ver(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
u32 ver = iommu_arch_version(); u32 ver = omap_iommu_arch_version();
char buf[MAXCOLUMN], *p = buf; char buf[MAXCOLUMN], *p = buf;
p += sprintf(p, "H/W version: %d.%d\n", (ver >> 4) & 0xf , ver & 0xf); p += sprintf(p, "H/W version: %d.%d\n", (ver >> 4) & 0xf , ver & 0xf);
...@@ -43,7 +43,7 @@ static ssize_t debug_read_ver(struct file *file, char __user *userbuf, ...@@ -43,7 +43,7 @@ static ssize_t debug_read_ver(struct file *file, char __user *userbuf,
static ssize_t debug_read_regs(struct file *file, char __user *userbuf, static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iommu *obj = file->private_data; struct omap_iommu *obj = file->private_data;
char *p, *buf; char *p, *buf;
ssize_t bytes; ssize_t bytes;
...@@ -54,7 +54,7 @@ static ssize_t debug_read_regs(struct file *file, char __user *userbuf, ...@@ -54,7 +54,7 @@ static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
mutex_lock(&iommu_debug_lock); mutex_lock(&iommu_debug_lock);
bytes = iommu_dump_ctx(obj, p, count); bytes = omap_iommu_dump_ctx(obj, p, count);
bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes); bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes);
mutex_unlock(&iommu_debug_lock); mutex_unlock(&iommu_debug_lock);
...@@ -66,7 +66,7 @@ static ssize_t debug_read_regs(struct file *file, char __user *userbuf, ...@@ -66,7 +66,7 @@ static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
static ssize_t debug_read_tlb(struct file *file, char __user *userbuf, static ssize_t debug_read_tlb(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iommu *obj = file->private_data; struct omap_iommu *obj = file->private_data;
char *p, *buf; char *p, *buf;
ssize_t bytes, rest; ssize_t bytes, rest;
...@@ -80,7 +80,7 @@ static ssize_t debug_read_tlb(struct file *file, char __user *userbuf, ...@@ -80,7 +80,7 @@ static ssize_t debug_read_tlb(struct file *file, char __user *userbuf,
p += sprintf(p, "%8s %8s\n", "cam:", "ram:"); p += sprintf(p, "%8s %8s\n", "cam:", "ram:");
p += sprintf(p, "-----------------------------------------\n"); p += sprintf(p, "-----------------------------------------\n");
rest = count - (p - buf); rest = count - (p - buf);
p += dump_tlb_entries(obj, p, rest); p += omap_dump_tlb_entries(obj, p, rest);
bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
...@@ -96,7 +96,7 @@ static ssize_t debug_write_pagetable(struct file *file, ...@@ -96,7 +96,7 @@ static ssize_t debug_write_pagetable(struct file *file,
struct iotlb_entry e; struct iotlb_entry e;
struct cr_regs cr; struct cr_regs cr;
int err; int err;
struct iommu *obj = file->private_data; struct omap_iommu *obj = file->private_data;
char buf[MAXCOLUMN], *p = buf; char buf[MAXCOLUMN], *p = buf;
count = min(count, sizeof(buf)); count = min(count, sizeof(buf));
...@@ -113,8 +113,8 @@ static ssize_t debug_write_pagetable(struct file *file, ...@@ -113,8 +113,8 @@ static ssize_t debug_write_pagetable(struct file *file,
return -EINVAL; return -EINVAL;
} }
iotlb_cr_to_e(&cr, &e); omap_iotlb_cr_to_e(&cr, &e);
err = iopgtable_store_entry(obj, &e); err = omap_iopgtable_store_entry(obj, &e);
if (err) if (err)
dev_err(obj->dev, "%s: fail to store cr\n", __func__); dev_err(obj->dev, "%s: fail to store cr\n", __func__);
...@@ -136,7 +136,7 @@ static ssize_t debug_write_pagetable(struct file *file, ...@@ -136,7 +136,7 @@ static ssize_t debug_write_pagetable(struct file *file,
__err; \ __err; \
}) })
static ssize_t dump_ioptable(struct iommu *obj, char *buf, ssize_t len) static ssize_t dump_ioptable(struct omap_iommu *obj, char *buf, ssize_t len)
{ {
int i; int i;
u32 *iopgd; u32 *iopgd;
...@@ -183,7 +183,7 @@ static ssize_t dump_ioptable(struct iommu *obj, char *buf, ssize_t len) ...@@ -183,7 +183,7 @@ static ssize_t dump_ioptable(struct iommu *obj, char *buf, ssize_t len)
static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf, static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iommu *obj = file->private_data; struct omap_iommu *obj = file->private_data;
char *p, *buf; char *p, *buf;
size_t bytes; size_t bytes;
...@@ -211,7 +211,7 @@ static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf, ...@@ -211,7 +211,7 @@ static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
static ssize_t debug_read_mmap(struct file *file, char __user *userbuf, static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iommu *obj = file->private_data; struct omap_iommu *obj = file->private_data;
char *p, *buf; char *p, *buf;
struct iovm_struct *tmp; struct iovm_struct *tmp;
int uninitialized_var(i); int uninitialized_var(i);
...@@ -253,7 +253,7 @@ static ssize_t debug_read_mmap(struct file *file, char __user *userbuf, ...@@ -253,7 +253,7 @@ static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
static ssize_t debug_read_mem(struct file *file, char __user *userbuf, static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iommu *obj = file->private_data; struct omap_iommu *obj = file->private_data;
char *p, *buf; char *p, *buf;
struct iovm_struct *area; struct iovm_struct *area;
ssize_t bytes; ssize_t bytes;
...@@ -267,7 +267,7 @@ static ssize_t debug_read_mem(struct file *file, char __user *userbuf, ...@@ -267,7 +267,7 @@ static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
mutex_lock(&iommu_debug_lock); mutex_lock(&iommu_debug_lock);
area = find_iovm_area(obj, (u32)ppos); area = omap_find_iovm_area(obj, (u32)ppos);
if (IS_ERR(area)) { if (IS_ERR(area)) {
bytes = -EINVAL; bytes = -EINVAL;
goto err_out; goto err_out;
...@@ -286,7 +286,7 @@ static ssize_t debug_read_mem(struct file *file, char __user *userbuf, ...@@ -286,7 +286,7 @@ static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
static ssize_t debug_write_mem(struct file *file, const char __user *userbuf, static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iommu *obj = file->private_data; struct omap_iommu *obj = file->private_data;
struct iovm_struct *area; struct iovm_struct *area;
char *p, *buf; char *p, *buf;
...@@ -304,7 +304,7 @@ static ssize_t debug_write_mem(struct file *file, const char __user *userbuf, ...@@ -304,7 +304,7 @@ static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
goto err_out; goto err_out;
} }
area = find_iovm_area(obj, (u32)ppos); area = omap_find_iovm_area(obj, (u32)ppos);
if (IS_ERR(area)) { if (IS_ERR(area)) {
count = -EINVAL; count = -EINVAL;
goto err_out; goto err_out;
...@@ -360,7 +360,7 @@ DEBUG_FOPS(mem); ...@@ -360,7 +360,7 @@ DEBUG_FOPS(mem);
static int iommu_debug_register(struct device *dev, void *data) static int iommu_debug_register(struct device *dev, void *data)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct iommu *obj = platform_get_drvdata(pdev); struct omap_iommu *obj = platform_get_drvdata(pdev);
struct dentry *d, *parent; struct dentry *d, *parent;
if (!obj || !obj->dev) if (!obj || !obj->dev)
...@@ -396,7 +396,7 @@ static int __init iommu_debug_init(void) ...@@ -396,7 +396,7 @@ static int __init iommu_debug_init(void)
return -ENOMEM; return -ENOMEM;
iommu_debug_root = d; iommu_debug_root = d;
err = foreach_iommu_device(d, iommu_debug_register); err = omap_foreach_iommu_device(d, iommu_debug_register);
if (err) if (err)
goto err_out; goto err_out;
return 0; return 0;
......
...@@ -763,8 +763,7 @@ source "drivers/media/video/m5mols/Kconfig" ...@@ -763,8 +763,7 @@ source "drivers/media/video/m5mols/Kconfig"
config VIDEO_OMAP3 config VIDEO_OMAP3
tristate "OMAP 3 Camera support (EXPERIMENTAL)" tristate "OMAP 3 Camera support (EXPERIMENTAL)"
select OMAP_IOMMU depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
---help--- ---help---
Driver for an OMAP 3 camera controller. Driver for an OMAP 3 camera controller.
......
...@@ -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 omap_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");
...@@ -1108,7 +1115,7 @@ static void isp_save_ctx(struct isp_device *isp) ...@@ -1108,7 +1115,7 @@ static void isp_save_ctx(struct isp_device *isp)
{ {
isp_save_context(isp, isp_reg_list); isp_save_context(isp, isp_reg_list);
if (isp->iommu) if (isp->iommu)
iommu_save_ctx(isp->iommu); omap_iommu_save_ctx(isp->iommu);
} }
/* /*
...@@ -1122,7 +1129,7 @@ static void isp_restore_ctx(struct isp_device *isp) ...@@ -1122,7 +1129,7 @@ static void isp_restore_ctx(struct isp_device *isp)
{ {
isp_restore_context(isp, isp_reg_list); isp_restore_context(isp, isp_reg_list);
if (isp->iommu) if (isp->iommu)
iommu_restore_ctx(isp->iommu); omap_iommu_restore_ctx(isp->iommu);
omap3isp_ccdc_restore_context(isp); omap3isp_ccdc_restore_context(isp);
omap3isp_preview_restore_context(isp); omap3isp_preview_restore_context(isp);
} }
...@@ -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(pdev->dev.bus);
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>
...@@ -294,7 +295,9 @@ struct isp_device { ...@@ -294,7 +295,9 @@ struct isp_device {
unsigned int sbl_resources; unsigned int sbl_resources;
unsigned int subclk_resources; unsigned int subclk_resources;
struct iommu *iommu; struct omap_iommu *iommu;
struct iommu_domain *domain;
struct device *iommu_dev;
struct isp_platform_callback platform_cb; struct isp_platform_callback platform_cb;
}; };
......
...@@ -366,7 +366,7 @@ static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc, ...@@ -366,7 +366,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); omap_iommu_vfree(isp->domain, isp->iommu, req->table);
kfree(req); kfree(req);
} }
...@@ -438,15 +438,15 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc, ...@@ -438,15 +438,15 @@ 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 = omap_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;
goto done; goto done;
} }
req->iovm = find_iovm_area(isp->iommu, req->table); req->iovm = omap_find_iovm_area(isp->iommu, req->table);
if (req->iovm == NULL) { if (req->iovm == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto done; goto done;
...@@ -462,7 +462,7 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc, ...@@ -462,7 +462,7 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl, dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
req->iovm->sgt->nents, DMA_TO_DEVICE); req->iovm->sgt->nents, DMA_TO_DEVICE);
table = da_to_va(isp->iommu, req->table); table = omap_da_to_va(isp->iommu, req->table);
if (copy_from_user(table, config->lsc, req->config.size)) { if (copy_from_user(table, config->lsc, req->config.size)) {
ret = -EFAULT; ret = -EFAULT;
goto done; goto done;
...@@ -731,18 +731,19 @@ static int ccdc_config(struct isp_ccdc_device *ccdc, ...@@ -731,18 +731,19 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
/* /*
* table_new must be 64-bytes aligned, but it's * table_new must be 64-bytes aligned, but it's
* already done by iommu_vmalloc(). * already done by omap_iommu_vmalloc().
*/ */
size = ccdc->fpc.fpnum * 4; size = ccdc->fpc.fpnum * 4;
table_new = iommu_vmalloc(isp->iommu, 0, size, table_new = omap_iommu_vmalloc(isp->domain, isp->iommu,
IOMMU_FLAG); 0, 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(omap_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); omap_iommu_vfree(isp->domain, isp->iommu,
table_new);
return -EFAULT; return -EFAULT;
} }
...@@ -752,7 +753,7 @@ static int ccdc_config(struct isp_ccdc_device *ccdc, ...@@ -752,7 +753,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); omap_iommu_vfree(isp->domain, isp->iommu, table_old);
} }
return ccdc_lsc_config(ccdc, ccdc_struct); return ccdc_lsc_config(ccdc, ccdc_struct);
...@@ -2287,5 +2288,5 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp) ...@@ -2287,5 +2288,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); omap_iommu_vfree(isp->domain, isp->iommu, ccdc->fpc.fpcaddr);
} }
...@@ -366,7 +366,8 @@ static void isp_stat_bufs_free(struct ispstat *stat) ...@@ -366,7 +366,8 @@ 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); omap_iommu_vfree(isp->domain, isp->iommu,
buf->iommu_addr);
} else { } else {
if (!buf->virt_addr) if (!buf->virt_addr)
continue; continue;
...@@ -399,8 +400,8 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size) ...@@ -399,8 +400,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 = omap_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 "
...@@ -409,7 +410,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size) ...@@ -409,7 +410,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
return -ENOMEM; return -ENOMEM;
} }
iovm = find_iovm_area(isp->iommu, buf->iommu_addr); iovm = omap_find_iovm_area(isp->iommu, buf->iommu_addr);
if (!iovm || if (!iovm ||
!dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents, !dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
DMA_FROM_DEVICE)) { DMA_FROM_DEVICE)) {
...@@ -418,7 +419,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size) ...@@ -418,7 +419,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
} }
buf->iovm = iovm; buf->iovm = iovm;
buf->virt_addr = da_to_va(stat->isp->iommu, buf->virt_addr = omap_da_to_va(stat->isp->iommu,
(u32)buf->iommu_addr); (u32)buf->iommu_addr);
buf->empty = 1; buf->empty = 1;
dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated." dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
......
...@@ -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 = omap_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 = omap_iommu_vunmap(isp->domain, isp->iommu, (u32)da);
kfree(sgt); kfree(sgt);
} }
......
...@@ -33,6 +33,7 @@ struct class; ...@@ -33,6 +33,7 @@ struct class;
struct subsys_private; struct subsys_private;
struct bus_type; struct bus_type;
struct device_node; struct device_node;
struct iommu_ops;
struct bus_attribute { struct bus_attribute {
struct attribute attr; struct attribute attr;
...@@ -67,6 +68,9 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); ...@@ -67,6 +68,9 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
* @resume: Called to bring a device on this bus out of sleep mode. * @resume: Called to bring a device on this bus out of sleep mode.
* @pm: Power management operations of this bus, callback the specific * @pm: Power management operations of this bus, callback the specific
* device driver's pm-ops. * device driver's pm-ops.
* @iommu_ops IOMMU specific operations for this bus, used to attach IOMMU
* driver implementations to a bus and allow the driver to do
* bus-specific setup
* @p: The private data of the driver core, only the driver core can * @p: The private data of the driver core, only the driver core can
* touch this. * touch this.
* *
...@@ -96,6 +100,8 @@ struct bus_type { ...@@ -96,6 +100,8 @@ struct bus_type {
const struct dev_pm_ops *pm; const struct dev_pm_ops *pm;
struct iommu_ops *iommu_ops;
struct subsys_private *p; struct subsys_private *p;
}; };
......
...@@ -25,15 +25,29 @@ ...@@ -25,15 +25,29 @@
#define IOMMU_WRITE (2) #define IOMMU_WRITE (2)
#define IOMMU_CACHE (4) /* DMA cache coherency */ #define IOMMU_CACHE (4) /* DMA cache coherency */
struct iommu_ops;
struct bus_type;
struct device; struct device;
struct iommu_domain;
/* iommu fault flags */
#define IOMMU_FAULT_READ 0x0
#define IOMMU_FAULT_WRITE 0x1
typedef int (*iommu_fault_handler_t)(struct iommu_domain *,
struct device *, unsigned long, int);
struct iommu_domain { struct iommu_domain {
struct iommu_ops *ops;
void *priv; void *priv;
iommu_fault_handler_t handler;
}; };
#define IOMMU_CAP_CACHE_COHERENCY 0x1 #define IOMMU_CAP_CACHE_COHERENCY 0x1
#define IOMMU_CAP_INTR_REMAP 0x2 /* isolates device intrs */ #define IOMMU_CAP_INTR_REMAP 0x2 /* isolates device intrs */
#ifdef CONFIG_IOMMU_API
struct iommu_ops { struct iommu_ops {
int (*domain_init)(struct iommu_domain *domain); int (*domain_init)(struct iommu_domain *domain);
void (*domain_destroy)(struct iommu_domain *domain); void (*domain_destroy)(struct iommu_domain *domain);
...@@ -49,11 +63,9 @@ struct iommu_ops { ...@@ -49,11 +63,9 @@ struct iommu_ops {
unsigned long cap); unsigned long cap);
}; };
#ifdef CONFIG_IOMMU_API extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops);
extern bool iommu_present(struct bus_type *bus);
extern void register_iommu(struct iommu_ops *ops); extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus);
extern bool iommu_found(void);
extern struct iommu_domain *iommu_domain_alloc(void);
extern void iommu_domain_free(struct iommu_domain *domain); extern void iommu_domain_free(struct iommu_domain *domain);
extern int iommu_attach_device(struct iommu_domain *domain, extern int iommu_attach_device(struct iommu_domain *domain,
struct device *dev); struct device *dev);
...@@ -67,19 +79,58 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, ...@@ -67,19 +79,58 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long iova); unsigned long iova);
extern int iommu_domain_has_cap(struct iommu_domain *domain, extern int iommu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap); unsigned long cap);
extern void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler);
/**
* report_iommu_fault() - report about an IOMMU fault to the IOMMU framework
* @domain: the iommu domain where the fault has happened
* @dev: the device where the fault has happened
* @iova: the faulting address
* @flags: mmu fault flags (e.g. IOMMU_FAULT_READ/IOMMU_FAULT_WRITE/...)
*
* This function should be called by the low-level IOMMU implementations
* whenever IOMMU faults happen, to allow high-level users, that are
* interested in such events, to know about them.
*
* This event may be useful for several possible use cases:
* - mere logging of the event
* - dynamic TLB/PTE loading
* - if restarting of the faulting device is required
*
* Returns 0 on success and an appropriate error code otherwise (if dynamic
* PTE/TLB loading will one day be supported, implementations will be able
* to tell whether it succeeded or not according to this return value).
*
* Specifically, -ENOSYS is returned if a fault handler isn't installed
* (though fault handlers can also return -ENOSYS, in case they want to
* elicit the default behavior of the IOMMU drivers).
*/
static inline int report_iommu_fault(struct iommu_domain *domain,
struct device *dev, unsigned long iova, int flags)
{
int ret = -ENOSYS;
#else /* CONFIG_IOMMU_API */ /*
* if upper layers showed interest and installed a fault handler,
* invoke it.
*/
if (domain->handler)
ret = domain->handler(domain, dev, iova, flags);
static inline void register_iommu(struct iommu_ops *ops) return ret;
{
} }
static inline bool iommu_found(void) #else /* CONFIG_IOMMU_API */
struct iommu_ops {};
static inline bool iommu_present(struct bus_type *bus)
{ {
return false; return false;
} }
static inline struct iommu_domain *iommu_domain_alloc(void) static inline struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
{ {
return NULL; return NULL;
} }
...@@ -123,6 +174,11 @@ static inline int domain_has_cap(struct iommu_domain *domain, ...@@ -123,6 +174,11 @@ static inline int domain_has_cap(struct iommu_domain *domain,
return 0; return 0;
} }
static inline void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler)
{
}
#endif /* CONFIG_IOMMU_API */ #endif /* CONFIG_IOMMU_API */
#endif /* __LINUX_IOMMU_H */ #endif /* __LINUX_IOMMU_H */
...@@ -62,6 +62,8 @@ struct dma_debug_entry { ...@@ -62,6 +62,8 @@ struct dma_debug_entry {
#endif #endif
}; };
typedef bool (*match_fn)(struct dma_debug_entry *, struct dma_debug_entry *);
struct hash_bucket { struct hash_bucket {
struct list_head list; struct list_head list;
spinlock_t lock; spinlock_t lock;
...@@ -240,18 +242,37 @@ static void put_hash_bucket(struct hash_bucket *bucket, ...@@ -240,18 +242,37 @@ static void put_hash_bucket(struct hash_bucket *bucket,
spin_unlock_irqrestore(&bucket->lock, __flags); spin_unlock_irqrestore(&bucket->lock, __flags);
} }
static bool exact_match(struct dma_debug_entry *a, struct dma_debug_entry *b)
{
return ((a->dev_addr == a->dev_addr) &&
(a->dev == b->dev)) ? true : false;
}
static bool containing_match(struct dma_debug_entry *a,
struct dma_debug_entry *b)
{
if (a->dev != b->dev)
return false;
if ((b->dev_addr <= a->dev_addr) &&
((b->dev_addr + b->size) >= (a->dev_addr + a->size)))
return true;
return false;
}
/* /*
* Search a given entry in the hash bucket list * Search a given entry in the hash bucket list
*/ */
static struct dma_debug_entry *hash_bucket_find(struct hash_bucket *bucket, static struct dma_debug_entry *__hash_bucket_find(struct hash_bucket *bucket,
struct dma_debug_entry *ref) struct dma_debug_entry *ref,
match_fn match)
{ {
struct dma_debug_entry *entry, *ret = NULL; struct dma_debug_entry *entry, *ret = NULL;
int matches = 0, match_lvl, last_lvl = 0; int matches = 0, match_lvl, last_lvl = 0;
list_for_each_entry(entry, &bucket->list, list) { list_for_each_entry(entry, &bucket->list, list) {
if ((entry->dev_addr != ref->dev_addr) || if (!match(ref, entry))
(entry->dev != ref->dev))
continue; continue;
/* /*
...@@ -293,6 +314,39 @@ static struct dma_debug_entry *hash_bucket_find(struct hash_bucket *bucket, ...@@ -293,6 +314,39 @@ static struct dma_debug_entry *hash_bucket_find(struct hash_bucket *bucket,
return ret; return ret;
} }
static struct dma_debug_entry *bucket_find_exact(struct hash_bucket *bucket,
struct dma_debug_entry *ref)
{
return __hash_bucket_find(bucket, ref, exact_match);
}
static struct dma_debug_entry *bucket_find_contain(struct hash_bucket **bucket,
struct dma_debug_entry *ref,
unsigned long *flags)
{
unsigned int max_range = dma_get_max_seg_size(ref->dev);
struct dma_debug_entry *entry, index = *ref;
unsigned int range = 0;
while (range <= max_range) {
entry = __hash_bucket_find(*bucket, &index, containing_match);
if (entry)
return entry;
/*
* Nothing found, go back a hash bucket
*/
put_hash_bucket(*bucket, flags);
range += (1 << HASH_FN_SHIFT);
index.dev_addr -= (1 << HASH_FN_SHIFT);
*bucket = get_hash_bucket(&index, flags);
}
return NULL;
}
/* /*
* Add an entry to a hash bucket * Add an entry to a hash bucket
*/ */
...@@ -802,7 +856,7 @@ static void check_unmap(struct dma_debug_entry *ref) ...@@ -802,7 +856,7 @@ static void check_unmap(struct dma_debug_entry *ref)
} }
bucket = get_hash_bucket(ref, &flags); bucket = get_hash_bucket(ref, &flags);
entry = hash_bucket_find(bucket, ref); entry = bucket_find_exact(bucket, ref);
if (!entry) { if (!entry) {
err_printk(ref->dev, NULL, "DMA-API: device driver tries " err_printk(ref->dev, NULL, "DMA-API: device driver tries "
...@@ -902,7 +956,7 @@ static void check_sync(struct device *dev, ...@@ -902,7 +956,7 @@ static void check_sync(struct device *dev,
bucket = get_hash_bucket(ref, &flags); bucket = get_hash_bucket(ref, &flags);
entry = hash_bucket_find(bucket, ref); entry = bucket_find_contain(&bucket, ref, &flags);
if (!entry) { if (!entry) {
err_printk(dev, NULL, "DMA-API: device driver tries " err_printk(dev, NULL, "DMA-API: device driver tries "
...@@ -1060,7 +1114,7 @@ static int get_nr_mapped_entries(struct device *dev, ...@@ -1060,7 +1114,7 @@ static int get_nr_mapped_entries(struct device *dev,
int mapped_ents; int mapped_ents;
bucket = get_hash_bucket(ref, &flags); bucket = get_hash_bucket(ref, &flags);
entry = hash_bucket_find(bucket, ref); entry = bucket_find_exact(bucket, ref);
mapped_ents = 0; mapped_ents = 0;
if (entry) if (entry)
......
...@@ -228,12 +228,12 @@ int kvm_iommu_map_guest(struct kvm *kvm) ...@@ -228,12 +228,12 @@ int kvm_iommu_map_guest(struct kvm *kvm)
{ {
int r; int r;
if (!iommu_found()) { if (!iommu_present(&pci_bus_type)) {
printk(KERN_ERR "%s: iommu not found\n", __func__); printk(KERN_ERR "%s: iommu not found\n", __func__);
return -ENODEV; return -ENODEV;
} }
kvm->arch.iommu_domain = iommu_domain_alloc(); kvm->arch.iommu_domain = iommu_domain_alloc(&pci_bus_type);
if (!kvm->arch.iommu_domain) if (!kvm->arch.iommu_domain)
return -ENOMEM; return -ENOMEM;
......
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