linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains
@ 2022-11-21 14:39 Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 01/40] irqchip/irq-mvebu-icu: Fix works by chance pointer assignment Thomas Gleixner
                   ` (40 more replies)
  0 siblings, 41 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

This builds on top of the per device MSI work which can be found here:

  https://lore.kernel.org/all/20221121083657.157152924@linutronix.de

and is available from git:

  git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git devmsi-v2-part3

This series converts the ARM MSI handling, especially the platform MSI
mechanics, to use per device MSI domains instead of the weird indirection
through platform MSI domains.

This also takes a different and less convoluted approach to the 'wire to
MSI' bridges by providing special MSI allocation/free functions which are
invoked from irq_create_fwspec_mapping() and irq_dispose_mapping() which
avoids the extra entry point msi_domain_populate_irqs() and its layering
violations.

The series has been tested on various systems (Ampere, Hisilicon HIP05,
ThunderX2, MVEBU MCBIN) but there is no full coverage yet.

Thanks to Marc, Mark and Robin for running this on their machines and
aiding with decoding the initial wreckage. Special thanks go to Marc for
patiently guiding me through the insanity of OF/ACPI related to this.

The series is also available from git:

  git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git devmsi-v2-arm

The work was done to validate that the design decisions for per device MSI
domains and the related data structures are up to the task to handle the
ARM oddities. The design held up, it was just necessary to extend some of
the data structures to handle the ARM specifics in a sane way, but there
was no fundamental shortcoming.

Thanks,

	tglx
---
 b/drivers/base/platform-msi.c                 |  354 +++-----------------------
 b/drivers/dma/mv_xor_v2.c                     |    8 
 b/drivers/dma/qcom/hidma.c                    |    6 
 b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |    5 
 b/drivers/irqchip/Kconfig                     |    8 
 b/drivers/irqchip/Makefile                    |    4 
 b/drivers/irqchip/irq-gic-common.h            |    3 
 b/drivers/irqchip/irq-gic-msi-lib.c           |  136 +++++++++
 b/drivers/irqchip/irq-gic-msi-lib.h           |   27 +
 b/drivers/irqchip/irq-gic-v2m.c               |   93 ++----
 b/drivers/irqchip/irq-gic-v3-its-msi-parent.c |  207 +++++++++++++++
 b/drivers/irqchip/irq-gic-v3-its.c            |    4 
 b/drivers/irqchip/irq-gic-v3-mbi.c            |  137 ++--------
 b/drivers/irqchip/irq-gic-v3.c                |    6 
 b/drivers/irqchip/irq-imx-mu-msi.c            |   53 +--
 b/drivers/irqchip/irq-mbigen.c                |   98 ++-----
 b/drivers/irqchip/irq-mvebu-gicp.c            |   44 +--
 b/drivers/irqchip/irq-mvebu-icu.c             |  278 ++++++++------------
 b/drivers/irqchip/irq-mvebu-odmi.c            |   39 +-
 b/drivers/irqchip/irq-mvebu-sei.c             |   52 +--
 b/drivers/irqchip/irq-ti-sci-inta.c           |    2 
 b/drivers/mailbox/bcm-flexrm-mailbox.c        |    8 
 b/drivers/pci/msi/irqdomain.c                 |   30 ++
 b/drivers/perf/arm_smmuv3_pmu.c               |    4 
 b/include/linux/acpi_iort.h                   |    4 
 b/include/linux/irqdomain.h                   |   17 +
 b/include/linux/irqdomain_defs.h              |    2 
 b/include/linux/msi.h                         |   81 +----
 b/kernel/irq/irqdomain.c                      |   26 +
 b/kernel/irq/msi.c                            |  253 ++++++++++++------
 drivers/irqchip/irq-gic-v3-its-pci-msi.c      |  202 --------------
 drivers/irqchip/irq-gic-v3-its-platform-msi.c |  163 -----------
 32 files changed, 1021 insertions(+), 1333 deletions(-)

^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 01/40] irqchip/irq-mvebu-icu: Fix works by chance pointer assignment
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-24 12:50   ` Marc Zyngier
  2022-11-21 14:39 ` [patch V2 02/40] ACPI/IORT: Make prototype of iort_pmsi_get_dev_id() always available Thomas Gleixner
                   ` (39 subsequent siblings)
  40 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Assigning a void pointer which points to a struct to two different data
types only works by chance if the second type is the first member of the
struct.

Replace this works by chance code by using the primary struct pointer.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Gregory Clement <gregory.clement@bootlin.com>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
 drivers/irqchip/irq-mvebu-icu.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/drivers/irqchip/irq-mvebu-icu.c
+++ b/drivers/irqchip/irq-mvebu-icu.c
@@ -151,9 +151,9 @@ static int
 mvebu_icu_irq_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
 			       unsigned long *hwirq, unsigned int *type)
 {
-	struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d);
-	struct mvebu_icu *icu = platform_msi_get_host_data(d);
 	unsigned int param_count = static_branch_unlikely(&legacy_bindings) ? 3 : 2;
+	struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d);
+	struct mvebu_icu *icu = msi_data->icu;
 
 	/* Check the count of the parameters in dt */
 	if (WARN_ON(fwspec->param_count != param_count)) {


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 02/40] ACPI/IORT: Make prototype of iort_pmsi_get_dev_id() always available
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 01/40] irqchip/irq-mvebu-icu: Fix works by chance pointer assignment Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 15:13   ` Robin Murphy
  2022-11-21 14:39 ` [patch V2 03/40] irqchip/gic-v2m: Include arm-gic-common.h Thomas Gleixner
                   ` (38 subsequent siblings)
  40 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

W=1 build complains:

drivers/irqchip/irq-gic-v3-its-msi-parent.c:110:12: warning: no previous prototype for function 'iort_pmsi_get_dev_id' [-Wmissing-prototypes]                                                                                              
   int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)

Reported-by: Ammar Faizi <ammarfaizi2@gnuweeb.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
---
 include/linux/acpi_iort.h |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -26,13 +26,15 @@ int iort_register_domain_token(int trans
 			       struct fwnode_handle *fw_node);
 void iort_deregister_domain_token(int trans_id);
 struct fwnode_handle *iort_find_domain_token(int trans_id);
+
+int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
+
 #ifdef CONFIG_ACPI_IORT
 void acpi_iort_init(void);
 u32 iort_msi_map_id(struct device *dev, u32 id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
 					  enum irq_domain_bus_token bus_token);
 void acpi_configure_pmsi_domain(struct device *dev);
-int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
 		       struct list_head *head);
 void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 03/40] irqchip/gic-v2m: Include arm-gic-common.h
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 01/40] irqchip/irq-mvebu-icu: Fix works by chance pointer assignment Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 02/40] ACPI/IORT: Make prototype of iort_pmsi_get_dev_id() always available Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-24 12:51   ` Marc Zyngier
  2022-11-21 14:39 ` [patch V2 04/40] irqchip/gic-v2m: Mark a few functions __init Thomas Gleixner
                   ` (37 subsequent siblings)
  40 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

W=1 build complains:

