Add the tiny bit of infrastructure to be able to use platform MSI
instead of the current hack. This means providing a write_msi_msg
callback, as well as irq domain and devid retrieval helpers.

Signed-off-by: Marc Zyngier <[email protected]>
---
 drivers/bus/fsl-mc/fsl-mc-msi.c     | 50 ++++++++++++++++++++++++-----
 drivers/bus/fsl-mc/fsl-mc-private.h |  1 +
 include/linux/fsl/mc.h              |  2 ++
 3 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c
index 82cd69f7884c6..c9f50969e88ce 100644
--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -110,13 +110,8 @@ static void __fsl_mc_msi_write_msg(struct fsl_mc_device 
*mc_bus_dev,
        }
 }
 
-/*
- * NOTE: This function is invoked with interrupts disabled
- */
-static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
-                                struct msi_msg *msg)
+static void fsl_mc_write_msi_msg(struct msi_desc *msi_desc, struct msi_msg 
*msg)
 {
-       struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
        struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
        struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
        struct fsl_mc_device_irq *mc_dev_irq =
@@ -130,6 +125,17 @@ static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
        __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq, msi_desc);
 }
 
+/*
+ * NOTE: This function is invoked with interrupts disabled
+ */
+static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
+                                struct msi_msg *msg)
+{
+       struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
+
+       fsl_mc_write_msi_msg(msi_desc, msg);
+}
+
 static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
 {
        struct irq_chip *chip = info->chip;
@@ -209,6 +215,20 @@ struct irq_domain *fsl_mc_find_msi_domain(struct device 
*dev)
        return msi_domain;
 }
 
+struct irq_domain *fsl_mc_get_msi_parent(struct device *dev)
+{
+       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+       struct device *root_dprc_dev;
+       struct device *bus_dev;
+
+       fsl_mc_get_root_dprc(dev, &root_dprc_dev);
+       bus_dev = root_dprc_dev->parent;
+
+       return (bus_dev->of_node ?
+               of_msi_get_domain(bus_dev, bus_dev->of_node, DOMAIN_BUS_NEXUS) :
+               iort_get_device_domain(bus_dev, mc_dev->icid, 
DOMAIN_BUS_NEXUS));
+}
+
 int fsl_mc_msi_domain_alloc_irqs(struct device *dev,  unsigned int irq_count)
 {
        int error = msi_setup_device_data(dev);
@@ -220,8 +240,10 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,  
unsigned int irq_count)
         * NOTE: Calling this function will trigger the invocation of the
         * its_fsl_mc_msi_prepare() callback
         */
-       error = msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, 
irq_count - 1);
-
+       if (!irq_domain_is_msi_parent(dev_get_msi_domain(dev)))
+               error = msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, 
irq_count - 1);
+       else
+               error = platform_device_msi_init_and_alloc_irqs(dev, irq_count, 
fsl_mc_write_msi_msg);
        if (error)
                dev_err(dev, "Failed to allocate IRQs\n");
        return error;
@@ -231,3 +253,15 @@ void fsl_mc_msi_domain_free_irqs(struct device *dev)
 {
        msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
 }
+
+u32 fsl_mc_get_msi_id(struct device *dev)
+{
+       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+       struct device *root_dprc_dev;
+
+       fsl_mc_get_root_dprc(dev, &root_dprc_dev);
+
+       return (root_dprc_dev->parent->of_node ?
+               of_msi_xlate(dev, NULL, mc_dev->icid) :
+               iort_msi_map_id(dev, mc_dev->icid));
+}
diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h 
b/drivers/bus/fsl-mc/fsl-mc-private.h
index beed4c53533d8..44868f874fd66 100644
--- a/drivers/bus/fsl-mc/fsl-mc-private.h
+++ b/drivers/bus/fsl-mc/fsl-mc-private.h
@@ -642,6 +642,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
 void fsl_mc_msi_domain_free_irqs(struct device *dev);
 
 struct irq_domain *fsl_mc_find_msi_domain(struct device *dev);
+struct irq_domain *fsl_mc_get_msi_parent(struct device *dev);
 
 int __must_check fsl_create_mc_io(struct device *dev,
                                  phys_addr_t mc_portal_phys_addr,
diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
index 897d6211c1635..bcc38c0fc230a 100644
--- a/include/linux/fsl/mc.h
+++ b/include/linux/fsl/mc.h
@@ -361,9 +361,11 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct 
fsl_mc_command *cmd);
 
 #ifdef CONFIG_FSL_MC_BUS
 #define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type)
+u32 fsl_mc_get_msi_id(struct device *dev);
 #else
 /* If fsl-mc bus is not present device cannot belong to fsl-mc bus */
 #define dev_is_fsl_mc(_dev) (0)
+#define fsl_mc_get_msi_id(_dev)        (0)
 #endif
 
 /* Macro to check if a device is a container device */
-- 
2.47.3


Reply via email to