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