drivers/irqchip/irq-gic-v2m.c:570:12: warning: no previous prototype for ‘gicv2m_init’ [-Wmissing-prototypes]
  570 | int __init gicv2m_init(struct fwnode_handle *parent_handle,

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v2m.c |    1 +
 1 file changed, 1 insertion(+)

--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/irqchip/arm-gic-common.h>
 
 /*
 * MSI_TYPER:


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 04/40] irqchip/gic-v2m: Mark a few functions __init
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (2 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 03/40] irqchip/gic-v2m: Include arm-gic-common.h Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-24 12:54   ` Marc Zyngier
  2022-11-21 14:39 ` [patch V2 05/40] irqchip/ti-sci-inta: Fix kernel doc Thomas Gleixner
                   ` (36 subsequent siblings)
  40 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

They are all part of the init sequence.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v2m.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -263,7 +263,7 @@ static struct msi_domain_info gicv2m_pms
 	.chip	= &gicv2m_pmsi_irq_chip,
 };
 
-static void gicv2m_teardown(void)
+static void __init gicv2m_teardown(void)
 {
 	struct v2m_data *v2m, *tmp;
 
@@ -278,7 +278,7 @@ static void gicv2m_teardown(void)
 	}
 }
 
-static int gicv2m_allocate_domains(struct irq_domain *parent)
+static __init int gicv2m_allocate_domains(struct irq_domain *parent)
 {
 	struct irq_domain *inner_domain, *pci_domain, *plat_domain;
 	struct v2m_data *v2m;
@@ -405,7 +405,7 @@ static int __init gicv2m_init_one(struct
 	return ret;
 }
 
-static const struct of_device_id gicv2m_device_id[] = {
+static __initconst struct of_device_id gicv2m_device_id[] = {
 	{	.compatible	= "arm,gic-v2m-frame",	},
 	{},
 };
@@ -455,7 +455,7 @@ static int __init gicv2m_of_init(struct
 #ifdef CONFIG_ACPI
 static int acpi_num_msi;
 
-static struct fwnode_handle *gicv2m_get_fwnode(struct device *dev)
+static __init struct fwnode_handle *gicv2m_get_fwnode(struct device *dev)
 {
 	struct v2m_data *data;
 
@@ -470,7 +470,7 @@ static struct fwnode_handle *gicv2m_get_
 	return data->fwnode;
 }
 
-static bool acpi_check_amazon_graviton_quirks(void)
+static __init bool acpi_check_amazon_graviton_quirks(void)
 {
 	static struct acpi_table_madt *madt;
 	acpi_status status;


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 05/40] irqchip/ti-sci-inta: Fix kernel doc
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (3 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 04/40] irqchip/gic-v2m: Mark a few functions __init Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-24 12:54   ` Marc Zyngier
  2022-11-21 14:39 ` [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask Thomas Gleixner
                   ` (35 subsequent siblings)
  40 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

W=1 build complains:

drivers/irqchip/irq-ti-sci-inta.c:177: warning: Function parameter or member 'vint_id' not described in 'ti_sci_inta_xlate_irq'
drivers/irqchip/irq-ti-sci-inta.c:177: warning: Excess function parameter 'irq' description in 'ti_sci_inta_xlate_irq'

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Nishanth Menon <nm@ti.com>
Cc: Tero Kristo <kristo@kernel.org>
Cc: Santosh Shilimkar <ssantosh@kernel.org>
Cc: Marc Zyngier <maz@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
---
 drivers/irqchip/irq-ti-sci-inta.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/irqchip/irq-ti-sci-inta.c
+++ b/drivers/irqchip/irq-ti-sci-inta.c
@@ -168,7 +168,7 @@ static void ti_sci_inta_irq_handler(stru
 /**
  * ti_sci_inta_xlate_irq() - Translate hwirq to parent's hwirq.
  * @inta:	IRQ domain corresponding to Interrupt Aggregator
- * @irq:	Hardware irq corresponding to the above irq domain
+ * @vint_id:	Hardware irq corresponding to the above irq domain
  *
  * Return parent irq number if translation is available else -ENOENT.
  */


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (4 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 05/40] irqchip/ti-sci-inta: Fix kernel doc Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-24 13:04   ` Marc Zyngier
  2022-11-21 14:39 ` [patch V2 07/40] irqchip/gic-v3: Make gic_irq_domain_select() robust for zero parameter count Thomas Gleixner
                   ` (34 subsequent siblings)
  40 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Most ARM(64) PCI/MSI domains mask and unmask in the parent domain after or
before the PCI mask/unmask operation takes place. So there are more than a
dozen of the same wrapper implementation all over the place.

Don't make the same mistake with the new per device PCI/MSI domains and
provide a static key which lets the domain implementation enable this
sequence in the PCI/MSI code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/msi/irqdomain.c |   30 ++++++++++++++++++++++++++++++
 include/linux/msi.h         |    2 ++
 2 files changed, 32 insertions(+)

--- a/drivers/pci/msi/irqdomain.c
+++ b/drivers/pci/msi/irqdomain.c
@@ -148,17 +148,45 @@ static void pci_device_domain_set_desc(m
 	arg->hwirq = desc->msi_index;
 }
 
+static DEFINE_STATIC_KEY_FALSE(pci_msi_mask_unmask_parent);
+
+/**
+ * pci_device_msi_mask_unmask_parent_enable - Enable propagation of mask/unmask
+ *					      to the parent interrupt chip
+ *
+ * For MSI parent interrupt domains which want to mask at the parent interrupt
+ * chip too.
+ */
+void pci_device_msi_mask_unmask_parent_enable(void)
+{
+	static_branch_enable(&pci_msi_mask_unmask_parent);
+}
+
+static __always_inline void cond_mask_parent(struct irq_data *data)
+{
+	if (static_branch_unlikely(&pci_msi_mask_unmask_parent))
+		irq_chip_mask_parent(data);
+}
+
+static __always_inline void cond_unmask_parent(struct irq_data *data)
+{
+	if (static_branch_unlikely(&pci_msi_mask_unmask_parent))
+		irq_chip_unmask_parent(data);
+}
+
 static void pci_mask_msi(struct irq_data *data)
 {
 	struct msi_desc *desc = irq_data_get_msi_desc(data);
 
 	pci_msi_mask(desc, BIT(data->irq - desc->irq));
+	cond_mask_parent(data);
 }
 
 static void pci_unmask_msi(struct irq_data *data)
 {
 	struct msi_desc *desc = irq_data_get_msi_desc(data);
 
+	cond_unmask_parent(data);
 	pci_msi_unmask(desc, BIT(data->irq - desc->irq));
 }
 
@@ -195,10 +223,12 @@ static struct msi_domain_template pci_ms
 static void pci_mask_msix(struct irq_data *data)
 {
 	pci_msix_mask(irq_data_get_msi_desc(data));
+	cond_mask_parent(data);
 }
 
 static void pci_unmask_msix(struct irq_data *data)
 {
+	cond_unmask_parent(data);
 	pci_msix_unmask(irq_data_get_msi_desc(data));
 }
 
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -653,12 +653,14 @@ struct irq_domain *pci_msi_create_irq_do
 					     struct irq_domain *parent);
 u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev);
 struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev);
+void pci_device_msi_mask_unmask_parent_enable(void);
 #else /* CONFIG_PCI_MSI */
 static inline struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
 {
 	return NULL;
 }
 static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg) { }
+static inline void pci_device_msi_mask_unmask_parent_enable(void) { }
 #endif /* !CONFIG_PCI_MSI */
 
 #endif /* LINUX_MSI_H */


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 07/40] irqchip/gic-v3: Make gic_irq_domain_select() robust for zero parameter count
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (5 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 08/40] genirq/irqdomain: Remove the param count restriction from select() Thomas Gleixner
                   ` (33 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Currently the irqdomain select callback is only invoked when the parameter
count of the fwspec arguments is not zero. That makes sense because then
the match is on the firmware node and eventually on the bus_token, which is
already handled in the core code.

The upcoming support for per device MSI domains requires to do real bus
token specific checks in the MSI parent domains with a zero parameter
count.

Make the gic-v3 select() callback handle that case.

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.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1613,9 +1613,13 @@ static int gic_irq_domain_select(struct
 	irq_hw_number_t hwirq;
 
 	/* Not for us */
-        if (fwspec->fwnode != d->fwnode)
+	if (fwspec->fwnode != d->fwnode)
 		return 0;
 
+	/* Handle pure domain searches */
+	if (!fwspec->param_count)
+		return d->bus_token == bus_token;
+
 	/* If this is not DT, then we have a single domain */
 	if (!is_of_node(fwspec->fwnode))
 		return 1;


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 08/40] genirq/irqdomain: Remove the param count restriction from select()
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (6 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 07/40] irqchip/gic-v3: Make gic_irq_domain_select() robust for zero parameter count Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 09/40] genirq/msi: Extend msi_parent_ops Thomas Gleixner
                   ` (32 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Now that the GIC-v3 callback can handle invocation with a fwspec parameter
count of 0 lift the restriction in the core code and invoke select()
unconditionally when the domain provides it.

Preparatory change for per device MSI domains.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/irq/irqdomain.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -417,7 +417,7 @@ struct irq_domain *irq_find_matching_fws
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
-		if (h->ops->select && fwspec->param_count)
+		if (h->ops->select)
 			rc = h->ops->select(h, fwspec, bus_token);
 		else if (h->ops->match)
 			rc = h->ops->match(h, to_of_node(fwnode), bus_token);


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 09/40] genirq/msi: Extend msi_parent_ops
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (7 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 08/40] genirq/irqdomain: Remove the param count restriction from select() Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 10/40] irqchip: Provide irq-gic-lib Thomas Gleixner
                   ` (31 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Supporting per device MSI domains on ARM64 and the zoo of interrupt
mechanisms needs a bit more information than what the initial x86
implementation provides.

Add the following fields:

  - required_flags: 	The flags which a parent domain requires to be set
  - bus_select_token:	The bus token of the parent domain for select()
  - bus_select_mask:	A bitmask of supported child domain bus types

This allows to provide library functions which can be shared between
various interrupt chip implementations and avoids replicating mostly
similar code all over the place.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/msi.h |   11 +++++++++++
 1 file changed, 11 insertions(+)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -556,6 +556,14 @@ enum {
  * struct msi_parent_ops - MSI parent domain callbacks and configuration info
  *
  * @supported_flags:	Required: The supported MSI flags of the parent domain
+ * @required_flags:	Optional: The required MSI flags of the parent MSI domain
+ *			Mandatory for ARM_GIC_MSI_LIB users
+ * @bus_select_token:	Optional: The bus token of the real parent domain for
+ *			irq_domain::select()
+ *			Mandatory for ARM_GIC_MSI_LIB users
+ * @bus_select_mask:	Optional: A mask of supported BUS_DOMAINs for
+ *			irq_domain::select()
+ *			Mandatory for ARM_GIC_MSI_LIB users
  * @prefix:		Optional: Prefix for the domain and chip name
  * @init_dev_msi_info:	Required: Callback for MSI parent domains to setup parent
  *			domain specific domain flags, domain ops and interrupt chip
@@ -563,6 +571,9 @@ enum {
  */
 struct msi_parent_ops {
 	u32		supported_flags;
+	u32		required_flags;
+	u32		bus_select_token;
+	u32		bus_select_mask;
 	const char	*prefix;
 	bool		(*init_dev_msi_info)(struct device *dev, struct irq_domain *domain,
 					     struct irq_domain *msi_parent_domain,


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 10/40] irqchip: Provide irq-gic-lib
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (8 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 09/40] genirq/msi: Extend msi_parent_ops Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 11/40] irqchip/gic-v3-its: Provide MSI parent infrastructure Thomas Gleixner
                   ` (30 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

All irqdomains which provide MSI parent domain functionality for per device
MSI domains need to provide a select() callback for the irqdomain and a
function to initialize the child domain.

Most of these functions would just be copy&pasta with minimal
modifications, so provide a library function which implements the required
functionality and is customizable via parent_domain::msi_parent_ops

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Export functions for modular irqchip drivers...
---
 drivers/irqchip/Kconfig           |    3 +
 drivers/irqchip/Makefile          |    1 
 drivers/irqchip/irq-gic-msi-lib.c |  112 ++++++++++++++++++++++++++++++++++++++
 drivers/irqchip/irq-gic-msi-lib.h |   19 ++++++
 4 files changed, 135 insertions(+)

--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -30,6 +30,9 @@ config ARM_GIC_V2M
 config GIC_NON_BANKED
 	bool
 
+config ARM_GIC_MSI_LIB
+	bool
+
 config ARM_GIC_V3
 	bool
 	select IRQ_DOMAIN_HIERARCHY
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-sh
 obj-$(CONFIG_ARM_GIC)			+= irq-gic.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_PM)		+= irq-gic-pm.o
 obj-$(CONFIG_ARCH_REALVIEW)		+= irq-gic-realview.o
+obj-$(CONFIG_ARM_GIC_MSI_LIB)		+= irq-gic-msi-lib.o
 obj-$(CONFIG_ARM_GIC_V2M)		+= irq-gic-v2m.o
 obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o
--- /dev/null
+++ b/drivers/irqchip/irq-gic-msi-lib.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2022 Linutronix GmbH
+// Copyright (C) 2022 Intel
+
+#include <linux/export.h>
+
+#include "irq-gic-msi-lib.h"
+
+/**
+ * gic_msi_lib_init_dev_msi_info - Domain info setup for MSI domains
+ * @dev:		The device for which the domain is created for
+ * @domain:		The domain providing this callback
+ * @real_parent:	The real parent domain of the to initialize domain
+ *			which might be a domain built on top of @domain
+ *			or @domain itself
+ * @info:		The domain info for the to initialize domain
+ *
+ * This function is to be used for all types of MSI domains above the root
+ * parent domain and any intermediates. The topmost parent domain specific
+ * functionality is determined via @real_parent.
+ *
+ * All intermediate domains between the root and the device domain must
+ * have either msi_parent_ops.init_dev_msi_info = msi_parent_init_dev_msi_info
+ * or invoke it down the line.
+ */
+bool gic_msi_lib_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
+				   struct irq_domain *real_parent,
+				   struct msi_domain_info *info)
+{
+	const struct msi_parent_ops *pops = real_parent->msi_parent_ops;
+
+	/*
+	 * MSI parent domain specific settings. For now there is only the
+	 * root parent domain, e.g. NEXUS, acting as a MSI parent, but it is
+	 * possible to stack MSI parents. See x86 vector -> irq remapping
+	 */
+	if (domain->bus_token == pops->bus_select_token) {
+		if (WARN_ON_ONCE(domain != real_parent))
+			return false;
+	} else {
+		WARN_ON_ONCE(1);
+		return false;
+	}
+
+	/* Parent ops available? */
+	if (WARN_ON_ONCE(!pops))
+		return false;
+
+	/* Is the target domain bus token supported ? */
+	switch(info->bus_token) {
+	default:
+		/*
+		 * This should never be reached. See
+		 * gic_msi_lib_irq_domain_select()
+		 */
+		WARN_ON_ONCE(1);
+		return false;
+	}
+
+	/*
+	 * Mask out the domain specific MSI feature flags which are not
+	 * supported by the real parent.
+	 */
+	info->flags			&= pops->supported_flags;
+	/* Enforce the required flags */
+	info->flags			|= pops->required_flags;
+
+	/* Chip updates for all child bus types */
+	if (!info->chip->irq_eoi)
+		info->chip->irq_eoi	= irq_chip_eoi_parent;
+
+	/*
+	 * The device MSI domain can never have a set affinity callback it
+	 * always has to rely on the parent domain to handle affinity
+	 * settings. The device MSI domain just has to write the resulting
+	 * MSI message into the hardware which is the whole purpose of the
+	 * device MSI domain aside of mask/unmask which is provided e.g. by
+	 * PCI/MSI device domains.
+	 */
+	info->chip->irq_set_affinity	= msi_domain_set_affinity;
+	return true;
+}
+EXPORT_SYMBOL_GPL(gic_msi_lib_init_dev_msi_info);
+
+/**
+ * gic_msi_lib_irq_domain_select - Shared select function for NEXUS domains
+ * @d:		Pointer to the irq domain on which select is invoked
+ * @fwspec:	Firmware spec describing what is searched
+ * @bus_token:	The bus token for which a matching irq domain is looked up
+ *
+ * Returns:	%0 if @d is not what is being looked for
+ *
+ *		%1 if @d is either the domain which is directly searched for or
+ *		   if @d is providing the parent MSI domain for the functionality
+ *			 requested with @bus_token.
+ */
+int gic_msi_lib_irq_domain_select(struct irq_domain *d, struct irq_fwspec *fwspec,
+				  enum irq_domain_bus_token bus_token)
+{
+	const struct msi_parent_ops *ops = d->msi_parent_ops;
+	u32 busmask = BIT(bus_token);
+
+	if (fwspec->fwnode != d->fwnode || fwspec->param_count != 0)
+		return 0;
+
+	/* Handle pure domain searches */
+	if (bus_token == ops->bus_select_token)
+		return 1;
+
+	return ops && !!(ops->bus_select_mask & busmask);
+}
+EXPORT_SYMBOL_GPL(gic_msi_lib_irq_domain_select);
--- /dev/null
+++ b/drivers/irqchip/irq-gic-msi-lib.h
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2022 Linutronix GmbH
+// Copyright (C) 2022 Intel
+
+#ifndef _DRIVERS_IRQCHIP_IRQ_GIC_MSI_LIB_H
+#define _DRIVERS_IRQCHIP_IRQ_GIC_MSI_LIB_H
+
+#include <linux/bits.h>
+#include <linux/irqdomain.h>
+#include <linux/msi.h>
+
+int gic_msi_lib_irq_domain_select(struct irq_domain *d, struct irq_fwspec *fwspec,
+				  enum irq_domain_bus_token bus_token);
+
+bool gic_msi_lib_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
+				   struct irq_domain *real_parent,
+				   struct msi_domain_info *info);
+
+#endif /* _DRIVERS_IRQCHIP_IRQ_GIC_MSI_LIB_H */


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 11/40] irqchip/gic-v3-its: Provide MSI parent infrastructure
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (9 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 10/40] irqchip: Provide irq-gic-lib Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 12/40] irqchip/gic-msi-lib: Prepare for PCI MSI/MSIX Thomas Gleixner
                   ` (29 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

To support per device MSI domains the ITS must provide MSI parent domain
functionality.

Provide the basic skeleton for this:

   - msi_parent_ops
   - child domain init callback
   - the MSI parent flag set in irqdomain::flags

This does not make ITS a functional parent domain as there is no bit set in
the bus_select_mask yet, but it provides the base to implement PCI and
platform MSI support gradualy on top.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/Kconfig                     |    1 
 drivers/irqchip/Makefile                    |    2 -
 drivers/irqchip/irq-gic-common.h            |    3 ++
 drivers/irqchip/irq-gic-v3-its-msi-parent.c |   30 ++++++++++++++++++++++++++++
 drivers/irqchip/irq-gic-v3-its.c            |    4 +++
 5 files changed, 39 insertions(+), 1 deletion(-)

--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -42,6 +42,7 @@ config ARM_GIC_V3
 config ARM_GIC_V3_ITS
 	bool
 	select GENERIC_MSI_IRQ
+	select ARM_GIC_MSI_LIB
 	default ARM_GIC_V3
 
 config ARM_GIC_V3_ITS_PCI
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -33,7 +33,7 @@ obj-$(CONFIG_ARCH_REALVIEW)		+= irq-gic-
 obj-$(CONFIG_ARM_GIC_MSI_LIB)		+= irq-gic-msi-lib.o
 obj-$(CONFIG_ARM_GIC_V2M)		+= irq-gic-v2m.o
 obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
-obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o
+obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o irq-gic-v3-its-msi-parent.o
 obj-$(CONFIG_ARM_GIC_V3_ITS_PCI)	+= irq-gic-v3-its-pci-msi.o
 obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC)	+= irq-gic-v3-its-fsl-mc-msi.o
 obj-$(CONFIG_PARTITION_PERCPU)		+= irq-partition-percpu.o
--- a/drivers/irqchip/irq-gic-common.h
+++ b/drivers/irqchip/irq-gic-common.h
@@ -8,6 +8,7 @@
 
 #include <linux/of.h>
 #include <linux/irqdomain.h>
+#include <linux/msi.h>
 #include <linux/irqchip/arm-gic-common.h>
 
 struct gic_quirk {
@@ -28,4 +29,6 @@ void gic_enable_quirks(u32 iidr, const s
 void gic_enable_of_quirks(const struct device_node *np,
 			  const struct gic_quirk *quirks, void *data);
 
+extern const struct msi_parent_ops gic_v3_its_msi_parent_ops;
+
 #endif /* _IRQ_GIC_COMMON_H */
--- /dev/null
+++ b/drivers/irqchip/irq-gic-v3-its-msi-parent.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2022 Linutronix GmbH
+// Copyright (C) 2022 Intel
+
+#include "irq-gic-common.h"
+#include "irq-gic-msi-lib.h"
+
+#define ITS_MSI_FLAGS_REQUIRED  (MSI_FLAG_USE_DEF_DOM_OPS |	\
+				 MSI_FLAG_USE_DEF_CHIP_OPS)
+
+#define ITS_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK |	\
+				 MSI_FLAG_PCI_MSIX      |	\
+				 MSI_FLAG_MULTI_PCI_MSI)
+
+static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
+				  struct irq_domain *real_parent, struct msi_domain_info *info)
+{
+	if (!gic_msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
+		return false;
+
+	return true;
+}
+
+const struct msi_parent_ops gic_v3_its_msi_parent_ops = {
+	.supported_flags	= ITS_MSI_FLAGS_SUPPORTED,
+	.required_flags		= ITS_MSI_FLAGS_REQUIRED,
+	.bus_select_token	= DOMAIN_BUS_NEXUS,
+	.prefix			= "ITS-",
+	.init_dev_msi_info	= its_init_dev_msi_info,
+};
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -38,6 +38,7 @@
 #include <asm/exception.h>
 
 #include "irq-gic-common.h"
+#include "irq-gic-msi-lib.h"
 
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING		(1ULL << 0)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_22375	(1ULL << 1)
@@ -3656,6 +3657,7 @@ static void its_irq_domain_free(struct i
 }
 
 static const struct irq_domain_ops its_domain_ops = {
+	.select			= gic_msi_lib_irq_domain_select,
 	.alloc			= its_irq_domain_alloc,
 	.free			= its_irq_domain_free,
 	.activate		= its_irq_domain_activate,
@@ -4918,6 +4920,8 @@ static int its_init_domain(struct fwnode
 	inner_domain->parent = its_parent;
 	irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS);
 	inner_domain->flags |= its->msi_domain_flags;
+	inner_domain->msi_parent_ops = &gic_v3_its_msi_parent_ops;
+	inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
 	info->ops = &its_msi_domain_ops;
 	info->data = its;
 	inner_domain->host_data = info;


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 12/40] irqchip/gic-msi-lib: Prepare for PCI MSI/MSIX
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (10 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 11/40] irqchip/gic-v3-its: Provide MSI parent infrastructure Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 13/40] irqchip/gic-v3-its: Provide MSI parent for PCI/MSI[-X] Thomas Gleixner
                   ` (28 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Add the bus tokens for DOMAIN_BUS_PCI_DEVICE_MSI and
DOMAIN_BUS_PCI_DEVICE_MSIX to the common child init
function and enable the parent mask/unmask static key
in the PCI/MSI core.

Provide the match mask which can be used by parent domain
implementation so the bitmask based child bus token match
works.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/irqchip/irq-gic-msi-lib.c |    7 +++++++
 drivers/irqchip/irq-gic-msi-lib.h |    6 ++++++
 2 files changed, 13 insertions(+)

--- a/drivers/irqchip/irq-gic-msi-lib.c
+++ b/drivers/irqchip/irq-gic-msi-lib.c
@@ -48,6 +48,13 @@ bool gic_msi_lib_init_dev_msi_info(struc
 
 	/* Is the target domain bus token supported ? */
 	switch(info->bus_token) {
+	case DOMAIN_BUS_PCI_DEVICE_MSI:
+	case DOMAIN_BUS_PCI_DEVICE_MSIX:
+		if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_PCI_MSI)))
+			return false;
+
+		pci_device_msi_mask_unmask_parent_enable();
+		break;
 	default:
 		/*
 		 * This should never be reached. See
--- a/drivers/irqchip/irq-gic-msi-lib.h
+++ b/drivers/irqchip/irq-gic-msi-lib.h
@@ -9,6 +9,12 @@
 #include <linux/irqdomain.h>
 #include <linux/msi.h>
 
+#ifdef CONFIG_PCI_MSI
+#define MATCH_PCI_MSI		BIT(DOMAIN_BUS_PCI_MSI)
+#else
+#define MATCH_PCI_MSI		(0)
+#endif
+
 int gic_msi_lib_irq_domain_select(struct irq_domain *d, struct irq_fwspec *fwspec,
 				  enum irq_domain_bus_token bus_token);
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 13/40] irqchip/gic-v3-its: Provide MSI parent for PCI/MSI[-X]
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (11 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 12/40] irqchip/gic-msi-lib: Prepare for PCI MSI/MSIX Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 14/40] genirq/irqdomain: Add BUS_DOMAIN_DEVICE_MSI Thomas Gleixner
                   ` (27 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Lift the its_pci_msi_prepare() function from the ITS-PCI/MSI code which
provides the 'global' PCI/MSI domains and amend it to use the domain
hardware size, which is the MSI[X] vector count, for allocating the ITS
slots for the PCI device.

Enable PCI matching in msi_parent_ops and provide the necessary update to
the ITS specific child domain initialization function so that the prepare
callback gets invoked on allocations.

The latter might be optimized to do the allocation right at the point where
the child domain is initialized, but keep it simple for now.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/Makefile                    |    1 
 drivers/irqchip/irq-gic-v3-its-msi-parent.c |  106 ++++++++++++++
 drivers/irqchip/irq-gic-v3-its-pci-msi.c    |  202 ----------------------------
 3 files changed, 106 insertions(+), 203 deletions(-)

--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -34,7 +34,6 @@ obj-$(CONFIG_ARM_GIC_MSI_LIB)		+= irq-gi
 obj-$(CONFIG_ARM_GIC_V2M)		+= irq-gic-v2m.o
 obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o irq-gic-v3-its-msi-parent.o
-obj-$(CONFIG_ARM_GIC_V3_ITS_PCI)	+= irq-gic-v3-its-pci-msi.o
 obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC)	+= irq-gic-v3-its-fsl-mc-msi.o
 obj-$(CONFIG_PARTITION_PERCPU)		+= irq-partition-percpu.o
 obj-$(CONFIG_HISILICON_IRQ_MBIGEN)	+= irq-mbigen.o
--- a/drivers/irqchip/irq-gic-v3-its-msi-parent.c
+++ b/drivers/irqchip/irq-gic-v3-its-msi-parent.c
@@ -1,7 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2013-2015 ARM Limited, All Rights Reserved.
+// Author: Marc Zyngier <marc.zyngier@arm.com>
 // Copyright (C) 2022 Linutronix GmbH
 // Copyright (C) 2022 Intel
 
+#include <linux/pci.h>
+
 #include "irq-gic-common.h"
 #include "irq-gic-msi-lib.h"
 
@@ -12,12 +16,113 @@
 				 MSI_FLAG_PCI_MSIX      |	\
 				 MSI_FLAG_MULTI_PCI_MSI)
 
+#ifdef CONFIG_PCI_MSI
+static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data)
+{
+	int msi, msix, *count = data;
+
+	msi = max(pci_msi_vec_count(pdev), 0);
+	msix = max(pci_msix_vec_count(pdev), 0);
+	*count += max(msi, msix);
+	return 0;
+}
+
+static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
+{
+	struct pci_dev **alias_dev = data;
+
+	*alias_dev = pdev;
+	return 0;
+}
+
+static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
+			       int nvec, msi_alloc_info_t *info)
+{
+	struct pci_dev *pdev, *alias_dev;
+	struct msi_domain_info *msi_info;
+	int alias_count = 0, minnvec = 1;
+
+	if (!dev_is_pci(dev))
+		return -EINVAL;
+
+	pdev = to_pci_dev(dev);
+	/*
+	 * If pdev is downstream of any aliasing bridges, take an upper
+	 * bound of how many other vectors could map to the same DevID.
+	 * Also tell the ITS that the signalling will come from a proxy
+	 * device, and that special allocation rules apply.
+	 */
+	pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev);
+	if (alias_dev != pdev) {
+		if (alias_dev->subordinate)
+			pci_walk_bus(alias_dev->subordinate,
+				     its_pci_msi_vec_count, &alias_count);
+		info->flags |= MSI_ALLOC_FLAGS_PROXY_DEVICE;
+	}
+
+	/* ITS specific DeviceID, as the core ITS ignores dev. */
+	info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev);
+
+	/*
+	 * @domain->msi_domain_info->hwsize contains the size of the
+	 * MSI[-X] domain, but vector allocation happens one by one. This
+	 * needs some thought when IMS comes into play as the size of IMS
+	 * might be unknown at domain creation time and therefore set to
+	 * MSI_MAX_INDEX.
+	 */
+	msi_info = msi_get_domain_info(domain);
+	if (msi_info->hwsize > nvec)
+		nvec = msi_info->hwsize;
+
+	/*
+	 * Always allocate a power of 2, and special case device 0 for
+	 * broken systems where the DevID is not wired (and all devices
+	 * appear as DevID 0). For that reason, we generously allocate a
+	 * minimum of 32 MSIs for DevID 0. If you want more because all
+	 * your devices are aliasing to DevID 0, consider fixing your HW.
+	 */
+	nvec = max(nvec, alias_count);
+	if (!info->scratchpad[0].ul)
+		minnvec = 32;
+	nvec = max_t(int, minnvec, roundup_pow_of_two(nvec));
+
+	msi_info = msi_get_domain_info(domain->parent);
+	return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info);
+}
+#else /* CONFIG_PCI_MSI */
+#define its_pci_msi_prepare	NULL
+#endif /* !CONFIG_PCI_MSI */
+
 static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
 				  struct irq_domain *real_parent, struct msi_domain_info *info)
 {
 	if (!gic_msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
 		return false;
 
+	switch(info->bus_token) {
+	case DOMAIN_BUS_PCI_DEVICE_MSI:
+	case DOMAIN_BUS_PCI_DEVICE_MSIX:
+		/*
+		 * FIXME: This probably should be done after a (not yet
+		 * existing) post domain creation callback once to make
+		 * support for dynamic post-enable MSI-X allocations
+		 * work without having to reevaluate the domain size
+		 * over and over. It is known already at allocation
+		 * time via info->hwsize.
+		 *
+		 * That should work perfectly fine for MSI/MSI-X but needs
+		 * some thoughts for purely software managed IMS domains
+		 * where the index space is only limited artificially via
+		 * %MSI_MAX_INDEX.
+		 */
+		info->ops->msi_prepare = its_pci_msi_prepare;
+		break;
+	default:
+		/* Confused. How did the lib return true? */
+		WARN_ON_ONCE(1);
+		return false;
+	}
+
 	return true;
 }
 
@@ -25,6 +130,7 @@ const struct msi_parent_ops gic_v3_its_m
 	.supported_flags	= ITS_MSI_FLAGS_SUPPORTED,
 	.required_flags		= ITS_MSI_FLAGS_REQUIRED,
 	.bus_select_token	= DOMAIN_BUS_NEXUS,
+	.bus_select_mask	= MATCH_PCI_MSI,
 	.prefix			= "ITS-",
 	.init_dev_msi_info	= its_init_dev_msi_info,
 };
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ /dev/null
@@ -1,202 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2013-2015 ARM Limited, All Rights Reserved.
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- */
-
-#include <linux/acpi_iort.h>
-#include <linux/pci.h>
-#include <linux/msi.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_pci.h>
-
-static void its_mask_msi_irq(struct irq_data *d)
-{
-	pci_msi_mask_irq(d);
-	irq_chip_mask_parent(d);
-}
-
-static void its_unmask_msi_irq(struct irq_data *d)
-{
-	pci_msi_unmask_irq(d);
-	irq_chip_unmask_parent(d);
-}
-
-static struct irq_chip its_msi_irq_chip = {
-	.name			= "ITS-MSI",
-	.irq_unmask		= its_unmask_msi_irq,
-	.irq_mask		= its_mask_msi_irq,
-	.irq_eoi		= irq_chip_eoi_parent,
-};
-
-static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data)
-{
-	int msi, msix, *count = data;
-
-	msi = max(pci_msi_vec_count(pdev), 0);
-	msix = max(pci_msix_vec_count(pdev), 0);
-	*count += max(msi, msix);
-
-	return 0;
-}
-
-static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
-{
-	struct pci_dev **alias_dev = data;
-
-	*alias_dev = pdev;
-
-	return 0;
-}
-
-static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
-			       int nvec, msi_alloc_info_t *info)
-{
-	struct pci_dev *pdev, *alias_dev;
-	struct msi_domain_info *msi_info;
-	int alias_count = 0, minnvec = 1;
-
-	if (!dev_is_pci(dev))
-		return -EINVAL;
-
-	msi_info = msi_get_domain_info(domain->parent);
-
-	pdev = to_pci_dev(dev);
-	/*
-	 * If pdev is downstream of any aliasing bridges, take an upper
-	 * bound of how many other vectors could map to the same DevID.
-	 * Also tell the ITS that the signalling will come from a proxy
-	 * device, and that special allocation rules apply.
-	 */
-	pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev);
-	if (alias_dev != pdev) {
-		if (alias_dev->subordinate)
-			pci_walk_bus(alias_dev->subordinate,
-				     its_pci_msi_vec_count, &alias_count);
-		info->flags |= MSI_ALLOC_FLAGS_PROXY_DEVICE;
-	}
-
-	/* ITS specific DeviceID, as the core ITS ignores dev. */
-	info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev);
-
-	/*
-	 * Always allocate a power of 2, and special case device 0 for
-	 * broken systems where the DevID is not wired (and all devices
-	 * appear as DevID 0). For that reason, we generously allocate a
-	 * minimum of 32 MSIs for DevID 0. If you want more because all
-	 * your devices are aliasing to DevID 0, consider fixing your HW.
-	 */
-	nvec = max(nvec, alias_count);
-	if (!info->scratchpad[0].ul)
-		minnvec = 32;
-	nvec = max_t(int, minnvec, roundup_pow_of_two(nvec));
-	return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info);
-}
-
-static struct msi_domain_ops its_pci_msi_ops = {
-	.msi_prepare	= its_pci_msi_prepare,
-};
-
-static struct msi_domain_info its_pci_msi_domain_info = {
-	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-		   MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
-	.ops	= &its_pci_msi_ops,
-	.chip	= &its_msi_irq_chip,
-};
-
-static struct of_device_id its_device_id[] = {
-	{	.compatible	= "arm,gic-v3-its",	},
-	{},
-};
-
-static int __init its_pci_msi_init_one(struct fwnode_handle *handle,
-				       const char *name)
-{
-	struct irq_domain *parent;
-
-	parent = irq_find_matching_fwnode(handle, DOMAIN_BUS_NEXUS);
-	if (!parent || !msi_get_domain_info(parent)) {
-		pr_err("%s: Unable to locate ITS domain\n", name);
-		return -ENXIO;
-	}
-
-	if (!pci_msi_create_irq_domain(handle, &its_pci_msi_domain_info,
-				       parent)) {
-		pr_err("%s: Unable to create PCI domain\n", name);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-static int __init its_pci_of_msi_init(void)
-{
-	struct device_node *np;
-
-	for (np = of_find_matching_node(NULL, its_device_id); np;
-	     np = of_find_matching_node(np, its_device_id)) {
-		if (!of_device_is_available(np))
-			continue;
-		if (!of_property_read_bool(np, "msi-controller"))
-			continue;
-
-		if (its_pci_msi_init_one(of_node_to_fwnode(np), np->full_name))
-			continue;
-
-		pr_info("PCI/MSI: %pOF domain created\n", np);
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_ACPI
-
-static int __init
-its_pci_msi_parse_madt(union acpi_subtable_headers *header,
-		       const unsigned long end)
-{
-	struct acpi_madt_generic_translator *its_entry;
-	struct fwnode_handle *dom_handle;
-	const char *node_name;
-	int err = -ENXIO;
-
-	its_entry = (struct acpi_madt_generic_translator *)header;
-	node_name = kasprintf(GFP_KERNEL, "ITS@0x%lx",
-			      (long)its_entry->base_address);
-	dom_handle = iort_find_domain_token(its_entry->translation_id);
-	if (!dom_handle) {
-		pr_err("%s: Unable to locate ITS domain handle\n", node_name);
-		goto out;
-	}
-
-	err = its_pci_msi_init_one(dom_handle, node_name);
-	if (!err)
-		pr_info("PCI/MSI: %s domain created\n", node_name);
-
-out:
-	kfree(node_name);
-	return err;
-}
-
-static int __init its_pci_acpi_msi_init(void)
-{
-	acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
-			      its_pci_msi_parse_madt, 0);
-	return 0;
-}
-#else
-static int __init its_pci_acpi_msi_init(void)
-{
-	return 0;
-}
-#endif
-
-static int __init its_pci_msi_init(void)
-{
-	its_pci_of_msi_init();
-	its_pci_acpi_msi_init();
-
-	return 0;
-}
-early_initcall(its_pci_msi_init);


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 14/40] genirq/irqdomain: Add BUS_DOMAIN_DEVICE_MSI
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (12 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 13/40] irqchip/gic-v3-its: Provide MSI parent for PCI/MSI[-X] Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 15/40] irqchip/gic-msi-lib: Prepare for DEVICE MSI to replace platform MSI Thomas Gleixner
                   ` (26 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Add a new domain bus token to prepare for device MSI which aims to replace
the existing platform MSI maze.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/irqdomain_defs.h |    1 +
 1 file changed, 1 insertion(+)

--- a/include/linux/irqdomain_defs.h
+++ b/include/linux/irqdomain_defs.h
@@ -26,6 +26,7 @@ enum irq_domain_bus_token {
 	DOMAIN_BUS_DMAR,
 	DOMAIN_BUS_AMDVI,
 	DOMAIN_BUS_PCI_DEVICE_IMS,
+	DOMAIN_BUS_DEVICE_IMS,
 };
 
 #endif /* _LINUX_IRQDOMAIN_DEFS_H */


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 15/40] irqchip/gic-msi-lib: Prepare for DEVICE MSI to replace platform MSI
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (13 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 14/40] genirq/irqdomain: Add BUS_DOMAIN_DEVICE_MSI Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 16/40] platform-msi: Prepare for real per device domains Thomas Gleixner
                   ` (25 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Add the prerequisites for DEVICE MSI into the shared select() and child
domain init function. These domains are really trivial and just provide a
custom irq chip callback to write the MSI message.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/irqchip/irq-gic-msi-lib.c |   13 +++++++++++++
 drivers/irqchip/irq-gic-msi-lib.h |    2 ++
 2 files changed, 15 insertions(+)

--- a/drivers/irqchip/irq-gic-msi-lib.c
+++ b/drivers/irqchip/irq-gic-msi-lib.c
@@ -55,6 +55,19 @@ bool gic_msi_lib_init_dev_msi_info(struc
 
 		pci_device_msi_mask_unmask_parent_enable();
 		break;
+	case DOMAIN_BUS_DEVICE_IMS:
+		/*
+		 * Per device IMS should never have any MSI feature bits
+		 * set. It's sole purpose is to create a dumb interrupt
+		 * chip which has a device specific irq_write_msi_msg()
+		 * callback.
+		 */
+		if (WARN_ON_ONCE(info->flags))
+			return false;
+
+		/* Core managed MSI descriptors */
+		info->flags = MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS | MSI_FLAG_FREE_MSI_DESCS;
+		break;
 	default:
 		/*
 		 * This should never be reached. See
--- a/drivers/irqchip/irq-gic-msi-lib.h
+++ b/drivers/irqchip/irq-gic-msi-lib.h
@@ -15,6 +15,8 @@
 #define MATCH_PCI_MSI		(0)
 #endif
 
+#define MATCH_PLATFORM_MSI	BIT(DOMAIN_BUS_PLATFORM_MSI)
+
 int gic_msi_lib_irq_domain_select(struct irq_domain *d, struct irq_fwspec *fwspec,
 				  enum irq_domain_bus_token bus_token);
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 16/40] platform-msi: Prepare for real per device domains
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (14 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 15/40] irqchip/gic-msi-lib: Prepare for DEVICE MSI to replace platform MSI Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 17/40] irqchip: Convert all platform MSI users to the new API Thomas Gleixner
                   ` (24 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Provide functions to create and remove per device MSI domains which replace
the platform-MSI domains. The new model is that each of the devices which
utilize platform-MSI gets now its private MSI domain which is "customized"
in size and with a device specific function to write the MSI message into
the device.

This is the same functionality as platform-MSI but it avoids all the down
sides of platform MSI, i.e. the extra ID book keeping, the special data
structure in the msi descriptor. Further the domains are only created when
the devices are really in use, so the burden is on the usage and not on the
infrastructure.

Fill in the domain template and provide two functions to init/allocate and
remove a per device MSI domain.

Until all users and parent domain providers are converted, the init/alloc
function invokes the original platform-MSI code when the irqdomain which is
associated to the device does not provide MSI parent functionality yet.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/base/platform-msi.c |   98 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/msi.h         |    4 +
 2 files changed, 102 insertions(+)

--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -13,6 +13,8 @@
 #include <linux/msi.h>
 #include <linux/slab.h>
 
+/* Begin of removal area. Once everything is converted over. Cleanup the includes too! */
+
 #define DEV_ID_SHIFT	21
 #define MAX_DEV_MSIS	(1 << (32 - DEV_ID_SHIFT))
 
@@ -349,3 +351,99 @@ int platform_msi_device_domain_alloc(str
 
 	return msi_domain_populate_irqs(domain->parent, dev, virq, nr_irqs, &data->arg);
 }
+
+/* End of removal area */
+
+/* Real per device domain interfaces */
+
+/*
+ * This indirection can go when platform_device_ims_init_and_alloc_irqs()
+ * is switched to a proper irq_chip::irq_write_msi_msg() callback. Keep it
+ * simple for now.
+ */
+static void platform_msi_write_msi_msg(struct irq_data *d, struct msi_msg *msg)
+{
+	irq_write_msi_msg_t cb = d->chip_data;
+
+	cb(irq_data_get_msi_desc(d), msg);
+}
+
+static void platform_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
+{
+	arg->desc = desc;
+	arg->hwirq = desc->msi_index;
+}
+
+static const struct msi_domain_template platform_msi_template = {
+	.chip = {
+		.name			= "pMSI",
+		.irq_mask		= irq_chip_mask_parent,
+		.irq_unmask		= irq_chip_unmask_parent,
+		.irq_write_msi_msg	= platform_msi_write_msi_msg,
+		/* The rest is filled in by the platform MSI parent */
+	},
+
+	.ops = {
+		.set_desc		= platform_msi_set_desc,
+	},
+
+	.info = {
+		.bus_token		= DOMAIN_BUS_DEVICE_IMS,
+	},
+};
+
+/**
+ * platform_device_ims_init_and_alloc_irqs - Initialize platform device IMS
+ *					     and allocate interrupts for @dev
+ * @dev:		The device for which to allocate interrupts
+ * @nvec:		The number of interrupts to allocate
+ * @write_msi_msg:	Callback to write an interrupt message for @dev
+ *
+ * Returns:
+ * Zero for success, or an error code in case of failure
+ *
+ * This creates a MSI domain on @dev which has @dev->msi.domain as
+ * parent. The parent domain sets up the new domain. The domain has
+ * a fixed size of @nvec. The domain is managed by devres and will
+ * be removed when the device is removed.
+ *
+ * Note: For migration purposes this falls back to the original platform_msi code
+ *	 up to the point where all platforms have been converted to the MSI
+ *	 parent model.
+ */
+int platform_device_ims_init_and_alloc_irqs(struct device *dev, unsigned int nvec,
+					    irq_write_msi_msg_t write_msi_msg)
+{
+	struct irq_domain *domain = dev->msi.domain;
+	int ret;
+
+	if (!domain || !write_msi_msg)
+		return -EINVAL;
+
+	/* Migration support. Will go away once everything is converted */
+	if (!irq_domain_is_msi_parent(domain))
+		return platform_msi_domain_alloc_irqs(dev, nvec, write_msi_msg);
+
+	/*
+	 * @write_msi_msg is stored in the resulting msi_domain_info::data.
+	 * The underlying domain creation mechanism will assign that
+	 * callback to the resulting irq chip.
+	 */
+	if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN,
+					  &platform_msi_template,
+					  nvec, NULL, write_msi_msg))
+		return -ENODEV;
+
+	return msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, nvec - 1);
+}
+EXPORT_SYMBOL_GPL(platform_device_ims_init_and_alloc_irqs);
+
+/**
+ * platform_device_ims_free_irqs_all - Free all interrupts for @dev
+ * @dev:	The device for which to free interrupts
+ */
+void platform_device_ims_free_irqs_all(struct device *dev)
+{
+	msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
+}
+EXPORT_SYMBOL_GPL(platform_device_ims_free_irqs_all);
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -649,6 +649,10 @@ int platform_msi_device_domain_alloc(str
 void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int virq,
 				     unsigned int nvec);
 void *platform_msi_get_host_data(struct irq_domain *domain);
