@@ -18,6 +18,8 @@
#include <linux/irqchip/arm-gic-v3.h>
+#include "irq-gic-msi-lib.h"
+
struct mbi_range {
u32 spi_start;
u32 nr_spis;
@@ -29,6 +31,15 @@ static phys_addr_t mbi_phys_base;
static struct mbi_range *mbi_ranges;
static unsigned int mbi_range_nr;
+static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ msg[0].address_hi = upper_32_bits(mbi_phys_base + GICD_SETSPI_NSR);
+ msg[0].address_lo = lower_32_bits(mbi_phys_base + GICD_SETSPI_NSR);
+ msg[0].data = data->hwirq;
+
+ iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
+}
+
static struct irq_chip mbi_irq_chip = {
.name = "MBI",
.irq_mask = irq_chip_mask_parent,
@@ -36,11 +47,11 @@ static struct irq_chip mbi_irq_chip = {
.irq_eoi = irq_chip_eoi_parent,
.irq_set_type = irq_chip_set_type_parent,
.irq_set_affinity = irq_chip_set_affinity_parent,
+ .irq_compose_msi_msg = mbi_compose_msi_msg,
};
-static int mbi_irq_gic_domain_alloc(struct irq_domain *domain,
- unsigned int virq,
- irq_hw_number_t hwirq)
+static int mbi_irq_gic_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq)
{
struct irq_fwspec fwspec;
struct irq_data *d;
@@ -138,85 +149,30 @@ static void mbi_irq_domain_free(struct i
}
static const struct irq_domain_ops mbi_domain_ops = {
+ .select = gic_msi_lib_irq_domain_select,
.alloc = mbi_irq_domain_alloc,
.free = mbi_irq_domain_free,
};
-static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-{
- msg[0].address_hi = upper_32_bits(mbi_phys_base + GICD_SETSPI_NSR);
- msg[0].address_lo = lower_32_bits(mbi_phys_base + GICD_SETSPI_NSR);
- msg[0].data = data->parent_data->hwirq;
-
- iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
-}
-
-#ifdef CONFIG_PCI_MSI
-/* PCI-specific irqchip */
-static void mbi_mask_msi_irq(struct irq_data *d)
-{
- pci_msi_mask_irq(d);
- irq_chip_mask_parent(d);
-}
+#define MBI_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
+ MSI_FLAG_USE_DEF_CHIP_OPS)
-static void mbi_unmask_msi_irq(struct irq_data *d)
-{
- pci_msi_unmask_irq(d);
- irq_chip_unmask_parent(d);
-}
+#define MBI_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \
+ MSI_FLAG_PCI_MSIX | \
+ MSI_FLAG_MULTI_PCI_MSI)
-static struct irq_chip mbi_msi_irq_chip = {
- .name = "MSI",
- .irq_mask = mbi_mask_msi_irq,
- .irq_unmask = mbi_unmask_msi_irq,
- .irq_eoi = irq_chip_eoi_parent,
- .irq_compose_msi_msg = mbi_compose_msi_msg,
+static const struct msi_parent_ops gic_v3_mbi_msi_parent_ops = {
+ .supported_flags = MBI_MSI_FLAGS_SUPPORTED,
+ .required_flags = MBI_MSI_FLAGS_REQUIRED,
+ .bus_select_token = DOMAIN_BUS_NEXUS,
+ .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
+ .prefix = "MBI-",
+ .init_dev_msi_info = gic_msi_lib_init_dev_msi_info,
};
-static struct msi_domain_info mbi_msi_domain_info = {
- .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
- MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI),
- .chip = &mbi_msi_irq_chip,
-};
-
-static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain,
- struct irq_domain **pci_domain)
-{
- *pci_domain = pci_msi_create_irq_domain(nexus_domain->parent->fwnode,
- &mbi_msi_domain_info,
- nexus_domain);
- if (!*pci_domain)
- return -ENOMEM;
-
- return 0;
-}
-#else
-static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain,
- struct irq_domain **pci_domain)
+static int mbi_allocate_domain(struct irq_domain *parent)
{
- *pci_domain = NULL;
- return 0;
-}
-#endif
-
-/* Platform-MSI specific irqchip */
-static struct irq_chip mbi_pmsi_irq_chip = {
- .name = "pMSI",
-};
-
-static struct msi_domain_ops mbi_pmsi_ops = {
-};
-
-static struct msi_domain_info mbi_pmsi_domain_info = {
- .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
- .ops = &mbi_pmsi_ops,
- .chip = &mbi_pmsi_irq_chip,
-};
-
-static int mbi_allocate_domains(struct irq_domain *parent)
-{
- struct irq_domain *nexus_domain, *pci_domain, *plat_domain;
- int err;
+ struct irq_domain *nexus_domain;
nexus_domain = irq_domain_create_tree(parent->fwnode,
&mbi_domain_ops, NULL);
@@ -225,22 +181,8 @@ static int mbi_allocate_domains(struct i
irq_domain_update_bus_token(nexus_domain, DOMAIN_BUS_NEXUS);
nexus_domain->parent = parent;
-
- err = mbi_allocate_pci_domain(nexus_domain, &pci_domain);
-
- plat_domain = platform_msi_create_irq_domain(parent->fwnode,
- &mbi_pmsi_domain_info,
- nexus_domain);
-
- if (err || !plat_domain) {
- if (plat_domain)
- irq_domain_remove(plat_domain);
- if (pci_domain)
- irq_domain_remove(pci_domain);
- irq_domain_remove(nexus_domain);
- return -ENOMEM;
- }
-
+ nexus_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
+ nexus_domain->msi_parent_ops = &gic_v3_mbi_msi_parent_ops;
return 0;
}
@@ -303,7 +245,7 @@ int __init mbi_init(struct fwnode_handle
pr_info("Using MBI frame %pa\n", &mbi_phys_base);
- ret = mbi_allocate_domains(parent);
+ ret = mbi_allocate_domain(parent);
if (ret)
goto err_free_mbi;
All platform MSI users and the PCI/MSI code handle per device MSI domains when the irqdomain associated to the device provides MSI parent functionality. Remove the "global" PCI/MSI and platform domain related code and provide the MSI parent functionality by filling in msi_parent_ops. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Marc Zyngier <maz@kernel.org> --- drivers/irqchip/irq-gic-v3-mbi.c | 122 ++++++++++----------------------------- 1 file changed, 32 insertions(+), 90 deletions(-)