Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver

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>

authored by

Diana Craciun and committed by
Catalin Marinas
998fb7ba 2bcdd8f2

+46 -39
+8 -23
drivers/bus/fsl-mc/dprc-driver.c
··· 592 592 bool mc_io_created = false; 593 593 bool msi_domain_set = false; 594 594 u16 major_ver, minor_ver; 595 + struct irq_domain *mc_msi_domain; 595 596 596 597 if (!is_fsl_mc_bus_dprc(mc_dev)) 597 598 return -EINVAL; ··· 622 621 return error; 623 622 624 623 mc_io_created = true; 624 + } 625 625 626 - /* 627 - * Inherit parent MSI domain: 628 - */ 629 - dev_set_msi_domain(&mc_dev->dev, 630 - dev_get_msi_domain(parent_dev)); 631 - msi_domain_set = true; 626 + mc_msi_domain = fsl_mc_find_msi_domain(&mc_dev->dev); 627 + if (!mc_msi_domain) { 628 + dev_warn(&mc_dev->dev, 629 + "WARNING: MC bus without interrupt support\n"); 632 630 } else { 633 - /* 634 - * This is a root DPRC 635 - */ 636 - struct irq_domain *mc_msi_domain; 637 - 638 - if (dev_is_fsl_mc(parent_dev)) 639 - return -EINVAL; 640 - 641 - error = fsl_mc_find_msi_domain(parent_dev, 642 - &mc_msi_domain); 643 - if (error < 0) { 644 - dev_warn(&mc_dev->dev, 645 - "WARNING: MC bus without interrupt support\n"); 646 - } else { 647 - dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); 648 - msi_domain_set = true; 649 - } 631 + dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); 632 + msi_domain_set = true; 650 633 } 651 634 652 635 error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
+2 -2
drivers/bus/fsl-mc/fsl-mc-bus.c
··· 370 370 /** 371 371 * fsl_mc_get_root_dprc - function to traverse to the root dprc 372 372 */ 373 - static void fsl_mc_get_root_dprc(struct device *dev, 374 - struct device **root_dprc_dev) 373 + void fsl_mc_get_root_dprc(struct device *dev, 374 + struct device **root_dprc_dev) 375 375 { 376 376 if (!dev) { 377 377 *root_dprc_dev = NULL;
+18 -11
drivers/bus/fsl-mc/fsl-mc-msi.c
··· 177 177 return domain; 178 178 } 179 179 180 - int fsl_mc_find_msi_domain(struct device *mc_platform_dev, 181 - struct irq_domain **mc_msi_domain) 180 + struct irq_domain *fsl_mc_find_msi_domain(struct device *dev) 182 181 { 183 - struct irq_domain *msi_domain; 184 - struct device_node *mc_of_node = mc_platform_dev->of_node; 182 + struct irq_domain *msi_domain = NULL; 183 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 185 184 186 - msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, 187 - DOMAIN_BUS_FSL_MC_MSI); 185 + msi_domain = of_msi_map_get_device_domain(dev, mc_dev->icid, 186 + DOMAIN_BUS_FSL_MC_MSI); 187 + 188 + /* 189 + * if the msi-map property is missing assume that all the 190 + * child containers inherit the domain from the parent 191 + */ 188 192 if (!msi_domain) { 189 - pr_err("Unable to find fsl-mc MSI domain for %pOF\n", 190 - mc_of_node); 193 + struct device *root_dprc_dev; 194 + struct device *bus_dev; 191 195 192 - return -ENOENT; 196 + fsl_mc_get_root_dprc(dev, &root_dprc_dev); 197 + bus_dev = root_dprc_dev->parent; 198 + msi_domain = of_msi_get_domain(bus_dev, 199 + bus_dev->of_node, 200 + DOMAIN_BUS_FSL_MC_MSI); 193 201 } 194 202 195 - *mc_msi_domain = msi_domain; 196 - return 0; 203 + return msi_domain; 197 204 } 198 205 199 206 static void fsl_mc_msi_free_descs(struct device *dev)
+4 -2
drivers/bus/fsl-mc/fsl-mc-private.h
··· 595 595 596 596 void fsl_mc_msi_domain_free_irqs(struct device *dev); 597 597 598 - int fsl_mc_find_msi_domain(struct device *mc_platform_dev, 599 - struct irq_domain **mc_msi_domain); 598 + struct irq_domain *fsl_mc_find_msi_domain(struct device *dev); 600 599 601 600 int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, 602 601 unsigned int irq_count); ··· 611 612 void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); 612 613 613 614 bool fsl_mc_is_root_dprc(struct device *dev); 615 + 616 + void fsl_mc_get_root_dprc(struct device *dev, 617 + struct device **root_dprc_dev); 614 618 615 619 struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc *obj_desc, 616 620 struct fsl_mc_device *mc_bus_dev);
+14 -1
drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
··· 23 23 .irq_set_affinity = msi_domain_set_affinity 24 24 }; 25 25 26 + static u32 fsl_mc_msi_domain_get_msi_id(struct irq_domain *domain, 27 + struct fsl_mc_device *mc_dev) 28 + { 29 + struct device_node *of_node; 30 + u32 out_id; 31 + 32 + of_node = irq_domain_get_of_node(domain); 33 + out_id = of_msi_map_id(&mc_dev->dev, of_node, mc_dev->icid); 34 + 35 + return out_id; 36 + } 37 + 26 38 static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, 27 39 struct device *dev, 28 40 int nvec, msi_alloc_info_t *info) ··· 55 43 * NOTE: This device id corresponds to the IOMMU stream ID 56 44 * associated with the DPRC object (ICID). 57 45 */ 58 - info->scratchpad[0].ul = mc_bus_dev->icid; 46 + info->scratchpad[0].ul = fsl_mc_msi_domain_get_msi_id(msi_domain, 47 + mc_bus_dev); 59 48 msi_info = msi_get_domain_info(msi_domain->parent); 60 49 61 50 /* Allocate at least 32 MSIs, and always as a power of 2 */