+/* Per device platform MSI */
+int platform_device_ims_init_and_alloc_irqs(struct device *dev, unsigned int nvec,
+					    irq_write_msi_msg_t write_msi_msg);
+void platform_device_ims_free_irqs_all(struct device *dev);
 #endif /* CONFIG_GENERIC_MSI_IRQ */
 
 /* PCI specific interfaces */


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 17/40] irqchip: Convert all platform MSI users to the new API
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (15 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 16/40] platform-msi: Prepare for real per device domains Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 18/40] genirq/msi: Provide optional translation op Thomas Gleixner
                   ` (23 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Switch all the users of the platform MSI domain over to invoke the new
interfaces which branch to the original platform MSI functions when the
irqdomain associated to the caller device does not yet provide MSI parent
functionality.

No functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: Sinan Kaya <okaya@kernel.org>
Cc: Andy Gross <agross@kernel.org>
Cc: Bjorn Andersson <andersson@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
---
 drivers/dma/mv_xor_v2.c                     |    8 ++++----
 drivers/dma/qcom/hidma.c                    |    6 +++---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |    5 +++--
 drivers/mailbox/bcm-flexrm-mailbox.c        |    8 ++++----
 drivers/perf/arm_smmuv3_pmu.c               |    4 ++--
 5 files changed, 16 insertions(+), 15 deletions(-)

--- a/drivers/dma/mv_xor_v2.c
+++ b/drivers/dma/mv_xor_v2.c
@@ -764,8 +764,8 @@ static int mv_xor_v2_probe(struct platfo
 			goto disable_reg_clk;
 	}
 
-	ret = platform_msi_domain_alloc_irqs(&pdev->dev, 1,
-					     mv_xor_v2_set_msi_msg);
+	ret = platform_device_ims_init_and_alloc_irqs(&pdev->dev, 1,
+						      mv_xor_v2_set_msi_msg);
 	if (ret)
 		goto disable_clk;
 
@@ -868,7 +868,7 @@ static int mv_xor_v2_probe(struct platfo
 			  xor_dev->desc_size * MV_XOR_V2_DESC_NUM,
 			  xor_dev->hw_desq_virt, xor_dev->hw_desq);
 free_msi_irqs:
-	platform_msi_domain_free_irqs(&pdev->dev);
+	platform_device_ims_free_irqs_all(&pdev->dev);
 disable_clk:
 	clk_disable_unprepare(xor_dev->clk);
 disable_reg_clk:
@@ -888,7 +888,7 @@ static int mv_xor_v2_remove(struct platf
 
 	devm_free_irq(&pdev->dev, xor_dev->irq, xor_dev);
 
-	platform_msi_domain_free_irqs(&pdev->dev);
+	platform_device_ims_free_irqs_all(&pdev->dev);
 
 	tasklet_kill(&xor_dev->irq_tasklet);
 
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -697,7 +697,7 @@ static void hidma_free_msis(struct hidma
 			devm_free_irq(dev, virq, &dmadev->lldev);
 	}
 
-	platform_msi_domain_free_irqs(dev);
+	platform_device_ims_free_irqs_all(dev);
 #endif
 }
 
@@ -707,8 +707,8 @@ static int hidma_request_msi(struct hidm
 #ifdef CONFIG_GENERIC_MSI_IRQ
 	int rc, i, virq;
 
-	rc = platform_msi_domain_alloc_irqs(&pdev->dev, HIDMA_MSI_INTS,
-					    hidma_write_msi_msg);
+	rc = platform_device_ims_init_and_alloc_irqs(&pdev->dev, HIDMA_MSI_INTS,
+						     hidma_write_msi_msg);
 	if (rc)
 		return rc;
 
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3122,7 +3122,8 @@ static int arm_smmu_update_gbpa(struct a
 static void arm_smmu_free_msis(void *data)
 {
 	struct device *dev = data;
-	platform_msi_domain_free_irqs(dev);
+
+	platform_device_ims_free_irqs_all(dev);
 }
 
 static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
@@ -3163,7 +3164,7 @@ static void arm_smmu_setup_msis(struct a
 	}
 
 	/* Allocate MSIs for evtq, gerror and priq. Ignore cmdq */
-	ret = platform_msi_domain_alloc_irqs(dev, nvec, arm_smmu_write_msi_msg);
+	ret = platform_device_ims_init_and_alloc_irqs(dev, nvec, arm_smmu_write_msi_msg);
 	if (ret) {
 		dev_warn(dev, "failed to allocate MSIs - falling back to wired irqs\n");
 		return;
--- a/drivers/mailbox/bcm-flexrm-mailbox.c
+++ b/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -1591,8 +1591,8 @@ static int flexrm_mbox_probe(struct plat
 	}
 
 	/* Allocate platform MSIs for each ring */
-	ret = platform_msi_domain_alloc_irqs(dev, mbox->num_rings,
-						flexrm_mbox_msi_write);
+	ret = platform_device_ims_init_and_alloc_irqs(dev, mbox->num_rings,
+						      flexrm_mbox_msi_write);
 	if (ret)
 		goto fail_destroy_cmpl_pool;
 
@@ -1645,7 +1645,7 @@ static int flexrm_mbox_probe(struct plat
 
 fail_free_debugfs_root:
 	debugfs_remove_recursive(mbox->root);
-	platform_msi_domain_free_irqs(dev);
+	platform_device_ims_free_irqs_all(dev);
 fail_destroy_cmpl_pool:
 	dma_pool_destroy(mbox->cmpl_pool);
 fail_destroy_bd_pool:
@@ -1661,7 +1661,7 @@ static int flexrm_mbox_remove(struct pla
 
 	debugfs_remove_recursive(mbox->root);
 
-	platform_msi_domain_free_irqs(dev);
+	platform_device_ims_free_irqs_all(dev);
 
 	dma_pool_destroy(mbox->cmpl_pool);
 	dma_pool_destroy(mbox->bd_pool);
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -685,7 +685,7 @@ static void smmu_pmu_free_msis(void *dat
 {
 	struct device *dev = data;
 
-	platform_msi_domain_free_irqs(dev);
+	platform_device_ims_free_irqs_all(dev);
 }
 
 static void smmu_pmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
@@ -715,7 +715,7 @@ static void smmu_pmu_setup_msi(struct sm
 	if (!(readl(pmu->reg_base + SMMU_PMCG_CFGR) & SMMU_PMCG_CFGR_MSI))
 		return;
 
-	ret = platform_msi_domain_alloc_irqs(dev, 1, smmu_pmu_write_msi_msg);
+	ret = platform_device_ims_init_and_alloc_irqs(dev, 1, smmu_pmu_write_msi_msg);
 	if (ret) {
 		dev_warn(dev, "failed to allocate MSIs\n");
 		return;


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 18/40] genirq/msi: Provide optional translation op
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (16 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 17/40] irqchip: Convert all platform MSI users to the new API Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 19/40] genirq/msi: Split msi_domain_alloc_irq_at() Thomas Gleixner
                   ` (22 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

irq_create_fwspec_mapping() requires translation of the firmware spec to a
hardware interrupt number and the trigger type information.

Wired interrupts which are connected to a wire to MSI bridge, like MBIGEN
are allocated that way. So far MBIGEN provides a regular irqdomain which
then hooks backwards into the MSI infrastructure. That's an unholy mess and
will be replaced with per device MSI domains which are regular MSI domains.

Interrupts on MSI domains are not supported by irq_create_fwspec_mapping(),
but for making the wire to MSI bridges sane it makes sense to provide a
special allocation/free interface in the MSI infrastructure. That avoids
the backdoors into the core MSI allocation code and just shares all the
regular MSI infrastructure.

Provide an optional translation callback in msi_domain_ops which can be
utilized by these wire to MSI bridges. No other MSI domain should provide a
translation callback. The default translation callback of the MSI
irqdomains will warn when it is invoked on a non-prepared MSI domain.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/msi.h |    5 +++++
 kernel/irq/msi.c    |   15 +++++++++++++++
 2 files changed, 20 insertions(+)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -393,6 +393,7 @@ bool arch_restore_msi_irqs(struct pci_de
 struct irq_domain;
 struct irq_domain_ops;
 struct irq_chip;
+struct irq_fwspec;
 struct device_node;
 struct fwnode_handle;
 struct msi_domain_info;
@@ -412,6 +413,8 @@ struct msi_domain_info;
  *			function.
  * @msi_post_free:	Optional function which is invoked after freeing
  *			all interrupts.
+ * @msi_translate:	Optional translate callback to support the odd wire to
+ *			MSI bridges, e.g. MBIGEN
  *
  * @get_hwirq, @msi_init and @msi_free are callbacks used by the underlying
  * irqdomain.
@@ -449,6 +452,8 @@ struct msi_domain_ops {
 					    struct device *dev);
 	void		(*msi_post_free)(struct irq_domain *domain,
 					 struct device *dev);
+	int		(*msi_translate)(struct irq_domain *domain, struct irq_fwspec *fwspec,
+					 irq_hw_number_t *hwirq, unsigned int *type);
 };
 
 /**
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -772,11 +772,26 @@ static void msi_domain_free(struct irq_d
 	irq_domain_free_irqs_top(domain, virq, nr_irqs);
 }
 
+static int msi_domain_translate(struct irq_domain *domain, struct irq_fwspec *fwspec,
+				irq_hw_number_t *hwirq, unsigned int *type)
+{
+	struct msi_domain_info *info = domain->host_data;
+
+	/*
+	 * This will catch allocations through the regular irqdomain path except
+	 * for MSI domains which really support this, e.g. MBIGEN.
+	 */
+	if (!info->ops->msi_translate)
+		return -ENOTSUPP;
+	return info->ops->msi_translate(domain, fwspec, hwirq, type);
+}
+
 static const struct irq_domain_ops msi_domain_ops = {
 	.alloc		= msi_domain_alloc,
 	.free		= msi_domain_free,
 	.activate	= msi_domain_activate,
 	.deactivate	= msi_domain_deactivate,
+	.translate	= msi_domain_translate,
 };
 
 static irq_hw_number_t msi_domain_ops_get_hwirq(struct msi_domain_info *info,


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 19/40] genirq/msi: Split msi_domain_alloc_irq_at()
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (17 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 18/40] genirq/msi: Provide optional translation op Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 20/40] genirq/msi: Provide BUS DEVICE_MSI_WIRED Thomas Gleixner
                   ` (21 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

In preparation for providing a special allocation function for wired
interrupt which are connected to a wire to MSI bridge, split the inner
workings of msi_domain_alloc_irq_at() out into a helper function so the
code can be shared.

No functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/irq/msi.c |   76 +++++++++++++++++++++++++++++++------------------------
 1 file changed, 43 insertions(+), 33 deletions(-)

--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -1465,34 +1465,10 @@ int msi_domain_alloc_irqs_all_locked(str
 	return msi_domain_alloc_locked(dev, &ctrl);
 }
 
-/**
- * msi_domain_alloc_irq_at - Allocate an interrupt from a MSI interrupt domain at
- *			     a given index - or at the next free index
- *
- * @dev:	Pointer to device struct of the device for which the interrupts
- *		are allocated
- * @domid:	Id of the interrupt domain to operate on
- * @index:	Index for allocation. If @index == %MSI_ANY_INDEX the allocation
- *		uses the next free index.
- * @affdesc:	Optional pointer to an interrupt affinity descriptor structure
- * @icookie:	Optional pointer to a domain specific per instance cookie. If
- *		non-NULL the content of the cookie is stored in msi_desc::data.
- *		Must be NULL for MSI-X allocations
- *
- * This requires a MSI interrupt domain which lets the core code manage the
- * MSI descriptors.
- *
- * Return: struct msi_map
- *
- *	On success msi_map::index contains the allocated index number and
- *	msi_map::virq the corresponding Linux interrupt number
- *
- *	On failure msi_map::index contains the error code and msi_map::virq
- *	is %0.
- */
-struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, unsigned int index,
-				       const struct irq_affinity_desc *affdesc,
-				       union msi_instance_cookie *icookie)
+static struct msi_map __msi_domain_alloc_irq_at(struct device *dev, unsigned int domid,
+						unsigned int index,
+						const struct irq_affinity_desc *affdesc,
+						union msi_instance_cookie *icookie)
 {
 	struct msi_ctrl ctrl = { .domid	= domid, .nirqs = 1, };
 	struct msi_domain_info *info;
@@ -1501,17 +1477,16 @@ struct msi_map msi_domain_alloc_irq_at(s
 	struct msi_desc *desc;
 	int ret;
 
-	msi_lock_descs(dev);
 	domain = msi_get_device_domain(dev, domid);
 	if (!domain) {
 		map.index = -ENODEV;
-		goto unlock;
+		return map;
 	}
 
 	desc = msi_alloc_desc(dev, 1, affdesc);
 	if (!desc) {
 		map.index = -ENOMEM;
-		goto unlock;
+		return map;
 	}
 
 	if (icookie)
@@ -1520,7 +1495,7 @@ struct msi_map msi_domain_alloc_irq_at(s
 	ret = msi_insert_desc(dev, desc, domid, index);
 	if (ret) {
 		map.index = ret;
-		goto unlock;
+		return map;
 	}
 
 	ctrl.first = ctrl.last = desc->msi_index;
@@ -1534,7 +1509,42 @@ struct msi_map msi_domain_alloc_irq_at(s
 		map.index = desc->msi_index;
 		map.virq = desc->irq;
 	}
-unlock:
+	return map;
+}
+
+/**
+ * msi_domain_alloc_irq_at - Allocate an interrupt from a MSI interrupt domain at
+ *			     a given index - or at the next free index
+ *
+ * @dev:	Pointer to device struct of the device for which the interrupts
+ *		are allocated
+ * @domid:	Id of the interrupt domain to operate on
+ * @index:	Index for allocation. If @index == %MSI_ANY_INDEX the allocation
+ *		uses the next free index.
+ * @affdesc:	Optional pointer to an interrupt affinity descriptor structure
+ * @icookie:	Optional pointer to a domain specific per instance cookie. If
+ *		non-NULL the content of the cookie is stored in msi_desc::data.
+ *		Must be NULL for MSI-X allocations
+ *
+ * This requires a MSI interrupt domain which lets the core code manage the
+ * MSI descriptors.
+ *
+ * Return: struct msi_map
+ *
+ *	On success msi_map::index contains the allocated index number and
+ *	msi_map::virq the corresponding Linux interrupt number
+ *
+ *	On failure msi_map::index contains the error code and msi_map::virq
+ *	is %0.
+ */
+struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, unsigned int index,
+				       const struct irq_affinity_desc *affdesc,
+				       union msi_instance_cookie *icookie)
+{
+	struct msi_map map;
+
+	msi_lock_descs(dev);
+	map = __msi_domain_alloc_irq_at(dev, domid, index, affdesc, icookie);
 	msi_unlock_descs(dev);
 	return map;
 }


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 20/40] genirq/msi: Provide BUS DEVICE_MSI_WIRED
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (18 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 19/40] genirq/msi: Split msi_domain_alloc_irq_at() Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 21/40] genirq/msi: Optionally use dev->fwnode for device domain Thomas Gleixner
                   ` (20 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Provide a domain bus token for the upcoming support for wire to MSI device
domains so the domain can be distinguished from regular device MSI domains.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/irqdomain_defs.h |    1 +
 1 file changed, 1 insertion(+)

--- a/include/linux/irqdomain_defs.h
+++ b/include/linux/irqdomain_defs.h
@@ -27,6 +27,7 @@ enum irq_domain_bus_token {
 	DOMAIN_BUS_AMDVI,
 	DOMAIN_BUS_PCI_DEVICE_IMS,
 	DOMAIN_BUS_DEVICE_IMS,
+	DOMAIN_BUS_WIRED_TO_MSI,
 };
 
 #endif /* _LINUX_IRQDOMAIN_DEFS_H */


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 21/40] genirq/msi: Optionally use dev->fwnode for device domain
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (19 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 20/40] genirq/msi: Provide BUS DEVICE_MSI_WIRED Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 22/40] genirq/msi: Provide allocation/free functions for "wired" MSI interrupts Thomas Gleixner
                   ` (19 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

To support wire to MSI domains via the MSI infrastructure it is required to
use the firmware node of the device which implements this for creating the
MSI domain. Otherwise the existing firmware match mechanisms to find the
correct irqdomain for a wired interrupt which is connected to a wire to MSI
bridge would fail.

This cannot be used for the general case because not all devices provide
firmware nodes and all regular per device MSI domains are directly
associated to the device and have not be searched for.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/msi.h |    2 ++
 kernel/irq/msi.c    |   20 ++++++++++++++++----
 2 files changed, 18 insertions(+), 4 deletions(-)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -536,6 +536,8 @@ enum {
 	 * handled in the core MSI code.
 	 */
 	MSI_FLAG_NOMASK_QUIRK		= (1 << 7),
+	/* Use dev->fwnode for MSI device domain creation */
+	MSI_FLAG_USE_DEV_FWNODE		= (1 << 8),
 
 	/* Mask for the generic functionality */
 	MSI_GENERIC_FLAGS_MASK		= GENMASK(15, 0),
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -998,9 +998,9 @@ bool msi_create_device_irq_domain(struct
 				  void *chip_data)
 {
 	struct irq_domain *domain, *parent = dev->msi.domain;
-	const struct msi_parent_ops *pops;
+	struct fwnode_handle *fwnode, *fwnalloced = NULL;
 	struct msi_domain_template *bundle;
-	struct fwnode_handle *fwnode;
+	const struct msi_parent_ops *pops;
 
 	if (!irq_domain_is_msi_parent(parent))
 		return false;
@@ -1023,7 +1023,19 @@ bool msi_create_device_irq_domain(struct
 		 pops->prefix ? : "", bundle->chip.name, dev_name(dev));
 	bundle->chip.name = bundle->name;
 
-	fwnode = irq_domain_alloc_named_fwnode(bundle->name);
+	/*
+	 * Using the device firmware node is required for wire to MSI
+	 * device domains so that the existing firmware results in a domain
+	 * match.
+	 * All other device domains like PCI/MSI use the named firmware
+	 * node as they are not guaranteed to have a fwnode. They are never
+	 * looked up and always handled in the context of the device.
+	 */
+	if (bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE)
+		fwnode = dev->fwnode;
+	else
+		fwnode = fwnalloced = irq_domain_alloc_named_fwnode(bundle->name);
+
 	if (!fwnode)
 		goto free_bundle;
 
@@ -1050,7 +1062,7 @@ bool msi_create_device_irq_domain(struct
 fail:
 	msi_unlock_descs(dev);
 free_fwnode:
-	kfree(fwnode);
+	kfree(fwnalloced);
 free_bundle:
 	kfree(bundle);
 	return false;


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 22/40] genirq/msi: Provide allocation/free functions for "wired" MSI interrupts
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (20 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 21/40] genirq/msi: Optionally use dev->fwnode for device domain Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 23/40] genirq/irqdomain: Reroute device MSI create_mapping Thomas Gleixner
                   ` (18 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

To support wire to MSI bridges proper in the MSI core infrastructure it is
required to have separate allocation/free interfaces which can be invoked
from the regular irqdomain allocaton/free functions.

The mechanism for allocation is:
  - Allocate the next free MSI descriptor index in the domain
  - Store the hardware interrupt number and the trigger type
    which was extracted by the irqdomain core from the firmware spec
    in the MSI descriptor device cookie so it can be retrieved by
    the underlying interrupt domain and interrupt chip
  - Use the regular MSI allocation mechanism for the newly allocated
    index which returns a fully initialized Linux interrupt on succes

This works because:
  - the domains have a fixed size
  - each hardware interrupt is only allocated once
  - the underlying domain does not care about the MSI index it only cares
    about the hardware interrupt number and the trigger type

The free function looks up the MSI index in the MSI descriptor of the
provided Linux interrupt number and uses the regular index based free
functions of the MSI core.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/irqdomain.h |   17 +++++++++++
 kernel/irq/msi.c          |   68 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -634,6 +634,23 @@ static inline bool irq_domain_is_msi_dev
 
 #endif	/* CONFIG_IRQ_DOMAIN_HIERARCHY */
 
+#ifdef CONFIG_GENERIC_MSI_IRQ
+int msi_device_domain_alloc_wired(struct irq_domain *domain, unsigned int hwirq,
+				  unsigned int type);
+void msi_device_domain_free_wired(struct irq_domain *domain, unsigned int virq);
+#else
+static inline int msi_device_domain_alloc_wired(struct irq_domain *domain, unsigned int hwirq,
+						unsigned int type)
+{
+	WARN_ON_ONCE(1);
+	return -EINVAL;
+}
+static inline void msi_device_domain_free_wired(struct irq_domain *domain, unsigned int virq)
+{
+	WARN_ON_ONCE(1);
+}
+#endif
+
 #else /* CONFIG_IRQ_DOMAIN */
 static inline void irq_dispose_mapping(unsigned int virq) { }
 static inline struct irq_domain *irq_find_matching_fwnode(
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -1561,6 +1561,50 @@ struct msi_map msi_domain_alloc_irq_at(s
 	return map;
 }
 
+/**
+ * msi_device_domain_alloc_wired - Allocate a "wired" interrupt on @domain
+ * @domain:	The domain to allocate on
+ * @hwirq:	The hardware interrupt number to allocate for
+ * @type:	The interrupt type
+ *
+ * This weirdness supports wire to MSI controllers like MBIGEN.
+ *
+ * @hwirq is the hardware interrupt number which is handed in from
+ * irq_create_fwspec_mapping(). As the wire to MSI domain is sparse, but
+ * sized in firmware, the hardware interrupt number cannot be used as MSI
+ * index. For the underlying irq chip the MSI index is irrelevant and
+ * all it needs is the hardware interrupt number.
+ *
+ * To handle this the MSI index is allocated with MSI_ANY_INDEX and the
+ * hardware interrupt number is stored along with the type information in
+ * msi_desc::cookie so the underlying interrupt chip and domain code can
+ * retrieve it.
+ *
+ * Return: The Linux interrupt number (> 0) or an error code
+ */
+int msi_device_domain_alloc_wired(struct irq_domain *domain, unsigned int hwirq,
+				  unsigned int type)
+{
+	unsigned int domid = MSI_DEFAULT_DOMAIN;
+	union msi_instance_cookie icookie = { };
+	struct device *dev = domain->dev;
+	struct msi_map map = { };
+
+	if (WARN_ON_ONCE(!dev || domain->bus_token != DOMAIN_BUS_WIRED_TO_MSI))
+		return -EINVAL;
+
+	icookie.value = ((u64)type << 32) | hwirq;
+
+	msi_lock_descs(dev);
+	if (WARN_ON_ONCE(msi_get_device_domain(dev, domid) != domain))
+		map.index = -EINVAL;
+	else
+		map = __msi_domain_alloc_irq_at(dev, domid, MSI_ANY_INDEX, NULL, &icookie);
+	msi_unlock_descs(dev);
+
+	return map.index >= 0 ? map.virq : map.index;
+}
+
 static void __msi_domain_free_irqs(struct device *dev, struct irq_domain *domain,
 				   struct msi_ctrl *ctrl)
 {
@@ -1688,6 +1732,30 @@ void msi_domain_free_irqs_all(struct dev
 	msi_unlock_descs(dev);
 }
 
+/**
+ * msi_device_domain_free_wired - Free a wired interrupt in @domain
+ * @domain:	The domain to free the interrupt on
+ * @virq:	The Linux interrupt number to free
+ *
+ * This is the counterpart of msi_device_domain_alloc_wired() for the
+ * weird wired to MSI converting domains.
+ */
+void msi_device_domain_free_wired(struct irq_domain *domain, unsigned int virq)
+{
+	struct msi_desc *desc = irq_get_msi_desc(virq);
+	struct device *dev = domain->dev;
+
+	if (WARN_ON_ONCE(!dev || !desc || domain->bus_token != DOMAIN_BUS_WIRED_TO_MSI))
+		return;
+
+	msi_lock_descs(dev);
+	if (!WARN_ON_ONCE(msi_get_device_domain(dev, MSI_DEFAULT_DOMAIN) != domain)) {
+		msi_domain_free_irqs_range_locked(dev, MSI_DEFAULT_DOMAIN, desc->msi_index,
+						  desc->msi_index);
+	}
+	msi_unlock_descs(dev);
+}
+
 /**
  * msi_get_domain_info - Get the MSI interrupt domain info for @domain
  * @domain:	The interrupt domain to retrieve data from


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 23/40] genirq/irqdomain: Reroute device MSI create_mapping
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (21 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 22/40] genirq/msi: Provide allocation/free functions for "wired" MSI interrupts Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 24/40] irqchip/mbigen: Prepare for real per device MSI Thomas Gleixner
                   ` (17 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Reroute interrupt allocation in irq_create_fwspec_mapping() if the domain
is a MSI device domain. This is required to convert the support for wire
to MSI bridges to per device MSI domains.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/irq/irqdomain.c |   24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -26,6 +26,7 @@ static DEFINE_MUTEX(irq_domain_mutex);
 static struct irq_domain *irq_default_domain;
 
 static void irq_domain_check_hierarchy(struct irq_domain *domain);
+static void irq_domain_free_one_irq(struct irq_domain *domain, unsigned int virq);
 
 struct irqchip_fwid {
 	struct fwnode_handle	fwnode;
@@ -822,7 +823,10 @@ unsigned int irq_create_fwspec_mapping(s
 	}
 
 	if (irq_domain_is_hierarchy(domain)) {
-		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
+		if (irq_domain_is_msi_device(domain))
+			virq = msi_device_domain_alloc_wired(domain, hwirq, type);
+		else
+			virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
 		if (virq <= 0)
 			return 0;
 	} else {
@@ -835,7 +839,7 @@ unsigned int irq_create_fwspec_mapping(s
 	irq_data = irq_get_irq_data(virq);
 	if (!irq_data) {
 		if (irq_domain_is_hierarchy(domain))
-			irq_domain_free_irqs(virq, 1);
+			irq_domain_free_one_irq(domain, virq);
 		else
 			irq_dispose_mapping(virq);
 		return 0;
@@ -876,7 +880,7 @@ void irq_dispose_mapping(unsigned int vi
 		return;
 
 	if (irq_domain_is_hierarchy(domain)) {
-		irq_domain_free_irqs(virq, 1);
+		irq_domain_free_one_irq(domain, virq);
 	} else {
 		irq_domain_disassociate(domain, virq);
 		irq_free_desc(virq);
@@ -1706,6 +1710,14 @@ void irq_domain_free_irqs(unsigned int v
 	irq_free_descs(virq, nr_irqs);
 }
 
+static void irq_domain_free_one_irq(struct irq_domain *domain, unsigned int virq)
+{
+	if (irq_domain_is_msi_device(domain))
+		msi_device_domain_free_wired(domain, virq);
+	else
+		irq_domain_free_irqs(virq, 1);
+}
+
 /**
  * irq_domain_alloc_irqs_parent - Allocate interrupts from parent domain
  * @domain:	Domain below which interrupts must be allocated
@@ -1865,9 +1877,9 @@ void irq_domain_set_info(struct irq_doma
 	irq_set_handler_data(virq, handler_data);
 }
 
-static void irq_domain_check_hierarchy(struct irq_domain *domain)
-{
-}
+static void irq_domain_check_hierarchy(struct irq_domain *domain) { }
+static void irq_domain_free_one_irq(struct irq_domain *domain, unsigned int virq) { }
+
 #endif	/* CONFIG_IRQ_DOMAIN_HIERARCHY */
 
 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 24/40] irqchip/mbigen: Prepare for real per device MSI
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (22 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 23/40] genirq/irqdomain: Reroute device MSI create_mapping Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:39 ` [patch V2 25/40] irqchip/gic-msi-lib: Prepare for DOMAIN_BUS_WIRED_TO_MSI Thomas Gleixner
                   ` (16 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

The core infrastructure has everything in place to switch MBIGEN to per
device MSI domains and avoid the convoluted construct of the existing
platform-MSI layering violation.

The new infrastructure provides a wired interrupt specific interface in the
MSI core which converts the 'hardware interrupt number + trigger type'
allocation which is required for wired interrupts in the regular irqdomain
code to a normal MSI allocation.

The hardware interrupt number and the trigger type are stored in the MSI
descriptor device cookie by the core code so the MBIGEN specific code can
retrieve them.

The new per device domain is only instantiated when the irqdomain which is
associated to the MBIGEN device provides MSI parent functionality. Up to
that point it invokes the existing code. Once the parent is converted the
code for the current platform-MSI mechanism is removed.

The new domain shares the interrupt chip callbacks and the translation
function. The only new functionality aside of filling out the
msi_domain_template is a domain specific set_desc() callback, which will go
away once all platform-MSI code has been converted.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
Cc: Zenghui Yu <yuzenghui@huawei.com>
---
 drivers/irqchip/irq-mbigen.c |  100 ++++++++++++++++++++++++++++++-------------
 1 file changed, 71 insertions(+), 29 deletions(-)

--- a/drivers/irqchip/irq-mbigen.c
+++ b/drivers/irqchip/irq-mbigen.c
@@ -135,24 +135,14 @@ static int mbigen_set_type(struct irq_da
 	return 0;
 }
 
-static struct irq_chip mbigen_irq_chip = {
-	.name =			"mbigen-v2",
-	.irq_mask =		irq_chip_mask_parent,
-	.irq_unmask =		irq_chip_unmask_parent,
-	.irq_eoi =		mbigen_eoi_irq,
-	.irq_set_type =		mbigen_set_type,
-	.irq_set_affinity =	irq_chip_set_affinity_parent,
-};
-
-static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg)
+static void mbigen_write_msi_msg(struct irq_data *d, struct msi_msg *msg)
 {
-	struct irq_data *d = irq_get_irq_data(desc->irq);
 	void __iomem *base = d->chip_data;
 	u32 val;
 
 	if (!msg->address_lo && !msg->address_hi)
 		return;
- 
+
 	base += get_mbigen_vec_reg(d->hwirq);
 	val = readl_relaxed(base);
 
@@ -165,10 +155,8 @@ static void mbigen_write_msg(struct msi_
 	writel_relaxed(val, base);
 }
 
-static int mbigen_domain_translate(struct irq_domain *d,
-				    struct irq_fwspec *fwspec,
-				    unsigned long *hwirq,
-				    unsigned int *type)
+static int mbigen_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
+				   unsigned long *hwirq, unsigned int *type)
 {
 	if (is_of_node(fwspec->fwnode) || is_acpi_device_node(fwspec->fwnode)) {
 		if (fwspec->param_count != 2)
@@ -192,6 +180,17 @@ static int mbigen_domain_translate(struc
 	return -EINVAL;
 }
 
+/* The following section will go away once ITS provides a MSI parent */
+
+static struct irq_chip mbigen_irq_chip = {
+	.name =			"mbigen-v2",
+	.irq_mask =		irq_chip_mask_parent,
+	.irq_unmask =		irq_chip_unmask_parent,
+	.irq_eoi =		mbigen_eoi_irq,
+	.irq_set_type =		mbigen_set_type,
+	.irq_set_affinity =	irq_chip_set_affinity_parent,
+};
+
 static int mbigen_irq_domain_alloc(struct irq_domain *domain,
 					unsigned int virq,
 					unsigned int nr_irqs,
@@ -232,13 +231,65 @@ static const struct irq_domain_ops mbige
 	.free		= mbigen_irq_domain_free,
 };
 
+static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg)
+{
+	mbigen_write_msi_msg(irq_get_irq_data(desc->irq), msg);
+}
+
+/* End of to be removed section */
+
+static void mbigen_domain_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
+{
+	arg->desc = desc;
+	arg->hwirq = (u32)desc->data.icookie.value;
+}
+
+static const struct msi_domain_template mbigen_msi_template = {
+	.chip = {
+		.name			= "mbigen-v2",
+		.irq_mask		= irq_chip_mask_parent,
+		.irq_unmask		= irq_chip_unmask_parent,
+		.irq_eoi		= mbigen_eoi_irq,
+		.irq_set_type		= mbigen_set_type,
+		.irq_write_msi_msg	= mbigen_write_msi_msg,
+	},
+
+	.ops = {
+		.set_desc		= mbigen_domain_set_desc,
+		.msi_translate		= mbigen_domain_translate,
+	},
+
+	.info = {
+		.bus_token		= DOMAIN_BUS_WIRED_TO_MSI,
+		.flags			= MSI_FLAG_USE_DEV_FWNODE,
+	},
+};
+
+static bool mbigen_create_device_domain(struct device *dev, unsigned int size,
+					struct mbigen_device *mgn_chip)
+{
+	struct irq_domain *domain = dev->msi.domain;
+
+	if (WARN_ON_ONCE(!domain))
+		return false;
+
+	if (irq_domain_is_msi_parent(domain)) {
+		return msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN,
+						    &mbigen_msi_template, size,
+						    NULL, mgn_chip->base);
+	}
+
+	/* Remove once ITS provides MSI parent */
+	return !!platform_msi_create_device_domain(dev, size, mbigen_write_msg,
+						   &mbigen_domain_ops, mgn_chip);
+}
+
 static int mbigen_of_create_domain(struct platform_device *pdev,
 				   struct mbigen_device *mgn_chip)
 {
-	struct device *parent;
 	struct platform_device *child;
-	struct irq_domain *domain;
 	struct device_node *np;
+	struct device *parent;
 	u32 num_pins;
 
 	for_each_child_of_node(pdev->dev.of_node, np) {
@@ -259,11 +310,7 @@ static int mbigen_of_create_domain(struc
 			return -EINVAL;
 		}
 
-		domain = platform_msi_create_device_domain(&child->dev, num_pins,
-							   mbigen_write_msg,
-							   &mbigen_domain_ops,
-							   mgn_chip);
-		if (!domain) {
+		if (!mbigen_create_device_domain(&child->dev, num_pins, mgn_chip)) {
 			of_node_put(np);
 			return -ENOMEM;
 		}
@@ -282,7 +329,6 @@ MODULE_DEVICE_TABLE(acpi, mbigen_acpi_ma
 static int mbigen_acpi_create_domain(struct platform_device *pdev,
 				     struct mbigen_device *mgn_chip)
 {
-	struct irq_domain *domain;
 	u32 num_pins = 0;
 	int ret;
 
@@ -313,11 +359,7 @@ static int mbigen_acpi_create_domain(str
 	if (ret || num_pins == 0)
 		return -EINVAL;
 
-	domain = platform_msi_create_device_domain(&pdev->dev, num_pins,
-						   mbigen_write_msg,
-						   &mbigen_domain_ops,
-						   mgn_chip);
-	if (!domain)
+	if (!mbigen_create_device_domain(&pdev->dev, num_pins, mgn_chip))
 		return -ENOMEM;
 
 	return 0;


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 25/40] irqchip/gic-msi-lib: Prepare for DOMAIN_BUS_WIRED_TO_MSI
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (23 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 24/40] irqchip/mbigen: Prepare for real per device MSI Thomas Gleixner
@ 2022-11-21 14:39 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 26/40] irqchip/gic-v3-its: Switch platform MSI to MSI parent Thomas Gleixner
                   ` (15 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:39 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Add the new bus token to the accepted list of child domain tokens.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/irqchip/irq-gic-msi-lib.c |    2 ++
 1 file changed, 2 insertions(+)

--- a/drivers/irqchip/irq-gic-msi-lib.c
+++ b/drivers/irqchip/irq-gic-msi-lib.c
@@ -68,6 +68,8 @@ bool gic_msi_lib_init_dev_msi_info(struc
 		/* Core managed MSI descriptors */
 		info->flags = MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS | MSI_FLAG_FREE_MSI_DESCS;
 		break;
+	case DOMAIN_BUS_WIRED_TO_MSI:
+		break;
 	default:
 		/*
 		 * This should never be reached. See


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 26/40] irqchip/gic-v3-its: Switch platform MSI to MSI parent
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (24 preceding siblings ...)
  2022-11-21 14:39 ` [patch V2 25/40] irqchip/gic-msi-lib: Prepare for DOMAIN_BUS_WIRED_TO_MSI Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 27/40] irqchip/mbigen: Remove platform_msi_create_device_domain() fallback Thomas Gleixner
                   ` (14 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Similar to the previous conversion of the PCI/MSI support lift the
prepare() callback from the existing platform MSI code and enable
platform MSI and the related device domain bus tokens in select
and the child domain initialization code.

All platform MSI users are automatically using the new per device MSI model
now.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/irqchip/Makefile                      |    2 
 drivers/irqchip/irq-gic-v3-its-msi-parent.c   |   73 +++++++++++
 drivers/irqchip/irq-gic-v3-its-platform-msi.c |  163 --------------------------
 3 files changed, 73 insertions(+), 165 deletions(-)

--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -33,7 +33,7 @@ obj-$(CONFIG_ARCH_REALVIEW)		+= irq-gic-
 obj-$(CONFIG_ARM_GIC_MSI_LIB)		+= irq-gic-msi-lib.o
 obj-$(CONFIG_ARM_GIC_V2M)		+= irq-gic-v2m.o
 obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
-obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o irq-gic-v3-its-msi-parent.o
+obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o irq-gic-v4.o irq-gic-v3-its-msi-parent.o
 obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC)	+= irq-gic-v3-its-fsl-mc-msi.o
 obj-$(CONFIG_PARTITION_PERCPU)		+= irq-partition-percpu.o
 obj-$(CONFIG_HISILICON_IRQ_MBIGEN)	+= irq-mbigen.o
--- a/drivers/irqchip/irq-gic-v3-its-msi-parent.c
+++ b/drivers/irqchip/irq-gic-v3-its-msi-parent.c
@@ -4,6 +4,7 @@
 // Copyright (C) 2022 Linutronix GmbH
 // Copyright (C) 2022 Intel
 
+#include <linux/acpi_iort.h>
 #include <linux/pci.h>
 
 #include "irq-gic-common.h"
@@ -93,6 +94,68 @@ static int its_pci_msi_prepare(struct ir
 #define its_pci_msi_prepare	NULL
 #endif /* !CONFIG_PCI_MSI */
 
+static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev,
+				  u32 *dev_id)
+{
+	int ret, index = 0;
+
+	/* Suck the DeviceID out of the msi-parent property */
+	do {
+		struct of_phandle_args args;
+
+		ret = of_parse_phandle_with_args(dev->of_node,
+						 "msi-parent", "#msi-cells",
+						 index, &args);
+		if (args.np == irq_domain_get_of_node(domain)) {
+			if (WARN_ON(args.args_count != 1))
+				return -EINVAL;
+			*dev_id = args.args[0];
+			break;
+		}
+		index++;
+	} while (!ret);
+
+	return ret;
+}
+
+int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
+{
+	return -1;
+}
+
+static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
+			    int nvec, msi_alloc_info_t *info)
+{
+	struct msi_domain_info *msi_info;
+	u32 dev_id;
+	int ret;
+
+	if (dev->of_node)
+		ret = of_pmsi_get_dev_id(domain, dev, &dev_id);
+	else
+		ret = iort_pmsi_get_dev_id(dev, &dev_id);
+	if (ret)
+		return ret;
+
+	/* ITS specific DeviceID, as the core ITS ignores dev. */
+	info->scratchpad[0].ul = dev_id;
+
+	/*
+	 * @domain->msi_domain_info->hwsize contains the size of the device
+	 * domain, but vector allocation happens one by one.
+	 */
+	msi_info = msi_get_domain_info(domain);
+	if (msi_info->hwsize > nvec)
+		nvec = msi_info->hwsize;
+
+	/* Allocate at least 32 MSIs, and always as a power of 2 */
+	nvec = max_t(int, 32, roundup_pow_of_two(nvec));
+
+	msi_info = msi_get_domain_info(domain->parent);
+	return msi_info->ops->msi_prepare(domain->parent,
+					  dev, nvec, info);
+}
+
 static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
 				  struct irq_domain *real_parent, struct msi_domain_info *info)
 {
@@ -117,6 +180,14 @@ static bool its_init_dev_msi_info(struct
 		 */
 		info->ops->msi_prepare = its_pci_msi_prepare;
 		break;
+	case DOMAIN_BUS_DEVICE_IMS:
+	case DOMAIN_BUS_WIRED_TO_MSI:
+		/*
+		 * FIXME: See the above PCI prepare comment. The domain
+		 * size is also known at domain creation time.
+		 */
+		info->ops->msi_prepare = its_pmsi_prepare;
+		break;
 	default:
 		/* Confused. How did the lib return true? */
 		WARN_ON_ONCE(1);
@@ -130,7 +201,7 @@ const struct msi_parent_ops gic_v3_its_m
 	.supported_flags	= ITS_MSI_FLAGS_SUPPORTED,
 	.required_flags		= ITS_MSI_FLAGS_REQUIRED,
 	.bus_select_token	= DOMAIN_BUS_NEXUS,
-	.bus_select_mask	= MATCH_PCI_MSI,
+	.bus_select_mask	= MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
 	.prefix			= "ITS-",
 	.init_dev_msi_info	= its_init_dev_msi_info,
 };
--- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c
+++ /dev/null
@@ -1,163 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2013-2015 ARM Limited, All Rights Reserved.
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- */
-
-#include <linux/acpi_iort.h>
-#include <linux/device.h>
-#include <linux/msi.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-
-static struct irq_chip its_pmsi_irq_chip = {
-	.name			= "ITS-pMSI",
-};
-
-static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev,
-				  u32 *dev_id)
-{
-	int ret, index = 0;
-
-	/* Suck the DeviceID out of the msi-parent property */
-	do {
-		struct of_phandle_args args;
-
-		ret = of_parse_phandle_with_args(dev->of_node,
-						 "msi-parent", "#msi-cells",
-						 index, &args);
-		if (args.np == irq_domain_get_of_node(domain)) {
-			if (WARN_ON(args.args_count != 1))
-				return -EINVAL;
-			*dev_id = args.args[0];
-			break;
-		}
-		index++;
-	} while (!ret);
-
-	return ret;
-}
-
-int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
-{
-	return -1;
-}
-
-static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
-			    int nvec, msi_alloc_info_t *info)
-{
-	struct msi_domain_info *msi_info;
-	u32 dev_id;
-	int ret;
-
-	msi_info = msi_get_domain_info(domain->parent);
-
-	if (dev->of_node)
-		ret = of_pmsi_get_dev_id(domain, dev, &dev_id);
-	else
-		ret = iort_pmsi_get_dev_id(dev, &dev_id);
-	if (ret)
-		return ret;
-
-	/* ITS specific DeviceID, as the core ITS ignores dev. */
-	info->scratchpad[0].ul = dev_id;
-
-	/* Allocate at least 32 MSIs, and always as a power of 2 */
-	nvec = max_t(int, 32, roundup_pow_of_two(nvec));
-	return msi_info->ops->msi_prepare(domain->parent,
-					  dev, nvec, info);
-}
-
-static struct msi_domain_ops its_pmsi_ops = {
-	.msi_prepare	= its_pmsi_prepare,
-};
-
-static struct msi_domain_info its_pmsi_domain_info = {
-	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
-	.ops	= &its_pmsi_ops,
-	.chip	= &its_pmsi_irq_chip,
-};
-
-static const struct of_device_id its_device_id[] = {
-	{	.compatible	= "arm,gic-v3-its",	},
-	{},
-};
-
-static int __init its_pmsi_init_one(struct fwnode_handle *fwnode,
-				const char *name)
-{
-	struct irq_domain *parent;
-
-	parent = irq_find_matching_fwnode(fwnode, DOMAIN_BUS_NEXUS);
-	if (!parent || !msi_get_domain_info(parent)) {
-		pr_err("%s: unable to locate ITS domain\n", name);
-		return -ENXIO;
-	}
-
-	if (!platform_msi_create_irq_domain(fwnode, &its_pmsi_domain_info,
-					    parent)) {
-		pr_err("%s: unable to create platform domain\n", name);
-		return -ENXIO;
-	}
-
-	pr_info("Platform MSI: %s domain created\n", name);
-	return 0;
-}
-
-#ifdef CONFIG_ACPI
-static int __init
-its_pmsi_parse_madt(union acpi_subtable_headers *header,
-			const unsigned long end)
-{
-	struct acpi_madt_generic_translator *its_entry;
-	struct fwnode_handle *domain_handle;
-	const char *node_name;
-	int err = -ENXIO;
-
-	its_entry = (struct acpi_madt_generic_translator *)header;
-	node_name = kasprintf(GFP_KERNEL, "ITS@0x%lx",
-			      (long)its_entry->base_address);
-	domain_handle = iort_find_domain_token(its_entry->translation_id);
-	if (!domain_handle) {
-		pr_err("%s: Unable to locate ITS domain handle\n", node_name);
-		goto out;
-	}
-
-	err = its_pmsi_init_one(domain_handle, node_name);
-
-out:
-	kfree(node_name);
-	return err;
-}
-
-static void __init its_pmsi_acpi_init(void)
-{
-	acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
-			      its_pmsi_parse_madt, 0);
-}
-#else
-static inline void its_pmsi_acpi_init(void) { }
-#endif
-
-static void __init its_pmsi_of_init(void)
-{
-	struct device_node *np;
-
-	for (np = of_find_matching_node(NULL, its_device_id); np;
-	     np = of_find_matching_node(np, its_device_id)) {
-		if (!of_device_is_available(np))
-			continue;
-		if (!of_property_read_bool(np, "msi-controller"))
-			continue;
-
-		its_pmsi_init_one(of_node_to_fwnode(np), np->full_name);
-	}
-}
-
-static int __init its_pmsi_init(void)
-{
-	its_pmsi_of_init();
-	its_pmsi_acpi_init();
-	return 0;
-}
-early_initcall(its_pmsi_init);


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 27/40] irqchip/mbigen: Remove platform_msi_create_device_domain() fallback
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (25 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 26/40] irqchip/gic-v3-its: Switch platform MSI to MSI parent Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 28/40] genirq/msi: Remove platform_msi_create_device_domain() Thomas Gleixner
                   ` (13 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Now that ITS provides the MSI parent domain, remove the unused fallback
code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/irqchip/irq-mbigen.c |   74 ++-----------------------------------------
 1 file changed, 4 insertions(+), 70 deletions(-)

--- a/drivers/irqchip/irq-mbigen.c
+++ b/drivers/irqchip/irq-mbigen.c
@@ -180,64 +180,6 @@ static int mbigen_domain_translate(struc
 	return -EINVAL;
 }
 
-/* The following section will go away once ITS provides a MSI parent */
-
-static struct irq_chip mbigen_irq_chip = {
-	.name =			"mbigen-v2",
-	.irq_mask =		irq_chip_mask_parent,
-	.irq_unmask =		irq_chip_unmask_parent,
-	.irq_eoi =		mbigen_eoi_irq,
-	.irq_set_type =		mbigen_set_type,
-	.irq_set_affinity =	irq_chip_set_affinity_parent,
-};
-
-static int mbigen_irq_domain_alloc(struct irq_domain *domain,
-					unsigned int virq,
-					unsigned int nr_irqs,
-					void *args)
-{
-	struct irq_fwspec *fwspec = args;
-	irq_hw_number_t hwirq;
-	unsigned int type;
-	struct mbigen_device *mgn_chip;
-	int i, err;
-
-	err = mbigen_domain_translate(domain, fwspec, &hwirq, &type);
-	if (err)
-		return err;
-
-	err = platform_msi_device_domain_alloc(domain, virq, nr_irqs);
-	if (err)
-		return err;
-
-	mgn_chip = platform_msi_get_host_data(domain);
-
-	for (i = 0; i < nr_irqs; i++)
-		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
-				      &mbigen_irq_chip, mgn_chip->base);
-
-	return 0;
-}
-
-static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int virq,
-				   unsigned int nr_irqs)
-{
-	platform_msi_device_domain_free(domain, virq, nr_irqs);
-}
-
-static const struct irq_domain_ops mbigen_domain_ops = {
-	.translate	= mbigen_domain_translate,
-	.alloc		= mbigen_irq_domain_alloc,
-	.free		= mbigen_irq_domain_free,
-};
-
-static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg)
-{
-	mbigen_write_msi_msg(irq_get_irq_data(desc->irq), msg);
-}
-
-/* End of to be removed section */
-
 static void mbigen_domain_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
 {
 	arg->desc = desc;
@@ -268,20 +210,12 @@ static const struct msi_domain_template
 static bool mbigen_create_device_domain(struct device *dev, unsigned int size,
 					struct mbigen_device *mgn_chip)
 {
-	struct irq_domain *domain = dev->msi.domain;
-
-	if (WARN_ON_ONCE(!domain))
+	if (WARN_ON_ONCE(!dev->msi.domain))
 		return false;
 
-	if (irq_domain_is_msi_parent(domain)) {
-		return msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN,
-						    &mbigen_msi_template, size,
-						    NULL, mgn_chip->base);
-	}
-
-	/* Remove once ITS provides MSI parent */
-	return !!platform_msi_create_device_domain(dev, size, mbigen_write_msg,
-						   &mbigen_domain_ops, mgn_chip);
+	return msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN,
+					    &mbigen_msi_template, size,
+					    NULL, mgn_chip->base);
 }
 
 static int mbigen_of_create_domain(struct platform_device *pdev,


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 28/40] genirq/msi: Remove platform_msi_create_device_domain()
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (26 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 27/40] irqchip/mbigen: Remove platform_msi_create_device_domain() fallback Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 29/40] genirq/gic-v3-mbi: Remove unused wired MSI mechanics Thomas Gleixner
                   ` (12 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

No more users.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/msi.h |    2 --
 1 file changed, 2 deletions(-)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -646,8 +646,6 @@ struct irq_domain *
 				    const struct irq_domain_ops *ops,
 				    void *host_data);
 
-#define platform_msi_create_device_domain(dev, nvec, write, ops, data)	\
-	__platform_msi_create_device_domain(dev, nvec, false, write, ops, data)
 #define platform_msi_create_device_tree_domain(dev, nvec, write, ops, data) \
 	__platform_msi_create_device_domain(dev, nvec, true, write, ops, data)
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 29/40] genirq/gic-v3-mbi: Remove unused wired MSI mechanics
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (27 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 28/40] genirq/msi: Remove platform_msi_create_device_domain() Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 30/40] genirq/gic-v3-mbi: Switch to MSI parent Thomas Gleixner
                   ` (11 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Nothing builds a platform_device MSI domain for wire to MSI on top of
this. The "regular" users of the platform MSI domain just provide their own
irq_write_msi_msg() callback.

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 |   17 +----------------
 1 file changed, 1 insertion(+), 16 deletions(-)

--- a/drivers/irqchip/irq-gic-v3-mbi.c
+++ b/drivers/irqchip/irq-gic-v3-mbi.c
@@ -199,31 +199,16 @@ static int mbi_allocate_pci_domain(struc
 }
 #endif
 
-static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg)
-{
-	mbi_compose_msi_msg(data, msg);
-
-	msg[1].address_hi = upper_32_bits(mbi_phys_base + GICD_CLRSPI_NSR);
-	msg[1].address_lo = lower_32_bits(mbi_phys_base + GICD_CLRSPI_NSR);
-	msg[1].data = data->parent_data->hwirq;
-
-	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), &msg[1]);
-}
-
 /* Platform-MSI specific irqchip */
 static struct irq_chip mbi_pmsi_irq_chip = {
 	.name			= "pMSI",
-	.irq_set_type		= irq_chip_set_type_parent,
-	.irq_compose_msi_msg	= mbi_compose_mbi_msg,
-	.flags			= IRQCHIP_SUPPORTS_LEVEL_MSI,
 };
 
 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 |
