]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/iommu/arm-smmu.c
Merge branches 'iommu/fixes', 'x86/vt-d', 'x86/amd', 'arm/smmu', 'arm/tegra' and...
[karo-tx-linux.git] / drivers / iommu / arm-smmu.c
index 6ac1846692950013d7a784472d3c42175b93893a..9f7e1d34a32bc8ec75c6470260c66f839419f502 100644 (file)
@@ -343,6 +343,7 @@ struct arm_smmu_domain {
        struct arm_smmu_cfg             cfg;
        enum arm_smmu_domain_stage      stage;
        struct mutex                    init_mutex; /* Protects smmu pointer */
+       struct iommu_domain             domain;
 };
 
 static struct iommu_ops arm_smmu_ops;
@@ -360,6 +361,11 @@ static struct arm_smmu_option_prop arm_smmu_options[] = {
        { 0, NULL},
 };
 
+static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
+{
+       return container_of(dom, struct arm_smmu_domain, domain);
+}
+
 static void parse_driver_options(struct arm_smmu_device *smmu)
 {
        int i = 0;
@@ -645,7 +651,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
        u32 fsr, far, fsynr, resume;
        unsigned long iova;
        struct iommu_domain *domain = dev;
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
        struct arm_smmu_device *smmu = smmu_domain->smmu;
        void __iomem *cb_base;
@@ -840,7 +846,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
        struct io_pgtable_ops *pgtbl_ops;
        struct io_pgtable_cfg pgtbl_cfg;
        enum io_pgtable_fmt fmt;
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
 
        mutex_lock(&smmu_domain->init_mutex);
@@ -962,7 +968,7 @@ out_unlock:
 
 static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 {
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_device *smmu = smmu_domain->smmu;
        struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
        void __iomem *cb_base;
@@ -989,10 +995,12 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
        __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
 }
 
-static int arm_smmu_domain_init(struct iommu_domain *domain)
+static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 {
        struct arm_smmu_domain *smmu_domain;
 
+       if (type != IOMMU_DOMAIN_UNMANAGED)
+               return NULL;
        /*
         * Allocate the domain and initialise some of its data structures.
         * We can't really do anything meaningful until we've added a
@@ -1000,17 +1008,17 @@ static int arm_smmu_domain_init(struct iommu_domain *domain)
         */
        smmu_domain = kzalloc(sizeof(*smmu_domain), GFP_KERNEL);
        if (!smmu_domain)
-               return -ENOMEM;
+               return NULL;
 
        mutex_init(&smmu_domain->init_mutex);
        spin_lock_init(&smmu_domain->pgtbl_lock);
-       domain->priv = smmu_domain;
-       return 0;
+
+       return &smmu_domain->domain;
 }
 
-static void arm_smmu_domain_destroy(struct iommu_domain *domain)
+static void arm_smmu_domain_free(struct iommu_domain *domain)
 {
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 
        /*
         * Free the domain resources. We assume that all devices have
@@ -1147,7 +1155,7 @@ static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain,
 static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
        int ret;
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_device *smmu;
        struct arm_smmu_master_cfg *cfg;
 
@@ -1191,7 +1199,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 
 static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
 {
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_master_cfg *cfg;
 
        cfg = find_smmu_master_cfg(dev);
@@ -1207,7 +1215,7 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
 {
        int ret;
        unsigned long flags;
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct io_pgtable_ops *ops= smmu_domain->pgtbl_ops;
 
        if (!ops)
@@ -1224,7 +1232,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
 {
        size_t ret;
        unsigned long flags;
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct io_pgtable_ops *ops= smmu_domain->pgtbl_ops;
 
        if (!ops)
@@ -1239,7 +1247,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
 static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
                                              dma_addr_t iova)
 {
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_device *smmu = smmu_domain->smmu;
        struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
        struct io_pgtable_ops *ops= smmu_domain->pgtbl_ops;
@@ -1285,17 +1293,20 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
 {
        phys_addr_t ret;
        unsigned long flags;
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct io_pgtable_ops *ops= smmu_domain->pgtbl_ops;
 
        if (!ops)
                return 0;
 
        spin_lock_irqsave(&smmu_domain->pgtbl_lock, flags);
-       if (smmu_domain->smmu->features & ARM_SMMU_FEAT_TRANS_OPS)
+       if (smmu_domain->smmu->features & ARM_SMMU_FEAT_TRANS_OPS &&
+                       smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
                ret = arm_smmu_iova_to_phys_hard(domain, iova);
-       else
+       } else {
                ret = ops->iova_to_phys(ops, iova);
+       }
+
        spin_unlock_irqrestore(&smmu_domain->pgtbl_lock, flags);
 
        return ret;
@@ -1415,7 +1426,7 @@ static void arm_smmu_remove_device(struct device *dev)
 static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
                                    enum iommu_attr attr, void *data)
 {
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 
        switch (attr) {
        case DOMAIN_ATTR_NESTING:
@@ -1430,7 +1441,7 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
                                    enum iommu_attr attr, void *data)
 {
        int ret = 0;
-       struct arm_smmu_domain *smmu_domain = domain->priv;
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 
        mutex_lock(&smmu_domain->init_mutex);
 
@@ -1458,8 +1469,8 @@ out_unlock:
 
 static struct iommu_ops arm_smmu_ops = {
        .capable                = arm_smmu_capable,
-       .domain_init            = arm_smmu_domain_init,
-       .domain_destroy         = arm_smmu_domain_destroy,
+       .domain_alloc           = arm_smmu_domain_alloc,
+       .domain_free            = arm_smmu_domain_free,
        .attach_dev             = arm_smmu_attach_dev,
        .detach_dev             = arm_smmu_detach_dev,
        .map                    = arm_smmu_map,
@@ -1582,7 +1593,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
                return -ENODEV;
        }
 
-       if (smmu->version == 1 || (!(id & ID0_ATOSNS) && (id & ID0_S1TS))) {
+       if ((id & ID0_S1TS) && ((smmu->version == 1) || (id & ID0_ATOSNS))) {
                smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;
                dev_notice(smmu->dev, "\taddress translation ops\n");
        }