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...@linux.intel.com>
Reviewed-by: Jerry Snitselaar <jsnit...@redhat.com>
Signed-off-by: Jason Gunthorpe <j...@nvidia.com>
---
 drivers/iommu/fsl_pamu_domain.c | 41 ++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index 4ac0e247ec2b51..e9d2bff4659b7c 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -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,
-- 
2.42.0

Reply via email to