-		   MSI_FLAG_LEVEL_CAPABLE),
+	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
 	.ops	= &mbi_pmsi_ops,
 	.chip	= &mbi_pmsi_irq_chip,
 };


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 30/40] genirq/gic-v3-mbi: Switch to MSI parent
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (28 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 29/40] genirq/gic-v3-mbi: Remove unused wired MSI mechanics Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 31/40] irqchip/gic-v2m: Switch to device MSI Thomas Gleixner
                   ` (10 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

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(-)

--- a/drivers/irqchip/irq-gic-v3-mbi.c
+++ b/drivers/irqchip/irq-gic-v3-mbi.c
@@ -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;
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 31/40] irqchip/gic-v2m: Switch to device MSI
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (29 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 30/40] genirq/gic-v3-mbi: Switch to MSI parent Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 32/40] genirq/msi: Provide MSI_FLAG_PARENT_PM_DEV Thomas Gleixner
                   ` (9 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

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/Kconfig       |    1 
 drivers/irqchip/irq-gic-v2m.c |   82 ++++++++++++------------------------------
 2 files changed, 25 insertions(+), 58 deletions(-)

--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -25,6 +25,7 @@ config ARM_GIC_V2M
 	bool
 	depends on PCI
 	select ARM_GIC
+	select ARM_GIC_MSI_LIB
 	select PCI_MSI
 
 config GIC_NON_BANKED
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -26,6 +26,8 @@
 #include <linux/irqchip/arm-gic.h>
 #include <linux/irqchip/arm-gic-common.h>
 
+#include "irq-gic-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(struc
 }
 
 static const struct irq_domain_ops gicv2m_domain_ops = {
+	.select			= gic_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, u
 	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,17 +243,32 @@ static void __init gicv2m_teardown(void)
 	}
 }
 
+#define GICV2M_MSI_FLAGS_REQUIRED  (MSI_FLAG_USE_DEF_DOM_OPS |	\
+				    MSI_FLAG_USE_DEF_CHIP_OPS)
+
+#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	= gic_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);
 	if (!v2m)
 		return 0;
 
-	inner_domain = irq_domain_create_tree(v2m->fwnode,
-					      &gicv2m_domain_ops, v2m);
+	inner_domain = irq_domain_create_tree(v2m->fwnode, &gicv2m_domain_ops, v2m);
 	if (!inner_domain) {
 		pr_err("Failed to create GICv2m domain\n");
 		return -ENOMEM;
@@ -296,22 +276,8 @@ static __init int gicv2m_allocate_domain
 
 	irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS);
 	inner_domain->parent = parent;
-	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;
 }
 
