iommu/fsl_pamu: Implement a PLATFORM domain
authorJason Gunthorpe <jgg@nvidia.com>
Wed, 13 Sep 2023 13:43:38 +0000 (10:43 -0300)
committerJoerg Roedel <jroedel@suse.de>
Mon, 25 Sep 2023 09:40:54 +0000 (11:40 +0200)
This driver is nonsensical. To not block migrating the core API away from
NULL default_domains give it a hacky of a PLATFORM domain that keeps it
working exactly as it always did.

Leave some comments around to warn away any future people looking at this.

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/5-v8-81230027b2fa+9d-iommu_all_defdom_jgg@nvidia.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/fsl_pamu_domain.c

index 4ac0e247ec2b51777b2b30d73e8d17fb2c401054..e9d2bff4659b7c09f4e14ea14032c861c088f7e1 100644 (file)
@@ -196,6 +196,13 @@ static struct iommu_domain *fsl_pamu_domain_alloc(unsigned type)
 {
        struct fsl_dma_domain *dma_domain;
 
+       /*
+        * FIXME: This isn't creating an unmanaged domain since the
+        * default_domain_ops do not have any map/unmap function it doesn't meet
+        * the requirements for __IOMMU_DOMAIN_PAGING. The only purpose seems to
+        * allow drivers/soc/fsl/qbman/qman_portal.c to do
+        * fsl_pamu_configure_l1_stash()
+        */
        if (type != IOMMU_DOMAIN_UNMANAGED)
                return NULL;
 
@@ -283,15 +290,33 @@ static int fsl_pamu_attach_device(struct iommu_domain *domain,
        return ret;
 }
 
-static void fsl_pamu_set_platform_dma(struct device *dev)
+/*
+ * FIXME: fsl/pamu is completely broken in terms of how it works with the iommu
+ * API. Immediately after probe the HW is left in an IDENTITY translation and
+ * the driver provides a non-working UNMANAGED domain that it can switch over
+ * to. However it cannot switch back to an IDENTITY translation, instead it
+ * switches to what looks like BLOCKING.
+ */
+static int fsl_pamu_platform_attach(struct iommu_domain *platform_domain,
+                                   struct device *dev)
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-       struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
+       struct fsl_dma_domain *dma_domain;
        const u32 *prop;
        int len;
        struct pci_dev *pdev = NULL;
        struct pci_controller *pci_ctl;
 
+       /*
+        * Hack to keep things working as they always have, only leaving an
+        * UNMANAGED domain makes it BLOCKING.
+        */
+       if (domain == platform_domain || !domain ||
+           domain->type != IOMMU_DOMAIN_UNMANAGED)
+               return 0;
+
+       dma_domain = to_fsl_dma_domain(domain);
+
        /*
         * Use LIODN of the PCI controller while detaching a
         * PCI device.
@@ -312,8 +337,18 @@ static void fsl_pamu_set_platform_dma(struct device *dev)
                detach_device(dev, dma_domain);
        else
                pr_debug("missing fsl,liodn property at %pOF\n", dev->of_node);
+       return 0;
 }
 
+static struct iommu_domain_ops fsl_pamu_platform_ops = {
+       .attach_dev = fsl_pamu_platform_attach,
+};
+
+static struct iommu_domain fsl_pamu_platform_domain = {
+       .type = IOMMU_DOMAIN_PLATFORM,
+       .ops = &fsl_pamu_platform_ops,
+};
+
 /* Set the domain stash attribute */
 int fsl_pamu_configure_l1_stash(struct iommu_domain *domain, u32 cpu)
 {
@@ -395,11 +430,11 @@ static struct iommu_device *fsl_pamu_probe_device(struct device *dev)
 }
 
 static const struct iommu_ops fsl_pamu_ops = {
+       .default_domain = &fsl_pamu_platform_domain,
        .capable        = fsl_pamu_capable,
        .domain_alloc   = fsl_pamu_domain_alloc,
        .probe_device   = fsl_pamu_probe_device,
        .device_group   = fsl_pamu_device_group,
-       .set_platform_dma_ops = fsl_pamu_set_platform_dma,
        .default_domain_ops = &(const struct iommu_domain_ops) {
                .attach_dev     = fsl_pamu_attach_device,
                .iova_to_phys   = fsl_pamu_iova_to_phys,