bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver
authorDiana Craciun <diana.craciun@oss.nxp.com>
Fri, 19 Jun 2020 08:20:12 +0000 (09:20 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Tue, 28 Jul 2020 14:51:32 +0000 (15:51 +0100)
The DPRC driver is not taking into account the msi-map property
and assumes that the icid is the same as the stream ID. Although
this assumption is correct, generalize the code to include a
translation between icid and streamID.

Furthermore do not just copy the MSI domain from parent (for child
containers), but use the information provided by the msi-map property.

If the msi-map property is missing from the device tree retain the old
behaviour for backward compatibility ie the child DPRC objects
inherit the MSI domain from the parent.

Signed-off-by: Diana Craciun <diana.craciun@oss.nxp.com>
Acked-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20200619082013.13661-12-lorenzo.pieralisi@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
drivers/bus/fsl-mc/dprc-driver.c
drivers/bus/fsl-mc/fsl-mc-bus.c
drivers/bus/fsl-mc/fsl-mc-msi.c
drivers/bus/fsl-mc/fsl-mc-private.h
drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c

index c8b1c38..189bff2 100644 (file)
@@ -592,6 +592,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
        bool mc_io_created = false;
        bool msi_domain_set = false;
        u16 major_ver, minor_ver;
+       struct irq_domain *mc_msi_domain;
 
        if (!is_fsl_mc_bus_dprc(mc_dev))
                return -EINVAL;
@@ -621,31 +622,15 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
                        return error;
 
                mc_io_created = true;
+       }
 
-               /*
-                * Inherit parent MSI domain:
-                */
-               dev_set_msi_domain(&mc_dev->dev,
-                                  dev_get_msi_domain(parent_dev));
-               msi_domain_set = true;
+       mc_msi_domain = fsl_mc_find_msi_domain(&mc_dev->dev);
+       if (!mc_msi_domain) {
+               dev_warn(&mc_dev->dev,
+                        "WARNING: MC bus without interrupt support\n");
        } else {
-               /*
-                * This is a root DPRC
-                */
-               struct irq_domain *mc_msi_domain;
-
-               if (dev_is_fsl_mc(parent_dev))
-                       return -EINVAL;
-
-               error = fsl_mc_find_msi_domain(parent_dev,
-                                              &mc_msi_domain);
-               if (error < 0) {
-                       dev_warn(&mc_dev->dev,
-                                "WARNING: MC bus without interrupt support\n");
-               } else {
-                       dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
-                       msi_domain_set = true;
-               }
+               dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
+               msi_domain_set = true;
        }
 
        error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
index 8ead3f0..824ff77 100644 (file)
@@ -370,8 +370,8 @@ EXPORT_SYMBOL_GPL(fsl_mc_get_version);
 /**
  * fsl_mc_get_root_dprc - function to traverse to the root dprc
  */
-static void fsl_mc_get_root_dprc(struct device *dev,
-                                struct device **root_dprc_dev)
+void fsl_mc_get_root_dprc(struct device *dev,
+                        struct device **root_dprc_dev)
 {
        if (!dev) {
                *root_dprc_dev = NULL;
index 8b9c66d..e7bbff4 100644 (file)
@@ -177,23 +177,30 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
        return domain;
 }
 
-int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
-                          struct irq_domain **mc_msi_domain)
+struct irq_domain *fsl_mc_find_msi_domain(struct device *dev)
 {
-       struct irq_domain *msi_domain;
-       struct device_node *mc_of_node = mc_platform_dev->of_node;
+       struct irq_domain *msi_domain = NULL;
+       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
 
-       msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
-                                      DOMAIN_BUS_FSL_MC_MSI);
-       if (!msi_domain) {
-               pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
-                      mc_of_node);
+       msi_domain = of_msi_map_get_device_domain(dev, mc_dev->icid,
+                                                 DOMAIN_BUS_FSL_MC_MSI);
 
-               return -ENOENT;
+       /*
+        * if the msi-map property is missing assume that all the
+        * child containers inherit the domain from the parent
+        */
+       if (!msi_domain) {
+               struct device *root_dprc_dev;
+               struct device *bus_dev;
+
+               fsl_mc_get_root_dprc(dev, &root_dprc_dev);
+               bus_dev = root_dprc_dev->parent;
+               msi_domain = of_msi_get_domain(bus_dev,
+                                              bus_dev->of_node,
+                                              DOMAIN_BUS_FSL_MC_MSI);
        }
 
-       *mc_msi_domain = msi_domain;
-       return 0;
+       return msi_domain;
 }
 
 static void fsl_mc_msi_free_descs(struct device *dev)
index 21ca8c7..7a46a12 100644 (file)
@@ -595,8 +595,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
 
 void fsl_mc_msi_domain_free_irqs(struct device *dev);
 
-int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
-                          struct irq_domain **mc_msi_domain);
+struct irq_domain *fsl_mc_find_msi_domain(struct device *dev);
 
 int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
                             unsigned int irq_count);
@@ -613,6 +612,9 @@ void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
 
 bool fsl_mc_is_root_dprc(struct device *dev);
 
+void fsl_mc_get_root_dprc(struct device *dev,
+                        struct device **root_dprc_dev);
+
 struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc *obj_desc,
                                           struct fsl_mc_device *mc_bus_dev);
 
index 606efa6..a5c8d57 100644 (file)
@@ -23,6 +23,18 @@ static struct irq_chip its_msi_irq_chip = {
        .irq_set_affinity = msi_domain_set_affinity
 };
 
+static u32 fsl_mc_msi_domain_get_msi_id(struct irq_domain *domain,
+                                       struct fsl_mc_device *mc_dev)
+{
+       struct device_node *of_node;
+       u32 out_id;
+
+       of_node = irq_domain_get_of_node(domain);
+       out_id = of_msi_map_id(&mc_dev->dev, of_node, mc_dev->icid);
+
+       return out_id;
+}
+
 static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
                                  struct device *dev,
                                  int nvec, msi_alloc_info_t *info)
@@ -43,7 +55,8 @@ static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
         * NOTE: This device id corresponds to the IOMMU stream ID
         * associated with the DPRC object (ICID).
         */
-       info->scratchpad[0].ul = mc_bus_dev->icid;
+       info->scratchpad[0].ul = fsl_mc_msi_domain_get_msi_id(msi_domain,
+                                                             mc_bus_dev);
        msi_info = msi_get_domain_info(msi_domain->parent);
 
        /* Allocate at least 32 MSIs, and always as a power of 2 */