iommu/qcom_iommu: Add an IOMMU_IDENTITIY_DOMAIN
authorJason Gunthorpe <jgg@nvidia.com>
Wed, 13 Sep 2023 13:43:49 +0000 (10:43 -0300)
committerJoerg Roedel <jroedel@suse.de>
Mon, 25 Sep 2023 09:41:01 +0000 (11:41 +0200)
This brings back the ops->detach_dev() code that commit
1b932ceddd19 ("iommu: Remove detach_dev callbacks") deleted and turns it
into an IDENTITY domain.

Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/16-v8-81230027b2fa+9d-iommu_all_defdom_jgg@nvidia.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/arm/arm-smmu/qcom_iommu.c

index 775a3cbaff4ed0522fadb2db80fd2e00f6dc1acc..bc45d18f350cb9d14453bc0cab27f5165cd2e0b6 100644 (file)
@@ -400,6 +400,44 @@ static int qcom_iommu_attach_dev(struct iommu_domain *domain, struct device *dev
        return 0;
 }
 
+static int qcom_iommu_identity_attach(struct iommu_domain *identity_domain,
+                                     struct device *dev)
+{
+       struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+       struct qcom_iommu_domain *qcom_domain;
+       struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+       struct qcom_iommu_dev *qcom_iommu = to_iommu(dev);
+       unsigned int i;
+
+       if (domain == identity_domain || !domain)
+               return 0;
+
+       qcom_domain = to_qcom_iommu_domain(domain);
+       if (WARN_ON(!qcom_domain->iommu))
+               return -EINVAL;
+
+       pm_runtime_get_sync(qcom_iommu->dev);
+       for (i = 0; i < fwspec->num_ids; i++) {
+               struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
+
+               /* Disable the context bank: */
+               iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0);
+
+               ctx->domain = NULL;
+       }
+       pm_runtime_put_sync(qcom_iommu->dev);
+       return 0;
+}
+
+static struct iommu_domain_ops qcom_iommu_identity_ops = {
+       .attach_dev = qcom_iommu_identity_attach,
+};
+
+static struct iommu_domain qcom_iommu_identity_domain = {
+       .type = IOMMU_DOMAIN_IDENTITY,
+       .ops = &qcom_iommu_identity_ops,
+};
+
 static int qcom_iommu_map(struct iommu_domain *domain, unsigned long iova,
                          phys_addr_t paddr, size_t pgsize, size_t pgcount,
                          int prot, gfp_t gfp, size_t *mapped)
@@ -565,6 +603,7 @@ static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
 }
 
 static const struct iommu_ops qcom_iommu_ops = {
+       .identity_domain = &qcom_iommu_identity_domain,
        .capable        = qcom_iommu_capable,
        .domain_alloc   = qcom_iommu_domain_alloc,
        .probe_device   = qcom_iommu_probe_device,