@@ -512,7 +478,7 @@ acpi_parse_madt_msi(union acpi_subtable_
 		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) {


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 32/40] genirq/msi: Provide MSI_FLAG_PARENT_PM_DEV
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (30 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 31/40] irqchip/gic-v2m: Switch to device MSI Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 33/40] irqchip/imx-mu-msi: Switch to MSI parent Thomas Gleixner
                   ` (8 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Some platform-MSI implementations require that power management is
redirected to the underlying interrupt chip device. To make this work
with per device MSI domains provide a new feature flag and let the
core code handle the setup of dev->pm_dev when set during device MSI
domain creation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/msi.h |    2 ++
 kernel/irq/msi.c    |    2 ++
 2 files changed, 4 insertions(+)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -538,6 +538,8 @@ enum {
 	MSI_FLAG_NOMASK_QUIRK		= (1 << 7),
 	/* Use dev->fwnode for MSI device domain creation */
 	MSI_FLAG_USE_DEV_FWNODE		= (1 << 8),
+	/* Set parent->dev into domain->pm_dev on device domain creation */
+	MSI_FLAG_PARENT_PM_DEV		= (1 << 9),
 
 	/* Mask for the generic functionality */
 	MSI_GENERIC_FLAGS_MASK		= GENMASK(15, 0),
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -884,6 +884,8 @@ static struct irq_domain *__msi_create_i
 		if (!domain->name && info->chip)
 			domain->name = info->chip->name;
 		irq_domain_update_bus_token(domain, info->bus_token);
+		if (info->flags & MSI_FLAG_PARENT_PM_DEV)
+			domain->pm_dev = parent->pm_dev;
 	}
 
 	return domain;


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 33/40] irqchip/imx-mu-msi: Switch to MSI parent
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (31 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 32/40] genirq/msi: Provide MSI_FLAG_PARENT_PM_DEV Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-28 20:47   ` Frank Li
  2022-11-21 14:40 ` [patch V2 34/40] irqchip/irq-mvebu-icu: Prepare for real per device MSI Thomas Gleixner
                   ` (7 subsequent siblings)
  40 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

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" 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>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Fabio Estevam <festevam@gmail.com>
---
 drivers/irqchip/Kconfig           |    1 
 drivers/irqchip/irq-gic-msi-lib.c |    2 +
 drivers/irqchip/irq-imx-mu-msi.c  |   53 +++++++++++++++-----------------------
 3 files changed, 25 insertions(+), 31 deletions(-)

--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -494,6 +494,7 @@ config IMX_MU_MSI
 	select IRQ_DOMAIN
 	select IRQ_DOMAIN_HIERARCHY
 	select GENERIC_MSI_IRQ
+	select ARM_GIC_MSI_LIB
 	help
 	  Provide a driver for the i.MX Messaging Unit block used as a
 	  CPU-to-CPU MSI controller. This requires a specially crafted DT
--- a/drivers/irqchip/irq-gic-msi-lib.c
+++ b/drivers/irqchip/irq-gic-msi-lib.c
@@ -90,6 +90,8 @@ bool gic_msi_lib_init_dev_msi_info(struc
 	/* Chip updates for all child bus types */
 	if (!info->chip->irq_eoi)
 		info->chip->irq_eoi	= irq_chip_eoi_parent;
+	if (!info->chip->irq_ack)
+		info->chip->irq_ack	= irq_chip_ack_parent;
 
 	/*
 	 * The device MSI domain can never have a set affinity callback it
--- a/drivers/irqchip/irq-imx-mu-msi.c
+++ b/drivers/irqchip/irq-imx-mu-msi.c
@@ -24,6 +24,8 @@
 #include <linux/pm_domain.h>
 #include <linux/spinlock.h>
 
+#include "irq-gic-msi-lib.h"
+
 #define IMX_MU_CHANS            4
 
 enum imx_mu_xcr {
@@ -114,20 +116,6 @@ static void imx_mu_msi_parent_ack_irq(st
 	imx_mu_read(msi_data, msi_data->cfg->xRR + data->hwirq * 4);
 }
 
-static struct irq_chip imx_mu_msi_irq_chip = {
-	.name = "MU-MSI",
-	.irq_ack = irq_chip_ack_parent,
-};
-
-static struct msi_domain_ops imx_mu_msi_irq_ops = {
-};
-
-static struct msi_domain_info imx_mu_msi_domain_info = {
-	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
-	.ops	= &imx_mu_msi_irq_ops,
-	.chip	= &imx_mu_msi_irq_chip,
-};
-
 static void imx_mu_msi_parent_compose_msg(struct irq_data *data,
 					  struct msi_msg *msg)
 {
@@ -195,6 +183,7 @@ static void imx_mu_msi_domain_irq_free(s
 }
 
 static const struct irq_domain_ops imx_mu_msi_domain_ops = {
+	.select	= gic_msi_lib_irq_domain_select,
 	.alloc	= imx_mu_msi_domain_irq_alloc,
 	.free	= imx_mu_msi_domain_irq_free,
 };
@@ -216,35 +205,37 @@ static void imx_mu_msi_irq_handler(struc
 	chained_irq_exit(chip, desc);
 }
 
+#define IMX_MU_MSI_FLAGS_REQUIRED	(MSI_FLAG_USE_DEF_DOM_OPS |	\
+					 MSI_FLAG_USE_DEF_CHIP_OPS |	\
+					 MSI_FLAG_PARENT_PM_DEV)
+
+#define IMX_MU_MSI_FLAGS_SUPPORTED	(MSI_GENERIC_FLAGS_MASK)
+
+static const struct msi_parent_ops imx_mu_msi_parent_ops = {
+	.supported_flags	= IMX_MU_MSI_FLAGS_SUPPORTED,
+	.required_flags		= IMX_MU_MSI_FLAGS_REQUIRED,
+	.bus_select_token       = DOMAIN_BUS_NEXUS,
+	.bus_select_mask	= MATCH_PLATFORM_MSI,
+	.prefix			= "MU-MSI-",
+	.init_dev_msi_info	= gic_msi_lib_init_dev_msi_info,
+};
+
 static int imx_mu_msi_domains_init(struct imx_mu_msi *msi_data, struct device *dev)
 {
 	struct fwnode_handle *fwnodes = dev_fwnode(dev);
 	struct irq_domain *parent;
 
 	/* Initialize MSI domain parent */
-	parent = irq_domain_create_linear(fwnodes,
-					    IMX_MU_CHANS,
-					    &imx_mu_msi_domain_ops,
-					    msi_data);
+	parent = irq_domain_create_linear(fwnodes, IMX_MU_CHANS, &imx_mu_msi_domain_ops, msi_data);
 	if (!parent) {
 		dev_err(dev, "failed to create IRQ domain\n");
 		return -ENOMEM;
 	}
 
 	irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS);
-
-	msi_data->msi_domain = platform_msi_create_irq_domain(fwnodes,
-					&imx_mu_msi_domain_info,
-					parent);
-
-	if (!msi_data->msi_domain) {
-		dev_err(dev, "failed to create MSI domain\n");
-		irq_domain_remove(parent);
-		return -ENOMEM;
-	}
-
-	irq_domain_set_pm_device(msi_data->msi_domain, dev);
-
+	parent->dev = parent->pm_dev = dev;
+	parent->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
+	parent->msi_parent_ops = &imx_mu_msi_parent_ops;
 	return 0;
 }
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 34/40] irqchip/irq-mvebu-icu: Prepare for real per device MSI
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (32 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 33/40] irqchip/imx-mu-msi: Switch to MSI parent Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 35/40] irqchip/mvebu-gicp: Switch to MSI parent Thomas Gleixner
                   ` (6 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

The core infrastructure has everything in place to switch ICU to per
device MSI domains and avoid the convoluted construct of the existing
platform-MSI layering violation.

The new infrastructure provides a wired interrupt specific interface in the
MSI core which converts the 'hardware interrupt number + trigger type'
allocation which is required for wired interrupts in the regular irqdomain
code to a normal MSI allocation.

The hardware interrupt number and the trigger type are stored in the MSI
descriptor device cookie by the core code so the ICU specific code can
retrieve them.

The new per device domain is only instantiated when the irqdomain which is
associated to the ICU device provides MSI parent functionality. Up to
that point it invokes the existing code. Once the parent is converted the
code for the current platform-MSI mechanism is removed.

The new domain shares the interrupt chip callbacks and the translation
function. The only new functionality aside of filling out the
msi_domain_templates is a domain specific set_desc() callback, which will go
away once all platform-MSI code has been converted.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Gregory Clement <gregory.clement@bootlin.com>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
 drivers/irqchip/irq-mvebu-icu.c |  181 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 170 insertions(+), 11 deletions(-)

--- a/drivers/irqchip/irq-mvebu-icu.c
+++ b/drivers/irqchip/irq-mvebu-icu.c
@@ -20,6 +20,8 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
+#include "irq-gic-msi-lib.h"
+
 #include <dt-bindings/interrupt-controller/mvebu-icu.h>
 
 /* ICU registers */
@@ -60,14 +62,52 @@ struct mvebu_icu_msi_data {
 	const struct mvebu_icu_subset_data *subset_data;
 };
 
-struct mvebu_icu_irq_data {
-	struct mvebu_icu *icu;
-	unsigned int icu_group;
-	unsigned int type;
-};
-
 static DEFINE_STATIC_KEY_FALSE(legacy_bindings);
 
+static int mvebu_icu_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
+			       unsigned long *hwirq, unsigned int *type)
+{
+	unsigned int param_count = static_branch_unlikely(&legacy_bindings) ? 3 : 2;
+	struct mvebu_icu_msi_data *msi_data = d->host_data;
+	struct mvebu_icu *icu = msi_data->icu;
+
+	/* Check the count of the parameters in dt */
+	if (WARN_ON(fwspec->param_count != param_count)) {
+		dev_err(icu->dev, "wrong ICU parameter count %d\n",
+			fwspec->param_count);
+		return -EINVAL;
+	}
+
+	if (static_branch_unlikely(&legacy_bindings)) {
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		if (fwspec->param[0] != ICU_GRP_NSR) {
+			dev_err(icu->dev, "wrong ICU group type %x\n",
+				fwspec->param[0]);
+			return -EINVAL;
+		}
+	} else {
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+
+		/*
+		 * The ICU receives level interrupts. While the NSR are also
+		 * level interrupts, SEI are edge interrupts. Force the type
+		 * here in this case. Please note that this makes the interrupt
+		 * handling unreliable.
+		 */
+		if (msi_data->subset_data->icu_group == ICU_GRP_SEI)
+			*type = IRQ_TYPE_EDGE_RISING;
+	}
+
+	if (*hwirq >= ICU_MAX_IRQS) {
+		dev_err(icu->dev, "invalid interrupt number %ld\n", *hwirq);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static void mvebu_icu_init(struct mvebu_icu *icu,
 			   struct mvebu_icu_msi_data *msi_data,
 			   struct msi_msg *msg)
@@ -89,6 +129,14 @@ static void mvebu_icu_init(struct mvebu_
 	writel_relaxed(msg[1].address_lo, icu->base + subset->offset_clr_al);
 }
 
+/* Start of area to be removed once all parent chips provide MSI parent */
+
+struct mvebu_icu_irq_data {
+	struct mvebu_icu *icu;
+	unsigned int icu_group;
+	unsigned int type;
+};
+
 static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg)
 {
 	struct irq_data *d = irq_get_irq_data(desc->irq);
@@ -269,6 +317,109 @@ static const struct irq_domain_ops mvebu
 	.free      = mvebu_icu_irq_domain_free,
 };
 
+/* End of removal area */
+
+static int mvebu_icu_msi_init(struct irq_domain *domain, struct msi_domain_info *info,
+			      unsigned int virq, irq_hw_number_t hwirq, msi_alloc_info_t *arg)
+{
+	irq_domain_set_hwirq_and_chip(domain, virq, hwirq, info->chip, info->chip_data);
+	return irq_set_irqchip_state(virq, IRQCHIP_STATE_PENDING, false);
+}
+
+static void mvebu_icu_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
+{
+	arg->desc = desc;
+	arg->hwirq = (u32)desc->data.icookie.value;
+}
+
+static void mvebu_icu_write_msi_msg(struct irq_data *d, struct msi_msg *msg)
+{
+	struct mvebu_icu_msi_data *msi_data = d->chip_data;
+	unsigned int icu_group = msi_data->subset_data->icu_group;
+	struct msi_desc *desc = irq_data_get_msi_desc(d);
+	struct mvebu_icu *icu = msi_data->icu;
+	unsigned int type;
+	u32 icu_int;
+
+	if (msg->address_lo || msg->address_hi) {
+		/* One off initialization per domain */
+		mvebu_icu_init(icu, msi_data, msg);
+		/* Configure the ICU with irq number & type */
+		icu_int = msg->data | ICU_INT_ENABLE;
+		type = (unsigned int)(desc->data.icookie.value >> 32);
+		if (type & IRQ_TYPE_EDGE_RISING)
+			icu_int |= ICU_IS_EDGE;
+		icu_int |= icu_group << ICU_GROUP_SHIFT;
+	} else {
+		/* De-configure the ICU */
+		icu_int = 0;
+	}
+
+	writel_relaxed(icu_int, icu->base + ICU_INT_CFG(d->hwirq));
+
+	/*
+	 * The SATA unit has 2 ports, and a dedicated ICU entry per
+	 * port. The ahci sata driver supports only one irq interrupt
+	 * per SATA unit. To solve this conflict, we configure the 2
+	 * SATA wired interrupts in the south bridge into 1 GIC
+	 * interrupt in the north bridge. Even if only a single port
+	 * is enabled, if sata node is enabled, both interrupts are
+	 * configured (regardless of which port is actually in use).
+	 */
+	if (d->hwirq == ICU_SATA0_ICU_ID || d->hwirq == ICU_SATA1_ICU_ID) {
+		writel_relaxed(icu_int, icu->base + ICU_INT_CFG(ICU_SATA0_ICU_ID));
+		writel_relaxed(icu_int, icu->base + ICU_INT_CFG(ICU_SATA1_ICU_ID));
+	}
+}
+
+static const struct msi_domain_template mvebu_icu_nsr_msi_template = {
+	.chip = {
+		.name			= "ICU-NSR",
+		.irq_mask		= irq_chip_mask_parent,
+		.irq_unmask		= irq_chip_unmask_parent,
+		.irq_eoi		= irq_chip_eoi_parent,
+		.irq_set_type		= irq_chip_set_type_parent,
+		.irq_write_msi_msg	= mvebu_icu_write_msi_msg,
+		.flags			= IRQCHIP_SUPPORTS_LEVEL_MSI,
+	},
+
+	.ops = {
+		.msi_translate		= mvebu_icu_translate,
+		.msi_init		= mvebu_icu_msi_init,
+		.set_desc		= mvebu_icu_set_desc,
+	},
+
+	.info = {
+		.bus_token		= DOMAIN_BUS_WIRED_TO_MSI,
+		.flags			= MSI_FLAG_LEVEL_CAPABLE |
+					  MSI_FLAG_USE_DEV_FWNODE,
+	},
+};
+
+static const struct msi_domain_template mvebu_icu_sei_msi_template = {
+	.chip = {
+		.name			= "ICU-SEI",
+		.irq_mask		= irq_chip_mask_parent,
+		.irq_unmask		= irq_chip_unmask_parent,
+		.irq_ack		= irq_chip_ack_parent,
+		.irq_set_type		= irq_chip_set_type_parent,
+		.irq_write_msi_msg	= mvebu_icu_write_msi_msg,
+		.flags			= IRQCHIP_SUPPORTS_LEVEL_MSI,
+	},
+
+	.ops = {
+		.msi_translate		= mvebu_icu_translate,
+		.msi_init		= mvebu_icu_msi_init,
+		.set_desc		= mvebu_icu_set_desc,
+	},
+
+	.info = {
+		.bus_token		= DOMAIN_BUS_WIRED_TO_MSI,
+		.flags			= MSI_FLAG_LEVEL_CAPABLE |
+					  MSI_FLAG_USE_DEV_FWNODE,
+	},
+};
+
 static const struct mvebu_icu_subset_data mvebu_icu_nsr_subset_data = {
 	.icu_group = ICU_GRP_NSR,
 	.offset_set_ah = ICU_SETSPI_NSR_AH,
@@ -298,7 +449,6 @@ static const struct of_device_id mvebu_i
 static int mvebu_icu_subset_probe(struct platform_device *pdev)
 {
 	struct mvebu_icu_msi_data *msi_data;
-	struct device_node *msi_parent_dn;
 	struct device *dev = &pdev->dev;
 	struct irq_domain *irq_domain;
 
@@ -314,15 +464,24 @@ static int mvebu_icu_subset_probe(struct
 		msi_data->subset_data = of_device_get_match_data(dev);
 	}
 
-	dev->msi.domain = of_msi_get_domain(dev, dev->of_node,
-					    DOMAIN_BUS_PLATFORM_MSI);
+	dev->msi.domain = of_msi_get_domain(dev, dev->of_node, DOMAIN_BUS_PLATFORM_MSI);
 	if (!dev->msi.domain)
 		return -EPROBE_DEFER;
 
-	msi_parent_dn = irq_domain_get_of_node(dev->msi.domain);
-	if (!msi_parent_dn)
+	if (!irq_domain_get_of_node(dev->msi.domain))
 		return -ENODEV;
 
+	if (irq_domain_is_msi_parent(dev->msi.domain)) {
+		bool sei = msi_data->subset_data->icu_group == ICU_GRP_SEI;
+		const struct msi_domain_template *tmpl;
+
+		tmpl = sei ? &mvebu_icu_sei_msi_template : &mvebu_icu_nsr_msi_template;
+
+		if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN, tmpl,
+						  ICU_MAX_IRQS, NULL, msi_data))
+			return -ENOMEM;
+	}
+
 	irq_domain = platform_msi_create_device_tree_domain(dev, ICU_MAX_IRQS,
 							    mvebu_icu_write_msg,
 							    &mvebu_icu_domain_ops,


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 35/40] irqchip/mvebu-gicp: Switch to MSI parent
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (33 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 34/40] irqchip/irq-mvebu-icu: Prepare for real per device MSI Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 36/40] irqchip/mvebu-odmi: Switch to parent MSI Thomas Gleixner
                   ` (5 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

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" 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: Andrew Lunn <andrew@lunn.ch>
Cc: Gregory Clement <gregory.clement@bootlin.com>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
 drivers/irqchip/Kconfig          |    1 
 drivers/irqchip/irq-mvebu-gicp.c |   44 ++++++++++++++++-----------------------
 2 files changed, 20 insertions(+), 25 deletions(-)

--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -373,6 +373,7 @@ config MSCC_OCELOT_IRQ
 	select GENERIC_IRQ_CHIP
 
 config MVEBU_GICP
+	select ARM_GIC_MSI_LIB
 	bool
 
 config MVEBU_ICU
--- a/drivers/irqchip/irq-mvebu-gicp.c
+++ b/drivers/irqchip/irq-mvebu-gicp.c
@@ -17,6 +17,8 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
+#include "irq-gic-msi-lib.h"
+
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 #define GICP_SETSPI_NSR_OFFSET	0x0
@@ -145,32 +147,32 @@ static void gicp_irq_domain_free(struct
 }
 
 static const struct irq_domain_ops gicp_domain_ops = {
+	.select	= gic_msi_lib_irq_domain_select,
 	.alloc	= gicp_irq_domain_alloc,
 	.free	= gicp_irq_domain_free,
 };
 
-static struct irq_chip gicp_msi_irq_chip = {
-	.name		= "GICP",
-	.irq_set_type	= irq_chip_set_type_parent,
-	.flags		= IRQCHIP_SUPPORTS_LEVEL_MSI,
-};
+#define GICP_MSI_FLAGS_REQUIRED  (MSI_FLAG_USE_DEF_DOM_OPS |	\
+				  MSI_FLAG_USE_DEF_CHIP_OPS)
 
-static struct msi_domain_ops gicp_msi_ops = {
-};
+#define GICP_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK |	\
+				  MSI_FLAG_LEVEL_CAPABLE)
 
-static struct msi_domain_info gicp_msi_domain_info = {
-	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-		   MSI_FLAG_LEVEL_CAPABLE),
-	.ops	= &gicp_msi_ops,
-	.chip	= &gicp_msi_irq_chip,
+static const struct msi_parent_ops gicp_msi_parent_ops = {
+	.supported_flags	= GICP_MSI_FLAGS_SUPPORTED,
+	.required_flags		= GICP_MSI_FLAGS_REQUIRED,
+	.bus_select_token       = DOMAIN_BUS_GENERIC_MSI,
+	.bus_select_mask	= MATCH_PLATFORM_MSI,
+	.prefix			= "GICP-",
+	.init_dev_msi_info	= gic_msi_lib_init_dev_msi_info,
 };
 
 static int mvebu_gicp_probe(struct platform_device *pdev)
 {
-	struct mvebu_gicp *gicp;
-	struct irq_domain *inner_domain, *plat_domain, *parent_domain;
+	struct irq_domain *inner_domain, *parent_domain;
 	struct device_node *node = pdev->dev.of_node;
 	struct device_node *irq_parent_dn;
+	struct mvebu_gicp *gicp;
 	int ret, i;
 
 	gicp = devm_kzalloc(&pdev->dev, sizeof(*gicp), GFP_KERNEL);
@@ -233,17 +235,9 @@ static int mvebu_gicp_probe(struct platf
 	if (!inner_domain)
 		return -ENOMEM;
 
-
-	plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
-						     &gicp_msi_domain_info,
-						     inner_domain);
-	if (!plat_domain) {
-		irq_domain_remove(inner_domain);
-		return -ENOMEM;
-	}
-
-	platform_set_drvdata(pdev, gicp);
-
+	irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_GENERIC_MSI);
+	inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
+	inner_domain->msi_parent_ops = &gicp_msi_parent_ops;
 	return 0;
 }
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 36/40] irqchip/mvebu-odmi: Switch to parent MSI
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (34 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 35/40] irqchip/mvebu-gicp: Switch to MSI parent Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 37/40] irqchip/irq-mvebu-sei: Switch to MSI parent Thomas Gleixner
                   ` (4 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

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" 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: Andrew Lunn <andrew@lunn.ch>
Cc: Gregory Clement <gregory.clement@bootlin.com>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
 drivers/irqchip/Kconfig          |    1 +
 drivers/irqchip/irq-mvebu-odmi.c |   39 ++++++++++++++++++---------------------
 2 files changed, 19 insertions(+), 21 deletions(-)

--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -381,6 +381,7 @@ config MVEBU_ICU
 
 config MVEBU_ODMI
 	bool
+	select ARM_GIC_MSI_LIB
 	select GENERIC_MSI_IRQ
 
 config MVEBU_PIC
--- a/drivers/irqchip/irq-mvebu-odmi.c
+++ b/drivers/irqchip/irq-mvebu-odmi.c
@@ -17,6 +17,9 @@
 #include <linux/msi.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
+
+#include "irq-gic-msi-lib.h"
+
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 #define GICP_ODMIN_SET			0x40
@@ -141,27 +144,29 @@ static void odmi_irq_domain_free(struct
 }
 
 static const struct irq_domain_ops odmi_domain_ops = {
+	.select	= gic_msi_lib_irq_domain_select,
 	.alloc	= odmi_irq_domain_alloc,
 	.free	= odmi_irq_domain_free,
 };
 
-static struct irq_chip odmi_msi_irq_chip = {
-	.name	= "ODMI",
-};
+#define ODMI_MSI_FLAGS_REQUIRED  (MSI_FLAG_USE_DEF_DOM_OPS |	\
+				  MSI_FLAG_USE_DEF_CHIP_OPS)
 
-static struct msi_domain_ops odmi_msi_ops = {
-};
+#define ODMI_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK)
 
-static struct msi_domain_info odmi_msi_domain_info = {
-	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
-	.ops	= &odmi_msi_ops,
-	.chip	= &odmi_msi_irq_chip,
+static const struct msi_parent_ops odmi_msi_parent_ops = {
+	.supported_flags	= ODMI_MSI_FLAGS_SUPPORTED,
+	.required_flags		= ODMI_MSI_FLAGS_REQUIRED,
+	.bus_select_token	= DOMAIN_BUS_GENERIC_MSI,
+	.bus_select_mask	= MATCH_PLATFORM_MSI,
+	.prefix			= "ODMI-",
+	.init_dev_msi_info	= gic_msi_lib_init_dev_msi_info,
 };
 
 static int __init mvebu_odmi_init(struct device_node *node,
 				  struct device_node *parent)
 {
-	struct irq_domain *inner_domain, *plat_domain;
+	struct irq_domain *inner_domain;
 	int ret, i;
 
 	if (of_property_read_u32(node, "marvell,odmi-frames", &odmis_count))
@@ -206,19 +211,11 @@ static int __init mvebu_odmi_init(struct
 	}
 
 	inner_domain->parent = irq_find_host(parent);
-
-	plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
-						     &odmi_msi_domain_info,
-						     inner_domain);
-	if (!plat_domain) {
-		ret = -ENOMEM;
-		goto err_remove_inner;
-	}
-
+	irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_GENERIC_MSI);
+	inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
+	inner_domain->msi_parent_ops = &odmi_msi_parent_ops;
 	return 0;
 
-err_remove_inner:
-	irq_domain_remove(inner_domain);
 err_unmap:
 	for (i = 0; i < odmis_count; i++) {
 		struct odmi_data *odmi = &odmis[i];


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 37/40] irqchip/irq-mvebu-sei: Switch to MSI parent
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (35 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 36/40] irqchip/mvebu-odmi: Switch to parent MSI Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 38/40] irqchip/irq-mvebu-icu: Remove platform MSI leftovers Thomas Gleixner
                   ` (3 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

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" 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: Andrew Lunn <andrew@lunn.ch>
Cc: Gregory Clement <gregory.clement@bootlin.com>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
 drivers/irqchip/irq-mvebu-sei.c |   52 +++++++++++++++-------------------------
 1 file changed, 20 insertions(+), 32 deletions(-)

--- a/drivers/irqchip/irq-mvebu-sei.c
+++ b/drivers/irqchip/irq-mvebu-sei.c
@@ -14,6 +14,8 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
+#include "irq-gic-msi-lib.h"
+
 /* Cause register */
 #define GICP_SECR(idx)		(0x0  + ((idx) * 0x4))
 /* Mask register */
@@ -190,6 +192,7 @@ static void mvebu_sei_domain_free(struct
 }
 
 static const struct irq_domain_ops mvebu_sei_domain_ops = {
+	.select	= gic_msi_lib_irq_domain_select,
 	.alloc	= mvebu_sei_domain_alloc,
 	.free	= mvebu_sei_domain_free,
 };
@@ -307,21 +310,6 @@ static const struct irq_domain_ops mvebu
 	.free	= mvebu_sei_cp_domain_free,
 };
 
-static struct irq_chip mvebu_sei_msi_irq_chip = {
-	.name		= "SEI pMSI",
-	.irq_ack	= irq_chip_ack_parent,
-	.irq_set_type	= irq_chip_set_type_parent,
-};
-
-static struct msi_domain_ops mvebu_sei_msi_ops = {
-};
-
-static struct msi_domain_info mvebu_sei_msi_domain_info = {
-	.flags	= MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS,
-	.ops	= &mvebu_sei_msi_ops,
-	.chip	= &mvebu_sei_msi_irq_chip,
-};
-
 static void mvebu_sei_handle_cascade_irq(struct irq_desc *desc)
 {
 	struct mvebu_sei *sei = irq_desc_get_handler_data(desc);
@@ -360,10 +348,23 @@ static void mvebu_sei_reset(struct mvebu
 	}
 }
 
