Commit 74e44454 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

irqchip/gic-v2m: Switch to device MSI



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: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarAnna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: default avatarShivamurthy Shastri <shivamurthy.shastri@linutronix.de>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240623142235.514419280@linutronix.de

parent da8ec795
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ config ARM_GIC_V2M
	bool
	depends on PCI
	select ARM_GIC
	select IRQ_MSI_LIB
	select PCI_MSI

config GIC_NON_BANKED
+25 −56
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@
#include <linux/irqchip/arm-gic.h>
#include <linux/irqchip/arm-gic-common.h>

#include "irq-msi-lib.h"

/*
* MSI_TYPER:
*     [31:26] Reserved
@@ -72,31 +74,6 @@ struct v2m_data {
	u32 flags;		/* v2m flags for specific implementation */
};

static void gicv2m_mask_msi_irq(struct irq_data *d)
{
	pci_msi_mask_irq(d);
	irq_chip_mask_parent(d);
}

static void gicv2m_unmask_msi_irq(struct irq_data *d)
{
	pci_msi_unmask_irq(d);
	irq_chip_unmask_parent(d);
}

static struct irq_chip gicv2m_msi_irq_chip = {
	.name			= "MSI",
	.irq_mask		= gicv2m_mask_msi_irq,
	.irq_unmask		= gicv2m_unmask_msi_irq,
	.irq_eoi		= irq_chip_eoi_parent,
};

static struct msi_domain_info gicv2m_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	= &gicv2m_msi_irq_chip,
};

static phys_addr_t gicv2m_get_msi_addr(struct v2m_data *v2m, int hwirq)
{
	if (v2m->flags & GICV2M_GRAVITON_ADDRESS_ONLY)
@@ -230,6 +207,7 @@ static void gicv2m_irq_domain_free(struct irq_domain *domain,
}

static const struct irq_domain_ops gicv2m_domain_ops = {
	.select			= msi_lib_irq_domain_select,
	.alloc			= gicv2m_irq_domain_alloc,
	.free			= gicv2m_irq_domain_free,
};
@@ -250,19 +228,6 @@ static bool is_msi_spi_valid(u32 base, u32 num)
	return true;
}

static struct irq_chip gicv2m_pmsi_irq_chip = {
	.name			= "pMSI",
};

static struct msi_domain_ops gicv2m_pmsi_ops = {
};

static struct msi_domain_info gicv2m_pmsi_domain_info = {
	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
	.ops	= &gicv2m_pmsi_ops,
	.chip	= &gicv2m_pmsi_irq_chip,
};

static void __init gicv2m_teardown(void)
{
	struct v2m_data *v2m, *tmp;
@@ -278,9 +243,27 @@ static void __init gicv2m_teardown(void)
	}
}


#define GICV2M_MSI_FLAGS_REQUIRED  (MSI_FLAG_USE_DEF_DOM_OPS |		\
				    MSI_FLAG_USE_DEF_CHIP_OPS |		\
				    MSI_FLAG_PCI_MSI_MASK_PARENT)

#define GICV2M_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK |	\
				    MSI_FLAG_PCI_MSIX      |	\
				    MSI_FLAG_MULTI_PCI_MSI)

static struct msi_parent_ops gicv2m_msi_parent_ops = {
	.supported_flags	= GICV2M_MSI_FLAGS_SUPPORTED,
	.required_flags		= GICV2M_MSI_FLAGS_REQUIRED,
	.bus_select_token	= DOMAIN_BUS_NEXUS,
	.bus_select_mask	= MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
	.prefix			= "GICv2m-",
	.init_dev_msi_info	= msi_lib_init_dev_msi_info,
};

static __init int gicv2m_allocate_domains(struct irq_domain *parent)
{
	struct irq_domain *inner_domain, *pci_domain, *plat_domain;
	struct irq_domain *inner_domain;
	struct v2m_data *v2m;

	v2m = list_first_entry_or_null(&v2m_nodes, struct v2m_data, entry);
@@ -295,22 +278,8 @@ static __init int gicv2m_allocate_domains(struct irq_domain *parent)
	}

	irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS);
	pci_domain = pci_msi_create_irq_domain(v2m->fwnode,
					       &gicv2m_msi_domain_info,
					       inner_domain);
	plat_domain = platform_msi_create_irq_domain(v2m->fwnode,
						     &gicv2m_pmsi_domain_info,
						     inner_domain);
	if (!pci_domain || !plat_domain) {
		pr_err("Failed to create MSI domains\n");
		if (plat_domain)
			irq_domain_remove(plat_domain);
		if (pci_domain)
			irq_domain_remove(pci_domain);
		irq_domain_remove(inner_domain);
		return -ENOMEM;
	}

	inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
	inner_domain->msi_parent_ops = &gicv2m_msi_parent_ops;
	return 0;
}

@@ -511,7 +480,7 @@ acpi_parse_madt_msi(union acpi_subtable_headers *header,
		pr_info("applying Amazon Graviton quirk\n");
		res.end = res.start + SZ_8K - 1;
		flags |= GICV2M_GRAVITON_ADDRESS_ONLY;
		gicv2m_msi_domain_info.flags &= ~MSI_FLAG_MULTI_PCI_MSI;
		gicv2m_msi_parent_ops.supported_flags &= ~MSI_FLAG_MULTI_PCI_MSI;
	}

	if (m->flags & ACPI_MADT_OVERRIDE_SPI_VALUES) {