diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 7848f4773d5c..1715ff0056b3 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -670,7 +670,7 @@ void iommu_set_fault_handler(struct iommu_domain *domain, } EXPORT_SYMBOL_GPL(iommu_set_fault_handler); -struct iommu_domain *iommu_domain_alloc(struct bus_type *bus, int flags) +struct iommu_domain *iommu_domain_alloc(struct bus_type *bus) { struct iommu_domain *domain; int ret; @@ -684,7 +684,7 @@ struct iommu_domain *iommu_domain_alloc(struct bus_type *bus, int flags) domain->ops = bus->iommu_ops; - ret = domain->ops->domain_init(domain, flags); + ret = domain->ops->domain_init(domain); if (ret) goto out_free; diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c index ab6b545c9164..52b7ec88369b 100644 --- a/drivers/iommu/msm_iommu-v0.c +++ b/drivers/iommu/msm_iommu-v0.c @@ -424,7 +424,7 @@ static void __program_context(struct msm_iommu_drvdata *iommu_drvdata, msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock); } -static int msm_iommu_domain_init(struct iommu_domain *domain, int flags) +static int msm_iommu_domain_init(struct iommu_domain *domain) { struct msm_iommu_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -438,9 +438,7 @@ static int msm_iommu_domain_init(struct iommu_domain *domain, int flags) if (!priv->pt.fl_table) goto fail_nomem; -#ifdef CONFIG_IOMMU_PGTABLES_L2 - priv->pt.redirect = flags & MSM_IOMMU_DOMAIN_PT_CACHEABLE; -#endif + priv->pt.redirect = 1; memset(priv->pt.fl_table, 0, SZ_16K); domain->priv = priv; @@ -1381,6 +1379,66 @@ static phys_addr_t msm_iommu_get_pt_base_addr(struct iommu_domain *domain) return __pa(priv->pt.fl_table); } +#ifdef CONFIG_IOMMU_PGTABLES_L2 +static void __do_set_redirect(struct iommu_domain *domain, void *data) +{ + struct msm_iommu_priv *priv; + int *no_redirect = data; + + mutex_lock(&msm_iommu_lock); + priv = domain->priv; + priv->pt.redirect = !(*no_redirect); + mutex_unlock(&msm_iommu_lock); +} + +static void __do_get_redirect(struct iommu_domain *domain, void *data) +{ + struct msm_iommu_priv *priv; + int *no_redirect = data; + + mutex_lock(&msm_iommu_lock); + priv = domain->priv; + *no_redirect = !priv->pt.redirect; + mutex_unlock(&msm_iommu_lock); +} + +#else + +static void __do_set_redirect(struct iommu_domain *domain, void *data) +{ +} + +static void __do_get_redirect(struct iommu_domain *domain, void *data) +{ +} +#endif + +static int msm_iommu_domain_set_attr(struct iommu_domain *domain, + enum iommu_attr attr, void *data) +{ + switch (attr) { + case DOMAIN_ATTR_COHERENT_HTW_DISABLE: + __do_set_redirect(domain, data); + break; + default: + return -EINVAL; + } + return 0; +} + +static int msm_iommu_domain_get_attr(struct iommu_domain *domain, + enum iommu_attr attr, void *data) +{ + switch (attr) { + case DOMAIN_ATTR_COHERENT_HTW_DISABLE: + __do_get_redirect(domain, data); + break; + default: + return -EINVAL; + } + return 0; +} + static struct iommu_ops msm_iommu_ops = { .domain_init = msm_iommu_domain_init, .domain_destroy = msm_iommu_domain_destroy, @@ -1394,6 +1452,8 @@ static struct iommu_ops msm_iommu_ops = { .domain_has_cap = msm_iommu_domain_has_cap, .get_pt_base_addr = msm_iommu_get_pt_base_addr, .pgsize_bitmap = MSM_IOMMU_PGSIZES, + .domain_set_attr = msm_iommu_domain_set_attr, + .domain_get_attr = msm_iommu_domain_get_attr, }; static int __init get_tex_class(int icp, int ocp, int mt, int nos) diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c index 4f7c3f18b586..b7399ed84b68 100644 --- a/drivers/iommu/msm_iommu-v1.c +++ b/drivers/iommu/msm_iommu-v1.c @@ -740,7 +740,7 @@ static void __program_context(struct msm_iommu_drvdata *iommu_drvdata, mb(); } -static int msm_iommu_domain_init(struct iommu_domain *domain, int flags) +static int msm_iommu_domain_init(struct iommu_domain *domain) { struct msm_iommu_priv *priv; @@ -748,9 +748,7 @@ static int msm_iommu_domain_init(struct iommu_domain *domain, int flags) if (!priv) goto fail_nomem; -#ifdef CONFIG_IOMMU_PGTABLES_L2 - priv->pt.redirect = flags & MSM_IOMMU_DOMAIN_PT_CACHEABLE; -#endif + priv->pt.redirect = 1; INIT_LIST_HEAD(&priv->list_attached); if (msm_iommu_pagetable_alloc(&priv->pt)) @@ -1451,6 +1449,66 @@ static void msm_iommu_build_dump_regs_table(void) DUMP_REG_INIT(DUMP_REG_CBFRSYNRA_N, CBFRSYNRA, 1, DRT_GLOBAL_REG_N); } +#ifdef CONFIG_IOMMU_PGTABLES_L2 +static void __do_set_redirect(struct iommu_domain *domain, void *data) +{ + struct msm_iommu_priv *priv; + int *no_redirect = data; + + mutex_lock(&msm_iommu_lock); + priv = domain->priv; + priv->pt.redirect = !(*no_redirect); + mutex_unlock(&msm_iommu_lock); +} + +static void __do_get_redirect(struct iommu_domain *domain, void *data) +{ + struct msm_iommu_priv *priv; + int *no_redirect = data; + + mutex_lock(&msm_iommu_lock); + priv = domain->priv; + *no_redirect = !priv->pt.redirect; + mutex_unlock(&msm_iommu_lock); +} + +#else + +static void __do_set_redirect(struct iommu_domain *domain, void *data) +{ +} + +static void __do_get_redirect(struct iommu_domain *domain, void *data) +{ +} +#endif + +static int msm_iommu_domain_set_attr(struct iommu_domain *domain, + enum iommu_attr attr, void *data) +{ + switch (attr) { + case DOMAIN_ATTR_COHERENT_HTW_DISABLE: + __do_set_redirect(domain, data); + break; + default: + return -EINVAL; + } + return 0; +} + +static int msm_iommu_domain_get_attr(struct iommu_domain *domain, + enum iommu_attr attr, void *data) +{ + switch (attr) { + case DOMAIN_ATTR_COHERENT_HTW_DISABLE: + __do_get_redirect(domain, data); + break; + default: + return -EINVAL; + } + return 0; +} + static struct iommu_ops msm_iommu_ops = { .domain_init = msm_iommu_domain_init, .domain_destroy = msm_iommu_domain_destroy, @@ -1464,6 +1522,8 @@ static struct iommu_ops msm_iommu_ops = { .domain_has_cap = msm_iommu_domain_has_cap, .get_pt_base_addr = msm_iommu_get_pt_base_addr, .pgsize_bitmap = MSM_IOMMU_PGSIZES, + .domain_set_attr = msm_iommu_domain_set_attr, + .domain_get_attr = msm_iommu_domain_get_attr, }; static int __init msm_iommu_init(void) diff --git a/drivers/iommu/msm_iommu_domains.c b/drivers/iommu/msm_iommu_domains.c index 0a49e0b535e4..a2aac1bccebc 100644 --- a/drivers/iommu/msm_iommu_domains.c +++ b/drivers/iommu/msm_iommu_domains.c @@ -468,6 +468,7 @@ int msm_register_domain(struct msm_iova_layout *layout) struct msm_iova_data *data; struct mem_pool *pools; struct bus_type *bus; + int no_redirect; if (!layout) return -EINVAL; @@ -524,10 +525,14 @@ int msm_register_domain(struct msm_iova_layout *layout) if (data->domain_num < 0) goto free_pools; - data->domain = iommu_domain_alloc(bus, layout->domain_flags); + data->domain = iommu_domain_alloc(bus); if (!data->domain) goto free_domain_num; + no_redirect = !(layout->domain_flags & MSM_IOMMU_DOMAIN_PT_CACHEABLE); + iommu_domain_set_attr(data->domain, + DOMAIN_ATTR_COHERENT_HTW_DISABLE, &no_redirect); + msm_iommu_set_client_name(data->domain, layout->client_name); add_domain(data); diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c index 69947d932b2c..2537c61e5a75 100644 --- a/drivers/iommu/msm_iommu_sec.c +++ b/drivers/iommu/msm_iommu_sec.c @@ -677,7 +677,7 @@ static int msm_iommu_sec_ptbl_unmap(struct msm_iommu_drvdata *iommu_drvdata, return ret; } -static int msm_iommu_domain_init(struct iommu_domain *domain, int flags) +static int msm_iommu_domain_init(struct iommu_domain *domain) { struct msm_iommu_priv *priv; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 7cfa3fbaaa2c..c7f4ec80edb3 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -66,6 +66,7 @@ enum iommu_attr { DOMAIN_ATTR_GEOMETRY, DOMAIN_ATTR_PAGING, DOMAIN_ATTR_WINDOWS, + DOMAIN_ATTR_COHERENT_HTW_DISABLE, DOMAIN_ATTR_MAX, }; @@ -88,7 +89,7 @@ enum iommu_attr { * @pgsize_bitmap: bitmap of supported page sizes */ struct iommu_ops { - int (*domain_init)(struct iommu_domain *domain, int flags); + int (*domain_init)(struct iommu_domain *domain); void (*domain_destroy)(struct iommu_domain *domain); int (*attach_dev)(struct iommu_domain *domain, struct device *dev); void (*detach_dev)(struct iommu_domain *domain, struct device *dev); @@ -133,7 +134,7 @@ struct iommu_ops { extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops); extern bool iommu_present(struct bus_type *bus); -extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus, int flags); +extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus); extern struct iommu_group *iommu_group_get_by_id(int id); extern void iommu_domain_free(struct iommu_domain *domain); extern int iommu_attach_device(struct iommu_domain *domain, @@ -239,7 +240,7 @@ static inline bool iommu_present(struct bus_type *bus) return false; } -static inline struct iommu_domain *iommu_domain_alloc(struct bus_type *bus, int flags) +static inline struct iommu_domain *iommu_domain_alloc(struct bus_type *bus) { return NULL; } diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c index fb9deef0b33f..c329c8fc57f4 100644 --- a/virt/kvm/iommu.c +++ b/virt/kvm/iommu.c @@ -244,7 +244,7 @@ int kvm_iommu_map_guest(struct kvm *kvm) mutex_lock(&kvm->slots_lock); - kvm->arch.iommu_domain = iommu_domain_alloc(&pci_bus_type, 0); + kvm->arch.iommu_domain = iommu_domain_alloc(&pci_bus_type); if (!kvm->arch.iommu_domain) { r = -ENOMEM; goto out_unlock;