+#define SEI_MSI_FLAGS_REQUIRED	(MSI_FLAG_USE_DEF_DOM_OPS |	\
+				 MSI_FLAG_USE_DEF_CHIP_OPS)
+
+#define SEI_MSI_FLAGS_SUPPORTED	(MSI_GENERIC_FLAGS_MASK)
+
+static const struct msi_parent_ops sei_msi_parent_ops = {
+	.supported_flags	= SEI_MSI_FLAGS_SUPPORTED,
+	.required_flags		= SEI_MSI_FLAGS_REQUIRED,
+	.bus_select_mask	= MATCH_PLATFORM_MSI,
+	.bus_select_token	= DOMAIN_BUS_GENERIC_MSI,
+	.prefix			= "SEI-",
+	.init_dev_msi_info	= gic_msi_lib_init_dev_msi_info,
+};
+
 static int mvebu_sei_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
-	struct irq_domain *plat_domain;
 	struct mvebu_sei *sei;
 	u32 parent_irq;
 	int ret;
@@ -441,33 +442,20 @@ static int mvebu_sei_probe(struct platfo
 	}
 
 	irq_domain_update_bus_token(sei->cp_domain, DOMAIN_BUS_GENERIC_MSI);
-
-	plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
-						     &mvebu_sei_msi_domain_info,
-						     sei->cp_domain);
-	if (!plat_domain) {
-		pr_err("Failed to create CPs MSI domain\n");
-		ret = -ENOMEM;
-		goto remove_cp_domain;
-	}
+	sei->cp_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
+	sei->cp_domain->msi_parent_ops = &sei_msi_parent_ops;
 
 	mvebu_sei_reset(sei);
 
-	irq_set_chained_handler_and_data(parent_irq,
-					 mvebu_sei_handle_cascade_irq,
-					 sei);
-
+	irq_set_chained_handler_and_data(parent_irq, mvebu_sei_handle_cascade_irq, sei);
 	return 0;
 
-remove_cp_domain:
-	irq_domain_remove(sei->cp_domain);
 remove_ap_domain:
 	irq_domain_remove(sei->ap_domain);
 remove_sei_domain:
 	irq_domain_remove(sei->sei_domain);
 dispose_irq:
 	irq_dispose_mapping(parent_irq);
-
 	return ret;
 }
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 38/40] irqchip/irq-mvebu-icu: Remove platform MSI leftovers
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (36 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 37/40] irqchip/irq-mvebu-sei: Switch to MSI parent Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 39/40] genirq/msi: " Thomas Gleixner
                   ` (2 subsequent siblings)
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

All related domains provide MSI parent functionality, so the fallback code
to the original platform MSI implementation is not longer required.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Gregory Clement <gregory.clement@bootlin.com>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
 drivers/irqchip/irq-mvebu-icu.c |  213 +---------------------------------------
 1 file changed, 6 insertions(+), 207 deletions(-)

--- a/drivers/irqchip/irq-mvebu-icu.c
+++ b/drivers/irqchip/irq-mvebu-icu.c
@@ -129,196 +129,6 @@ static void mvebu_icu_init(struct mvebu_
 	writel_relaxed(msg[1].address_lo, icu->base + subset->offset_clr_al);
 }
 
-/* Start of area to be removed once all parent chips provide MSI parent */
-
-struct mvebu_icu_irq_data {
-	struct mvebu_icu *icu;
-	unsigned int icu_group;
-	unsigned int type;
-};
-
-static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg)
-{
-	struct irq_data *d = irq_get_irq_data(desc->irq);
-	struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d->domain);
-	struct mvebu_icu_irq_data *icu_irqd = d->chip_data;
-	struct mvebu_icu *icu = icu_irqd->icu;
-	unsigned int icu_int;
-
-	if (msg->address_lo || msg->address_hi) {
-		/* One off initialization per domain */
-		mvebu_icu_init(icu, msi_data, msg);
-		/* Configure the ICU with irq number & type */
-		icu_int = msg->data | ICU_INT_ENABLE;
-		if (icu_irqd->type & IRQ_TYPE_EDGE_RISING)
-			icu_int |= ICU_IS_EDGE;
-		icu_int |= icu_irqd->icu_group << ICU_GROUP_SHIFT;
-	} else {
-		/* De-configure the ICU */
-		icu_int = 0;
-	}
-
-	writel_relaxed(icu_int, icu->base + ICU_INT_CFG(d->hwirq));
-
-	/*
-	 * The SATA unit has 2 ports, and a dedicated ICU entry per
-	 * port. The ahci sata driver supports only one irq interrupt
-	 * per SATA unit. To solve this conflict, we configure the 2
-	 * SATA wired interrupts in the south bridge into 1 GIC
-	 * interrupt in the north bridge. Even if only a single port
-	 * is enabled, if sata node is enabled, both interrupts are
-	 * configured (regardless of which port is actually in use).
-	 */
-	if (d->hwirq == ICU_SATA0_ICU_ID || d->hwirq == ICU_SATA1_ICU_ID) {
-		writel_relaxed(icu_int,
-			       icu->base + ICU_INT_CFG(ICU_SATA0_ICU_ID));
-		writel_relaxed(icu_int,
-			       icu->base + ICU_INT_CFG(ICU_SATA1_ICU_ID));
-	}
-}
-
-static struct irq_chip mvebu_icu_nsr_chip = {
-	.name			= "ICU-NSR",
-	.irq_mask		= irq_chip_mask_parent,
-	.irq_unmask		= irq_chip_unmask_parent,
-	.irq_eoi		= irq_chip_eoi_parent,
-	.irq_set_type		= irq_chip_set_type_parent,
-	.irq_set_affinity	= irq_chip_set_affinity_parent,
-};
-
-static struct irq_chip mvebu_icu_sei_chip = {
-	.name			= "ICU-SEI",
-	.irq_ack		= irq_chip_ack_parent,
-	.irq_mask		= irq_chip_mask_parent,
-	.irq_unmask		= irq_chip_unmask_parent,
-	.irq_set_type		= irq_chip_set_type_parent,
-	.irq_set_affinity	= irq_chip_set_affinity_parent,
-};
-
-static int
-mvebu_icu_irq_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
-			       unsigned long *hwirq, unsigned int *type)
-{
-	unsigned int param_count = static_branch_unlikely(&legacy_bindings) ? 3 : 2;
-	struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d);
-	struct mvebu_icu *icu = msi_data->icu;
-
-	/* Check the count of the parameters in dt */
-	if (WARN_ON(fwspec->param_count != param_count)) {
-		dev_err(icu->dev, "wrong ICU parameter count %d\n",
-			fwspec->param_count);
-		return -EINVAL;
-	}
-
-	if (static_branch_unlikely(&legacy_bindings)) {
-		*hwirq = fwspec->param[1];
-		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
-		if (fwspec->param[0] != ICU_GRP_NSR) {
-			dev_err(icu->dev, "wrong ICU group type %x\n",
-				fwspec->param[0]);
-			return -EINVAL;
-		}
-	} else {
-		*hwirq = fwspec->param[0];
-		*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
-
-		/*
-		 * The ICU receives level interrupts. While the NSR are also
-		 * level interrupts, SEI are edge interrupts. Force the type
-		 * here in this case. Please note that this makes the interrupt
-		 * handling unreliable.
-		 */
-		if (msi_data->subset_data->icu_group == ICU_GRP_SEI)
-			*type = IRQ_TYPE_EDGE_RISING;
-	}
-
-	if (*hwirq >= ICU_MAX_IRQS) {
-		dev_err(icu->dev, "invalid interrupt number %ld\n", *hwirq);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int
-mvebu_icu_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
-			   unsigned int nr_irqs, void *args)
-{
-	int err;
-	unsigned long hwirq;
-	struct irq_fwspec *fwspec = args;
-	struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(domain);
-	struct mvebu_icu *icu = msi_data->icu;
-	struct mvebu_icu_irq_data *icu_irqd;
-	struct irq_chip *chip = &mvebu_icu_nsr_chip;
-
-	icu_irqd = kmalloc(sizeof(*icu_irqd), GFP_KERNEL);
-	if (!icu_irqd)
-		return -ENOMEM;
-
-	err = mvebu_icu_irq_domain_translate(domain, fwspec, &hwirq,
-					     &icu_irqd->type);
-	if (err) {
-		dev_err(icu->dev, "failed to translate ICU parameters\n");
-		goto free_irqd;
-	}
-
-	if (static_branch_unlikely(&legacy_bindings))
-		icu_irqd->icu_group = fwspec->param[0];
-	else
-		icu_irqd->icu_group = msi_data->subset_data->icu_group;
-	icu_irqd->icu = icu;
-
-	err = platform_msi_device_domain_alloc(domain, virq, nr_irqs);
-	if (err) {
-		dev_err(icu->dev, "failed to allocate ICU interrupt in parent domain\n");
-		goto free_irqd;
-	}
-
-	/* Make sure there is no interrupt left pending by the firmware */
-	err = irq_set_irqchip_state(virq, IRQCHIP_STATE_PENDING, false);
-	if (err)
-		goto free_msi;
-
-	if (icu_irqd->icu_group == ICU_GRP_SEI)
-		chip = &mvebu_icu_sei_chip;
-
-	err = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
-					    chip, icu_irqd);
-	if (err) {
-		dev_err(icu->dev, "failed to set the data to IRQ domain\n");
-		goto free_msi;
-	}
-
-	return 0;
-
-free_msi:
-	platform_msi_device_domain_free(domain, virq, nr_irqs);
-free_irqd:
-	kfree(icu_irqd);
-	return err;
-}
-
-static void
-mvebu_icu_irq_domain_free(struct irq_domain *domain, unsigned int virq,
-			  unsigned int nr_irqs)
-{
-	struct irq_data *d = irq_get_irq_data(virq);
-	struct mvebu_icu_irq_data *icu_irqd = d->chip_data;
-
-	kfree(icu_irqd);
-
-	platform_msi_device_domain_free(domain, virq, nr_irqs);
-}
-
-static const struct irq_domain_ops mvebu_icu_domain_ops = {
-	.translate = mvebu_icu_irq_domain_translate,
-	.alloc     = mvebu_icu_irq_domain_alloc,
-	.free      = mvebu_icu_irq_domain_free,
-};
-
-/* End of removal area */
-
 static int mvebu_icu_msi_init(struct irq_domain *domain, struct msi_domain_info *info,
 			      unsigned int virq, irq_hw_number_t hwirq, msi_alloc_info_t *arg)
 {
@@ -448,9 +258,10 @@ static const struct of_device_id mvebu_i
 
 static int mvebu_icu_subset_probe(struct platform_device *pdev)
 {
+	const struct msi_domain_template *tmpl;
 	struct mvebu_icu_msi_data *msi_data;
 	struct device *dev = &pdev->dev;
-	struct irq_domain *irq_domain;
+	bool sei;
 
 	msi_data = devm_kzalloc(dev, sizeof(*msi_data), GFP_KERNEL);
 	if (!msi_data)
@@ -471,26 +282,14 @@ static int mvebu_icu_subset_probe(struct
 	if (!irq_domain_get_of_node(dev->msi.domain))
 		return -ENODEV;
 
-	if (irq_domain_is_msi_parent(dev->msi.domain)) {
-		bool sei = msi_data->subset_data->icu_group == ICU_GRP_SEI;
-		const struct msi_domain_template *tmpl;
-
-		tmpl = sei ? &mvebu_icu_sei_msi_template : &mvebu_icu_nsr_msi_template;
-
-		if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN, tmpl,
-						  ICU_MAX_IRQS, NULL, msi_data))
-			return -ENOMEM;
-	}
+	sei = msi_data->subset_data->icu_group == ICU_GRP_SEI;
+	tmpl = sei ? &mvebu_icu_sei_msi_template : &mvebu_icu_nsr_msi_template;
 
-	irq_domain = platform_msi_create_device_tree_domain(dev, ICU_MAX_IRQS,
-							    mvebu_icu_write_msg,
-							    &mvebu_icu_domain_ops,
-							    msi_data);
-	if (!irq_domain) {
+	if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN, tmpl,
+					  ICU_MAX_IRQS, NULL, msi_data)) {
 		dev_err(dev, "Failed to create ICU MSI domain\n");
 		return -ENOMEM;
 	}
-
 	return 0;
 }
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 39/40] genirq/msi: Remove platform MSI leftovers
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (37 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 38/40] irqchip/irq-mvebu-icu: Remove platform MSI leftovers Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2022-11-21 14:40 ` [patch V2 40/40] genirq/msi: Move msi_device_data to core Thomas Gleixner
  2023-01-11 19:29 ` [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Frank Li
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

No more users!

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/base/platform-msi.c |  352 --------------------------------------------
 include/linux/msi.h         |   31 ---
 kernel/irq/msi.c            |   48 ------
 3 files changed, 3 insertions(+), 428 deletions(-)

--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -4,357 +4,12 @@
  *
  * Copyright (C) 2015 ARM Limited, All Rights Reserved.
  * Author: Marc Zyngier <marc.zyngier@arm.com>
+ * Copyright (C) 2022 Linutronix GmbH
  */
 
 #include <linux/device.h>
-#include <linux/idr.h>
-#include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/msi.h>
-#include <linux/slab.h>
-
-/* Begin of removal area. Once everything is converted over. Cleanup the includes too! */
-
-#define DEV_ID_SHIFT	21
-#define MAX_DEV_MSIS	(1 << (32 - DEV_ID_SHIFT))
-
-/*
- * Internal data structure containing a (made up, but unique) devid
- * and the callback to write the MSI message.
- */
-struct platform_msi_priv_data {
-	struct device			*dev;
-	void				*host_data;
-	msi_alloc_info_t		arg;
-	irq_write_msi_msg_t		write_msg;
-	int				devid;
-};
-
-/* The devid allocator */
-static DEFINE_IDA(platform_msi_devid_ida);
-
-#ifdef GENERIC_MSI_DOMAIN_OPS
-/*
- * Convert an msi_desc to a globaly unique identifier (per-device
- * devid + msi_desc position in the msi_list).
- */
-static irq_hw_number_t platform_msi_calc_hwirq(struct msi_desc *desc)
-{
-	u32 devid = desc->dev->msi.data->platform_data->devid;
-
-	return (devid << (32 - DEV_ID_SHIFT)) | desc->msi_index;
-}
-
-static void platform_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
-{
-	arg->desc = desc;
-	arg->hwirq = platform_msi_calc_hwirq(desc);
-}
-
-static int platform_msi_init(struct irq_domain *domain,
-			     struct msi_domain_info *info,
-			     unsigned int virq, irq_hw_number_t hwirq,
-			     msi_alloc_info_t *arg)
-{
-	return irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
-					     info->chip, info->chip_data);
-}
-
-static void platform_msi_set_proxy_dev(msi_alloc_info_t *arg)
-{
-	arg->flags |= MSI_ALLOC_FLAGS_PROXY_DEVICE;
-}
-#else
-#define platform_msi_set_desc		NULL
-#define platform_msi_init		NULL
-#define platform_msi_set_proxy_dev(x)	do {} while(0)
-#endif
-
-static void platform_msi_update_dom_ops(struct msi_domain_info *info)
-{
-	struct msi_domain_ops *ops = info->ops;
-
-	BUG_ON(!ops);
-
-	if (ops->msi_init == NULL)
-		ops->msi_init = platform_msi_init;
-	if (ops->set_desc == NULL)
-		ops->set_desc = platform_msi_set_desc;
-}
-
-static void platform_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
-{
-	struct msi_desc *desc = irq_data_get_msi_desc(data);
-
-	desc->dev->msi.data->platform_data->write_msg(desc, msg);
-}
-
-static void platform_msi_update_chip_ops(struct msi_domain_info *info)
-{
-	struct irq_chip *chip = info->chip;
-
-	BUG_ON(!chip);
-	if (!chip->irq_mask)
-		chip->irq_mask = irq_chip_mask_parent;
-	if (!chip->irq_unmask)
-		chip->irq_unmask = irq_chip_unmask_parent;
-	if (!chip->irq_eoi)
-		chip->irq_eoi = irq_chip_eoi_parent;
-	if (!chip->irq_set_affinity)
-		chip->irq_set_affinity = msi_domain_set_affinity;
-	if (!chip->irq_write_msi_msg)
-		chip->irq_write_msi_msg = platform_msi_write_msg;
-	if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE) &&
-		    !(chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI)))
-		info->flags &= ~MSI_FLAG_LEVEL_CAPABLE;
-}
-
-/**
- * platform_msi_create_irq_domain - Create a platform MSI interrupt domain
- * @fwnode:		Optional fwnode of the interrupt controller
- * @info:	MSI domain info
- * @parent:	Parent irq domain
- *
- * Updates the domain and chip ops and creates a platform MSI
- * interrupt domain.
- *
- * Returns:
- * A domain pointer or NULL in case of failure.
- */
-struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
-						  struct msi_domain_info *info,
-						  struct irq_domain *parent)
-{
-	struct irq_domain *domain;
-
-	if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
-		platform_msi_update_dom_ops(info);
-	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
-		platform_msi_update_chip_ops(info);
-	info->flags |= MSI_FLAG_DEV_SYSFS | MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS |
-		       MSI_FLAG_FREE_MSI_DESCS;
-
-	domain = msi_create_irq_domain(fwnode, info, parent);
-	if (domain)
-		irq_domain_update_bus_token(domain, DOMAIN_BUS_PLATFORM_MSI);
-
-	return domain;
-}
-EXPORT_SYMBOL_GPL(platform_msi_create_irq_domain);
-
-static int platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
-					irq_write_msi_msg_t write_msi_msg)
-{
-	struct platform_msi_priv_data *datap;
-	int err;
-
-	/*
-	 * Limit the number of interrupts to 2048 per device. Should we
-	 * need to bump this up, DEV_ID_SHIFT should be adjusted
-	 * accordingly (which would impact the max number of MSI
-	 * capable devices).
-	 */
-	if (!dev->msi.domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
-		return -EINVAL;
-
-	if (dev->msi.domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
-		dev_err(dev, "Incompatible msi_domain, giving up\n");
-		return -EINVAL;
-	}
-
-	err = msi_setup_device_data(dev);
-	if (err)
-		return err;
-
-	/* Already initialized? */
-	if (dev->msi.data->platform_data)
-		return -EBUSY;
-
-	datap = kzalloc(sizeof(*datap), GFP_KERNEL);
-	if (!datap)
-		return -ENOMEM;
-
-	datap->devid = ida_simple_get(&platform_msi_devid_ida,
-				      0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
-	if (datap->devid < 0) {
-		err = datap->devid;
-		kfree(datap);
-		return err;
-	}
-
-	datap->write_msg = write_msi_msg;
-	datap->dev = dev;
-	dev->msi.data->platform_data = datap;
-	return 0;
-}
-
-static void platform_msi_free_priv_data(struct device *dev)
-{
-	struct platform_msi_priv_data *data = dev->msi.data->platform_data;
-
-	dev->msi.data->platform_data = NULL;
-	ida_simple_remove(&platform_msi_devid_ida, data->devid);
-	kfree(data);
-}
-
-/**
- * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev
- * @dev:		The device for which to allocate interrupts
- * @nvec:		The number of interrupts to allocate
- * @write_msi_msg:	Callback to write an interrupt message for @dev
- *
- * Returns:
- * Zero for success, or an error code in case of failure
- */
-int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
-				   irq_write_msi_msg_t write_msi_msg)
-{
-	int err;
-
-	err = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
-	if (err)
-		return err;
-
-	err = msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, nvec - 1);
-	if (err)
-		platform_msi_free_priv_data(dev);
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(platform_msi_domain_alloc_irqs);
-
-/**
- * platform_msi_domain_free_irqs - Free MSI interrupts for @dev
- * @dev:	The device for which to free interrupts
- */
-void platform_msi_domain_free_irqs(struct device *dev)
-{
-	msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
-	platform_msi_free_priv_data(dev);
-}
-EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs);
-
-/**
- * platform_msi_get_host_data - Query the private data associated with
- *                              a platform-msi domain
- * @domain:	The platform-msi domain
- *
- * Return: The private data provided when calling
- * platform_msi_create_device_domain().
- */
-void *platform_msi_get_host_data(struct irq_domain *domain)
-{
-	struct platform_msi_priv_data *data = domain->host_data;
-
-	return data->host_data;
-}
-
-static struct lock_class_key platform_device_msi_lock_class;
-
-/**
- * __platform_msi_create_device_domain - Create a platform-msi device domain
- *
- * @dev:		The device generating the MSIs
- * @nvec:		The number of MSIs that need to be allocated
- * @is_tree:		flag to indicate tree hierarchy
- * @write_msi_msg:	Callback to write an interrupt message for @dev
- * @ops:		The hierarchy domain operations to use
- * @host_data:		Private data associated to this domain
- *
- * Return: An irqdomain for @nvec interrupts on success, NULL in case of error.
- *
- * This is for interrupt domains which stack on a platform-msi domain
- * created by platform_msi_create_irq_domain(). @dev->msi.domain points to
- * that platform-msi domain which is the parent for the new domain.
- */
-struct irq_domain *
-__platform_msi_create_device_domain(struct device *dev,
-				    unsigned int nvec,
-				    bool is_tree,
-				    irq_write_msi_msg_t write_msi_msg,
-				    const struct irq_domain_ops *ops,
-				    void *host_data)
-{
-	struct platform_msi_priv_data *data;
-	struct irq_domain *domain;
-	int err;
-
-	err = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
-	if (err)
-		return NULL;
-
-	/*
-	 * Use a separate lock class for the MSI descriptor mutex on
-	 * platform MSI device domains because the descriptor mutex nests
-	 * into the domain mutex. See alloc/free below.
-	 */
-	lockdep_set_class(&dev->msi.data->mutex, &platform_device_msi_lock_class);
-
-	data = dev->msi.data->platform_data;
-	data->host_data = host_data;
-	domain = irq_domain_create_hierarchy(dev->msi.domain, 0,
-					     is_tree ? 0 : nvec,
-					     dev->fwnode, ops, data);
-	if (!domain)
-		goto free_priv;
-
-	platform_msi_set_proxy_dev(&data->arg);
-	err = msi_domain_prepare_irqs(domain->parent, dev, nvec, &data->arg);
-	if (err)
-		goto free_domain;
-
-	return domain;
-
-free_domain:
-	irq_domain_remove(domain);
-free_priv:
-	platform_msi_free_priv_data(dev);
-	return NULL;
-}
-
-/**
- * platform_msi_device_domain_free - Free interrupts associated with a platform-msi
- *				     device domain
- *
- * @domain:	The platform-msi device domain
- * @virq:	The base irq from which to perform the free operation
- * @nr_irqs:	How many interrupts to free from @virq
- */
-void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int virq,
-				     unsigned int nr_irqs)
-{
-	struct platform_msi_priv_data *data = domain->host_data;
-
-	msi_lock_descs(data->dev);
-	irq_domain_free_irqs_common(domain, virq, nr_irqs);
-	msi_free_msi_descs_range(data->dev, virq, virq + nr_irqs - 1);
-	msi_unlock_descs(data->dev);
-}
-
-/**
- * platform_msi_device_domain_alloc - Allocate interrupts associated with
- *				      a platform-msi device domain
- *
- * @domain:	The platform-msi device domain
- * @virq:	The base irq from which to perform the allocate operation
- * @nr_irqs:	How many interrupts to allocate from @virq
- *
- * Return 0 on success, or an error code on failure. Must be called
- * with irq_domain_mutex held (which can only be done as part of a
- * top-level interrupt allocation).
- */
-int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int virq,
-				     unsigned int nr_irqs)
-{
-	struct platform_msi_priv_data *data = domain->host_data;
-	struct device *dev = data->dev;
-
-	return msi_domain_populate_irqs(domain->parent, dev, virq, nr_irqs, &data->arg);
-}
-
-/* End of removal area */
-
-/* Real per device domain interfaces */
 
 /*
  * This indirection can go when platform_device_ims_init_and_alloc_irqs()
@@ -415,15 +70,10 @@ int platform_device_ims_init_and_alloc_i
 					    irq_write_msi_msg_t write_msi_msg)
 {
 	struct irq_domain *domain = dev->msi.domain;
-	int ret;
 
 	if (!domain || !write_msi_msg)
 		return -EINVAL;
 
-	/* Migration support. Will go away once everything is converted */
-	if (!irq_domain_is_msi_parent(domain))
-		return platform_msi_domain_alloc_irqs(dev, nvec, write_msi_msg);
-
 	/*
 	 * @write_msi_msg is stored in the resulting msi_domain_info::data.
 	 * The underlying domain creation mechanism will assign that
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -77,7 +77,6 @@ extern int pci_msi_ignore_mask;
 /* Helper functions */
 struct msi_desc;
 struct pci_dev;
-struct platform_msi_priv_data;
 struct device_attribute;
 struct irq_domain;
 struct irq_affinity_desc;
@@ -216,7 +215,6 @@ enum msi_desc_filter {
 /**
  * msi_device_data - MSI per device data
  * @properties:		MSI properties which are interesting to drivers
- * @platform_data:	Platform-MSI specific data
  * @mutex:		Mutex protecting the MSI descriptor store
  * @__store:		Xarray for storing MSI descriptor pointers
  * @__iter_idx:		Index to search the next entry for iterators
@@ -225,7 +223,6 @@ enum msi_desc_filter {
  */
 struct msi_device_data {
 	unsigned long			properties;
-	struct platform_msi_priv_data	*platform_data;
 	struct mutex			mutex;
 	struct xarray			__store;
 	unsigned long			__iter_idx;
@@ -628,34 +625,6 @@ void msi_domain_free_irqs_all(struct dev
 
 struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain);
 
-struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
-						  struct msi_domain_info *info,
-						  struct irq_domain *parent);
-int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
-				   irq_write_msi_msg_t write_msi_msg);
-void platform_msi_domain_free_irqs(struct device *dev);
-
-/* When an MSI domain is used as an intermediate domain */
-int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
-			    int nvec, msi_alloc_info_t *args);
-int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
-			     int virq, int nvec, msi_alloc_info_t *args);
-struct irq_domain *
-__platform_msi_create_device_domain(struct device *dev,
-				    unsigned int nvec,
-				    bool is_tree,
-				    irq_write_msi_msg_t write_msi_msg,
-				    const struct irq_domain_ops *ops,
-				    void *host_data);
-
-#define platform_msi_create_device_tree_domain(dev, nvec, write, ops, data) \
-	__platform_msi_create_device_domain(dev, nvec, true, write, ops, data)
-
-int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int virq,
-				     unsigned int nr_irqs);
-void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int virq,
-				     unsigned int nvec);
-void *platform_msi_get_host_data(struct irq_domain *domain);
 /* Per device platform MSI */
 int platform_device_ims_init_and_alloc_irqs(struct device *dev, unsigned int nvec,
 					    irq_write_msi_msg_t write_msi_msg);
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -1121,8 +1121,8 @@ bool msi_match_device_irq_domain(struct
 	return ret;
 }
 
-int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
-			    int nvec, msi_alloc_info_t *arg)
+static int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
+				   int nvec, msi_alloc_info_t *arg)
 {
 	struct msi_domain_info *info = domain->host_data;
 	struct msi_domain_ops *ops = info->ops;
@@ -1130,50 +1130,6 @@ int msi_domain_prepare_irqs(struct irq_d
 	return ops->msi_prepare(domain, dev, nvec, arg);
 }
 
-int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
-			     int virq_base, int nvec, msi_alloc_info_t *arg)
-{
-	struct msi_domain_info *info = domain->host_data;
-	struct msi_domain_ops *ops = info->ops;
-	struct msi_ctrl ctrl = {
-		.domid	= MSI_DEFAULT_DOMAIN,
-		.first  = virq_base,
-		.last	= virq_base + nvec - 1,
-	};
-	struct msi_desc *desc;
-	int ret, virq;
-
-	if (!msi_ctrl_range_valid(dev, &ctrl))
-		return -EINVAL;
-
-	msi_lock_descs(dev);
-	ret = msi_domain_add_simple_msi_descs(dev, &ctrl);
-	if (ret)
-		goto unlock;
-
-	for (virq = virq_base; virq < virq_base + nvec; virq++) {
-		desc = xa_load(&dev->msi.data->__store, virq);
-		desc->irq = virq;
-
-		ops->set_desc(arg, desc);
-		ret = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg);
-		if (ret)
-			goto fail;
-
-		irq_set_msi_desc(virq, desc);
-	}
-	msi_unlock_descs(dev);
-	return 0;
-
-fail:
-	for (--virq; virq >= virq_base; virq--)
-		irq_domain_free_irqs_common(domain, virq, 1);
-	msi_domain_free_descs(dev, &ctrl);
-unlock:
-	msi_unlock_descs(dev);
-	return ret;
-}
-
 /*
  * Carefully check whether the device can use reservation mode. If
  * reservation mode is enabled then the early activation will assign a


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 40/40] genirq/msi: Move msi_device_data to core
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (38 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 39/40] genirq/msi: " Thomas Gleixner
@ 2022-11-21 14:40 ` Thomas Gleixner
  2023-01-11 19:29 ` [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Frank Li
  40 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-21 14:40 UTC (permalink / raw)
  To: LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Marc Zyngier, Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

Now that the platform MSI hack is gone, nothing needs to know about struct
msi_device_data outside of the core code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/msi.h |   22 ----------------------
 kernel/irq/msi.c    |   24 ++++++++++++++++++++++--
 2 files changed, 22 insertions(+), 24 deletions(-)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -21,11 +21,7 @@
 #include <linux/irqdomain_defs.h>
 #include <linux/cpumask.h>
 #include <linux/msi_api.h>
-#include <linux/xarray.h>
-#include <linux/mutex.h>
-#include <linux/list.h>
 #include <linux/irq.h>
-#include <linux/bits.h>
 
 #include <asm/msi.h>
 
@@ -212,24 +208,6 @@ enum msi_desc_filter {
 	MSI_DESC_ASSOCIATED,
 };
 
-/**
- * msi_device_data - MSI per device data
- * @properties:		MSI properties which are interesting to drivers
- * @mutex:		Mutex protecting the MSI descriptor store
- * @__store:		Xarray for storing MSI descriptor pointers
- * @__iter_idx:		Index to search the next entry for iterators
- * @__iter_max:		Index to limit the search
- * @__irqdomains:	Per device interrupt domains
- */
-struct msi_device_data {
-	unsigned long			properties;
-	struct mutex			mutex;
-	struct xarray			__store;
-	unsigned long			__iter_idx;
-	unsigned long			__iter_max;
-	struct irq_domain		*__irqdomains[MSI_MAX_DEVICE_IRQDOMAINS];
-};
-
 int msi_setup_device_data(struct device *dev);
 
 void msi_lock_descs(struct device *dev);
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -8,18 +8,38 @@
  * This file contains common code to support Message Signaled Interrupts for
  * PCI compatible and non PCI compatible devices.
  */
-#include <linux/types.h>
 #include <linux/device.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/msi.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
-#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/xarray.h>
 
 #include "internals.h"
 
 /**
+ * msi_device_data - MSI per device data
+ * @properties:		MSI properties which are interesting to drivers
+ * @mutex:		Mutex protecting the MSI descriptor store
+ * @__store:		Xarray for storing MSI descriptor pointers
+ * @__iter_idx:		Index to search the next entry for iterators
+ * @__iter_max:		Index to limit the search
+ * @__irqdomains:	Per device interrupt domains
+ */
+struct msi_device_data {
+	unsigned long			properties;
+	struct mutex			mutex;
+	struct xarray			__store;
+	unsigned long			__iter_idx;
+	unsigned long			__iter_max;
+	struct irq_domain		*__irqdomains[MSI_MAX_DEVICE_IRQDOMAINS];
+};
+
+/**
  * struct msi_ctrl - MSI internal management control structure
  * @domid:	ID of the domain on which management operations should be done
  * @first:	First (hardware) slot index to operate on


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 02/40] ACPI/IORT: Make prototype of iort_pmsi_get_dev_id() always available
  2022-11-21 14:39 ` [patch V2 02/40] ACPI/IORT: Make prototype of iort_pmsi_get_dev_id() always available Thomas Gleixner
@ 2022-11-21 15:13   ` Robin Murphy
  0 siblings, 0 replies; 57+ messages in thread
From: Robin Murphy @ 2022-11-21 15:13 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Will Deacon, linux-pci, Bjorn Helgaas, Marc Zyngier,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam, Lorenzo Pieralisi

On 2022-11-21 14:39, Thomas Gleixner wrote:
> W=1 build complains:
> 
> drivers/irqchip/irq-gic-v3-its-msi-parent.c:110:12: warning: no previous prototype for function 'iort_pmsi_get_dev_id' [-Wmissing-prototypes]
>     int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
> 
> Reported-by: Ammar Faizi <ammarfaizi2@gnuweeb.org>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
> ---
>   include/linux/acpi_iort.h |    4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
> 
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -26,13 +26,15 @@ int iort_register_domain_token(int trans
>   			       struct fwnode_handle *fw_node);
>   void iort_deregister_domain_token(int trans_id);
>   struct fwnode_handle *iort_find_domain_token(int trans_id);
> +
> +int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
> +
>   #ifdef CONFIG_ACPI_IORT
>   void acpi_iort_init(void);
>   u32 iort_msi_map_id(struct device *dev, u32 id);
>   struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
>   					  enum irq_domain_bus_token bus_token);
>   void acpi_configure_pmsi_domain(struct device *dev);
> -int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);

FWIW I'd prefer to add a "return -ENODEV" stub in the #else section to 
match the others.

<wonders why this was inconsistent to begin with, goes off to dig 
through Git history...>

Oh hey, then we could also finally make good on that 6-year-old promise 
that "The weak function will be removed when the ACPI counterpart is 
merged." :)

Thanks,
Robin.

>   void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
>   		       struct list_head *head);
>   void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,
> 

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 01/40] irqchip/irq-mvebu-icu: Fix works by chance pointer assignment
  2022-11-21 14:39 ` [patch V2 01/40] irqchip/irq-mvebu-icu: Fix works by chance pointer assignment Thomas Gleixner
@ 2022-11-24 12:50   ` Marc Zyngier
  0 siblings, 0 replies; 57+ messages in thread
From: Marc Zyngier @ 2022-11-24 12:50 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

On Mon, 21 Nov 2022 14:39:29 +0000,
Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> Assigning a void pointer which points to a struct to two different data
> types only works by chance if the second type is the first member of the
> struct.
> 
> Replace this works by chance code by using the primary struct pointer.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Gregory Clement <gregory.clement@bootlin.com>
> Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

Acked-by: Marc Zyngier <maz@kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 03/40] irqchip/gic-v2m: Include arm-gic-common.h
  2022-11-21 14:39 ` [patch V2 03/40] irqchip/gic-v2m: Include arm-gic-common.h Thomas Gleixner
@ 2022-11-24 12:51   ` Marc Zyngier
  0 siblings, 0 replies; 57+ messages in thread
From: Marc Zyngier @ 2022-11-24 12:51 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

On Mon, 21 Nov 2022 14:39:32 +0000,
Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> W=1 build complains:
> 
> drivers/irqchip/irq-gic-v2m.c:570:12: warning: no previous prototype for ‘gicv2m_init’ [-Wmissing-prototypes]
>   570 | int __init gicv2m_init(struct fwnode_handle *parent_handle,
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Marc Zyngier <maz@kernel.org>

Acked-by: Marc Zyngier <maz@kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 04/40] irqchip/gic-v2m: Mark a few functions __init
  2022-11-21 14:39 ` [patch V2 04/40] irqchip/gic-v2m: Mark a few functions __init Thomas Gleixner
@ 2022-11-24 12:54   ` Marc Zyngier
  0 siblings, 0 replies; 57+ messages in thread
From: Marc Zyngier @ 2022-11-24 12:54 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

On Mon, 21 Nov 2022 14:39:33 +0000,
Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> They are all part of the init sequence.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Marc Zyngier <maz@kernel.org>
> ---
>  drivers/irqchip/irq-gic-v2m.c |   10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)

Acked-by: Marc Zyngier <maz@kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 05/40] irqchip/ti-sci-inta: Fix kernel doc
  2022-11-21 14:39 ` [patch V2 05/40] irqchip/ti-sci-inta: Fix kernel doc Thomas Gleixner
@ 2022-11-24 12:54   ` Marc Zyngier
  0 siblings, 0 replies; 57+ messages in thread
From: Marc Zyngier @ 2022-11-24 12:54 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

On Mon, 21 Nov 2022 14:39:34 +0000,
Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> W=1 build complains:
> 
> drivers/irqchip/irq-ti-sci-inta.c:177: warning: Function parameter or member 'vint_id' not described in 'ti_sci_inta_xlate_irq'
> drivers/irqchip/irq-ti-sci-inta.c:177: warning: Excess function parameter 'irq' description in 'ti_sci_inta_xlate_irq'
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Nishanth Menon <nm@ti.com>
> Cc: Tero Kristo <kristo@kernel.org>
> Cc: Santosh Shilimkar <ssantosh@kernel.org>
> Cc: Marc Zyngier <maz@kernel.org>
> Cc: linux-arm-kernel@lists.infradead.org
> ---
>  drivers/irqchip/irq-ti-sci-inta.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Acked-by: Marc Zyngier <maz@kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask
  2022-11-21 14:39 ` [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask Thomas Gleixner
@ 2022-11-24 13:04   ` Marc Zyngier
  2022-11-24 13:17     ` Thomas Gleixner
  0 siblings, 1 reply; 57+ messages in thread
From: Marc Zyngier @ 2022-11-24 13:04 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

On Mon, 21 Nov 2022 14:39:36 +0000,
Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> Most ARM(64) PCI/MSI domains mask and unmask in the parent domain after or
> before the PCI mask/unmask operation takes place. So there are more than a
> dozen of the same wrapper implementation all over the place.
> 
> Don't make the same mistake with the new per device PCI/MSI domains and
> provide a static key which lets the domain implementation enable this
> sequence in the PCI/MSI code.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> ---
>  drivers/pci/msi/irqdomain.c |   30 ++++++++++++++++++++++++++++++
>  include/linux/msi.h         |    2 ++
>  2 files changed, 32 insertions(+)
> 
> --- a/drivers/pci/msi/irqdomain.c
> +++ b/drivers/pci/msi/irqdomain.c
> @@ -148,17 +148,45 @@ static void pci_device_domain_set_desc(m
>  	arg->hwirq = desc->msi_index;
>  }
>  
> +static DEFINE_STATIC_KEY_FALSE(pci_msi_mask_unmask_parent);
> +
> +/**
> + * pci_device_msi_mask_unmask_parent_enable - Enable propagation of mask/unmask
> + *					      to the parent interrupt chip
> + *
> + * For MSI parent interrupt domains which want to mask at the parent interrupt
> + * chip too.
> + */
> +void pci_device_msi_mask_unmask_parent_enable(void)
> +{
> +	static_branch_enable(&pci_msi_mask_unmask_parent);
> +}
> +
> +static __always_inline void cond_mask_parent(struct irq_data *data)
> +{
> +	if (static_branch_unlikely(&pci_msi_mask_unmask_parent))
> +		irq_chip_mask_parent(data);
> +}
> +
> +static __always_inline void cond_unmask_parent(struct irq_data *data)
> +{
> +	if (static_branch_unlikely(&pci_msi_mask_unmask_parent))
> +		irq_chip_unmask_parent(data);
> +}
> +
>  static void pci_mask_msi(struct irq_data *data)
>  {
>  	struct msi_desc *desc = irq_data_get_msi_desc(data);
>  
>  	pci_msi_mask(desc, BIT(data->irq - desc->irq));
> +	cond_mask_parent(data);

I find this a bit odd. If anything, I'd rather drop the masking at the
PCI level and keep it local to the interrupt controller, because this
is likely to be more universal than the equivalent PCI operation
(think multi-MSI, for example, which cannot masks individual MSIs).

Another thing is that the static key is a global state. Nothing says
that masking one way or the other is a universal thing, specially when
you have multiple interrupt controllers dealing with MSIs in different
ways. For example, GICv3 can use both the ITS and the GICv3-MBI frame
at the same time for different PCI RC. OK, they happen to deal with
MSIs in the same way, but you hopefully get my point.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask
  2022-11-24 13:04   ` Marc Zyngier
@ 2022-11-24 13:17     ` Thomas Gleixner
  2022-11-24 13:38       ` Marc Zyngier
  0 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-24 13:17 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

On Thu, Nov 24 2022 at 13:04, Marc Zyngier wrote:
> On Mon, 21 Nov 2022 14:39:36 +0000,
>>  static void pci_mask_msi(struct irq_data *data)
>>  {
>>  	struct msi_desc *desc = irq_data_get_msi_desc(data);
>>  
>>  	pci_msi_mask(desc, BIT(data->irq - desc->irq));
>> +	cond_mask_parent(data);
>
> I find this a bit odd. If anything, I'd rather drop the masking at the
> PCI level and keep it local to the interrupt controller, because this
> is likely to be more universal than the equivalent PCI operation
> (think multi-MSI, for example, which cannot masks individual MSIs).
>
> Another thing is that the static key is a global state. Nothing says
> that masking one way or the other is a universal thing, specially when
> you have multiple interrupt controllers dealing with MSIs in different
> ways. For example, GICv3 can use both the ITS and the GICv3-MBI frame
> at the same time for different PCI RC. OK, they happen to deal with
> MSIs in the same way, but you hopefully get my point.

I'm fine with dropping that. I did this because basically all of the
various ARM PCI/MSI domain implementation have a copy of the same
functions. Some of them have pointlessly the wrong order because copy &
pasta is so wonderful....

So the alternative solution is to provide _ONE_ set of correct callbacks
and let the domain initialization code override the irq chip callbacks
of the default PCI/MSI template.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask
  2022-11-24 13:17     ` Thomas Gleixner
@ 2022-11-24 13:38       ` Marc Zyngier
  2022-11-25  0:11         ` Thomas Gleixner
  0 siblings, 1 reply; 57+ messages in thread
From: Marc Zyngier @ 2022-11-24 13:38 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

On Thu, 24 Nov 2022 13:17:00 +0000,
Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> On Thu, Nov 24 2022 at 13:04, Marc Zyngier wrote:
> > On Mon, 21 Nov 2022 14:39:36 +0000,
> >>  static void pci_mask_msi(struct irq_data *data)
> >>  {
> >>  	struct msi_desc *desc = irq_data_get_msi_desc(data);
> >>  
> >>  	pci_msi_mask(desc, BIT(data->irq - desc->irq));
> >> +	cond_mask_parent(data);
> >
> > I find this a bit odd. If anything, I'd rather drop the masking at the
> > PCI level and keep it local to the interrupt controller, because this
> > is likely to be more universal than the equivalent PCI operation
> > (think multi-MSI, for example, which cannot masks individual MSIs).
> >
> > Another thing is that the static key is a global state. Nothing says
> > that masking one way or the other is a universal thing, specially when
> > you have multiple interrupt controllers dealing with MSIs in different
> > ways. For example, GICv3 can use both the ITS and the GICv3-MBI frame
> > at the same time for different PCI RC. OK, they happen to deal with
> > MSIs in the same way, but you hopefully get my point.
> 
> I'm fine with dropping that. I did this because basically all of the
> various ARM PCI/MSI domain implementation have a copy of the same
> functions. Some of them have pointlessly the wrong order because copy &
> pasta is so wonderful....
> 
> So the alternative solution is to provide _ONE_ set of correct callbacks
> and let the domain initialization code override the irq chip callbacks
> of the default PCI/MSI template.

If the various irqchips can tell the core code whether they want
things to be masked at the PCI level or at the irqchip level, this
would be a move in the right direction. For the GIC, I'd definitely
want things masked locally.

What I'd like to get rid off is the double masking, as I agree it is
on the "pretty dumb" side of things.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask
  2022-11-24 13:38       ` Marc Zyngier
@ 2022-11-25  0:11         ` Thomas Gleixner
  2023-05-22 14:19           ` Thomas Gleixner
  0 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-25  0:11 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam

On Thu, Nov 24 2022 at 13:38, Marc Zyngier wrote:
> On Thu, 24 Nov 2022 13:17:00 +0000,
> Thomas Gleixner <tglx@linutronix.de> wrote:
>> > I find this a bit odd. If anything, I'd rather drop the masking at the
>> > PCI level and keep it local to the interrupt controller, because this
>> > is likely to be more universal than the equivalent PCI operation
>> > (think multi-MSI, for example, which cannot masks individual MSIs).
>> >
>> > Another thing is that the static key is a global state. Nothing says
>> > that masking one way or the other is a universal thing, specially when
>> > you have multiple interrupt controllers dealing with MSIs in different
>> > ways. For example, GICv3 can use both the ITS and the GICv3-MBI frame
>> > at the same time for different PCI RC. OK, they happen to deal with
>> > MSIs in the same way, but you hopefully get my point.
>> 
>> I'm fine with dropping that. I did this because basically all of the
>> various ARM PCI/MSI domain implementation have a copy of the same
>> functions. Some of them have pointlessly the wrong order because copy &
>> pasta is so wonderful....
>> 
>> So the alternative solution is to provide _ONE_ set of correct callbacks
>> and let the domain initialization code override the irq chip callbacks
>> of the default PCI/MSI template.
>
> If the various irqchips can tell the core code whether they want
> things to be masked at the PCI level or at the irqchip level, this
> would be a move in the right direction. For the GIC, I'd definitely
> want things masked locally.
>
> What I'd like to get rid off is the double masking, as I agree it is
> on the "pretty dumb" side of things.

Not necessarily. It mitigates the problem of MSI interrupts which can't
be masked because the implementers decided to spare the gates. MSI
allows that as masking is opt-in...

Let me think about it.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 33/40] irqchip/imx-mu-msi: Switch to MSI parent
  2022-11-21 14:40 ` [patch V2 33/40] irqchip/imx-mu-msi: Switch to MSI parent Thomas Gleixner
@ 2022-11-28 20:47   ` Frank Li
  2022-11-28 21:03     ` Thomas Gleixner
  0 siblings, 1 reply; 57+ messages in thread
From: Frank Li @ 2022-11-28 20:47 UTC (permalink / raw)
  To: tglx
  Cc: agross, ammarfaizi2, andersson, andrew, bhelgaas, festevam,
	gregkh, gregory.clement, jgg, kristo, linux-arm-kernel,
	linux-kernel, linux-pci, lorenzo.pieralisi, lpieralisi,
	mark.rutland, maz, nm, okaya, robin.murphy, s.hauer,
	sebastian.hesselbarth, shameerali.kolothum.thodi, shawnguo,
	ssantosh, vkoul, will, yuzenghui, imx

From: Frank Li <Frank.li@nxp.com>

On Mon, Nov 21, 2022 at 03:40:09PM +0100, Thomas Gleixner wrote:
> 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" 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>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Fabio Estevam <festevam@gmail.com>
> ---
>  drivers/irqchip/Kconfig           |    1 
>  drivers/irqchip/irq-gic-msi-lib.c |    2 +
>  drivers/irqchip/irq-imx-mu-msi.c  |   53 +++++++++++++++-----------------------
>  3 files changed, 25 insertions(+), 31 deletions(-)
> 
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -494,6 +494,7 @@ config IMX_MU_MSI
>  	select IRQ_DOMAIN
>  	select IRQ_DOMAIN_HIERARCHY
>  	select GENERIC_MSI_IRQ
> +	select ARM_GIC_MSI_LIB
>  	help
>  	  Provide a driver for the i.MX Messaging Unit block used as a
>  	  CPU-to-CPU MSI controller. This requires a specially crafted DT
> --- a/drivers/irqchip/irq-gic-msi-lib.c
> +++ b/drivers/irqchip/irq-gic-msi-lib.c
> @@ -90,6 +90,8 @@ bool gic_msi_lib_init_dev_msi_info(struc
>  	/* Chip updates for all child bus types */
>  	if (!info->chip->irq_eoi)
>  		info->chip->irq_eoi	= irq_chip_eoi_parent;
> +	if (!info->chip->irq_ack)
> +		info->chip->irq_ack	= irq_chip_ack_parent;
>  
>  	/*
>  	 * The device MSI domain can never have a set affinity callback it
> --- a/drivers/irqchip/irq-imx-mu-msi.c
> +++ b/drivers/irqchip/irq-imx-mu-msi.c
> @@ -24,6 +24,8 @@
>  #include <linux/pm_domain.h>
>  #include <linux/spinlock.h>
>  
> +#include "irq-gic-msi-lib.h"
> +

I think irq-gic-msi-lib.h is not good name. Actually mu-msi is not arm gic.
irq-gic-msi-lib do common work, which not related arm gic at all.

>  #define IMX_MU_CHANS            4
>  
>  enum imx_mu_xcr {
> @@ -114,20 +116,6 @@ static void imx_mu_msi_parent_ack_irq(st
>  	imx_mu_read(msi_data, msi_data->cfg->xRR + data->hwirq * 4);
>  }
>  
> -static struct irq_chip imx_mu_msi_irq_chip = {
> -	.name = "MU-MSI",
> -	.irq_ack = irq_chip_ack_parent,
> -};
> -
> -static struct msi_domain_ops imx_mu_msi_irq_ops = {
> -};
> -
> -static struct msi_domain_info imx_mu_msi_domain_info = {
> -	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
> -	.ops	= &imx_mu_msi_irq_ops,
> -	.chip	= &imx_mu_msi_irq_chip,
> -};
> -
>  static void imx_mu_msi_parent_compose_msg(struct irq_data *data,
>  					  struct msi_msg *msg)
>  {
> @@ -195,6 +183,7 @@ static void imx_mu_msi_domain_irq_free(s
>  }
>  
>  static const struct irq_domain_ops imx_mu_msi_domain_ops = {
> +	.select	= gic_msi_lib_irq_domain_select,
>  	.alloc	= imx_mu_msi_domain_irq_alloc,
>  	.free	= imx_mu_msi_domain_irq_free,
>  };
> @@ -216,35 +205,37 @@ static void imx_mu_msi_irq_handler(struc
>  	chained_irq_exit(chip, desc);
>  }
>  
> +#define IMX_MU_MSI_FLAGS_REQUIRED	(MSI_FLAG_USE_DEF_DOM_OPS |	\
> +					 MSI_FLAG_USE_DEF_CHIP_OPS |	\
> +					 MSI_FLAG_PARENT_PM_DEV)
> +
> +#define IMX_MU_MSI_FLAGS_SUPPORTED	(MSI_GENERIC_FLAGS_MASK)
> +
> +static const struct msi_parent_ops imx_mu_msi_parent_ops = {
> +	.supported_flags	= IMX_MU_MSI_FLAGS_SUPPORTED,
> +	.required_flags		= IMX_MU_MSI_FLAGS_REQUIRED,
> +	.bus_select_token       = DOMAIN_BUS_NEXUS,
> +	.bus_select_mask	= MATCH_PLATFORM_MSI,
> +	.prefix			= "MU-MSI-",
> +	.init_dev_msi_info	= gic_msi_lib_init_dev_msi_info,
> +};
> +
>  static int imx_mu_msi_domains_init(struct imx_mu_msi *msi_data, struct device *dev)
>  {
>  	struct fwnode_handle *fwnodes = dev_fwnode(dev);
>  	struct irq_domain *parent;
>  
>  	/* Initialize MSI domain parent */
> -	parent = irq_domain_create_linear(fwnodes,
> -					    IMX_MU_CHANS,
> -					    &imx_mu_msi_domain_ops,
> -					    msi_data);
> +	parent = irq_domain_create_linear(fwnodes, IMX_MU_CHANS, &imx_mu_msi_domain_ops, msi_data);

coding style change should be in sperated patch.

>  	if (!parent) {
>  		dev_err(dev, "failed to create IRQ domain\n");
>  		return -ENOMEM;
>  	}
>  
>  	irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS);
> -
> -	msi_data->msi_domain = platform_msi_create_irq_domain(fwnodes,
> -					&imx_mu_msi_domain_info,
> -					parent);
> -
> -	if (!msi_data->msi_domain) {
> -		dev_err(dev, "failed to create MSI domain\n");
> -		irq_domain_remove(parent);
> -		return -ENOMEM;
> -	}
> -
> -	irq_domain_set_pm_device(msi_data->msi_domain, dev);
> -
> +	parent->dev = parent->pm_dev = dev;
> +	parent->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
> +	parent->msi_parent_ops = &imx_mu_msi_parent_ops;
>  	return 0;
>  }

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 33/40] irqchip/imx-mu-msi: Switch to MSI parent
  2022-11-28 20:47   ` Frank Li
@ 2022-11-28 21:03     ` Thomas Gleixner
  0 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2022-11-28 21:03 UTC (permalink / raw)
  To: Frank Li
  Cc: agross, ammarfaizi2, andersson, andrew, bhelgaas, festevam,
	gregkh, gregory.clement, jgg, kristo, linux-arm-kernel,
	linux-kernel, linux-pci, lorenzo.pieralisi, lpieralisi,
	mark.rutland, maz, nm, okaya, robin.murphy, s.hauer,
	sebastian.hesselbarth, shameerali.kolothum.thodi, shawnguo,
	ssantosh, vkoul, will, yuzenghui, imx

Frank!

On Mon, Nov 28 2022 at 15:47, Frank Li wrote:
> On Mon, Nov 21, 2022 at 03:40:09PM +0100, Thomas Gleixner wrote:
>>  	 * The device MSI domain can never have a set affinity callback it
>> --- a/drivers/irqchip/irq-imx-mu-msi.c
>> +++ b/drivers/irqchip/irq-imx-mu-msi.c
>> @@ -24,6 +24,8 @@
>>  #include <linux/pm_domain.h>
>>  #include <linux/spinlock.h>
>>  
>> +#include "irq-gic-msi-lib.h"
>> +
>
> I think irq-gic-msi-lib.h is not good name. Actually mu-msi is not arm gic.
> irq-gic-msi-lib do common work, which not related arm gic at all.

I realized that after a while too, but the main purpose of this series
was to establish that the core design holds up to handle the gazillions
of ARM variants out there and to solicit technical feedback from the
involved parties.

>>  static int imx_mu_msi_domains_init(struct imx_mu_msi *msi_data, struct device *dev)
>>  {
>>  	struct fwnode_handle *fwnodes = dev_fwnode(dev);
>>  	struct irq_domain *parent;
>>  
>>  	/* Initialize MSI domain parent */
>> -	parent = irq_domain_create_linear(fwnodes,
>> -					    IMX_MU_CHANS,
>> -					    &imx_mu_msi_domain_ops,
>> -					    msi_data);
>> +	parent = irq_domain_create_linear(fwnodes, IMX_MU_CHANS, &imx_mu_msi_domain_ops, msi_data);
>
> coding style change should be in sperated patch.

Thanks for the thorough technical feedback!

       tglx

^ permalink raw reply	[flat|nested] 57+ messages in thread

* RE: [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains
  2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
                   ` (39 preceding siblings ...)
  2022-11-21 14:40 ` [patch V2 40/40] genirq/msi: Move msi_device_data to core Thomas Gleixner
@ 2023-01-11 19:29 ` Frank Li
  40 siblings, 0 replies; 57+ messages in thread
From: Frank Li @ 2023-01-11 19:29 UTC (permalink / raw)
  To: tglx
  Cc: agross, ammarfaizi2, andersson, andrew, bhelgaas, festevam,
	gregkh, gregory.clement, jgg, kristo, linux-arm-kernel,
	linux-kernel, linux-pci, lorenzo.pieralisi, lpieralisi,
	mark.rutland, maz, nm, okaya, robin.murphy, s.hauer,
	sebastian.hesselbarth, shameerali.kolothum.thodi, shawnguo,
	ssantosh, vkoul, will, yuzenghui

From: Frank Li <frank.li@nxp.com>

On Mon, Nov 21, 2022 at 03:39:28PM +0100, Thomas Gleixner wrote:
> The series is also available from git:
>
>   git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git devmsi-v2-arm
>
> The work was done to validate that the design decisions for per device MSI
> domains and the related data structures are up to the task to handle the
> ARM oddities. The design held up, it was just necessary to extend some of
> the data structures to handle the ARM specifics in a sane way, but there
> was no fundamental shortcoming.

I based on branch devmsi-arm, and run at ls1028a platform. And found 
Integrated Endpoint Root Complex and enetc can't work.

The reason is that pci_msi_domain_get_msi_rid can't get correct rid.

[    5.153596]  pci_msi_domain_get_msi_rid+0x94/0x110
[    5.158399]  its_pci_msi_prepare+0xac/0x180
[    5.162594]  __msi_domain_alloc_irqs+0x78/0x464
[    5.167138]  __msi_domain_alloc_locked+0x148/0x190
[    5.171942]  msi_domain_alloc_irqs_all_locked+0x54/0xb0
[    5.177184]  pci_msi_setup_msi_irqs+0x2c/0x4c
[    5.181551]  __pci_enable_msix_range+0x374/0x600
[    5.186182]  pci_alloc_irq_vectors_affinity+0xbc/0x13c
[    5.191336]  pci_alloc_irq_vectors+0x14/0x20
[    5.195618]  enetc_alloc_msix+0x40/0x2cc
[    5.199550]  enetc_pf_probe+0x788/0xea0
[    5.203395]  local_pci_probe+0x40/0x9c
[    5.207151]  pci_device_probe+0xac/0x20c


u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
{
        struct device_node *of_node;
        u32 rid = pci_dev_id(pdev);

        pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);

        of_node = irq_domain_get_of_node(domain);
        rid = of_node ? of_msi_map_id(&pdev->dev, of_node, rid) :
                        iort_msi_map_id(&pdev->dev, rid);

}

supposed of_msi_map_id get map informaiton from device tree
msi-map = <0 &its 0x17 0xe>;


but when msi_create_device_irq_domain pre device msi domain, 
fwnode is NOT PCI host controller's device node.

bool msi_create_device_irq_domain()
{
	...
	if (bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE)
                fwnode = dev->fwnode;
        else
                fwnode = fwnalloced = irq_domain_alloc_named_fwnode(bundle->name);
	...
}



[    4.601732]  msi_create_device_irq_domain+0x1bc/0x20c
[    4.606800]  pci_setup_msix_device_domain+0x98/0xd4
[    4.611691]  __pci_enable_msix_range+0x21c/0x600
[    4.616322]  pci_alloc_irq_vectors_affinity+0xbc/0x13c
[    4.621477]  pci_alloc_irq_vectors+0x14/0x20
[    4.625760]  enetc_alloc_msix+0x40/0x2cc
[    4.629693]  enetc_pf_probe+0x788/0xea0
[    4.633537]  local_pci_probe+0x40/0x9c
[    4.637294]  pci_device_probe+0xac/0x20c


I don't know how to correct fix this problem. Can you give some suggestion?

Frank

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask
  2022-11-25  0:11         ` Thomas Gleixner
@ 2023-05-22 14:19           ` Thomas Gleixner
  2023-05-23 10:25             ` Marc Zyngier
  0 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2023-05-22 14:19 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam, Anna-Maria Behnsen

On Fri, Nov 25 2022 at 01:11, Thomas Gleixner wrote:
> On Thu, Nov 24 2022 at 13:38, Marc Zyngier wrote:
>> On Thu, 24 Nov 2022 13:17:00 +0000,
>> Thomas Gleixner <tglx@linutronix.de> wrote:
>>> > I find this a bit odd. If anything, I'd rather drop the masking at the
>>> > PCI level and keep it local to the interrupt controller, because this
>>> > is likely to be more universal than the equivalent PCI operation
>>> > (think multi-MSI, for example, which cannot masks individual MSIs).
>>> >
>>> > Another thing is that the static key is a global state. Nothing says
>>> > that masking one way or the other is a universal thing, specially when
>>> > you have multiple interrupt controllers dealing with MSIs in different
>>> > ways. For example, GICv3 can use both the ITS and the GICv3-MBI frame
>>> > at the same time for different PCI RC. OK, they happen to deal with
>>> > MSIs in the same way, but you hopefully get my point.
>>> 
>>> I'm fine with dropping that. I did this because basically all of the
>>> various ARM PCI/MSI domain implementation have a copy of the same
>>> functions. Some of them have pointlessly the wrong order because copy &
>>> pasta is so wonderful....
>>> 
>>> So the alternative solution is to provide _ONE_ set of correct callbacks
>>> and let the domain initialization code override the irq chip callbacks
>>> of the default PCI/MSI template.
>>
>> If the various irqchips can tell the core code whether they want
>> things to be masked at the PCI level or at the irqchip level, this
>> would be a move in the right direction. For the GIC, I'd definitely
>> want things masked locally.
>>
>> What I'd like to get rid off is the double masking, as I agree it is
>> on the "pretty dumb" side of things.
>
> Not necessarily. It mitigates the problem of MSI interrupts which can't
> be masked because the implementers decided to spare the gates. MSI
> allows that as masking is opt-in...
>
> Let me think about it.

That really took a while to think about it :)

We have the following cases on the PCI/MSI side:

 1) The MSI[X] entry can be masked

 2) The MSI[X] entry cannot be masked because hardware did not implement
    it, masking is globally disabled due to XEN, masking does not exist
    for this horrible virtual MSI hackery

Now you said:

 "For the GIC, I'd definitely want things masked locally."

I decoded this, that you want to have these interrupts masked at the GIC
level too independent of #1 or #2 above. And then:

 "What I'd like to get rid off is the double masking."

But relying on the GIC alone is not really a good thing IMO. There is no
point to let some confused device send unwanted MSI messages around
without a way to shut it up from the generic code via the regular
mask/unmask callbacks.

On the other hand for PCI/MSI[x] the mask/unmask operations are not in
the hot path as PCI/MSI[x] are strictly edge. Mask/unmask is only
happening on startup, shutdown and when an interrupt arrives after
disable_irq() incremented the lazy disable counter.

For regular interrupt handling mask/unmask is not involved.

So to avoid that global key we can let the parent domain set a new flag,
e.g. MSI_FLAG_PCI_MSI_MASK_PARENT, in msi_parent_ops::supported_flags
and let the PCI/MSI core code query that information when the per device
domain is created and select the appropriate template or fixup the
callbacks after the domain is created.

Does that address your concerns?

Thanks,

        tglx






^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask
  2023-05-22 14:19           ` Thomas Gleixner
@ 2023-05-23 10:25             ` Marc Zyngier
  2023-05-23 13:05               ` Thomas Gleixner
  0 siblings, 1 reply; 57+ messages in thread
From: Marc Zyngier @ 2023-05-23 10:25 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam, Anna-Maria Behnsen

On Mon, 22 May 2023 15:19:39 +0100,
Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> On Fri, Nov 25 2022 at 01:11, Thomas Gleixner wrote:
> > On Thu, Nov 24 2022 at 13:38, Marc Zyngier wrote:
> >> On Thu, 24 Nov 2022 13:17:00 +0000,
> >> Thomas Gleixner <tglx@linutronix.de> wrote:
> >>> > I find this a bit odd. If anything, I'd rather drop the masking at the
> >>> > PCI level and keep it local to the interrupt controller, because this
> >>> > is likely to be more universal than the equivalent PCI operation
> >>> > (think multi-MSI, for example, which cannot masks individual MSIs).
> >>> >
> >>> > Another thing is that the static key is a global state. Nothing says
> >>> > that masking one way or the other is a universal thing, specially when
> >>> > you have multiple interrupt controllers dealing with MSIs in different
> >>> > ways. For example, GICv3 can use both the ITS and the GICv3-MBI frame
> >>> > at the same time for different PCI RC. OK, they happen to deal with
> >>> > MSIs in the same way, but you hopefully get my point.
> >>> 
> >>> I'm fine with dropping that. I did this because basically all of the
> >>> various ARM PCI/MSI domain implementation have a copy of the same
> >>> functions. Some of them have pointlessly the wrong order because copy &
> >>> pasta is so wonderful....
> >>> 
> >>> So the alternative solution is to provide _ONE_ set of correct callbacks
> >>> and let the domain initialization code override the irq chip callbacks
> >>> of the default PCI/MSI template.
> >>
> >> If the various irqchips can tell the core code whether they want
> >> things to be masked at the PCI level or at the irqchip level, this
> >> would be a move in the right direction. For the GIC, I'd definitely
> >> want things masked locally.
> >>
> >> What I'd like to get rid off is the double masking, as I agree it is
> >> on the "pretty dumb" side of things.
> >
> > Not necessarily. It mitigates the problem of MSI interrupts which can't
> > be masked because the implementers decided to spare the gates. MSI
> > allows that as masking is opt-in...
> >
> > Let me think about it.
> 
> That really took a while to think about it :)
> 
> We have the following cases on the PCI/MSI side:
> 
>  1) The MSI[X] entry can be masked
> 
>  2) The MSI[X] entry cannot be masked because hardware did not implement
>     it, masking is globally disabled due to XEN, masking does not exist
>     for this horrible virtual MSI hackery

And as a bonus the case of non-PCI MSIs, which are definitely a thing,
and I'd like them to fit in the same model (because life is too short
to do anything else). As for the Xen side, I hope to never have to
care about it for the architecture I care about (I've long proclaimed
Xen/arm64 dead and buried).

> 
> Now you said:
> 
>  "For the GIC, I'd definitely want things masked locally."
> 
> I decoded this, that you want to have these interrupts masked at the GIC
> level too independent of #1 or #2 above. And then:
> 
>  "What I'd like to get rid off is the double masking."
> 
> But relying on the GIC alone is not really a good thing IMO. There is no
> point to let some confused device send unwanted MSI messages around
> without a way to shut it up from the generic code via the regular
> mask/unmask callbacks.

I have a slightly different view of the problem. The device masking is
somehow orthogonal with the masking at the GIC level:

- can the interrupt be generated: this is a device property

- can the interrupt be signalled: this is an interrupt controller
  property

In a way, this is no different from your basic device, such as a
timer: you need both the interrupt generation to be enabled at the
timer level, and the interrupt signalling to be enabled (unmasked) at
the irqchip level.

Today, we conflate the two, because we have either:

- devices that cannot selectively mask interrupts

- interrupt controllers that are limited in what they can mask

and this results in the terrible pattern that's all over the
GIC-related stuff.

> On the other hand for PCI/MSI[x] the mask/unmask operations are not in
> the hot path as PCI/MSI[x] are strictly edge. Mask/unmask is only
> happening on startup, shutdown and when an interrupt arrives after
> disable_irq() incremented the lazy disable counter.
> 
> For regular interrupt handling mask/unmask is not involved.
> 
> So to avoid that global key we can let the parent domain set a new flag,
> e.g. MSI_FLAG_PCI_MSI_MASK_PARENT, in msi_parent_ops::supported_flags
> and let the PCI/MSI core code query that information when the per device
> domain is created and select the appropriate template or fixup the
> callbacks after the domain is created.
> 
> Does that address your concerns?

It does to a certain extent.

But what I'd really like is that in the most common case where the
interrupt controller is capable of masking MSIs, the PCI/MSI
*enabling* becomes the responsibility of the PCI core code and not the
IRQ code.

The IRQ code should ideally only be concerned with the masking of the
interrupt at the irqchip level, and not beyond that. And that'd solve
the Xen problem by merely ignoring it.

If we have HW out there that cannot mask MSIs at the interrupt
controller level, then we'd have to fallback to device-side masking,
which doesn't really work in general (MultiMSI being my favourite
example). My gut feeling is that this is rare, but I'm pretty sure it
exists.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask
  2023-05-23 10:25             ` Marc Zyngier
@ 2023-05-23 13:05               ` Thomas Gleixner
  2023-05-31  8:35                 ` Marc Zyngier
  0 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2023-05-23 13:05 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam, Anna-Maria Behnsen

On Tue, May 23 2023 at 11:25, Marc Zyngier wrote:
> On Mon, 22 May 2023 15:19:39 +0100,
> Thomas Gleixner <tglx@linutronix.de> wrote:
>> On the other hand for PCI/MSI[x] the mask/unmask operations are not in
>> the hot path as PCI/MSI[x] are strictly edge. Mask/unmask is only
>> happening on startup, shutdown and when an interrupt arrives after
>> disable_irq() incremented the lazy disable counter.
>> 
>> For regular interrupt handling mask/unmask is not involved.
>> 
>> So to avoid that global key we can let the parent domain set a new flag,
>> e.g. MSI_FLAG_PCI_MSI_MASK_PARENT, in msi_parent_ops::supported_flags
>> and let the PCI/MSI core code query that information when the per device
>> domain is created and select the appropriate template or fixup the
>> callbacks after the domain is created.
>> 
>> Does that address your concerns?
>
> It does to a certain extent.
>
> But what I'd really like is that in the most common case where the
> interrupt controller is capable of masking MSIs, the PCI/MSI
> *enabling* becomes the responsibility of the PCI core code and not the
> IRQ code.
>
> The IRQ code should ideally only be concerned with the masking of the
> interrupt at the irqchip level, and not beyond that. And that'd solve
> the Xen problem by merely ignoring it.
>
> If we have HW out there that cannot mask MSIs at the interrupt
> controller level, then we'd have to fallback to device-side masking,
> which doesn't really work in general (MultiMSI being my favourite
> example). My gut feeling is that this is rare, but I'm pretty sure it
> exists.

Sure. There are 3 parts involved:

      [Device]--->[PCI/MSI]---->[GIC]
                   irqchip      irqchip

Controlling the interrupt machinery in the device happens at the device
driver level and is conceptually independent of the interrupt
manangement code. The device driver has no access to the PCI/MSI irqchip
and all it can do is to enable/disable the source of the interrupt in
the device.

For the interrupt management code the job is to ensure that an interrupt
can be prevented from disrupting the OS operation independent of the
device driver correctness.

As a matter of fact we know that PCI/MSI masking ranges from not
possible over flaky to properly working. So we can't reliably prevent
that a rougue device spams the PCIe bus with messages.

Which means that we should utilize the fact that the next interrupt chip
in the hierarchy can mask reliably. I wish I could disable individual
vectors at the local APIC level on x86...

Now the question is whether we want to make this conditional depending
on what the PCI/MSI[X] hardware advertises or just keep it simple and do
it unconditionally.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask
  2023-05-23 13:05               ` Thomas Gleixner
@ 2023-05-31  8:35                 ` Marc Zyngier
  0 siblings, 0 replies; 57+ messages in thread
From: Marc Zyngier @ 2023-05-31  8:35 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Will Deacon, linux-pci, Bjorn Helgaas, Lorenzo Pieralisi,
	Greg Kroah-Hartman, Jason Gunthorpe, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Ammar Faizi,
	Robin Murphy, Lorenzo Pieralisi, Nishanth Menon, Tero Kristo,
	Santosh Shilimkar, linux-arm-kernel, Vinod Koul, Sinan Kaya,
	Andy Gross, Bjorn Andersson, Mark Rutland,
	Shameerali Kolothum Thodi, Zenghui Yu, Shawn Guo, Sascha Hauer,
	Fabio Estevam, Anna-Maria Behnsen

On Tue, 23 May 2023 14:05:56 +0100,
Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> On Tue, May 23 2023 at 11:25, Marc Zyngier wrote:
> > On Mon, 22 May 2023 15:19:39 +0100,
> > Thomas Gleixner <tglx@linutronix.de> wrote:
> >> On the other hand for PCI/MSI[x] the mask/unmask operations are not in
> >> the hot path as PCI/MSI[x] are strictly edge. Mask/unmask is only
> >> happening on startup, shutdown and when an interrupt arrives after
> >> disable_irq() incremented the lazy disable counter.
> >> 
> >> For regular interrupt handling mask/unmask is not involved.
> >> 
> >> So to avoid that global key we can let the parent domain set a new flag,
> >> e.g. MSI_FLAG_PCI_MSI_MASK_PARENT, in msi_parent_ops::supported_flags
> >> and let the PCI/MSI core code query that information when the per device
> >> domain is created and select the appropriate template or fixup the
> >> callbacks after the domain is created.
> >> 
> >> Does that address your concerns?
> >
> > It does to a certain extent.
> >
> > But what I'd really like is that in the most common case where the
> > interrupt controller is capable of masking MSIs, the PCI/MSI
> > *enabling* becomes the responsibility of the PCI core code and not the
> > IRQ code.
> >
> > The IRQ code should ideally only be concerned with the masking of the
> > interrupt at the irqchip level, and not beyond that. And that'd solve
> > the Xen problem by merely ignoring it.
> >
> > If we have HW out there that cannot mask MSIs at the interrupt
> > controller level, then we'd have to fallback to device-side masking,
> > which doesn't really work in general (MultiMSI being my favourite
> > example). My gut feeling is that this is rare, but I'm pretty sure it
> > exists.
> 
> Sure. There are 3 parts involved:
> 
>       [Device]--->[PCI/MSI]---->[GIC]
>                    irqchip      irqchip
> 
> Controlling the interrupt machinery in the device happens at the device
> driver level and is conceptually independent of the interrupt
> manangement code. The device driver has no access to the PCI/MSI irqchip
> and all it can do is to enable/disable the source of the interrupt in
> the device.
> 
> For the interrupt management code the job is to ensure that an interrupt
> can be prevented from disrupting the OS operation independent of the
> device driver correctness.
> 
> As a matter of fact we know that PCI/MSI masking ranges from not
> possible over flaky to properly working. So we can't reliably prevent
> that a rougue device spams the PCIe bus with messages.
> 
> Which means that we should utilize the fact that the next interrupt chip
> in the hierarchy can mask reliably. I wish I could disable individual
> vectors at the local APIC level on x86...
> 
> Now the question is whether we want to make this conditional depending
> on what the PCI/MSI[X] hardware advertises or just keep it simple and do
> it unconditionally.

I think this should be unconditional if the root irqchip (the GIC in
this instance) is capable of it.

So a suggestion where the root irqchip exposes its masking capability,
which upon detection by the upper layer (whateverbusyouwant/MSI) makes
it stop playing with its own device-level mask has my full support
(and now breathe normally).

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 57+ messages in thread

end of thread, other threads:[~2023-05-31  8:35 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-21 14:39 [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Thomas Gleixner
2022-11-21 14:39 ` [patch V2 01/40] irqchip/irq-mvebu-icu: Fix works by chance pointer assignment Thomas Gleixner
2022-11-24 12:50   ` Marc Zyngier
2022-11-21 14:39 ` [patch V2 02/40] ACPI/IORT: Make prototype of iort_pmsi_get_dev_id() always available Thomas Gleixner
2022-11-21 15:13   ` Robin Murphy
2022-11-21 14:39 ` [patch V2 03/40] irqchip/gic-v2m: Include arm-gic-common.h Thomas Gleixner
2022-11-24 12:51   ` Marc Zyngier
2022-11-21 14:39 ` [patch V2 04/40] irqchip/gic-v2m: Mark a few functions __init Thomas Gleixner
2022-11-24 12:54   ` Marc Zyngier
2022-11-21 14:39 ` [patch V2 05/40] irqchip/ti-sci-inta: Fix kernel doc Thomas Gleixner
2022-11-24 12:54   ` Marc Zyngier
2022-11-21 14:39 ` [patch V2 06/40] PCI/MSI: Provide static key for parent mask/unmask Thomas Gleixner
2022-11-24 13:04   ` Marc Zyngier
2022-11-24 13:17     ` Thomas Gleixner
2022-11-24 13:38       ` Marc Zyngier
2022-11-25  0:11         ` Thomas Gleixner
2023-05-22 14:19           ` Thomas Gleixner
2023-05-23 10:25             ` Marc Zyngier
2023-05-23 13:05               ` Thomas Gleixner
2023-05-31  8:35                 ` Marc Zyngier
2022-11-21 14:39 ` [patch V2 07/40] irqchip/gic-v3: Make gic_irq_domain_select() robust for zero parameter count Thomas Gleixner
2022-11-21 14:39 ` [patch V2 08/40] genirq/irqdomain: Remove the param count restriction from select() Thomas Gleixner
2022-11-21 14:39 ` [patch V2 09/40] genirq/msi: Extend msi_parent_ops Thomas Gleixner
2022-11-21 14:39 ` [patch V2 10/40] irqchip: Provide irq-gic-lib Thomas Gleixner
2022-11-21 14:39 ` [patch V2 11/40] irqchip/gic-v3-its: Provide MSI parent infrastructure Thomas Gleixner
2022-11-21 14:39 ` [patch V2 12/40] irqchip/gic-msi-lib: Prepare for PCI MSI/MSIX Thomas Gleixner
2022-11-21 14:39 ` [patch V2 13/40] irqchip/gic-v3-its: Provide MSI parent for PCI/MSI[-X] Thomas Gleixner
2022-11-21 14:39 ` [patch V2 14/40] genirq/irqdomain: Add BUS_DOMAIN_DEVICE_MSI Thomas Gleixner
2022-11-21 14:39 ` [patch V2 15/40] irqchip/gic-msi-lib: Prepare for DEVICE MSI to replace platform MSI Thomas Gleixner
2022-11-21 14:39 ` [patch V2 16/40] platform-msi: Prepare for real per device domains Thomas Gleixner
2022-11-21 14:39 ` [patch V2 17/40] irqchip: Convert all platform MSI users to the new API Thomas Gleixner
2022-11-21 14:39 ` [patch V2 18/40] genirq/msi: Provide optional translation op Thomas Gleixner
2022-11-21 14:39 ` [patch V2 19/40] genirq/msi: Split msi_domain_alloc_irq_at() Thomas Gleixner
2022-11-21 14:39 ` [patch V2 20/40] genirq/msi: Provide BUS DEVICE_MSI_WIRED Thomas Gleixner
2022-11-21 14:39 ` [patch V2 21/40] genirq/msi: Optionally use dev->fwnode for device domain Thomas Gleixner
2022-11-21 14:39 ` [patch V2 22/40] genirq/msi: Provide allocation/free functions for "wired" MSI interrupts Thomas Gleixner
2022-11-21 14:39 ` [patch V2 23/40] genirq/irqdomain: Reroute device MSI create_mapping Thomas Gleixner
2022-11-21 14:39 ` [patch V2 24/40] irqchip/mbigen: Prepare for real per device MSI Thomas Gleixner
2022-11-21 14:39 ` [patch V2 25/40] irqchip/gic-msi-lib: Prepare for DOMAIN_BUS_WIRED_TO_MSI Thomas Gleixner
2022-11-21 14:40 ` [patch V2 26/40] irqchip/gic-v3-its: Switch platform MSI to MSI parent Thomas Gleixner
2022-11-21 14:40 ` [patch V2 27/40] irqchip/mbigen: Remove platform_msi_create_device_domain() fallback Thomas Gleixner
2022-11-21 14:40 ` [patch V2 28/40] genirq/msi: Remove platform_msi_create_device_domain() Thomas Gleixner
2022-11-21 14:40 ` [patch V2 29/40] genirq/gic-v3-mbi: Remove unused wired MSI mechanics Thomas Gleixner
2022-11-21 14:40 ` [patch V2 30/40] genirq/gic-v3-mbi: Switch to MSI parent Thomas Gleixner
2022-11-21 14:40 ` [patch V2 31/40] irqchip/gic-v2m: Switch to device MSI Thomas Gleixner
2022-11-21 14:40 ` [patch V2 32/40] genirq/msi: Provide MSI_FLAG_PARENT_PM_DEV Thomas Gleixner
2022-11-21 14:40 ` [patch V2 33/40] irqchip/imx-mu-msi: Switch to MSI parent Thomas Gleixner
2022-11-28 20:47   ` Frank Li
2022-11-28 21:03     ` Thomas Gleixner
2022-11-21 14:40 ` [patch V2 34/40] irqchip/irq-mvebu-icu: Prepare for real per device MSI Thomas Gleixner
2022-11-21 14:40 ` [patch V2 35/40] irqchip/mvebu-gicp: Switch to MSI parent Thomas Gleixner
2022-11-21 14:40 ` [patch V2 36/40] irqchip/mvebu-odmi: Switch to parent MSI Thomas Gleixner
2022-11-21 14:40 ` [patch V2 37/40] irqchip/irq-mvebu-sei: Switch to MSI parent Thomas Gleixner
2022-11-21 14:40 ` [patch V2 38/40] irqchip/irq-mvebu-icu: Remove platform MSI leftovers Thomas Gleixner
2022-11-21 14:40 ` [patch V2 39/40] genirq/msi: " Thomas Gleixner
2022-11-21 14:40 ` [patch V2 40/40] genirq/msi: Move msi_device_data to core Thomas Gleixner
2023-01-11 19:29 ` [patch V2 00/40] genirq, irqchip: Convert ARM MSI handling to per device MSI domains Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).