Skip to contentSkip to conversation

MSI support for Marvell EBU PCIe driver

PATCH Superseded Thomas Petazzoni 8 participants 49 messages Jul 15, 2013 – Aug 7, 2013

Subsystems (14)

v5 of 9 Superseded Latest is v9 →

lore
Share & tools
lore
#0 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Hello,

This set of patches introduces Message Signaled Interrupt support in the Marvell EBU PCIe driver. It has been successfully tested on the Armada XP GP platform with an Intel e1000e PCIe network card that supports MSI.

This patch set is intended for merging in 3.12, so the respective maintainers of the different areas are invited to review/ack the patches, see below for the details. This set of patches applies on top of 3.11-rc1.

The patches do the following:

* Patch 1 adds an IRQ domain function that allows to allocate dynamically a free hwirq number from an IRQ domain, and create a virq mapping to it. It was suggested by Grant Likely in order to remove the hwirq allocation code from the IRQ driver itself.

This patch needs the Ack of Grant Likely.

* Patch 2 reworks how the architecture-specific MSI functions can be overriden by architecture-specific code, by using weak functions. It was suggested by Bjorn Helgaas.

This patch needs the Ack from Bjorn Helgaas, and the relevant architecture maintainers.

* Patch 3 removes the ARCH_SUPPORTS_MSI hidden kconfig boolean which is no longer needed now that we have weak functions for all MSI architecture-specific hooks.

This patch needs the Ack from Bjorn Helgaas, and the relevant architecture maintainers.

* Patch 4 adds a minimal msi_chip infrastructure, that allows a pci_bus to be connected to a msi_chip, and that provides default implementations of the architecture-specific MSI functions to use msi_chip.

This patch needs the Ack from Bjorn Helgaas.

* Patch 5 adds a small registry of msi_chip <-> of_node in the OF code.

This patch needs the Ack from Grant Likely or Rob Herring, and probably Bjorn Helgaas as well.

* Patch 6 makes some not very interesting preparation in the Armada 370/XP IRQ controller driver.

This patch needs the Ack from Thomas Gleixner.

* Patch 7 implements the MSI support in the Armada 370/XP IRQ controller driver. It registers an msi_chip using the msi_chip_add() function added in PATCH 3.

This patch needs the Ack from Thomas Gleixner.

* Patch 8 extends the ARM PCI core to expose ->add_bus() and ->remove_bus() hooks to PCI drivers. This was suggested by Bjorn Helgaas to allow the PCI driver to connected the PCI busses with the corresponding MSI chip.

This patch needs the Ack from Russell King.

* Patch 9 adjust the Armada 370/XP Device Tree to indicate that the MPIC is not only an interrupt-controller, but also an msi-controller.

This patch needs the Ack from Jason Cooper, Gregory Clement and/or Andrew Lunn, the Marvell Maintainers.

* Patch 10 adds MSI support in the Marvell PCIe host controller driver. The work to do here is minimal: get a reference to the msi-parent controller thanks to msi_chip_find_by_of_node(), and link it to the pci_bus structure before the bus gets enumerated.

This patch needs the Ack from Bjorn Helgaas.

* Patch 11 adjusts the Armada 370/XP Device Tree to add the msi-parent properties in the PCIe controller nodes.

This patch needs the Ack from Jason Cooper, Gregory Clement and/or Andrew Lunn, the Marvell Maintainers.

This version 5 follows:
* PATCH version 4 sent on July, 1st 2013
* PATCH version 3 sent on June, 19th 2013
* PATCH version 2 sent on June, 6th 2013
* RFC version 1 sent on March, 26th 2013

Changes since v4:

* Rebased on top of 3.11-rc1.

* Slightly rework the implementation of arch_setup_msi_irq(), arch_teardown_msi_irq and arch_msi_check_device() according to the suggestions of Bjorn Helgaas (PATCH 4)

* Make a few improvements to the msi_chip registry, according to the suggestion of Bjorn Helgaas and Rob Herring: coding style fixes, usage of mutex while traversing the list of msi_chip, usage of of_pci_msi_* prefix instead of just of_msi_*.

Changes since v3:

* Keep only a default_teardown_msi_irqs() function needed for the Xen PCI x86 code, and remove all other default_*() function and put the default behavior directly in the weak functions. Suggested by Thierry Redding and Bjorn Helgaas.

* Misc small improvements the MSI chip registry code: compiled only under CONFIG_PCI_MSI, functions exported to modules, addition of an of_msi_chip_remove() function, renaming of of_msi_chip_find_by_node() to of_find_msi_chip_by_node(), move the test of the "msi-controller" property to the of_msi_chip_add() function, renamed the list_head field from link to list, added dummy functions in the header files when !CONFIG_PCI_MSI && !CONFIG_OF. All suggested by Thierry Redding.

* Add a patch that entirely removes the ARCH_SUPPORTS_MSI, as we now have weak functions, so even if an arch doesn't actually use/support MSI, the code will build properly. Suggested by Thierry Redding.

* Added Device Tree binding documentation updates for the IRQ controller and the PCIe controller.

Changes since v2:

* Add an IRQ domain function that allows to allocate dynamically a free hwirq number from an IRQ domain, and create a virq mapping to it. It was suggested by Grant Likely in order to remove the hwirq allocation code from the IRQ driver itself. (PATCH 1)

* Separate the use of weak functions from the introduction of the msi_chip infrastructure, and use weak functions for all architecture-specific MSI hooks. Suggested by Bjorn Helgaas (PATCH 2).

* Move the msi_chip registry to drivers/of. Suggested by Bjorn Helgaas (PATCH 4).

* Use pcibios_add_bus() and pcibios_remove_bus() to connect the PCI busses to their msi_chip, as suggested by Bjorn Helgaas. Requires some ARM PCI core changes (PATCH 7), and then changes to the PCI driver itself (PATCH 9).

Thanks,

Thomas

Thierry Reding (1):
PCI: Introduce new MSI chip infrastructure

Thomas Petazzoni (10):
irqdomain: add irq_alloc_mapping() function
PCI: use weak functions for MSI arch-specific functions
PCI: remove ARCH_SUPPORTS_MSI kconfig option
of: pci: add registry of MSI chips
irqchip: armada-370-xp: properly request resources
irqchip: armada-370-xp: implement MSI support
ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci
ARM: mvebu: the MPIC now provides MSI controller features
PCI: mvebu: add support for MSI
ARM: mvebu: link PCIe controllers to the MSI controller

 .../devicetree/bindings/arm/armada-370-xp-mpic.txt |   3 +
 .../devicetree/bindings/pci/mvebu-pci.txt          |   3 +
 arch/arm/Kconfig                                   |   1 -
 arch/arm/boot/dts/armada-370-xp.dtsi               |   1 +
 arch/arm/boot/dts/armada-370.dtsi                  |   1 +
 arch/arm/boot/dts/armada-xp-mv78230.dtsi           |   1 +
 arch/arm/boot/dts/armada-xp-mv78260.dtsi           |   1 +
 arch/arm/boot/dts/armada-xp-mv78460.dtsi           |   1 +
 arch/arm/include/asm/mach/pci.h                    |   4 +
 arch/arm/kernel/bios32.c                           |  16 ++
 arch/ia64/Kconfig                                  |   1 -
 arch/mips/Kconfig                                  |   2 -
 arch/mips/include/asm/pci.h                        |   5 -
 arch/powerpc/Kconfig                               |   1 -
 arch/powerpc/include/asm/pci.h                     |   5 -
 arch/s390/Kconfig                                  |   1 -
 arch/s390/include/asm/pci.h                        |   4 -
 arch/sparc/Kconfig                                 |   1 -
 arch/tile/Kconfig                                  |   1 -
 arch/x86/Kconfig                                   |   1 -
 arch/x86/include/asm/pci.h                         |  28 ----
 arch/x86/kernel/x86_init.c                         |  21 +++
 drivers/irqchip/irq-armada-370-xp.c                | 161 ++++++++++++++++++++-
 drivers/of/of_pci.c                                |  45 ++++++
 drivers/pci/Kconfig                                |   4 -
 drivers/pci/host/pci-mvebu.c                       |  26 ++++
 drivers/pci/msi.c                                  |  66 ++++++---
 drivers/pci/probe.c                                |   1 +
 include/linux/irqdomain.h                          |   2 +
 include/linux/msi.h                                |  20 ++-
 include/linux/of_pci.h                             |  12 ++
 include/linux/pci.h                                |   1 +
 kernel/irq/irqdomain.c                             |  32 ++++
 33 files changed, 388 insertions(+), 85 deletions(-)
Signature · 1 line
1.8.1.2
#1 lore raw

PATCH v5 1/11 irqdomain: add irq_alloc_mapping() function

This commit extends the irqdomain subsystem with an irq_alloc_mapping() function which allows to let the irqdomain code find an available hwirq number in the range [ 0 ; domain size ] for the given domain, and create a virq mapping for it.

---
 include/linux/irqdomain.h |  2 ++
 kernel/irq/irqdomain.c    | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)
include/linux/irqdomain.h +2 -0
index c983ed1..1ffa336 100644
@@ -195,6 +195,8 @@ static inline unsigned int irq_linear_revmap(struct irq_domain *domain,
 extern unsigned int irq_find_mapping(struct irq_domain *host,
 				     irq_hw_number_t hwirq);
 extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
+extern unsigned int irq_alloc_mapping(struct irq_domain *host,
+				      irq_hw_number_t *hwirq);
 extern int irq_create_strict_mappings(struct irq_domain *domain,
 				      unsigned int irq_base,
 				      irq_hw_number_t hwirq_base, int count);
kernel/irq/irqdomain.c +32 -0
index 706724e..b9ddb94 100644
@@ -375,6 +375,38 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
 
 /**
+ * irq_alloc_mapping() - Allocate an irq for mapping
+ * @domain: domain to allocate the irq for or NULL for default domain
+ * @hwirq:  reference to the returned hwirq
+ *
+ * This routine are used for irq controllers which can choose the
+ * hardware interrupt number from a range [ 0 ; domain size ], such as
+ * is often the case with PCI MSI controllers. The function will
+ * returned the allocated hwirq number in the hwirq pointer, and the
+ * corresponding virq number as the return value.
+ */
+unsigned int irq_alloc_mapping(struct irq_domain *domain,
+			       irq_hw_number_t *out_hwirq)
+{
+	irq_hw_number_t hwirq;
+
+	pr_debug("irq_alloc_mapping(0x%p)\n", domain);
+
+	for (hwirq = 0; hwirq < domain->hwirq_max; hwirq++)
+		if (!irq_find_mapping(domain, hwirq))
+			break;
+
+	if (hwirq == domain->hwirq_max) {
+		pr_debug("-> no available hwirq found\n");
+		return 0;
+	}
+
+	*out_hwirq = hwirq;
+	return irq_create_mapping(domain, hwirq);
+}
+EXPORT_SYMBOL_GPL(irq_alloc_mapping);
+
+/**
  * irq_create_mapping() - Map a hardware interrupt into linux irq space
  * @domain: domain owning this hardware interrupt or NULL for default domain
  * @hwirq: hardware irq number in that domain space
Signature · 1 line
1.8.1.2
#2 lore raw

PATCH v5 1/11 irqdomain: add irq_alloc_mapping() function

Grant,

Would it be possible to get your opinion on the below patch? We have already discussed it in the past, and it was implemented according to your suggestions, so I guess it should be fine, but I'd like to have your formal Acked-by if possible, or additional comments. It is needed for the MSI support on Marvell PCIe, but now the Tegra people are also interested by it, and we hope to get this merged in 3.12.

Thanks!

Thomas

Quoted 67 lines · Thomas Petazzoni

This commit extends the irqdomain subsystem with an irq_alloc_mapping() function which allows to let the irqdomain code find an available hwirq number in the range [ 0 ; domain size ] for the given domain, and create a virq mapping for it.

---
 include/linux/irqdomain.h |  2 ++
 kernel/irq/irqdomain.c    | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)
include/linux/irqdomain.h +2 -0
index c983ed1..1ffa336 100644
@@ -195,6 +195,8 @@ static inline unsigned int irq_linear_revmap(struct irq_domain *domain,
 extern unsigned int irq_find_mapping(struct irq_domain *host,
 				     irq_hw_number_t hwirq);
 extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
+extern unsigned int irq_alloc_mapping(struct irq_domain *host,
+				      irq_hw_number_t *hwirq);
 extern int irq_create_strict_mappings(struct irq_domain *domain,
 				      unsigned int irq_base,
 				      irq_hw_number_t hwirq_base, int count);
kernel/irq/irqdomain.c +32 -0
index 706724e..b9ddb94 100644
@@ -375,6 +375,38 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
 
 /**
+ * irq_alloc_mapping() - Allocate an irq for mapping
+ * @domain: domain to allocate the irq for or NULL for default domain
+ * @hwirq:  reference to the returned hwirq
+ *
+ * This routine are used for irq controllers which can choose the
+ * hardware interrupt number from a range [ 0 ; domain size ], such as
+ * is often the case with PCI MSI controllers. The function will
+ * returned the allocated hwirq number in the hwirq pointer, and the
+ * corresponding virq number as the return value.
+ */
+unsigned int irq_alloc_mapping(struct irq_domain *domain,
+			       irq_hw_number_t *out_hwirq)
+{
+	irq_hw_number_t hwirq;
+
+	pr_debug("irq_alloc_mapping(0x%p)\n", domain);
+
+	for (hwirq = 0; hwirq < domain->hwirq_max; hwirq++)
+		if (!irq_find_mapping(domain, hwirq))
+			break;
+
+	if (hwirq == domain->hwirq_max) {
+		pr_debug("-> no available hwirq found\n");
+		return 0;
+	}
+
+	*out_hwirq = hwirq;
+	return irq_create_mapping(domain, hwirq);
+}
+EXPORT_SYMBOL_GPL(irq_alloc_mapping);
+
+/**
  * irq_create_mapping() - Map a hardware interrupt into linux irq space
  * @domain: domain owning this hardware interrupt or NULL for default domain
  * @hwirq: hardware irq number in that domain space
Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#3 lore raw

PATCH v5 1/11 irqdomain: add irq_alloc_mapping() function

In reply to Thomas Petazzoni
Quoted 42 lines · Thomas Petazzoni

This commit extends the irqdomain subsystem with an irq_alloc_mapping() function which allows to let the irqdomain code find an available hwirq number in the range [ 0 ; domain size ] for the given domain, and create a virq mapping for it.

---
 include/linux/irqdomain.h |  2 ++
 kernel/irq/irqdomain.c    | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)
include/linux/irqdomain.h +2 -0
index c983ed1..1ffa336 100644
@@ -195,6 +195,8 @@ static inline unsigned int irq_linear_revmap(struct irq_domain *domain,
 extern unsigned int irq_find_mapping(struct irq_domain *host,
 				     irq_hw_number_t hwirq);
 extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
+extern unsigned int irq_alloc_mapping(struct irq_domain *host,
+				      irq_hw_number_t *hwirq);
 extern int irq_create_strict_mappings(struct irq_domain *domain,
 				      unsigned int irq_base,
 				      irq_hw_number_t hwirq_base, int count);
kernel/irq/irqdomain.c +10 -0
index 706724e..b9ddb94 100644
@@ -375,6 +375,38 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
 
 /**
+ * irq_alloc_mapping() - Allocate an irq for mapping
+ * @domain: domain to allocate the irq for or NULL for default domain
+ * @hwirq:  reference to the returned hwirq
+ *
+ * This routine are used for irq controllers which can choose the
+ * hardware interrupt number from a range [ 0 ; domain size ], such as
+ * is often the case with PCI MSI controllers. The function will
+ * returned the allocated hwirq number in the hwirq pointer, and the
+ * corresponding virq number as the return value.
+ */

kernel/irq/irqdomain.c unsigned int irq_create_direct_mapping(struct irq_domain *domain) · line 397

Quoted 10 lines
kernel/irq/irqdomain.c +10 -0
+unsigned int irq_alloc_mapping(struct irq_domain *domain,
+			       irq_hw_number_t *out_hwirq)
+{
+	irq_hw_number_t hwirq;
+
+	pr_debug("irq_alloc_mapping(0x%p)\n", domain);
+
+	for (hwirq = 0; hwirq < domain->hwirq_max; hwirq++)
+		if (!irq_find_mapping(domain, hwirq))
+			break;

Okay, you can add my acked-by, but only if you change the above hunk to:

	for (hwirq = 0; hwirq < domain->revmap_size; hwirq++)
		if (domain->linear_revmap[hwirq] == 0)
			break;

In some cases hwirq_max will be set to ~0, which means calling irq_find_mapping about 4 billion times. Not safe. The above change prevents that problem, but it also means the function won't work for the tree map. A followup patch can be crafted to add support for the tree mapping.

kernel/irq/irqdomain.c unsigned int irq_create_direct_mapping(struct irq_domain *domain) · line 405

Quoted 8 lines
kernel/irq/irqdomain.c +8 -0
+
+	if (hwirq == domain->hwirq_max) {
+		pr_debug("-> no available hwirq found\n");
+		return 0;
+	}
+
+	*out_hwirq = hwirq;
+	return irq_create_mapping(domain, hwirq);

out_hwirq should *not* be modified if irq_create_mapping fails. You'll need to rework the above to:

	rc = irq_create_mapping(domain, hwirq);
	if (rc)
		*out_hwirq = hwirq;
	return rc;

When the above two issues are fixed:

Quoted 10 lines
kernel/irq/irqdomain.c +4 -0
+}
+EXPORT_SYMBOL_GPL(irq_alloc_mapping);
+
+/**
  * irq_create_mapping() - Map a hardware interrupt into linux irq space
  * @domain: domain owning this hardware interrupt or NULL for default domain
  * @hwirq: hardware irq number in that domain space
Signature · 1 line
1.8.1.2
#4 lore raw

PATCH v5 2/11 PCI: use weak functions for MSI arch-specific functions

In reply to Thomas Petazzoni

Until now, the MSI architecture-specific functions could be overloaded using a fairly complex set of #define and compile-time conditionals. In order to prepare for the introduction of the msi_chip infrastructure, it is desirable to switch all those functions to use the 'weak' mechanism. This commit converts all the architectures that were overidding those MSI functions to use the new strategy.

Note that we keep a separate, non-weak, function default_teardown_msi_irqs() for the default behavior of the arch_teardown_msi_irqs(), as the default behavior is needed by the Xen x86 PCI code.

Cc Benjamin Herrenschmidt <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc linuxppc-dev at lists.ozlabs.org
Cc Martin Schwidefsky <[email protected]>
Cc Heiko Carstens <[email protected]>
Cc linux390 at de.ibm.com
Cc linux-s390 at vger.kernel.org
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc x86 at kernel.org
Cc Russell King <[email protected]>
Cc Tony Luck <[email protected]>
Cc Fenghua Yu <[email protected]>
Cc linux-ia64 at vger.kernel.org
Cc Ralf Baechle <[email protected]>
Cc linux-mips at linux-mips.org
Cc David S. Miller <[email protected]>
Cc sparclinux at vger.kernel.org
Cc Chris Metcalf <[email protected]>
---
 arch/mips/include/asm/pci.h    |  5 -----
 arch/powerpc/include/asm/pci.h |  5 -----
 arch/s390/include/asm/pci.h    |  4 ----
 arch/x86/include/asm/pci.h     | 28 --------------------------
 arch/x86/kernel/x86_init.c     | 21 ++++++++++++++++++++
 drivers/pci/msi.c              | 45 +++++++++++++++++++-----------------------
 include/linux/msi.h            |  7 ++++++-
 7 files changed, 47 insertions(+), 68 deletions(-)
arch/mips/include/asm/pci.h +0 -5
index fa8e0aa..f194c08 100644
@@ -136,11 +136,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 	return channel ? 15 : 14;
 }
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-/* MSI arch hook for OCTEON */
-#define arch_setup_msi_irqs arch_setup_msi_irqs
-#endif
-
 extern char * (*pcibios_plat_setup)(char *str);
 
 #ifdef CONFIG_OF
arch/powerpc/include/asm/pci.h +0 -5
index 6653f27..95145a1 100644
@@ -113,11 +113,6 @@ extern int pci_domain_nr(struct pci_bus *bus);
 /* Decide whether to display the domain number in /proc */
 extern int pci_proc_domain(struct pci_bus *bus);
 
-/* MSI arch hooks */
-#define arch_setup_msi_irqs arch_setup_msi_irqs
-#define arch_teardown_msi_irqs arch_teardown_msi_irqs
-#define arch_msi_check_device arch_msi_check_device
-
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
arch/s390/include/asm/pci.h +0 -4
index 6e577ba..262b91b 100644
@@ -21,10 +21,6 @@ void pci_iounmap(struct pci_dev *, void __iomem *);
 int pci_domain_nr(struct pci_bus *);
 int pci_proc_domain(struct pci_bus *);
 
-/* MSI arch hooks */
-#define arch_setup_msi_irqs	arch_setup_msi_irqs
-#define arch_teardown_msi_irqs	arch_teardown_msi_irqs
-
 #define ZPCI_BUS_NR			0	/* default bus number */
 #define ZPCI_DEVFN			0	/* default device number */
 
arch/x86/include/asm/pci.h +0 -28
index d9e9e6c..8c61de0 100644
@@ -100,29 +100,6 @@ static inline void early_quirks(void) { }
 extern void pci_iommu_alloc(void);
 
 #ifdef CONFIG_PCI_MSI
-/* MSI arch specific hooks */
-static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-	return x86_msi.setup_msi_irqs(dev, nvec, type);
-}
-
-static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
-{
-	x86_msi.teardown_msi_irqs(dev);
-}
-
-static inline void x86_teardown_msi_irq(unsigned int irq)
-{
-	x86_msi.teardown_msi_irq(irq);
-}
-static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq)
-{
-	x86_msi.restore_msi_irqs(dev, irq);
-}
-#define arch_setup_msi_irqs x86_setup_msi_irqs
-#define arch_teardown_msi_irqs x86_teardown_msi_irqs
-#define arch_teardown_msi_irq x86_teardown_msi_irq
-#define arch_restore_msi_irqs x86_restore_msi_irqs
 /* implemented in arch/x86/kernel/apic/io_apic. */
 struct msi_desc;
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
@@ -130,11 +107,6 @@ void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev, int irq);
 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
 		  unsigned int irq_base, unsigned int irq_offset);
-/* default to the implementation in drivers/lib/msi.c */
-#define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
-#define HAVE_DEFAULT_MSI_RESTORE_IRQS
-void default_teardown_msi_irqs(struct pci_dev *dev);
-void default_restore_msi_irqs(struct pci_dev *dev, int irq);
 #else
 #define native_setup_msi_irqs		NULL
 #define native_teardown_msi_irq		NULL
arch/x86/kernel/x86_init.c +21 -0
index 45a14db..a2b189c 100644
@@ -116,6 +116,27 @@ struct x86_msi_ops x86_msi = {
 	.setup_hpet_msi		= default_setup_hpet_msi,
 };
 
+/* MSI arch specific hooks */
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	return x86_msi.setup_msi_irqs(dev, nvec, type);
+}
+
+void arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	x86_msi.teardown_msi_irqs(dev);
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	x86_msi.teardown_msi_irq(irq);
+}
+
+void arch_restore_msi_irqs(struct pci_dev *dev, int irq)
+{
+	x86_msi.restore_msi_irqs(dev, irq);
+}
+
 struct x86_io_apic_ops x86_io_apic_ops = {
 	.init			= native_io_apic_init_mappings,
 	.read			= native_io_apic_read,
drivers/pci/msi.c +20 -25

76 lines not on this page · raw message

include/linux/msi.h +6 -1
index ee66f3a..18870b0 100644
@@ -51,12 +51,17 @@ struct msi_desc {
 };
 
 /*
- * The arch hook for setup up msi irqs
+ * The arch hooks to setup up msi irqs. Those functions are
+ * implemented as weak symbols so that they /can/ be overriden by
+ * architecture specific code if needed.
  */
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void arch_teardown_msi_irqs(struct pci_dev *dev);
 int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
+void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
+
+void default_teardown_msi_irqs(struct pci_dev *dev);
 
 #endif /* LINUX_MSI_H */
Signature · 1 line
1.8.1.2
#5 lore raw

PATCH v5 2/11 PCI: use weak functions for MSI arch-specific functions

Quoted 33 lines · Thomas Petazzoni

Until now, the MSI architecture-specific functions could be overloaded using a fairly complex set of #define and compile-time conditionals. In order to prepare for the introduction of the msi_chip infrastructure, it is desirable to switch all those functions to use the 'weak' mechanism. This commit converts all the architectures that were overidding those MSI functions to use the new strategy.

Note that we keep a separate, non-weak, function default_teardown_msi_irqs() for the default behavior of the arch_teardown_msi_irqs(), as the default behavior is needed by the Xen x86 PCI code.

Cc Benjamin Herrenschmidt <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc linuxppc-dev at lists.ozlabs.org
Cc Martin Schwidefsky <[email protected]>
Cc Heiko Carstens <[email protected]>
Cc linux390 at de.ibm.com
Cc linux-s390 at vger.kernel.org
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc x86 at kernel.org
Cc Russell King <[email protected]>
Cc Tony Luck <[email protected]>
Cc Fenghua Yu <[email protected]>
Cc linux-ia64 at vger.kernel.org
Cc Ralf Baechle <[email protected]>
Cc linux-mips at linux-mips.org
Cc David S. Miller <[email protected]>
Cc sparclinux at vger.kernel.org
Cc Chris Metcalf <[email protected]>
Quoted 9 lines
---
 arch/mips/include/asm/pci.h    |  5 -----
 arch/powerpc/include/asm/pci.h |  5 -----
 arch/s390/include/asm/pci.h    |  4 ----
 arch/x86/include/asm/pci.h     | 28 --------------------------
 arch/x86/kernel/x86_init.c     | 21 ++++++++++++++++++++
 drivers/pci/msi.c              | 45 +++++++++++++++++++-----------------------
 include/linux/msi.h            |  7 ++++++-
 7 files changed, 47 insertions(+), 68 deletions(-)

Bjorn,

any chance that we can get your Acked-by on this?

Thierry

Quoted 236 lines
arch/mips/include/asm/pci.h +0 -5
index fa8e0aa..f194c08 100644
@@ -136,11 +136,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 	return channel ? 15 : 14;
 }
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-/* MSI arch hook for OCTEON */
-#define arch_setup_msi_irqs arch_setup_msi_irqs
-#endif
-
 extern char * (*pcibios_plat_setup)(char *str);
 
 #ifdef CONFIG_OF
arch/powerpc/include/asm/pci.h +0 -5
index 6653f27..95145a1 100644
@@ -113,11 +113,6 @@ extern int pci_domain_nr(struct pci_bus *bus);
 /* Decide whether to display the domain number in /proc */
 extern int pci_proc_domain(struct pci_bus *bus);
 
-/* MSI arch hooks */
-#define arch_setup_msi_irqs arch_setup_msi_irqs
-#define arch_teardown_msi_irqs arch_teardown_msi_irqs
-#define arch_msi_check_device arch_msi_check_device
-
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
arch/s390/include/asm/pci.h +0 -4
index 6e577ba..262b91b 100644
@@ -21,10 +21,6 @@ void pci_iounmap(struct pci_dev *, void __iomem *);
 int pci_domain_nr(struct pci_bus *);
 int pci_proc_domain(struct pci_bus *);
 
-/* MSI arch hooks */
-#define arch_setup_msi_irqs	arch_setup_msi_irqs
-#define arch_teardown_msi_irqs	arch_teardown_msi_irqs
-
 #define ZPCI_BUS_NR			0	/* default bus number */
 #define ZPCI_DEVFN			0	/* default device number */
 
arch/x86/include/asm/pci.h +0 -28
index d9e9e6c..8c61de0 100644
@@ -100,29 +100,6 @@ static inline void early_quirks(void) { }
 extern void pci_iommu_alloc(void);
 
 #ifdef CONFIG_PCI_MSI
-/* MSI arch specific hooks */
-static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-	return x86_msi.setup_msi_irqs(dev, nvec, type);
-}
-
-static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
-{
-	x86_msi.teardown_msi_irqs(dev);
-}
-
-static inline void x86_teardown_msi_irq(unsigned int irq)
-{
-	x86_msi.teardown_msi_irq(irq);
-}
-static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq)
-{
-	x86_msi.restore_msi_irqs(dev, irq);
-}
-#define arch_setup_msi_irqs x86_setup_msi_irqs
-#define arch_teardown_msi_irqs x86_teardown_msi_irqs
-#define arch_teardown_msi_irq x86_teardown_msi_irq
-#define arch_restore_msi_irqs x86_restore_msi_irqs
 /* implemented in arch/x86/kernel/apic/io_apic. */
 struct msi_desc;
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
@@ -130,11 +107,6 @@ void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev, int irq);
 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
 		  unsigned int irq_base, unsigned int irq_offset);
-/* default to the implementation in drivers/lib/msi.c */
-#define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
-#define HAVE_DEFAULT_MSI_RESTORE_IRQS
-void default_teardown_msi_irqs(struct pci_dev *dev);
-void default_restore_msi_irqs(struct pci_dev *dev, int irq);
 #else
 #define native_setup_msi_irqs		NULL
 #define native_teardown_msi_irq		NULL
arch/x86/kernel/x86_init.c +21 -0
index 45a14db..a2b189c 100644
@@ -116,6 +116,27 @@ struct x86_msi_ops x86_msi = {
 	.setup_hpet_msi		= default_setup_hpet_msi,
 };
 
+/* MSI arch specific hooks */
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	return x86_msi.setup_msi_irqs(dev, nvec, type);
+}
+
+void arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	x86_msi.teardown_msi_irqs(dev);
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	x86_msi.teardown_msi_irq(irq);
+}
+
+void arch_restore_msi_irqs(struct pci_dev *dev, int irq)
+{
+	x86_msi.restore_msi_irqs(dev, irq);
+}
+
 struct x86_io_apic_ops x86_io_apic_ops = {
 	.init			= native_io_apic_init_mappings,
 	.read			= native_io_apic_read,
drivers/pci/msi.c +20 -25
index aca7578..aa2f697 100644
@@ -30,20 +30,21 @@ static int pci_msi_enable = 1;
 
 /* Arch hooks */
 
-#ifndef arch_msi_check_device
-int arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-	return 0;
+	return -EINVAL;
 }
-#endif
 
-#ifndef arch_setup_msi_irqs
-# define arch_setup_msi_irqs default_setup_msi_irqs
-# define HAVE_DEFAULT_MSI_SETUP_IRQS
-#endif
+void __weak arch_teardown_msi_irq(unsigned int irq)
+{
+}
 
-#ifdef HAVE_DEFAULT_MSI_SETUP_IRQS
-int default_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+	return 0;
+}
+
+int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
 	struct msi_desc *entry;
 	int ret;
@@ -65,14 +66,11 @@ int default_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 
 	return 0;
 }
-#endif
 
-#ifndef arch_teardown_msi_irqs
-# define arch_teardown_msi_irqs default_teardown_msi_irqs
-# define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
-#endif
-
-#ifdef HAVE_DEFAULT_MSI_TEARDOWN_IRQS
+/*
+ * We have a default implementation available as a separate non-weak
+ * function, as it is used by the Xen x86 PCI code
+ */
 void default_teardown_msi_irqs(struct pci_dev *dev)
 {
 	struct msi_desc *entry;
@@ -89,15 +87,13 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
 			arch_teardown_msi_irq(entry->irq + i);
 	}
 }
-#endif
 
-#ifndef arch_restore_msi_irqs
-# define arch_restore_msi_irqs default_restore_msi_irqs
-# define HAVE_DEFAULT_MSI_RESTORE_IRQS
-#endif
+void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	return default_teardown_msi_irqs(dev);
+}
 
-#ifdef HAVE_DEFAULT_MSI_RESTORE_IRQS
-void default_restore_msi_irqs(struct pci_dev *dev, int irq)
+void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq)
 {
 	struct msi_desc *entry;
 
@@ -114,7 +110,6 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)
 	if (entry)
 		write_msi_msg(irq, &entry->msg);
 }
-#endif
 
 static void msi_set_enable(struct pci_dev *dev, int enable)
 {
include/linux/msi.h +6 -1
index ee66f3a..18870b0 100644
@@ -51,12 +51,17 @@ struct msi_desc {
 };
 
 /*
- * The arch hook for setup up msi irqs
+ * The arch hooks to setup up msi irqs. Those functions are
+ * implemented as weak symbols so that they /can/ be overriden by
+ * architecture specific code if needed.
  */
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void arch_teardown_msi_irqs(struct pci_dev *dev);
 int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
+void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
+
+void default_teardown_msi_irqs(struct pci_dev *dev);
 
 #endif /* LINUX_MSI_H */
Signature · 1 line
1.8.1.2

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130725/ea958105/attachment-0001.sig>

maintainer
#6 lore raw

PATCH v5 2/11 PCI: use weak functions for MSI arch-specific functions

In reply to Thomas Petazzoni
Quoted 25 lines · Thomas Petazzoni

Until now, the MSI architecture-specific functions could be overloaded using a fairly complex set of #define and compile-time conditionals. In order to prepare for the introduction of the msi_chip infrastructure, it is desirable to switch all those functions to use the 'weak' mechanism. This commit converts all the architectures that were overidding those MSI functions to use the new strategy.

Note that we keep a separate, non-weak, function default_teardown_msi_irqs() for the default behavior of the arch_teardown_msi_irqs(), as the default behavior is needed by the Xen x86 PCI code.

Cc Benjamin Herrenschmidt <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc linuxppc-dev at lists.ozlabs.org
Cc Martin Schwidefsky <[email protected]>
Cc Heiko Carstens <[email protected]>
Cc linux390 at de.ibm.com
Cc linux-s390 at vger.kernel.org
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc x86 at kernel.org
Cc Russell King <[email protected]>
Quoted 8 lines
Cc Tony Luck <[email protected]>
Cc Fenghua Yu <[email protected]>
Cc linux-ia64 at vger.kernel.org
Cc Ralf Baechle <[email protected]>
Cc linux-mips at linux-mips.org
Cc David S. Miller <[email protected]>
Cc sparclinux at vger.kernel.org
Cc Chris Metcalf <[email protected]>
Quoted 245 lines
---
 arch/mips/include/asm/pci.h    |  5 -----
 arch/powerpc/include/asm/pci.h |  5 -----
 arch/s390/include/asm/pci.h    |  4 ----
 arch/x86/include/asm/pci.h     | 28 --------------------------
 arch/x86/kernel/x86_init.c     | 21 ++++++++++++++++++++
 drivers/pci/msi.c              | 45 +++++++++++++++++++-----------------------
 include/linux/msi.h            |  7 ++++++-
 7 files changed, 47 insertions(+), 68 deletions(-)
arch/mips/include/asm/pci.h +0 -5
index fa8e0aa..f194c08 100644
@@ -136,11 +136,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
        return channel ? 15 : 14;
 }
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-/* MSI arch hook for OCTEON */
-#define arch_setup_msi_irqs arch_setup_msi_irqs
-#endif
-
 extern char * (*pcibios_plat_setup)(char *str);
 
 #ifdef CONFIG_OF
arch/powerpc/include/asm/pci.h +0 -5
index 6653f27..95145a1 100644
@@ -113,11 +113,6 @@ extern int pci_domain_nr(struct pci_bus *bus);
 /* Decide whether to display the domain number in /proc */
 extern int pci_proc_domain(struct pci_bus *bus);
 
-/* MSI arch hooks */
-#define arch_setup_msi_irqs arch_setup_msi_irqs
-#define arch_teardown_msi_irqs arch_teardown_msi_irqs
-#define arch_msi_check_device arch_msi_check_device
-
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
arch/s390/include/asm/pci.h +0 -4
index 6e577ba..262b91b 100644
@@ -21,10 +21,6 @@ void pci_iounmap(struct pci_dev *, void __iomem *);
 int pci_domain_nr(struct pci_bus *);
 int pci_proc_domain(struct pci_bus *);
 
-/* MSI arch hooks */
-#define arch_setup_msi_irqs    arch_setup_msi_irqs
-#define arch_teardown_msi_irqs arch_teardown_msi_irqs
-
 #define ZPCI_BUS_NR                    0       /* default bus number */
 #define ZPCI_DEVFN                     0       /* default device number */
 
arch/x86/include/asm/pci.h +0 -28
index d9e9e6c..8c61de0 100644
@@ -100,29 +100,6 @@ static inline void early_quirks(void) { }
 extern void pci_iommu_alloc(void);
 
 #ifdef CONFIG_PCI_MSI
-/* MSI arch specific hooks */
-static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-       return x86_msi.setup_msi_irqs(dev, nvec, type);
-}
-
-static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
-{
-       x86_msi.teardown_msi_irqs(dev);
-}
-
-static inline void x86_teardown_msi_irq(unsigned int irq)
-{
-       x86_msi.teardown_msi_irq(irq);
-}
-static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq)
-{
-       x86_msi.restore_msi_irqs(dev, irq);
-}
-#define arch_setup_msi_irqs x86_setup_msi_irqs
-#define arch_teardown_msi_irqs x86_teardown_msi_irqs
-#define arch_teardown_msi_irq x86_teardown_msi_irq
-#define arch_restore_msi_irqs x86_restore_msi_irqs
 /* implemented in arch/x86/kernel/apic/io_apic. */
 struct msi_desc;
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
@@ -130,11 +107,6 @@ void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev, int irq);
 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
                  unsigned int irq_base, unsigned int irq_offset);
-/* default to the implementation in drivers/lib/msi.c */
-#define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
-#define HAVE_DEFAULT_MSI_RESTORE_IRQS
-void default_teardown_msi_irqs(struct pci_dev *dev);
-void default_restore_msi_irqs(struct pci_dev *dev, int irq);
 #else
 #define native_setup_msi_irqs          NULL
 #define native_teardown_msi_irq                NULL
arch/x86/kernel/x86_init.c +21 -0
index 45a14db..a2b189c 100644
@@ -116,6 +116,27 @@ struct x86_msi_ops x86_msi = {
        .setup_hpet_msi         = default_setup_hpet_msi,
 };
 
+/* MSI arch specific hooks */
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+       return x86_msi.setup_msi_irqs(dev, nvec, type);
+}
+
+void arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+       x86_msi.teardown_msi_irqs(dev);
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+       x86_msi.teardown_msi_irq(irq);
+}
+
+void arch_restore_msi_irqs(struct pci_dev *dev, int irq)
+{
+       x86_msi.restore_msi_irqs(dev, irq);
+}
+
 struct x86_io_apic_ops x86_io_apic_ops = {
        .init                   = native_io_apic_init_mappings,
        .read                   = native_io_apic_read,
drivers/pci/msi.c +20 -25
index aca7578..aa2f697 100644
@@ -30,20 +30,21 @@ static int pci_msi_enable = 1;
 
 /* Arch hooks */
 
-#ifndef arch_msi_check_device
-int arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-       return 0;
+       return -EINVAL;
 }
-#endif
 
-#ifndef arch_setup_msi_irqs
-# define arch_setup_msi_irqs default_setup_msi_irqs
-# define HAVE_DEFAULT_MSI_SETUP_IRQS
-#endif
+void __weak arch_teardown_msi_irq(unsigned int irq)
+{
+}
 
-#ifdef HAVE_DEFAULT_MSI_SETUP_IRQS
-int default_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+       return 0;
+}
+
+int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
        struct msi_desc *entry;
        int ret;
@@ -65,14 +66,11 @@ int default_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 
        return 0;
 }
-#endif
 
-#ifndef arch_teardown_msi_irqs
-# define arch_teardown_msi_irqs default_teardown_msi_irqs
-# define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
-#endif
-
-#ifdef HAVE_DEFAULT_MSI_TEARDOWN_IRQS
+/*
+ * We have a default implementation available as a separate non-weak
+ * function, as it is used by the Xen x86 PCI code
+ */
 void default_teardown_msi_irqs(struct pci_dev *dev)
 {
        struct msi_desc *entry;
@@ -89,15 +87,13 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
                        arch_teardown_msi_irq(entry->irq + i);
        }
 }
-#endif
 
-#ifndef arch_restore_msi_irqs
-# define arch_restore_msi_irqs default_restore_msi_irqs
-# define HAVE_DEFAULT_MSI_RESTORE_IRQS
-#endif
+void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+       return default_teardown_msi_irqs(dev);
+}
 
-#ifdef HAVE_DEFAULT_MSI_RESTORE_IRQS
-void default_restore_msi_irqs(struct pci_dev *dev, int irq)
+void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq)
 {
        struct msi_desc *entry;
 
@@ -114,7 +110,6 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)
        if (entry)
                write_msi_msg(irq, &entry->msg);
 }
-#endif
 
 static void msi_set_enable(struct pci_dev *dev, int enable)
 {
include/linux/msi.h +6 -2
index ee66f3a..18870b0 100644
@@ -51,12 +51,17 @@ struct msi_desc {
 };
 
 /*
- * The arch hook for setup up msi irqs
+ * The arch hooks to setup up msi irqs. Those functions are
+ * implemented as weak symbols so that they /can/ be overriden by
+ * architecture specific code if needed.
  */
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void arch_teardown_msi_irqs(struct pci_dev *dev);
 int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
+void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
+
+void default_teardown_msi_irqs(struct pci_dev *dev);
 
 #endif /* LINUX_MSI_H */
--

1.8.1.2

#7 lore raw

PATCH v5 3/11 PCI: remove ARCH_SUPPORTS_MSI kconfig option

In reply to Thomas Petazzoni

Now that we have weak versions for each of the PCI MSI architecture functions, we can actually build the MSI support for all platforms, regardless of whether they provide or not architecture-specific versions of those functions. For this reason, the ARCH_SUPPORTS_MSI hidden kconfig boolean becomes useless, and this patch gets rid of it.

Cc Benjamin Herrenschmidt <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc linuxppc-dev at lists.ozlabs.org
Cc Martin Schwidefsky <[email protected]>
Cc Heiko Carstens <[email protected]>
Cc linux390 at de.ibm.com
Cc linux-s390 at vger.kernel.org
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc x86 at kernel.org
Cc Russell King <[email protected]>
Cc Tony Luck <[email protected]>
Cc Fenghua Yu <[email protected]>
Cc linux-ia64 at vger.kernel.org
Cc Ralf Baechle <[email protected]>
Cc linux-mips at linux-mips.org
Cc David S. Miller <[email protected]>
Cc sparclinux at vger.kernel.org
Cc Chris Metcalf <[email protected]>
---
 arch/arm/Kconfig     | 1 -
 arch/ia64/Kconfig    | 1 -
 arch/mips/Kconfig    | 2 --
 arch/powerpc/Kconfig | 1 -
 arch/s390/Kconfig    | 1 -
 arch/sparc/Kconfig   | 1 -
 arch/tile/Kconfig    | 1 -
 arch/x86/Kconfig     | 1 -
 drivers/pci/Kconfig  | 4 ----
 9 files changed, 13 deletions(-)
arch/arm/Kconfig +0 -1
index ba412e0..b173c1d 100644
@@ -441,7 +441,6 @@ config ARCH_NETX
 config ARCH_IOP13XX
 	bool "IOP13xx-based"
 	depends on MMU
-	select ARCH_SUPPORTS_MSI
 	select CPU_XSC3
 	select NEED_MACH_MEMORY_H
 	select NEED_RET_TO_USER
arch/ia64/Kconfig +0 -1
index 5a768ad..098602b 100644
@@ -9,7 +9,6 @@ config IA64
 	select PCI if (!IA64_HP_SIM)
 	select ACPI if (!IA64_HP_SIM)
 	select PM if (!IA64_HP_SIM)
-	select ARCH_SUPPORTS_MSI
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select HAVE_IDE
 	select HAVE_OPROFILE
arch/mips/Kconfig +0 -2
index 4758a8f..00b2698 100644
@@ -726,7 +726,6 @@ config CAVIUM_OCTEON_SOC
 	select SYS_HAS_CPU_CAVIUM_OCTEON
 	select SWAP_IO_SPACE
 	select HW_HAS_PCI
-	select ARCH_SUPPORTS_MSI
 	select ZONE_DMA32
 	select USB_ARCH_HAS_OHCI
 	select USB_ARCH_HAS_EHCI
@@ -762,7 +761,6 @@ config NLM_XLR_BOARD
 	select CEVT_R4K
 	select CSRC_R4K
 	select IRQ_CPU
-	select ARCH_SUPPORTS_MSI
 	select ZONE_DMA32 if 64BIT
 	select SYNC_R4K
 	select SYS_HAS_EARLY_PRINTK
arch/powerpc/Kconfig +0 -1
index 3bf72cd..183a165 100644
@@ -727,7 +727,6 @@ config PCI
 	default y if !40x && !CPM2 && !8xx && !PPC_83xx \
 		&& !PPC_85xx && !PPC_86xx && !GAMECUBE_COMMON
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
-	select ARCH_SUPPORTS_MSI
 	select GENERIC_PCI_IOMAP
 	help
 	  Find out whether your system includes a PCI bus. PCI is the name of
arch/s390/Kconfig +0 -1
index 22f75b5..e9982a3 100644
@@ -428,7 +428,6 @@ menuconfig PCI
 	bool "PCI support"
 	default n
 	depends on 64BIT
-	select ARCH_SUPPORTS_MSI
 	select PCI_MSI
 	help
 	  Enable PCI support.
arch/sparc/Kconfig +0 -1
index a00cbd3..1570ad2 100644
@@ -52,7 +52,6 @@ config SPARC32
 
 config SPARC64
 	def_bool 64BIT
-	select ARCH_SUPPORTS_MSI
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_GRAPH_FP_TEST
arch/tile/Kconfig +0 -1
index 24565a7..74dff90 100644
@@ -380,7 +380,6 @@ config PCI
 	select PCI_DOMAINS
 	select GENERIC_PCI_IOMAP
 	select TILE_GXIO_TRIO if TILEGX
-	select ARCH_SUPPORTS_MSI if TILEGX
 	select PCI_MSI if TILEGX
 	---help---
 	  Enable PCI root complex support, so PCIe endpoint devices can
arch/x86/Kconfig +0 -1
index b32ebf9..5db62ef 100644
@@ -2014,7 +2014,6 @@ menu "Bus options (PCI etc.)"
 config PCI
 	bool "PCI support"
 	default y
-	select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
 	---help---
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
drivers/pci/Kconfig +0 -4
index 81944fb..b6a99f7 100644
@@ -1,13 +1,9 @@
 #
 # PCI configuration
 #
-config ARCH_SUPPORTS_MSI
-	bool
-
 config PCI_MSI
 	bool "Message Signaled Interrupts (MSI and MSI-X)"
 	depends on PCI
-	depends on ARCH_SUPPORTS_MSI
 	help
 	   This allows device drivers to enable MSI (Message Signaled
 	   Interrupts).  Message Signaled Interrupts enable a device to
Signature · 1 line
1.8.1.2
#8 lore raw

PATCH v5 4/11 PCI: Introduce new MSI chip infrastructure

In reply to Thomas Petazzoni

From: Thierry Reding <[email protected]>

The new struct msi_chip is used to associated an MSI controller with a PCI bus. It is automatically handed down from the root to its children during bus enumeration.

This patch provides default (weak) implementations for the architecture- specific MSI functions (arch_setup_msi_irq(), arch_teardown_msi_irq() and arch_msi_check_device()) which check if a PCI device's bus has an attached MSI chip and forward the call appropriately.

---
 drivers/pci/msi.c   | 27 +++++++++++++++++++++++++--
 drivers/pci/probe.c |  1 +
 include/linux/msi.h | 11 +++++++++++
 include/linux/pci.h |  1 +
 4 files changed, 38 insertions(+), 2 deletions(-)
drivers/pci/msi.c +25 -2
index aa2f697..d5b6378 100644
@@ -32,16 +32,39 @@ static int pci_msi_enable = 1;
 
 int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-	return -EINVAL;
+	struct msi_chip *chip = dev->bus->msi;
+	int err;
+
+	if (!chip || !chip->setup_irq)
+		return -EINVAL;
+
+	err = chip->setup_irq(chip, dev, desc);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_data(desc->irq, chip);
+
+	return 0;
 }
 
 void __weak arch_teardown_msi_irq(unsigned int irq)
 {
+	struct msi_chip *chip = irq_get_chip_data(irq);
+
+	if (!chip || !chip->teardown_irq)
+		return;
+
+	chip->teardown_irq(chip, irq);
 }
 
 int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
 {
-	return 0;
+	struct msi_chip *chip = dev->bus->msi;
+
+	if (!chip || !chip->check_device)
+		return 0;
+
+	return chip->check_device(chip, dev, nvec, type);
 }
 
 int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
drivers/pci/probe.c +1 -0
index 46ada5c..b8eaa81 100644
@@ -666,6 +666,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 
 	child->parent = parent;
 	child->ops = parent->ops;
+	child->msi = parent->msi;
 	child->sysdata = parent->sysdata;
 	child->bus_flags = parent->bus_flags;
 
include/linux/msi.h +11 -0
index 18870b0..cbf5d05 100644
@@ -64,4 +64,15 @@ void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
 
 void default_teardown_msi_irqs(struct pci_dev *dev);
 
+struct msi_chip {
+	struct module *owner;
+	struct device *dev;
+
+	int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
+			 struct msi_desc *desc);
+	void (*teardown_irq)(struct msi_chip *chip, unsigned int irq);
+	int (*check_device)(struct msi_chip *chip, struct pci_dev *dev,
+			    int nvec, int type);
+};
+
 #endif /* LINUX_MSI_H */
include/linux/pci.h +1 -0
index 0fd1f15..4044e3c 100644
@@ -433,6 +433,7 @@ struct pci_bus {
 	struct resource busn_res;	/* bus numbers routed to this bus */
 
 	struct pci_ops	*ops;		/* configuration access functions */
+	struct msi_chip	*msi;		/* MSI controller */
 	void		*sysdata;	/* hook for sys-specific extension */
 	struct proc_dir_entry *procdir;	/* directory entry in /proc/bus/pci */
 
Signature · 1 line
1.8.1.2
#9 lore raw

PATCH v5 4/11 PCI: Introduce new MSI chip infrastructure

Quoted 11 lines · Thomas Petazzoni

From: Thierry Reding <[email protected]>

The new struct msi_chip is used to associated an MSI controller with a PCI bus. It is automatically handed down from the root to its children during bus enumeration.

This patch provides default (weak) implementations for the architecture- specific MSI functions (arch_setup_msi_irq(), arch_teardown_msi_irq() and arch_msi_check_device()) which check if a PCI device's bus has an attached MSI chip and forward the call appropriately.

Quoted 8 lines
---
 drivers/pci/msi.c   | 27 +++++++++++++++++++++++++--
 drivers/pci/probe.c |  1 +
 include/linux/msi.h | 11 +++++++++++
 include/linux/pci.h |  1 +
 4 files changed, 38 insertions(+), 2 deletions(-)

Bjorn,

We'll need this as part of a stable branch as well, so any chance you could ack it?

Thierry

Quoted 93 lines
drivers/pci/msi.c +25 -2
index aa2f697..d5b6378 100644
@@ -32,16 +32,39 @@ static int pci_msi_enable = 1;
 
 int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-	return -EINVAL;
+	struct msi_chip *chip = dev->bus->msi;
+	int err;
+
+	if (!chip || !chip->setup_irq)
+		return -EINVAL;
+
+	err = chip->setup_irq(chip, dev, desc);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_data(desc->irq, chip);
+
+	return 0;
 }
 
 void __weak arch_teardown_msi_irq(unsigned int irq)
 {
+	struct msi_chip *chip = irq_get_chip_data(irq);
+
+	if (!chip || !chip->teardown_irq)
+		return;
+
+	chip->teardown_irq(chip, irq);
 }
 
 int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
 {
-	return 0;
+	struct msi_chip *chip = dev->bus->msi;
+
+	if (!chip || !chip->check_device)
+		return 0;
+
+	return chip->check_device(chip, dev, nvec, type);
 }
 
 int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
drivers/pci/probe.c +1 -0
index 46ada5c..b8eaa81 100644
@@ -666,6 +666,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 
 	child->parent = parent;
 	child->ops = parent->ops;
+	child->msi = parent->msi;
 	child->sysdata = parent->sysdata;
 	child->bus_flags = parent->bus_flags;
 
include/linux/msi.h +11 -0
index 18870b0..cbf5d05 100644
@@ -64,4 +64,15 @@ void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
 
 void default_teardown_msi_irqs(struct pci_dev *dev);
 
+struct msi_chip {
+	struct module *owner;
+	struct device *dev;
+
+	int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
+			 struct msi_desc *desc);
+	void (*teardown_irq)(struct msi_chip *chip, unsigned int irq);
+	int (*check_device)(struct msi_chip *chip, struct pci_dev *dev,
+			    int nvec, int type);
+};
+
 #endif /* LINUX_MSI_H */
include/linux/pci.h +1 -0
index 0fd1f15..4044e3c 100644
@@ -433,6 +433,7 @@ struct pci_bus {
 	struct resource busn_res;	/* bus numbers routed to this bus */
 
 	struct pci_ops	*ops;		/* configuration access functions */
+	struct msi_chip	*msi;		/* MSI controller */
 	void		*sysdata;	/* hook for sys-specific extension */
 	struct proc_dir_entry *procdir;	/* directory entry in /proc/bus/pci */
 
Signature · 1 line
1.8.1.2

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130725/6ec029e2/attachment.sig>

maintainer
#10 lore raw

PATCH v5 4/11 PCI: Introduce new MSI chip infrastructure

In reply to Thomas Petazzoni
Quoted 6 lines · Thomas Petazzoni

From: Thierry Reding <[email protected]>

The new struct msi_chip is used to associated an MSI controller with a PCI bus. It is automatically handed down from the root to its children during bus enumeration.

Quoted 7 lines

This patch provides default (weak) implementations for the architecture- specific MSI functions (arch_setup_msi_irq(), arch_teardown_msi_irq() and arch_msi_check_device()) which check if a PCI device's bus has an attached MSI chip and forward the call appropriately.

Quoted 100 lines
---
 drivers/pci/msi.c   | 27 +++++++++++++++++++++++++--
 drivers/pci/probe.c |  1 +
 include/linux/msi.h | 11 +++++++++++
 include/linux/pci.h |  1 +
 4 files changed, 38 insertions(+), 2 deletions(-)
drivers/pci/msi.c +25 -2
index aa2f697..d5b6378 100644
@@ -32,16 +32,39 @@ static int pci_msi_enable = 1;
 
 int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-       return -EINVAL;
+       struct msi_chip *chip = dev->bus->msi;
+       int err;
+
+       if (!chip || !chip->setup_irq)
+               return -EINVAL;
+
+       err = chip->setup_irq(chip, dev, desc);
+       if (err < 0)
+               return err;
+
+       irq_set_chip_data(desc->irq, chip);
+
+       return 0;
 }
 
 void __weak arch_teardown_msi_irq(unsigned int irq)
 {
+       struct msi_chip *chip = irq_get_chip_data(irq);
+
+       if (!chip || !chip->teardown_irq)
+               return;
+
+       chip->teardown_irq(chip, irq);
 }
 
 int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
 {
-       return 0;
+       struct msi_chip *chip = dev->bus->msi;
+
+       if (!chip || !chip->check_device)
+               return 0;
+
+       return chip->check_device(chip, dev, nvec, type);
 }
 
 int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
drivers/pci/probe.c +1 -0
index 46ada5c..b8eaa81 100644
@@ -666,6 +666,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 
        child->parent = parent;
        child->ops = parent->ops;
+       child->msi = parent->msi;
        child->sysdata = parent->sysdata;
        child->bus_flags = parent->bus_flags;
 
include/linux/msi.h +11 -0
index 18870b0..cbf5d05 100644
@@ -64,4 +64,15 @@ void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
 
 void default_teardown_msi_irqs(struct pci_dev *dev);
 
+struct msi_chip {
+       struct module *owner;
+       struct device *dev;
+
+       int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
+                        struct msi_desc *desc);
+       void (*teardown_irq)(struct msi_chip *chip, unsigned int irq);
+       int (*check_device)(struct msi_chip *chip, struct pci_dev *dev,
+                           int nvec, int type);
+};
+
 #endif /* LINUX_MSI_H */
include/linux/pci.h +1 -1
index 0fd1f15..4044e3c 100644
@@ -433,6 +433,7 @@ struct pci_bus {
        struct resource busn_res;       /* bus numbers routed to this bus */
 
        struct pci_ops  *ops;           /* configuration access functions */
+       struct msi_chip *msi;           /* MSI controller */
        void            *sysdata;       /* hook for sys-specific extension */
        struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */
 
--

1.8.1.2

#11 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

In reply to Thomas Petazzoni

This commit adds a very basic registry of msi_chip structures, so that an IRQ controller driver can register an msi_chip, and a PCIe host controller can find it, based on a 'struct device_node'.

---
 drivers/of/of_pci.c    | 45 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/msi.h    |  2 ++
 include/linux/of_pci.h | 12 ++++++++++++
 3 files changed, 59 insertions(+)
drivers/of/of_pci.c +45 -0
index 42c687a..e5ca008 100644
@@ -89,3 +89,48 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
+
+#ifdef CONFIG_PCI_MSI
+
+static LIST_HEAD(of_pci_msi_chip_list);
+static DEFINE_MUTEX(of_pci_msi_chip_mutex);
+
+int of_pci_msi_chip_add(struct msi_chip *chip)
+{
+	if (!of_property_read_bool(chip->of_node, "msi-controller"))
+		return -EINVAL;
+
+	mutex_lock(&of_pci_msi_chip_mutex);
+	list_add(&chip->list, &of_pci_msi_chip_list);
+	mutex_unlock(&of_pci_msi_chip_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_pci_msi_chip_add);
+
+void of_pci_msi_chip_remove(struct msi_chip *chip)
+{
+	mutex_lock(&of_pci_msi_chip_mutex);
+	list_del(&chip->list);
+	mutex_unlock(&of_pci_msi_chip_mutex);
+}
+EXPORT_SYMBOL_GPL(of_pci_msi_chip_remove);
+
+struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node)
+{
+	struct msi_chip *c;
+
+	mutex_lock(&of_pci_msi_chip_mutex);
+	list_for_each_entry(c, &of_pci_msi_chip_list, list) {
+		if (c->of_node == of_node) {
+			mutex_unlock(&of_pci_msi_chip_mutex);
+			return c;
+		}
+	}
+	mutex_unlock(&of_pci_msi_chip_mutex);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(of_pci_find_msi_chip_by_node);
+
+#endif /* CONFIG_PCI_MSI */
include/linux/msi.h +2 -0
index cbf5d05..80900e0 100644
@@ -67,6 +67,8 @@ void default_teardown_msi_irqs(struct pci_dev *dev);
 struct msi_chip {
 	struct module *owner;
 	struct device *dev;
+	struct device_node *of_node;
+	struct list_head list;
 
 	int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
 			 struct msi_desc *desc);
include/linux/of_pci.h +12 -0
index 7a04826..29631eb 100644
@@ -2,6 +2,7 @@
 #define __OF_PCI_H
 
 #include <linux/pci.h>
+#include <linux/msi.h>
 
 struct pci_dev;
 struct of_irq;
@@ -13,4 +14,15 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 int of_pci_get_devfn(struct device_node *np);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
 
+#if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
+int of_pci_msi_chip_add(struct msi_chip *chip);
+void of_pci_msi_chip_remove(struct msi_chip *chip);
+struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node);
+#else
+static inline int of_pci_msi_chip_add(struct msi_chip *chip) { return -EINVAL; }
+static inline void of_pci_msi_chip_remove(struct msi_chip *chip) { }
+static inline struct msi_chip *
+of_pci_find_msi_chip_by_node(struct device_node *of_node) { return NULL };
+#endif
+
 #endif
Signature · 1 line
1.8.1.2
#12 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

Quoted 5 lines · Thomas Petazzoni

This commit adds a very basic registry of msi_chip structures, so that an IRQ controller driver can register an msi_chip, and a PCIe host controller can find it, based on a 'struct device_node'.

Quoted 101 lines
---
 drivers/of/of_pci.c    | 45 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/msi.h    |  2 ++
 include/linux/of_pci.h | 12 ++++++++++++
 3 files changed, 59 insertions(+)
drivers/of/of_pci.c +45 -0
index 42c687a..e5ca008 100644
@@ -89,3 +89,48 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
+
+#ifdef CONFIG_PCI_MSI
+
+static LIST_HEAD(of_pci_msi_chip_list);
+static DEFINE_MUTEX(of_pci_msi_chip_mutex);
+
+int of_pci_msi_chip_add(struct msi_chip *chip)
+{
+	if (!of_property_read_bool(chip->of_node, "msi-controller"))
+		return -EINVAL;
+
+	mutex_lock(&of_pci_msi_chip_mutex);
+	list_add(&chip->list, &of_pci_msi_chip_list);
+	mutex_unlock(&of_pci_msi_chip_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_pci_msi_chip_add);
+
+void of_pci_msi_chip_remove(struct msi_chip *chip)
+{
+	mutex_lock(&of_pci_msi_chip_mutex);
+	list_del(&chip->list);
+	mutex_unlock(&of_pci_msi_chip_mutex);
+}
+EXPORT_SYMBOL_GPL(of_pci_msi_chip_remove);
+
+struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node)
+{
+	struct msi_chip *c;
+
+	mutex_lock(&of_pci_msi_chip_mutex);
+	list_for_each_entry(c, &of_pci_msi_chip_list, list) {
+		if (c->of_node == of_node) {
+			mutex_unlock(&of_pci_msi_chip_mutex);
+			return c;
+		}
+	}
+	mutex_unlock(&of_pci_msi_chip_mutex);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(of_pci_find_msi_chip_by_node);
+
+#endif /* CONFIG_PCI_MSI */
include/linux/msi.h +2 -0
index cbf5d05..80900e0 100644
@@ -67,6 +67,8 @@ void default_teardown_msi_irqs(struct pci_dev *dev);
 struct msi_chip {
 	struct module *owner;
 	struct device *dev;
+	struct device_node *of_node;
+	struct list_head list;
 
 	int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
 			 struct msi_desc *desc);
include/linux/of_pci.h +12 -0
index 7a04826..29631eb 100644
@@ -2,6 +2,7 @@
 #define __OF_PCI_H
 
 #include <linux/pci.h>
+#include <linux/msi.h>
 
 struct pci_dev;
 struct of_irq;
@@ -13,4 +14,15 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 int of_pci_get_devfn(struct device_node *np);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
 
+#if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
+int of_pci_msi_chip_add(struct msi_chip *chip);
+void of_pci_msi_chip_remove(struct msi_chip *chip);
+struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node);
+#else
+static inline int of_pci_msi_chip_add(struct msi_chip *chip) { return -EINVAL; }
+static inline void of_pci_msi_chip_remove(struct msi_chip *chip) { }
+static inline struct msi_chip *
+of_pci_find_msi_chip_by_node(struct device_node *of_node) { return NULL };
+#endif
+
 #endif
#13 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

Quoted 8 lines · Rob Herring
Quoted 5 lines · Thomas Petazzoni

This commit adds a very basic registry of msi_chip structures, so that an IRQ controller driver can register an msi_chip, and a PCIe host controller can find it, based on a 'struct device_node'.

Actually, I'm going to disagree on this one and say NAK. I don't think it is a good idea to create a completely separate registry of msi_chips for binding to dt nodes. I think it would be better to include the msi_chip pointer directly into the irq_domain which has to be there anyway. It then becomes another feature for irq controllers if it can support doing MSI.

In fact, I would even go so far as to say it would make sense for the msi_chip functionality to be rolled directly into the irq_domain without a separate structure; but I'm not nacking on that point.

g.

Quoted 104 lines
Quoted 103 lines

---
 drivers/of/of_pci.c    | 45 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/msi.h    |  2 ++
 include/linux/of_pci.h | 12 ++++++++++++
 3 files changed, 59 insertions(+)
drivers/of/of_pci.c +45 -0
index 42c687a..e5ca008 100644
@@ -89,3 +89,48 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
+
+#ifdef CONFIG_PCI_MSI
+
+static LIST_HEAD(of_pci_msi_chip_list);
+static DEFINE_MUTEX(of_pci_msi_chip_mutex);
+
+int of_pci_msi_chip_add(struct msi_chip *chip)
+{
+	if (!of_property_read_bool(chip->of_node, "msi-controller"))
+		return -EINVAL;
+
+	mutex_lock(&of_pci_msi_chip_mutex);
+	list_add(&chip->list, &of_pci_msi_chip_list);
+	mutex_unlock(&of_pci_msi_chip_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_pci_msi_chip_add);
+
+void of_pci_msi_chip_remove(struct msi_chip *chip)
+{
+	mutex_lock(&of_pci_msi_chip_mutex);
+	list_del(&chip->list);
+	mutex_unlock(&of_pci_msi_chip_mutex);
+}
+EXPORT_SYMBOL_GPL(of_pci_msi_chip_remove);
+
+struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node)
+{
+	struct msi_chip *c;
+
+	mutex_lock(&of_pci_msi_chip_mutex);
+	list_for_each_entry(c, &of_pci_msi_chip_list, list) {
+		if (c->of_node == of_node) {
+			mutex_unlock(&of_pci_msi_chip_mutex);
+			return c;
+		}
+	}
+	mutex_unlock(&of_pci_msi_chip_mutex);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(of_pci_find_msi_chip_by_node);
+
+#endif /* CONFIG_PCI_MSI */
include/linux/msi.h +2 -0
index cbf5d05..80900e0 100644
@@ -67,6 +67,8 @@ void default_teardown_msi_irqs(struct pci_dev *dev);
 struct msi_chip {
 	struct module *owner;
 	struct device *dev;
+	struct device_node *of_node;
+	struct list_head list;
 
 	int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
 			 struct msi_desc *desc);
include/linux/of_pci.h +12 -0
index 7a04826..29631eb 100644
@@ -2,6 +2,7 @@
 #define __OF_PCI_H
 
 #include <linux/pci.h>
+#include <linux/msi.h>
 
 struct pci_dev;
 struct of_irq;
@@ -13,4 +14,15 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 int of_pci_get_devfn(struct device_node *np);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
 
+#if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
+int of_pci_msi_chip_add(struct msi_chip *chip);
+void of_pci_msi_chip_remove(struct msi_chip *chip);
+struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node);
+#else
+static inline int of_pci_msi_chip_add(struct msi_chip *chip) { return -EINVAL; }
+static inline void of_pci_msi_chip_remove(struct msi_chip *chip) { }
+static inline struct msi_chip *
+of_pci_find_msi_chip_by_node(struct device_node *of_node) { return NULL };
+#endif
+
 #endif
#14 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

Dear Grant Likely,

Thanks for your feedback! Some comments below.

Quoted 10 lines · Grant Likely
Quoted 3 lines
Quoted 1 line

Actually, I'm going to disagree on this one and say NAK. I don't think it is a good idea to create a completely separate registry of msi_chips for binding to dt nodes. I think it would be better to include the msi_chip pointer directly into the irq_domain which has to be there anyway. It then becomes another feature for irq controllers if it can support doing MSI.

The problem that this patch tries to solve is how can the PCIe driver work get a pointer to the msi_chip structure from the DT device node pointed to by the 'msi-parent' property. I.e, we have:

	interrupt-parent = <&mpic>;

	mpic {
		reg = <...>;
		compatible = "...";
		interrupt-controller;
		msi-controller;
	};

	pcie-controller {
		msi-parent = <&mpic>;
	};

The 'mpic' driver registers two irq_domains, one for the "normal" interrupts, and one for the MSI interrupts. Both irq_domain cannot be associated to the same &mpic node, or the irq_domain lookup for interrupt-parent and msi-parent is going to be confused.

In the very first version of this patch set, I was using two separate DT device nodes to avoid this problem:

	interrupt-parent = <&mpic>;

	interrupt-controller {
		reg = <...>;
		compatible = "...";

		mpic {
			interrupt-controller;
		};

		msi {
			msi-controller;
		};
	};

	pcie-controller {
		msi-parent = <&msi>;
	};

This way, each of the two irq_domain was associated to a distinct DT device node, and everything was working fine. But during the review, I was pointed by Arnd that it wasn't the proper way of describing the interrupt controller, and that there should be only one DT device node having both the interrupt-controller and msi-controller roles.

So what is your suggestion to allow the PCIe controller to retrieve the correct irq_domain if we have only one DT node for the IRQ controller that registers two irq_domains ?

See:

[RFCv1 00/11] MSI support for Marvell EBU PCIe driver
https://lists.ozlabs.org/pipermail/devicetree-discuss/2013-March/030578.html

and particularly:

[RFCv1 07/11] irqchip: armada-370-xp: add MSI support to interrupt controller driver
https://lists.ozlabs.org/pipermail/devicetree-discuss/2013-March/030584.html

Thanks,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#15 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

Quoted 67 lines · Thomas Petazzoni

Dear Grant Likely,

Thanks for your feedback! Some comments below.

Quoted 10 lines · Grant Likely
Quoted 3 lines
Quoted 1 line

Actually, I'm going to disagree on this one and say NAK. I don't think it is a good idea to create a completely separate registry of msi_chips for binding to dt nodes. I think it would be better to include the msi_chip pointer directly into the irq_domain which has to be there anyway. It then becomes another feature for irq controllers if it can support doing MSI.

The problem that this patch tries to solve is how can the PCIe driver work get a pointer to the msi_chip structure from the DT device node pointed to by the 'msi-parent' property. I.e, we have:

	interrupt-parent = <&mpic>;

	mpic {
		reg = <...>;
		compatible = "...";
		interrupt-controller;
		msi-controller;
	};

	pcie-controller {
		msi-parent = <&mpic>;
	};

The 'mpic' driver registers two irq_domains, one for the "normal" interrupts, and one for the MSI interrupts. Both irq_domain cannot be associated to the same &mpic node, or the irq_domain lookup for interrupt-parent and msi-parent is going to be confused.

In the very first version of this patch set, I was using two separate DT device nodes to avoid this problem:

	interrupt-parent = <&mpic>;

	interrupt-controller {
		reg = <...>;
		compatible = "...";

		mpic {
			interrupt-controller;
		};

		msi {
			msi-controller;
		};
	};

	pcie-controller {
		msi-parent = <&msi>;
	};

This way, each of the two irq_domain was associated to a distinct DT device node, and everything was working fine. But during the review, I was pointed by Arnd that it wasn't the proper way of describing the interrupt controller, and that there should be only one DT device node having both the interrupt-controller and msi-controller roles.

Quoted 3 lines

So what is your suggestion to allow the PCIe controller to retrieve the correct irq_domain if we have only one DT node for the IRQ controller that registers two irq_domains ?

If I understand correctly, Grant isn't objecting to the introduction of the lookup function, but rather its implementation. You could add a pointer to a struct msi_chip within struct irq_domain and then iterate over all irq_domain instances (see irq_find_host()) and find one which has the correct device_node pointer and the msi_chip pointer set.

So I think that pretty much boils down to setting the (new) .msi_chip field of armada_370_xp_msi_domain to the newly allocated MSI chip in armada_370_xp_msi_init() and modify the lookup function to use the irq_domain_list instead of the list of of_pci_msi_chip_list(). And a whole lot of the infrastructure code can go away because it's already there for irq_domain.

The good thing about it is that it couples the MSI chip more strongly with its associated IRQ domain. And as a bonus we get to omit the list and of_node fields from struct msi_chip. =)

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130729/3994fc92/attachment.sig>

#16 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

Dear Thierry Reding,

Quoted 9 lines · Thierry Reding
Quoted 3 lines

So what is your suggestion to allow the PCIe controller to retrieve the correct irq_domain if we have only one DT node for the IRQ controller that registers two irq_domains ?

If I understand correctly, Grant isn't objecting to the introduction of the lookup function, but rather its implementation. You could add a pointer to a struct msi_chip within struct irq_domain and then iterate over all irq_domain instances (see irq_find_host()) and find one which has the correct device_node pointer and the msi_chip pointer set.

Ah ok. The only trick is that we have to change irq_find_host() to *not* match on MSI domains. Can you check the below patch to see if it matches what Grant suggested? It works for me, and it allows to completely remove the registry of msi_chip in drivers/of, as well as the of_node pointer in struct msi_chip.

Thanks!

Thomas

Quoted 1 line

From c2c0137cb110270f96e1e0fa298a5d585b8d829e Mon Sep 17 00:00:00 2001

From: Thomas Petazzoni <[email protected]>
Date: Mon, 29 Jul 2013 14:12:31 +0200
Subject: [PATCHv6 05/11] irqdomain: add support to associate an irq_domain
with a msi_chip

Message Signaled Interrupts are a PCI-specific mechanism that allows PCI devices to notify interrupts to the CPU using in-band messages. The PCI subsystem represents an MSI-capable interrupt controller as an msi_chip structure, and this patch improves the irqdomain subsystem with a new pointer associating an irq_domain with the corresponding msi_chip.

The __irq_domain_add() function is augmented with an additional argument, the 'msi_chip' pointer, and all callers of this function are updated.

A new function irq_domain_add_msi() function is added to allow the registration of an MSI-type irq domain.

The irq_find_host() function is modified to not match on MSI-type irq
domains: a given DT device node may represent both a normal interrupt controller and a MSI interrupt controller. irq_find_host() should return the irq_domain that corresponds to the normal interupt controller.

An irq_find_msi() function is added to get the MSI_type irq domain given a DT device node.

---
 include/linux/irqdomain.h | 20 +++++++++++++++++---
 kernel/irq/irqdomain.c    | 35 +++++++++++++++++++++++++++++++++--
 2 files changed, 50 insertions(+), 5 deletions(-)
include/linux/irqdomain.h +17 -3
index 1ffa336..f1b11c8 100644
@@ -38,6 +38,7 @@
 struct device_node;
 struct irq_domain;
 struct of_device_id;
+struct msi_chip;
 
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS	16
@@ -101,6 +102,7 @@ struct irq_domain {
 	/* Optional data */
 	struct device_node *of_node;
 	struct irq_domain_chip_generic *gc;
+	struct msi_chip *msi_chip;
 
 	/* reverse map data. The linear map gets appended to the irq_domain */
 	irq_hw_number_t hwirq_max;
@@ -114,6 +116,7 @@ struct irq_domain {
 struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
+				    struct msi_chip *msi_chip,
 				    void *host_data);
 struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 					 unsigned int size,
@@ -127,6 +130,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 					 const struct irq_domain_ops *ops,
 					 void *host_data);
 extern struct irq_domain *irq_find_host(struct device_node *node);
+extern struct irq_domain *irq_find_msi(struct device_node *node);
 extern void irq_set_default_host(struct irq_domain *host);
 
 /**
@@ -141,14 +145,15 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	return __irq_domain_add(of_node, size, size, 0, ops, NULL, host_data);
 }
 static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
 					 unsigned int max_irq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data);
+	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, NULL,
+				host_data);
 }
 static inline struct irq_domain *irq_domain_add_legacy_isa(
 				struct device_node *of_node,
@@ -162,7 +167,16 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
+	return __irq_domain_add(of_node, 0, ~0, 0, ops, NULL, host_data);
+}
+static inline struct irq_domain *irq_domain_add_msi(struct device_node *of_node,
+						    unsigned int size,
+						    const struct irq_domain_ops *ops,
+						    struct msi_chip *msi_chip,
+						    void *host_data)
+{
+	return __irq_domain_add(of_node, size, size, 0, ops,
+				msi_chip, host_data);
 }
 
 extern void irq_domain_remove(struct irq_domain *host);
kernel/irq/irqdomain.c +33 -2
index b9ddb94..80dc1ca 100644
@@ -29,6 +29,7 @@ static struct irq_domain *irq_default_domain;
  * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no
  *              direct mapping
  * @ops: map/unmap domain callbacks
+ * @msi_chip: pointer to MSI chip structure, for MSI domains
  * @host_data: Controller private data pointer
  *
  * Allocates and initialize and irq_domain structure.  Caller is expected to
@@ -38,6 +39,7 @@ static struct irq_domain *irq_default_domain;
 struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
+				    struct msi_chip *msi_chip,
 				    void *host_data)
 {
 	struct irq_domain *domain;
@@ -52,6 +54,7 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 	domain->ops = ops;
 	domain->host_data = host_data;
 	domain->of_node = of_node_get(of_node);
+	domain->msi_chip = msi_chip;
 	domain->hwirq_max = hwirq_max;
 	domain->revmap_size = size;
 	domain->revmap_direct_max_irq = direct_max;
@@ -127,7 +130,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	domain = __irq_domain_add(of_node, size, size, 0, ops, NULL, host_data);
 	if (!domain)
 		return NULL;
 
@@ -172,7 +175,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 	struct irq_domain *domain;
 
 	domain = __irq_domain_add(of_node, first_hwirq + size,
-				  first_hwirq + size, 0, ops, host_data);
+				  first_hwirq + size, 0, ops, NULL, host_data);
 	if (!domain)
 		return NULL;
 
@@ -198,6 +201,12 @@ struct irq_domain *irq_find_host(struct device_node *node)
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
+		/*
+		 * We only want to match normal interrupt domains, not
+		 * MSI domains
+		 */
+		if (h->msi_chip)
+			continue;
 		if (h->ops->match)
 			rc = h->ops->match(h, node);
 		else
@@ -214,6 +223,28 @@ struct irq_domain *irq_find_host(struct device_node *node)
 EXPORT_SYMBOL_GPL(irq_find_host);
 
 /**
+ * irq_find_msi() - Locates a MSI domain for a given device node
+ * @node: device-tree node of the interrupt controller
+ */
+struct irq_domain *irq_find_msi(struct device_node *node)
+{
+	struct irq_domain *h, *found = NULL;
+
+	mutex_lock(&irq_domain_mutex);
+	list_for_each_entry(h, &irq_domain_list, link) {
+		if (!h->msi_chip)
+			continue;
+		if (h->of_node && h->of_node == node) {
+			found = h;
+			break;
+		}
+	}
+	mutex_unlock(&irq_domain_mutex);
+	return found;
+}
+EXPORT_SYMBOL_GPL(irq_find_msi);
+
+/**
  * irq_set_default_host() - Set a "default" irq domain
  * @domain: default domain pointer
  *
Signature · 10 lines
1.8.1.2




-- 
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#17 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

Quoted 41 lines · Thomas Petazzoni

Dear Thierry Reding,

Quoted 9 lines · Thierry Reding
Quoted 3 lines

So what is your suggestion to allow the PCIe controller to retrieve the correct irq_domain if we have only one DT node for the IRQ controller that registers two irq_domains ?

If I understand correctly, Grant isn't objecting to the introduction of the lookup function, but rather its implementation. You could add a pointer to a struct msi_chip within struct irq_domain and then iterate over all irq_domain instances (see irq_find_host()) and find one which has the correct device_node pointer and the msi_chip pointer set.

Ah ok. The only trick is that we have to change irq_find_host() to *not* match on MSI domains. Can you check the below patch to see if it matches what Grant suggested? It works for me, and it allows to completely remove the registry of msi_chip in drivers/of, as well as the of_node pointer in struct msi_chip.

Thanks!

Thomas

From c2c0137cb110270f96e1e0fa298a5d585b8d829e Mon Sep 17 00:00:00 2001
From: Thomas Petazzoni <[email protected]>
Date: Mon, 29 Jul 2013 14:12:31 +0200
Subject: [PATCHv6 05/11] irqdomain: add support to associate an irq_domain
with a msi_chip

Message Signaled Interrupts are a PCI-specific mechanism that allows PCI devices to notify interrupts to the CPU using in-band messages. The PCI subsystem represents an MSI-capable interrupt controller as an msi_chip structure, and this patch improves the irqdomain subsystem with a new pointer associating an irq_domain with the corresponding msi_chip.

The __irq_domain_add() function is augmented with an additional argument, the 'msi_chip' pointer, and all callers of this function are updated.

Quoted 7 lines

A new function irq_domain_add_msi() function is added to allow the registration of an MSI-type irq domain.

The irq_find_host() function is modified to not match on MSI-type irq
domains: a given DT device node may represent both a normal interrupt controller and a MSI interrupt controller. irq_find_host() should return the irq_domain that corresponds to the normal interupt

"interupt" -> "interrupt"

Quoted 3 lines

controller.

An irq_find_msi() function is added to get the MSI_type irq domain

"MSI_type" -> "MSI-type".

Quoted 1 line

given a DT device node.

And "irq domain" -> "IRQ domain" in all of the above.

Quoted 1 line
include/linux/irqdomain.h +0 -0

[...]

Quoted 6 lines
include/linux/irqdomain.h +1 -1
@@ -162,7 +167,16 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
+	return __irq_domain_add(of_node, 0, ~0, 0, ops, NULL, host_data);

include/linux/irqdomain.h static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node · line 180

Quoted 10 lines
include/linux/irqdomain.h +9 -0
+}
+static inline struct irq_domain *irq_domain_add_msi(struct device_node *of_node,
+						    unsigned int size,
+						    const struct irq_domain_ops *ops,
+						    struct msi_chip *msi_chip,
+						    void *host_data)
+{
+	return __irq_domain_add(of_node, size, size, 0, ops,
+				msi_chip, host_data);
 }

Given that the majority of interrupt controllers probably don't have any MSI functionality, I wonder if perhaps this should be done in a more helper-oriented way, see below...

Quoted 1 line
kernel/irq/irqdomain.c +0 -0

[...]

Quoted 27 lines
kernel/irq/irqdomain.c +16 -0
@@ -198,6 +201,12 @@ struct irq_domain *irq_find_host(struct device_node *node)
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
+		/*
+		 * We only want to match normal interrupt domains, not
+		 * MSI domains
+		 */
+		if (h->msi_chip)
+			continue;
 		if (h->ops->match)
 			rc = h->ops->match(h, node);
 		else
@@ -214,6 +223,28 @@ struct irq_domain *irq_find_host(struct device_node *node)
 EXPORT_SYMBOL_GPL(irq_find_host);
 
 /**
+ * irq_find_msi() - Locates a MSI domain for a given device node
+ * @node: device-tree node of the interrupt controller
+ */
+struct irq_domain *irq_find_msi(struct device_node *node)
+{
+	struct irq_domain *h, *found = NULL;
+
+	mutex_lock(&irq_domain_mutex);
+	list_for_each_entry(h, &irq_domain_list, link) {
+		if (!h->msi_chip)

kernel/irq/irqdomain.c struct irq_domain *irq_find_host(struct device_node *node) · line 245

Quoted 10 lines
kernel/irq/irqdomain.c +10 -0
+			continue;
+		if (h->of_node && h->of_node == node) {
+			found = h;
+			break;
+		}
+	}
+	mutex_unlock(&irq_domain_mutex);
+	return found;
+}
+EXPORT_SYMBOL_GPL(irq_find_msi);

This doesn't quite copy what irq_find_host() does, since it ignores the associated ops->match().

But given that ops->match() already provides a way to hook into the lookup, perhaps we could add a function such as this:

	int irq_domain_supports_msi(struct irq_domain *d, struct device_node *node)
	{
		if ((d->of_node == NULL) || (d->of_node != node))
			return 0;

		return d->msi_chip != NULL;
	}

Then use that in drivers that expose MSI functionality via an IRQ domain like this:

	static const struct irq_domain_ops foo_irq_domain_ops = {
		...
		.match = irq_domain_supports_msi,
		...
	};

One problem with this is that it doesn't solve your problem where two different IRQ domains are exposed by the same device, because the irq_find_host() will still match the MSI IRQ domain for the non-MSI device node as well. This could be solved by adding another match function...

This goes in hand with the helper-style API that I mentioned above. But it's really up to Grant to decide which way he wants this to go.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130729/4b52a29e/attachment-0001.sig>

#18 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

Dear Thierry Reding,

Quoted 16 lines · Thierry Reding
Quoted 16 lines

/**
+ * irq_find_msi() - Locates a MSI domain for a given device node
+ * @node: device-tree node of the interrupt controller
+ */

kernel/irq/irqdomain.c +12 -0
+struct irq_domain *irq_find_msi(struct device_node *node)
+{
+	struct irq_domain *h, *found = NULL;
+
+	mutex_lock(&irq_domain_mutex);
+	list_for_each_entry(h, &irq_domain_list, link) {
+		if (!h->msi_chip)
+			continue;
+		if (h->of_node && h->of_node == node) {
+			found = h;
+			break;
+		}
Quoted 8 lines

kernel/irq/irqdomain.c struct irq_domain *irq_find_host(struct device_node *node) · line 245

Quoted 5 lines
kernel/irq/irqdomain.c +5 -0
+	}
+	mutex_unlock(&irq_domain_mutex);
+	return found;
+}
+EXPORT_SYMBOL_GPL(irq_find_msi);

This doesn't quite copy what irq_find_host() does, since it ignores the associated ops->match().

Correct.

Quoted 20 lines

But given that ops->match() already provides a way to hook into the lookup, perhaps we could add a function such as this:

	int irq_domain_supports_msi(struct irq_domain *d, struct device_node *node)
	{
		if ((d->of_node == NULL) || (d->of_node != node))
			return 0;

		return d->msi_chip != NULL;
	}

Then use that in drivers that expose MSI functionality via an IRQ domain like this:

	static const struct irq_domain_ops foo_irq_domain_ops = {
		...
		.match = irq_domain_supports_msi,
		...
	};
Quoted 4 lines

One problem with this is that it doesn't solve your problem where two different IRQ domains are exposed by the same device, because the irq_find_host() will still match the MSI IRQ domain for the non-MSI device node as well.

Indeed.

Quoted 1 line

This could be solved by adding another match function...

But this would involve changing all the users of irq_find_host(), no?

Quoted 2 lines

This goes in hand with the helper-style API that I mentioned above. But it's really up to Grant to decide which way he wants this to go.

Yes, Grant, your suggestions are welcome on this. Thanks!

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#19 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

In reply to Thierry Reding

Dear Thierry Reding,

Quoted 5 lines · Thierry Reding
Quoted 5 lines
include/linux/irqdomain.h +5 -0
+static inline struct irq_domain *irq_domain_add_msi(struct device_node *of_node,
+						    unsigned int size,
+						    const struct irq_domain_ops *ops,
+						    struct msi_chip *msi_chip,
+						    void *host_data)
Quoted 8 lines

include/linux/irqdomain.h static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node · line 180

Quoted 4 lines
include/linux/irqdomain.h +3 -0
+{
+	return __irq_domain_add(of_node, size, size, 0, ops,
+				msi_chip, host_data);
 }

Given that the majority of interrupt controllers probably don't have any MSI functionality, I wonder if perhaps this should be done in a more helper-oriented way, see below...

I'm not sure I get the relation between this comment on this specific part of the code and the match helpers suggestion that you did below. Could you explain?

Quoted 41 lines
Quoted 7 lines
kernel/irq/irqdomain.c +7 -0
+struct irq_domain *irq_find_msi(struct device_node *node)
+{
+	struct irq_domain *h, *found = NULL;
+
+	mutex_lock(&irq_domain_mutex);
+	list_for_each_entry(h, &irq_domain_list, link) {
+		if (!h->msi_chip)

kernel/irq/irqdomain.c struct irq_domain *irq_find_host(struct device_node *node) · line 245

Quoted 10 lines
kernel/irq/irqdomain.c +10 -0
+			continue;
+		if (h->of_node && h->of_node == node) {
+			found = h;
+			break;
+		}
+	}
+	mutex_unlock(&irq_domain_mutex);
+	return found;
+}
+EXPORT_SYMBOL_GPL(irq_find_msi);

This doesn't quite copy what irq_find_host() does, since it ignores the associated ops->match().

But given that ops->match() already provides a way to hook into the lookup, perhaps we could add a function such as this:

	int irq_domain_supports_msi(struct irq_domain *d, struct device_node *node)
	{
		if ((d->of_node == NULL) || (d->of_node != node))
			return 0;

		return d->msi_chip != NULL;
	}

Then use that in drivers that expose MSI functionality via an IRQ domain like this:

	static const struct irq_domain_ops foo_irq_domain_ops = {
		...
		.match = irq_domain_supports_msi,
		...
	};
Quoted 5 lines

One problem with this is that it doesn't solve your problem where two different IRQ domains are exposed by the same device, because the irq_find_host() will still match the MSI IRQ domain for the non-MSI device node as well. This could be solved by adding another match function...

I've given this some thought, and I don't see how ->match() functions can solve the problem. The irq_find_host() is simply given as input a DT node, and is asked to find the irqdomain attached to this DT node. To do so, for each irqdomain in the system, it calls the ->match() operation, or does some default DT node equality checking. However, nor the irq_find_host() function, nor a custom ->match() function has a way of knowing whether what you're looking for is the "normal" IRQ controller, or the MSI controller.

Quoted 2 lines

This goes in hand with the helper-style API that I mentioned above. But it's really up to Grant to decide which way he wants this to go.

Again, I am not sure what you meant with "helper-style API". I do understand the idea of providing a helper irq_domain_supports_msi() that can be used as the ->match() operation in irq_domain_ops, but I fail to see how this solves the problem.

Thanks!

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#20 lore raw

PATCH v5 5/11 of: pci: add registry of MSI chips

In reply to Thomas Petazzoni

Grant,

Would it be possible to get your opinion on the patch below?

You're the one who disagreed about the "of: pci: add registry of MSI chips", so I implemented something that hopefully is more in line with what you expected, so it'd be great if you could take some time to review it.

This MSI stuff has been around for quite some time, the specific patch you NAKed had originally been posted on June, 6th, and was thought to be ready for merging thanks to the ACK of Rob Herring. While I certainly understand that patches can continue to be discussed by other maintainers, it'd be nice to have quick feedback from you after this NAK so that we can converge towards an accepted solution to be merged in 3.12.

Thanks a lot,

Thomas

Quoted 219 lines · Thomas Petazzoni

Dear Thierry Reding,

Quoted 9 lines · Thierry Reding
Quoted 3 lines

So what is your suggestion to allow the PCIe controller to retrieve the correct irq_domain if we have only one DT node for the IRQ controller that registers two irq_domains ?

If I understand correctly, Grant isn't objecting to the introduction of the lookup function, but rather its implementation. You could add a pointer to a struct msi_chip within struct irq_domain and then iterate over all irq_domain instances (see irq_find_host()) and find one which has the correct device_node pointer and the msi_chip pointer set.

Ah ok. The only trick is that we have to change irq_find_host() to *not* match on MSI domains. Can you check the below patch to see if it matches what Grant suggested? It works for me, and it allows to completely remove the registry of msi_chip in drivers/of, as well as the of_node pointer in struct msi_chip.

Thanks!

Thomas

From c2c0137cb110270f96e1e0fa298a5d585b8d829e Mon Sep 17 00:00:00 2001
From: Thomas Petazzoni <[email protected]>
Date: Mon, 29 Jul 2013 14:12:31 +0200
Subject: [PATCHv6 05/11] irqdomain: add support to associate an irq_domain
with a msi_chip

Message Signaled Interrupts are a PCI-specific mechanism that allows PCI devices to notify interrupts to the CPU using in-band messages. The PCI subsystem represents an MSI-capable interrupt controller as an msi_chip structure, and this patch improves the irqdomain subsystem with a new pointer associating an irq_domain with the corresponding msi_chip.

The __irq_domain_add() function is augmented with an additional argument, the 'msi_chip' pointer, and all callers of this function are updated.

A new function irq_domain_add_msi() function is added to allow the registration of an MSI-type irq domain.

The irq_find_host() function is modified to not match on MSI-type irq
domains: a given DT device node may represent both a normal interrupt controller and a MSI interrupt controller. irq_find_host() should return the irq_domain that corresponds to the normal interupt controller.

An irq_find_msi() function is added to get the MSI_type irq domain given a DT device node.

---
 include/linux/irqdomain.h | 20 +++++++++++++++++---
 kernel/irq/irqdomain.c    | 35 +++++++++++++++++++++++++++++++++--
 2 files changed, 50 insertions(+), 5 deletions(-)
include/linux/irqdomain.h +17 -3
index 1ffa336..f1b11c8 100644
@@ -38,6 +38,7 @@
 struct device_node;
 struct irq_domain;
 struct of_device_id;
+struct msi_chip;
 
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS	16
@@ -101,6 +102,7 @@ struct irq_domain {
 	/* Optional data */
 	struct device_node *of_node;
 	struct irq_domain_chip_generic *gc;
+	struct msi_chip *msi_chip;
 
 	/* reverse map data. The linear map gets appended to the irq_domain */
 	irq_hw_number_t hwirq_max;
@@ -114,6 +116,7 @@ struct irq_domain {
 struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
+				    struct msi_chip *msi_chip,
 				    void *host_data);
 struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 					 unsigned int size,
@@ -127,6 +130,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 					 const struct irq_domain_ops *ops,
 					 void *host_data);
 extern struct irq_domain *irq_find_host(struct device_node *node);
+extern struct irq_domain *irq_find_msi(struct device_node *node);
 extern void irq_set_default_host(struct irq_domain *host);
 
 /**
@@ -141,14 +145,15 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	return __irq_domain_add(of_node, size, size, 0, ops, NULL, host_data);
 }
 static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
 					 unsigned int max_irq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data);
+	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, NULL,
+				host_data);
 }
 static inline struct irq_domain *irq_domain_add_legacy_isa(
 				struct device_node *of_node,
@@ -162,7 +167,16 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
+	return __irq_domain_add(of_node, 0, ~0, 0, ops, NULL, host_data);
+}
+static inline struct irq_domain *irq_domain_add_msi(struct device_node *of_node,
+						    unsigned int size,
+						    const struct irq_domain_ops *ops,
+						    struct msi_chip *msi_chip,
+						    void *host_data)
+{
+	return __irq_domain_add(of_node, size, size, 0, ops,
+				msi_chip, host_data);
 }
 
 extern void irq_domain_remove(struct irq_domain *host);
kernel/irq/irqdomain.c +33 -2
index b9ddb94..80dc1ca 100644
@@ -29,6 +29,7 @@ static struct irq_domain *irq_default_domain;
  * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no
  *              direct mapping
  * @ops: map/unmap domain callbacks
+ * @msi_chip: pointer to MSI chip structure, for MSI domains
  * @host_data: Controller private data pointer
  *
  * Allocates and initialize and irq_domain structure.  Caller is expected to
@@ -38,6 +39,7 @@ static struct irq_domain *irq_default_domain;
 struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
+				    struct msi_chip *msi_chip,
 				    void *host_data)
 {
 	struct irq_domain *domain;
@@ -52,6 +54,7 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 	domain->ops = ops;
 	domain->host_data = host_data;
 	domain->of_node = of_node_get(of_node);
+	domain->msi_chip = msi_chip;
 	domain->hwirq_max = hwirq_max;
 	domain->revmap_size = size;
 	domain->revmap_direct_max_irq = direct_max;
@@ -127,7 +130,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	domain = __irq_domain_add(of_node, size, size, 0, ops, NULL, host_data);
 	if (!domain)
 		return NULL;
 
@@ -172,7 +175,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 	struct irq_domain *domain;
 
 	domain = __irq_domain_add(of_node, first_hwirq + size,
-				  first_hwirq + size, 0, ops, host_data);
+				  first_hwirq + size, 0, ops, NULL, host_data);
 	if (!domain)
 		return NULL;
 
@@ -198,6 +201,12 @@ struct irq_domain *irq_find_host(struct device_node *node)
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
+		/*
+		 * We only want to match normal interrupt domains, not
+		 * MSI domains
+		 */
+		if (h->msi_chip)
+			continue;
 		if (h->ops->match)
 			rc = h->ops->match(h, node);
 		else
@@ -214,6 +223,28 @@ struct irq_domain *irq_find_host(struct device_node *node)
 EXPORT_SYMBOL_GPL(irq_find_host);
 
 /**
+ * irq_find_msi() - Locates a MSI domain for a given device node
+ * @node: device-tree node of the interrupt controller
+ */
+struct irq_domain *irq_find_msi(struct device_node *node)
+{
+	struct irq_domain *h, *found = NULL;
+
+	mutex_lock(&irq_domain_mutex);
+	list_for_each_entry(h, &irq_domain_list, link) {
+		if (!h->msi_chip)
+			continue;
+		if (h->of_node && h->of_node == node) {
+			found = h;
+			break;
+		}
+	}
+	mutex_unlock(&irq_domain_mutex);
+	return found;
+}
+EXPORT_SYMBOL_GPL(irq_find_msi);
+
+/**
  * irq_set_default_host() - Set a "default" irq domain
  * @domain: default domain pointer
  *
Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#21 lore raw

PATCH v5 6/11 irqchip: armada-370-xp: properly request resources

In reply to Thomas Petazzoni

Instead of using of_iomap(), we now use of_address_to_resource(), request_mem_region() and ioremap(). This allows the corresponding I/O regions to be properly requested and visible in /proc/iomem.

The main motivation for this change is that the introduction of the MSI support requires us to get the physical address of the main interrupt controller registers, so we will need the corresponding 'struct resource' anyway.

We also take this opportunity to change a panic() to BUG_ON(), in order to be consistent with the rest of the driver.

---
 drivers/irqchip/irq-armada-370-xp.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +16 -4
index bb328a3..26adc74 100644
@@ -248,12 +248,25 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
 static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 					     struct device_node *parent)
 {
+	struct resource main_int_res, per_cpu_int_res;
 	u32 control;
 
-	main_int_base = of_iomap(node, 0);
-	per_cpu_int_base = of_iomap(node, 1);
+	BUG_ON(of_address_to_resource(node, 0, &main_int_res));
+	BUG_ON(of_address_to_resource(node, 1, &per_cpu_int_res));
 
+	BUG_ON(!request_mem_region(main_int_res.start,
+				   resource_size(&main_int_res),
+				   node->full_name));
+	BUG_ON(!request_mem_region(per_cpu_int_res.start,
+				   resource_size(&per_cpu_int_res),
+				   node->full_name));
+
+	main_int_base = ioremap(main_int_res.start,
+				resource_size(&main_int_res));
 	BUG_ON(!main_int_base);
+
+	per_cpu_int_base = ioremap(per_cpu_int_res.start,
+				   resource_size(&per_cpu_int_res));
 	BUG_ON(!per_cpu_int_base);
 
 	control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
@@ -262,8 +275,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 		irq_domain_add_linear(node, (control >> 2) & 0x3ff,
 				&armada_370_xp_mpic_irq_ops, NULL);
 
-	if (!armada_370_xp_mpic_domain)
-		panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n");
+	BUG_ON(!armada_370_xp_mpic_domain);
 
 	irq_set_default_host(armada_370_xp_mpic_domain);
 
Signature · 1 line
1.8.1.2
#22 lore raw

PATCH v5 7/11 irqchip: armada-370-xp: implement MSI support

In reply to Thomas Petazzoni

This commit introduces the support for the MSI interrupts in the armada-370-xp interrupt controller driver. It registers an MSI chip to the MSI chip registry, which will be used by the Marvell PCIe host controller driver.

The MSI interrupts use the 16 high doorbells, and are therefore notified using IRQ1 of the main interrupt controller.

---
 .../devicetree/bindings/arm/armada-370-xp-mpic.txt |   3 +
 drivers/irqchip/irq-armada-370-xp.c                | 141 ++++++++++++++++++++-
 2 files changed, 143 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt +3 -0
index 61df564..d74091a 100644
@@ -4,6 +4,8 @@ Marvell Armada 370 and Armada XP Interrupt Controller
 Required properties:
 - compatible: Should be "marvell,mpic"
 - interrupt-controller: Identifies the node as an interrupt controller.
+- msi-controller: Identifies the node as an PCI Message Signaled
+  Interrupt controller.
 - #interrupt-cells: The number of cells to define the interrupts. Should be 1.
   The cell is the IRQ number
 
@@ -24,6 +26,7 @@ Example:
               #address-cells = <1>;
               #size-cells = <1>;
               interrupt-controller;
+              msi-controller;
               reg = <0xd0020a00 0x1d0>,
                     <0xd0021070 0x58>;
         };
drivers/irqchip/irq-armada-370-xp.c +140 -1

189 lines not on this page · raw message

Signature · 1 line
1.8.1.2
#23 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

In reply to Thomas Petazzoni

Some PCI drivers may need to adjust the pci_bus structure after it has been allocated by the Linux PCI core. The PCI core allows architectures to implement the pcibios_add_bus() and pcibios_remove_bus() for this purpose. This commit therefore extends the hw_pci and pci_sys_data structures of the ARM PCI core to allow PCI drivers to register ->add_bus() and ->remove_bus() in hw_pci, which will get called when a bus is added or removed from the system.

This will be used for example by the Marvell PCIe driver to connect a particular PCI bus with its corresponding MSI chip to handle Message Signaled Interrupts.

---
 arch/arm/include/asm/mach/pci.h |  4 ++++
 arch/arm/kernel/bios32.c        | 16 ++++++++++++++++
 2 files changed, 20 insertions(+)
arch/arm/include/asm/mach/pci.h +4 -0
index a1c90d7..487155c 100644
@@ -36,6 +36,8 @@ struct hw_pci {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);
 };
 
 /*
@@ -63,6 +65,8 @@ struct pci_sys_data {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);
 	void		*private_data;	/* platform controller private data	*/
 };
 
arch/arm/kernel/bios32.c +16 -0
index 261fcc8..530e59d 100644
@@ -363,6 +363,20 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
+void pcibios_add_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	if (sys->add_bus)
+		sys->add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	if (sys->remove_bus)
+		sys->remove_bus(bus);
+}
+
 /*
  * Swizzle the device pin each time we cross a bridge.  If a platform does
  * not provide a swizzle function, we perform the standard PCI swizzling.
@@ -464,6 +478,8 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
 		sys->align_resource = hw->align_resource;
+		sys->add_bus        = hw->add_bus;
+		sys->remove_bus     = hw->remove_bus;
 		INIT_LIST_HEAD(&sys->resources);
 
 		if (hw->private_data)
Signature · 1 line
1.8.1.2
#24 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

Hello Russell,

Would it be possible to have your opinion on the below patch? It has already been sent on June, 19th and July, 1st, and I'd really like to see it merged for 3.12, as part of this series enabling MSI support for the Marvell PCIe driver.

Thanks!

Thomas

Quoted 75 lines · Thomas Petazzoni

Some PCI drivers may need to adjust the pci_bus structure after it has been allocated by the Linux PCI core. The PCI core allows architectures to implement the pcibios_add_bus() and pcibios_remove_bus() for this purpose. This commit therefore extends the hw_pci and pci_sys_data structures of the ARM PCI core to allow PCI drivers to register ->add_bus() and ->remove_bus() in hw_pci, which will get called when a bus is added or removed from the system.

This will be used for example by the Marvell PCIe driver to connect a particular PCI bus with its corresponding MSI chip to handle Message Signaled Interrupts.

---
 arch/arm/include/asm/mach/pci.h |  4 ++++
 arch/arm/kernel/bios32.c        | 16 ++++++++++++++++
 2 files changed, 20 insertions(+)
arch/arm/include/asm/mach/pci.h +4 -0
index a1c90d7..487155c 100644
@@ -36,6 +36,8 @@ struct hw_pci {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);
 };
 
 /*
@@ -63,6 +65,8 @@ struct pci_sys_data {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);
 	void		*private_data;	/* platform controller private data	*/
 };
 
arch/arm/kernel/bios32.c +16 -0
index 261fcc8..530e59d 100644
@@ -363,6 +363,20 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
+void pcibios_add_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	if (sys->add_bus)
+		sys->add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	if (sys->remove_bus)
+		sys->remove_bus(bus);
+}
+
 /*
  * Swizzle the device pin each time we cross a bridge.  If a platform does
  * not provide a swizzle function, we perform the standard PCI swizzling.
@@ -464,6 +478,8 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
 		sys->align_resource = hw->align_resource;
+		sys->add_bus        = hw->add_bus;
+		sys->remove_bus     = hw->remove_bus;
 		INIT_LIST_HEAD(&sys->resources);
 
 		if (hw->private_data)
Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#25 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

In reply to Thomas Petazzoni

On Mon, Jul 15, 2013 at 01:52:44PM +0200, Thomas Petazzoni wrote:
[...]

Hi Thomas,

I just noticed two minor issues, see below.

Quoted 1 line
arch/arm/include/asm/mach/pci.h +0 -0

[...]

arch/arm/include/asm/mach/pci.h struct hw_pci { · line 40

Quoted 6 lines
arch/arm/include/asm/mach/pci.h +2 -0
@@ -36,6 +36,8 @@ struct hw_pci {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);

This hunk...

arch/arm/include/asm/mach/pci.h struct pci_sys_data { · line 71

Quoted 8 lines
arch/arm/include/asm/mach/pci.h +2 -0
@@ -63,6 +65,8 @@ struct pci_sys_data {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);
 	void		*private_data;	/* platform controller private data	*/
 };

and this one use inconsistent indentation (spaces instead of tabs).

Quoted 1 line
arch/arm/kernel/bios32.c +0 -0

[...]

arch/arm/kernel/bios32.c static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, · line 482

Quoted 6 lines
arch/arm/kernel/bios32.c +2 -0
@@ -464,6 +478,8 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
 		sys->align_resource = hw->align_resource;
+		sys->add_bus        = hw->add_bus;
+		sys->remove_bus     = hw->remove_bus;

And this one aligns the '=' sign, whereas none of the other assignments do.

Might be nice to fix those up before sending them to Russell's patch tracker.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130725/6f6205d2/attachment.sig>

#26 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

Dear Thierry Reding,

Quoted 13 lines · Thierry Reding

I just noticed two minor issues, see below.

Quoted 1 line
arch/arm/include/asm/mach/pci.h +0 -0

[...]

arch/arm/include/asm/mach/pci.h struct hw_pci { · line 40

Quoted 6 lines
arch/arm/include/asm/mach/pci.h +2 -0
@@ -36,6 +36,8 @@ struct hw_pci {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);

This hunk...

Quoted 10 lines

arch/arm/include/asm/mach/pci.h struct pci_sys_data { · line 71

Quoted 8 lines
arch/arm/include/asm/mach/pci.h +2 -0
@@ -63,6 +65,8 @@ struct pci_sys_data {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);
 	void		*private_data;	/* platform controller private data	*/
 };

and this one use inconsistent indentation (spaces instead of tabs).

Hum, I must be missing something here. Looking at the patch you're quoting, and my code, I see one tab before 'void' in both cases, and spaces between 'void' and the (*function) in both cases.

Am I missing something here?

Quoted 11 lines
Quoted 1 line
arch/arm/kernel/bios32.c +0 -0

[...]

arch/arm/kernel/bios32.c static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, · line 482

Quoted 6 lines
arch/arm/kernel/bios32.c +2 -0
@@ -464,6 +478,8 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
 		sys->align_resource = hw->align_resource;
+		sys->add_bus        = hw->add_bus;
+		sys->remove_bus     = hw->remove_bus;

And this one aligns the '=' sign, whereas none of the other assignments do.

Right, will be fixed as part of PATCHv7.

Thanks,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#27 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

Quoted 28 lines · Thomas Petazzoni

Dear Thierry Reding,

Quoted 13 lines · Thierry Reding

I just noticed two minor issues, see below.

Quoted 1 line
arch/arm/include/asm/mach/pci.h +0 -0

[...]

arch/arm/include/asm/mach/pci.h struct hw_pci { · line 40

Quoted 6 lines
arch/arm/include/asm/mach/pci.h +2 -0
@@ -36,6 +36,8 @@ struct hw_pci {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);

This hunk...

Quoted 10 lines

arch/arm/include/asm/mach/pci.h struct pci_sys_data { · line 71

Quoted 8 lines
arch/arm/include/asm/mach/pci.h +2 -0
@@ -63,6 +65,8 @@ struct pci_sys_data {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);
 	void		*private_data;	/* platform controller private data	*/
 };

and this one use inconsistent indentation (spaces instead of tabs).

Quoted 5 lines

Hum, I must be missing something here. Looking at the patch you're quoting, and my code, I see one tab before 'void' in both cases, and spaces between 'void' and the (*function) in both cases.

Am I missing something here?

Perhaps I should've said "alignment" instead of "indentation" to make it more explicit. All other members use tabs to separate the data type and the field name, while the lines that you add use spaces.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/bb9e4d41/attachment.sig>

#28 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

Dear Thierry Reding,

Quoted 9 lines · Thierry Reding
Quoted 5 lines

Hum, I must be missing something here. Looking at the patch you're quoting, and my code, I see one tab before 'void' in both cases, and spaces between 'void' and the (*function) in both cases.

Am I missing something here?

Perhaps I should've said "alignment" instead of "indentation" to make it more explicit. All other members use tabs to separate the data type and the field name, while the lines that you add use spaces.

Ah, right, I understand now. Unfortunately, I've already sent PATCHv7 with some other fixes. So either Jason Cooper can fix this when applying, or I'll fix it if a PATCHv8 is needed for some other reason.

Thanks!

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#29 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

In reply to Thomas Petazzoni
Quoted 12 lines · Thomas Petazzoni

Some PCI drivers may need to adjust the pci_bus structure after it has been allocated by the Linux PCI core. The PCI core allows architectures to implement the pcibios_add_bus() and pcibios_remove_bus() for this purpose. This commit therefore extends the hw_pci and pci_sys_data structures of the ARM PCI core to allow PCI drivers to register ->add_bus() and ->remove_bus() in hw_pci, which will get called when a bus is added or removed from the system.

This will be used for example by the Marvell PCIe driver to connect a particular PCI bus with its corresponding MSI chip to handle Message Signaled Interrupts.

Quoted 6 lines
---
 arch/arm/include/asm/mach/pci.h |  4 ++++
 arch/arm/kernel/bios32.c        | 16 ++++++++++++++++
 2 files changed, 20 insertions(+)

Hi Russell,

Can we have your Acked-by on this patch so that it can be moved to a stable branch along with some of the other patches in this branch that both Marvell and Tegra PCIe drivers need?

Thanks,
Thierry

Quoted 60 lines
arch/arm/include/asm/mach/pci.h +4 -0
index a1c90d7..487155c 100644
@@ -36,6 +36,8 @@ struct hw_pci {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);
 };
 
 /*
@@ -63,6 +65,8 @@ struct pci_sys_data {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void            (*add_bus)(struct pci_bus *bus);
+	void            (*remove_bus)(struct pci_bus *bus);
 	void		*private_data;	/* platform controller private data	*/
 };
 
arch/arm/kernel/bios32.c +16 -0
index 261fcc8..530e59d 100644
@@ -363,6 +363,20 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
+void pcibios_add_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	if (sys->add_bus)
+		sys->add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	if (sys->remove_bus)
+		sys->remove_bus(bus);
+}
+
 /*
  * Swizzle the device pin each time we cross a bridge.  If a platform does
  * not provide a swizzle function, we perform the standard PCI swizzling.
@@ -464,6 +478,8 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
 		sys->align_resource = hw->align_resource;
+		sys->add_bus        = hw->add_bus;
+		sys->remove_bus     = hw->remove_bus;
 		INIT_LIST_HEAD(&sys->resources);
 
 		if (hw->private_data)
Signature · 1 line
1.8.1.2

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130725/28eff599/attachment.sig>

#30 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

Dear Thierry Reding,

Quoted 20 lines · Thierry Reding
Quoted 12 lines · Thomas Petazzoni

Some PCI drivers may need to adjust the pci_bus structure after it has been allocated by the Linux PCI core. The PCI core allows architectures to implement the pcibios_add_bus() and pcibios_remove_bus() for this purpose. This commit therefore extends the hw_pci and pci_sys_data structures of the ARM PCI core to allow PCI drivers to register ->add_bus() and ->remove_bus() in hw_pci, which will get called when a bus is added or removed from the system.

This will be used for example by the Marvell PCIe driver to connect a particular PCI bus with its corresponding MSI chip to handle Message Signaled Interrupts.

Quoted 6 lines
---
 arch/arm/include/asm/mach/pci.h |  4 ++++
 arch/arm/kernel/bios32.c        | 16 ++++++++++++++++
 2 files changed, 20 insertions(+)
Quoted 5 lines

Hi Russell,

Can we have your Acked-by on this patch so that it can be moved to a stable branch along with some of the other patches in this branch that both Marvell and Tegra PCIe drivers need?

I've pinged Russell a few times about this patch already, but haven't received feedback from him. Do you think I can just go ahead and submit the patch to Russell's patch system, after fixing the minor nits you mentioned?

Thanks,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#31 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

Quoted 25 lines · Thomas Petazzoni

Dear Thierry Reding,

Quoted 22 lines · Thierry Reding
Quoted 12 lines · Thomas Petazzoni

Some PCI drivers may need to adjust the pci_bus structure after it has been allocated by the Linux PCI core. The PCI core allows architectures to implement the pcibios_add_bus() and pcibios_remove_bus() for this purpose. This commit therefore extends the hw_pci and pci_sys_data structures of the ARM PCI core to allow PCI drivers to register ->add_bus() and ->remove_bus() in hw_pci, which will get called when a bus is added or removed from the system.

This will be used for example by the Marvell PCIe driver to connect a particular PCI bus with its corresponding MSI chip to handle Message Signaled Interrupts.

Quoted 6 lines
---
 arch/arm/include/asm/mach/pci.h |  4 ++++
 arch/arm/kernel/bios32.c        | 16 ++++++++++++++++
 2 files changed, 20 insertions(+)

Hi Russell,

Quoted 8 lines
Quoted 3 lines

Can we have your Acked-by on this patch so that it can be moved to a stable branch along with some of the other patches in this branch that both Marvell and Tegra PCIe drivers need?

I've pinged Russell a few times about this patch already, but haven't received feedback from him. Do you think I can just go ahead and submit the patch to Russell's patch system, after fixing the minor nits you mentioned?

When you do that, please ask Russell to place it in a publicly accessible, stable topic branch for us to base off of.

thx,

Jason.

#32 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

In reply to Thierry Reding
Quoted 20 lines · Thierry Reding
Quoted 12 lines · Thomas Petazzoni

Some PCI drivers may need to adjust the pci_bus structure after it has been allocated by the Linux PCI core. The PCI core allows architectures to implement the pcibios_add_bus() and pcibios_remove_bus() for this purpose. This commit therefore extends the hw_pci and pci_sys_data structures of the ARM PCI core to allow PCI drivers to register ->add_bus() and ->remove_bus() in hw_pci, which will get called when a bus is added or removed from the system.

This will be used for example by the Marvell PCIe driver to connect a particular PCI bus with its corresponding MSI chip to handle Message Signaled Interrupts.

Quoted 6 lines
---
 arch/arm/include/asm/mach/pci.h |  4 ++++
 arch/arm/kernel/bios32.c        | 16 ++++++++++++++++
 2 files changed, 20 insertions(+)
Quoted 5 lines

Hi Russell,

Can we have your Acked-by on this patch so that it can be moved to a stable branch along with some of the other patches in this branch that both Marvell and Tegra PCIe drivers need?

#33 lore raw

PATCH v5 8/11 ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci

Quoted 21 lines · Russell King - ARM Linux
Quoted 20 lines · Thierry Reding
Quoted 18 lines · Thomas Petazzoni

Some PCI drivers may need to adjust the pci_bus structure after it has been allocated by the Linux PCI core. The PCI core allows architectures to implement the pcibios_add_bus() and pcibios_remove_bus() for this purpose. This commit therefore extends the hw_pci and pci_sys_data structures of the ARM PCI core to allow PCI drivers to register ->add_bus() and ->remove_bus() in hw_pci, which will get called when a bus is added or removed from the system.

This will be used for example by the Marvell PCIe driver to connect a particular PCI bus with its corresponding MSI chip to handle Message Signaled Interrupts.

---
 arch/arm/include/asm/mach/pci.h |  4 ++++
 arch/arm/kernel/bios32.c        | 16 ++++++++++++++++
 2 files changed, 20 insertions(+)
Quoted 7 lines
Quoted 5 lines

Hi Russell,

Can we have your Acked-by on this patch so that it can be moved to a stable branch along with some of the other patches in this branch that both Marvell and Tegra PCIe drivers need?

Thanks, Russell.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130729/978fd981/attachment-0001.sig>

#34 lore raw

PATCH v5 9/11 ARM: mvebu: the MPIC now provides MSI controller features

In reply to Thomas Petazzoni

Adds the 'msi-controller' property to the main interrupt controller Device Tree node, to indicate that it can now behave as a MSI controller.

---
 arch/arm/boot/dts/armada-370-xp.dtsi | 1 +
 1 file changed, 1 insertion(+)
arch/arm/boot/dts/armada-370-xp.dtsi +1 -0
index 90b1176..ac0bbc0 100644
@@ -56,6 +56,7 @@
 				#interrupt-cells = <1>;
 				#size-cells = <1>;
 				interrupt-controller;
+				msi-controller;
 			};
 
 			coherency-fabric at 20200 {
Signature · 1 line
1.8.1.2
#35 lore raw

PATCH v5 10/11 PCI: mvebu: add support for MSI

In reply to Thomas Petazzoni

This commit adds support for Message Signaled Interrupts in the Marvell PCIe host controller. The work is very simple: it simply gets a reference to the msi_chip associated to the PCIe controller thanks to the msi-parent DT property, and stores this reference in the pci_bus structure. This is enough to let the Linux PCI core use the functions of msi_chip to setup and teardown MSIs.

---
 .../devicetree/bindings/pci/mvebu-pci.txt          |  3 +++
 drivers/pci/host/pci-mvebu.c                       | 26 ++++++++++++++++++++++
 2 files changed, 29 insertions(+)
Documentation/devicetree/bindings/pci/mvebu-pci.txt +3 -0
index f8d4058..77e0ffe 100644
@@ -12,6 +12,8 @@ Mandatory properties:
 - device_type, set to "pci"
 - ranges: ranges for the PCI memory and I/O regions, as well as the
   MMIO registers to control the PCIe interfaces.
+- msi-parent: Link to the hardware entity that serves as the Message
+  Signaled Interrupt controller for this PCI controller.
 
 In addition, the Device Tree node must have sub-nodes describing each
 PCIe interface, having the following mandatory properties:
@@ -46,6 +48,7 @@ pcie-controller {
 	#size-cells = <2>;
 
 	bus-range = <0x00 0xff>;
+	msi-parent = <&mpic>;
 
 	ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000   /* Port 0.0 registers */
 		  0x82000000 0 0xd0042000 0xd0042000 0 0x00002000   /* Port 2.0 registers */
drivers/pci/host/pci-mvebu.c +26 -0
index 13a633b..5715a97 100644
@@ -11,6 +11,7 @@
 #include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/mbus.h>
+#include <linux/msi.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/of_address.h>
@@ -107,6 +108,7 @@ struct mvebu_pcie_port;
 struct mvebu_pcie {
 	struct platform_device *pdev;
 	struct mvebu_pcie_port *ports;
+	struct msi_chip *msi;
 	struct resource io;
 	struct resource realio;
 	struct resource mem;
@@ -695,6 +697,12 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
 	return bus;
 }
 
+void mvebu_pcie_add_bus(struct pci_bus *bus)
+{
+	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
+	bus->msi = pcie->msi;
+}
+
 resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
 					  const struct resource *res,
 					  resource_size_t start,
@@ -731,6 +739,7 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)
 	hw.map_irq        = mvebu_pcie_map_irq;
 	hw.ops            = &mvebu_pcie_ops;
 	hw.align_resource = mvebu_pcie_align_resource;
+	hw.add_bus        = mvebu_pcie_add_bus;
 
 	pci_common_init(&hw);
 }
@@ -755,6 +764,21 @@ mvebu_pcie_map_registers(struct platform_device *pdev,
 	return devm_request_and_ioremap(&pdev->dev, &regs);
 }
 
+static void __init mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
+{
+	struct device_node *msi_node;
+
+	msi_node = of_parse_phandle(pcie->pdev->dev.of_node,
+				    "msi-parent", 0);
+	if (!msi_node)
+		return;
+
+	pcie->msi = of_pci_find_msi_chip_by_node(msi_node);
+
+	if (pcie->msi)
+		pcie->msi->dev = &pcie->pdev->dev;
+}
+
 static int __init mvebu_pcie_probe(struct platform_device *pdev)
 {
 	struct mvebu_pcie *pcie;
@@ -879,6 +903,8 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
 		i++;
 	}
 
+	mvebu_pcie_msi_enable(pcie);
+
 	mvebu_pcie_enable(pcie);
 
 	return 0;
Signature · 1 line
1.8.1.2
#36 lore raw

PATCH v5 11/11 ARM: mvebu: link PCIe controllers to the MSI controller

In reply to Thomas Petazzoni

This commit adjusts the Armada 370 and Armada XP PCIe controllers Device Tree informations to reference their MSI controller. In the case of this platform, the MSI controller is implemented by the MPIC.

---
 arch/arm/boot/dts/armada-370.dtsi        | 1 +
 arch/arm/boot/dts/armada-xp-mv78230.dtsi | 1 +
 arch/arm/boot/dts/armada-xp-mv78260.dtsi | 1 +
 arch/arm/boot/dts/armada-xp-mv78460.dtsi | 1 +
 4 files changed, 4 insertions(+)
arch/arm/boot/dts/armada-370.dtsi +1 -0
index fa3dfc6..a60018d 100644
@@ -178,6 +178,7 @@
 				#address-cells = <3>;
 				#size-cells = <2>;
 
+				msi-parent = <&mpic>;
 				bus-range = <0x00 0xff>;
 
 				ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000   /* Port 0.0 registers */
arch/arm/boot/dts/armada-xp-mv78230.dtsi +1 -0
index f8eaa38..4a9a305 100644
@@ -91,6 +91,7 @@
 #address-cells = <3>;
 #size-cells = <2>;
 
+				msi-parent = <&mpic>;
 				bus-range = <0x00 0xff>;
 
 				ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000   /* Port 0.0 registers */
arch/arm/boot/dts/armada-xp-mv78260.dtsi +1 -0
index 2d9335d..dd23e96 100644
@@ -111,6 +111,7 @@
 				#address-cells = <3>;
 				#size-cells = <2>;
 
+				msi-parent = <&mpic>;
 				bus-range = <0x00 0xff>;
 
 				ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000   /* Port 0.0 registers */
arch/arm/boot/dts/armada-xp-mv78460.dtsi +1 -0
index c7b1f4d..77db2bc 100644
@@ -127,6 +127,7 @@
 				#address-cells = <3>;
 				#size-cells = <2>;
 
+				msi-parent = <&mpic>;
 				bus-range = <0x00 0xff>;
 
 				ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000   /* Port 0.0 registers */
Signature · 1 line
1.8.1.2
#37 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

In reply to Thomas Petazzoni
Quoted 11 lines · Thomas Petazzoni

Hello,

This set of patches introduces Message Signaled Interrupt support in the Marvell EBU PCIe driver. It has been successfully tested on the Armada XP GP platform with an Intel e1000e PCIe network card that supports MSI.

This patch set is intended for merging in 3.12, so the respective maintainers of the different areas are invited to review/ack the patches, see below for the details. This set of patches applies on top of 3.11-rc1.

Thomas, who is going to merge this series?

I believe at least patches 1-8 (or perhaps just 1-5 plus 8; I /think/ all the other patches are MVEBU-specific) are dependencies for the new Tegra PCIe driver which should be posted very soon for 3.12. As such, I'd like to see these dependencies merged into a standalone stable (100% non-rebasable) topic branch based on 3.11-rc1 so that the topic branch is available for merging into whichever tree takes the new Tegra PCIe driver (which I'm guessing will be the Tegra tree to reduce conflicts). So, whoever merges these patches is going to need to know to set up that topic branch.

Thierry, please correct me if I'm wrong here.

#38 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Quoted 25 lines · Stephen Warren
Quoted 11 lines · Thomas Petazzoni

Hello,

This set of patches introduces Message Signaled Interrupt support in the Marvell EBU PCIe driver. It has been successfully tested on the Armada XP GP platform with an Intel e1000e PCIe network card that supports MSI.

This patch set is intended for merging in 3.12, so the respective maintainers of the different areas are invited to review/ack the patches, see below for the details. This set of patches applies on top of 3.11-rc1.

Thomas, who is going to merge this series?

I believe at least patches 1-8 (or perhaps just 1-5 plus 8; I /think/ all the other patches are MVEBU-specific) are dependencies for the new Tegra PCIe driver which should be posted very soon for 3.12. As such, I'd like to see these dependencies merged into a standalone stable (100% non-rebasable) topic branch based on 3.11-rc1 so that the topic branch is available for merging into whichever tree takes the new Tegra PCIe driver (which I'm guessing will be the Tegra tree to reduce conflicts). So, whoever merges these patches is going to need to know to set up that topic branch.

Quoted 1 line

Thierry, please correct me if I'm wrong here.

We need at least patches 2, 4 and 8 for Tegra. There's still the option of working around patch 8 by using the custom root bus scan function that we have to use anyway, so I guess we could even trim the requirement down to patches 2 and 4 if we really need.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130715/97e67ff4/attachment.sig>

#39 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Dear Thierry Reding,

Quoted 1 line · Thierry Reding

We need at least patches 2, 4 and 8 for Tegra.

Are you sure you don't want patch 1 ? It allows to replace the allocation of MSI interrupt numbers for the MSI driver by a generic facility based on irq domains.

Quoted 4 lines

There's still the option
of working around patch 8 by using the custom root bus scan function that we have to use anyway, so I guess we could even trim the requirement down to patches 2 and 4 if we really need.

Bjorn said he didn't like having the msi chip assignment in the middle of the root bus scan function, because he was hoping someday to refactor this function. Quoting Bjorn:

"""

Review

Quoted 1 line
(quoted diff) +1 -0
+	bus->msi = pcie->msi;  

Ideally, arches could use pci_scan_root_bus(), which does the pci_scan_child_bus() itself, so I never like to add arch-specific code between pci_create_root_bus() and pci_scan_child_bus().

But you should be able to accomplish this by setting bus->msi in a pcibios_add_bus() hook. There is a corresponding pcibios_remove_bus() hook that might be useful for deallocating the msi_chip. I'm not too clear on how you manage the msi_chip lifetime -- I see the alloc in armada_370_xp_msi_init(), but I'm not sure whether you ever deallocate it or how you know when it would be safe to do so.
"""

This is from:

Subject: Re: [PATCH v2 6/8] pci: mvebu: add support for MSI
Date: Tue, 18 Jun 2013 16:57:11 -0600

Best regards,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#40 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Quoted 9 lines · Thomas Petazzoni

Dear Thierry Reding,

Quoted 1 line · Thierry Reding

We need at least patches 2, 4 and 8 for Tegra.

Are you sure you don't want patch 1 ? It allows to replace the allocation of MSI interrupt numbers for the MSI driver by a generic facility based on irq domains.

Yes, I could use it to replace some of the functionality. I was just saying that we don't absolutely need it. If it makes things easier for the merge, it would be trivial to convert the Tegra driver to using the new generic facility in a follow-up patch.

Quoted 24 lines
Quoted 4 lines

There's still the option
of working around patch 8 by using the custom root bus scan function that we have to use anyway, so I guess we could even trim the requirement down to patches 2 and 4 if we really need.

Bjorn said he didn't like having the msi chip assignment in the middle of the root bus scan function, because he was hoping someday to refactor this function. Quoting Bjorn:

"""

Review

Quoted 1 line
(quoted diff) +1 -0
+	bus->msi = pcie->msi;  

Ideally, arches could use pci_scan_root_bus(), which does the pci_scan_child_bus() itself, so I never like to add arch-specific code between pci_create_root_bus() and pci_scan_child_bus().

But you should be able to accomplish this by setting bus->msi in a pcibios_add_bus() hook. There is a corresponding pcibios_remove_bus() hook that might be useful for deallocating the msi_chip. I'm not too clear on how you manage the msi_chip lifetime -- I see the alloc in armada_370_xp_msi_init(), but I'm not sure whether you ever deallocate it or how you know when it would be safe to do so.
"""

Quoted 4 lines

This is from:

Subject: Re: [PATCH v2 6/8] pci: mvebu: add support for MSI
Date: Tue, 18 Jun 2013 16:57:11 -0600

Yes, I'm aware of that discussion. However we currently need to have the custom root bus scan implementation anyway because pci_scan_root_bus() just doesn't work on ARM. So again, since we'll have to rework the driver anyway in order to use pci_scan_root_bus() once the issues have been resolved, it wouldn't hurt to postpone the transition to the new ARM pcibios_add_bus() support until that point.

All I was trying to do was reduce the list of common dependencies in an attempt to make merging it easier.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130716/917057ff/attachment.sig>

#41 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Thierry,

Quoted 12 lines · Thierry Reding
Quoted 4 lines

This is from:

Subject: Re: [PATCH v2 6/8] pci: mvebu: add support for MSI
Date: Tue, 18 Jun 2013 16:57:11 -0600

Yes, I'm aware of that discussion. However we currently need to have the custom root bus scan implementation anyway because pci_scan_root_bus() just doesn't work on ARM. So again, since we'll have to rework the driver anyway in order to use pci_scan_root_bus() once the issues have been resolved, it wouldn't hurt to postpone the transition to the new ARM pcibios_add_bus() support until that point.

Quoted 2 lines

All I was trying to do was reduce the list of common dependencies in an attempt to make merging it easier.

Understood. Bjorn, since you are the one who originally requested the usage of pcibios_add_bus(), would you agree with the idea proposed by Thierry? It would remove one dependency for both the Marvell MSI support and Tegra PCIe support, which would help getting this code merged.

As Thierry points out, this can easily be resolved at a later point, once the new hooks are merged in the ARM PCI core.

Thanks,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
maintainer
#42 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Quoted 19 lines · Thomas Petazzoni

Thierry,

Quoted 12 lines · Thierry Reding
Quoted 4 lines

This is from:

Subject: Re: [PATCH v2 6/8] pci: mvebu: add support for MSI
Date: Tue, 18 Jun 2013 16:57:11 -0600

Yes, I'm aware of that discussion. However we currently need to have the custom root bus scan implementation anyway because pci_scan_root_bus() just doesn't work on ARM. So again, since we'll have to rework the driver anyway in order to use pci_scan_root_bus() once the issues have been resolved, it wouldn't hurt to postpone the transition to the new ARM pcibios_add_bus() support until that point.

Quoted 2 lines

All I was trying to do was reduce the list of common dependencies in an attempt to make merging it easier.

Quoted 8 lines

Understood. Bjorn, since you are the one who originally requested the usage of pcibios_add_bus(), would you agree with the idea proposed by Thierry? It would remove one dependency for both the Marvell MSI support and Tegra PCIe support, which would help getting this code merged.

As Thierry points out, this can easily be resolved at a later point, once the new hooks are merged in the ARM PCI core.

Yep, that's fine with me.

#43 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

In reply to Stephen Warren
Quoted 8 lines · Stephen Warren
Quoted 7 lines · Thomas Petazzoni

Hello,

This set of patches introduces Message Signaled Interrupt support in the Marvell EBU PCIe driver. It has been successfully tested on the Armada XP GP platform with an Intel e1000e PCIe network card that supports MSI.

Quoted 6 lines
Quoted 4 lines

This patch set is intended for merging in 3.12, so the respective maintainers of the different areas are invited to review/ack the patches, see below for the details. This set of patches applies on top of 3.11-rc1.

Thomas, who is going to merge this series?

In a previous version of this series, Thomas and I discussed the feasibility of sending the irq changes through tglx, the pci changes through Bjorn, and the mvebu stuff through us. With that version, Thomas felt it would work out fine, without depending on each other.

If this is still the case, we'll just ask Thomas and Bjorn (or, at least Bjorn) to make topic branches for us.

thx,

Jason.

#44 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

In reply to Stephen Warren

Dear Stephen Warren,

Quoted 6 lines · Stephen Warren
Quoted 4 lines

This patch set is intended for merging in 3.12, so the respective maintainers of the different areas are invited to review/ack the patches, see below for the details. This set of patches applies on top of 3.11-rc1.

Thomas, who is going to merge this series?

I don't know. There are quite a few build dependencies in there:

* PATCH 7 build depends on PATCH 1 and PATCH 5, and obviously depends on PATCH 6.

* PATCH 2 to 5 really are one thing, they depend on each other.

* PATCH 10 build depends on PATCH 5 and PATCH 8.

A quick diagram of the dependencies, best viewed with a fixed-size font mailer.

kernel/irq/irqdomain drivers/pci arch/arm/kernel

     patch 1           patch 2, 3, 4           patch 8
        ||                  ||                   ||
        ||                  \/                   \/
        ||               drivers/of   ==> drivers/pci/host
        ||                patch 5           patch 10
        ||                  ||
        \\__________________//
                  ||
                  \/
            drivers/irqchip
              patch 6, 7

Patches 9 and 11 are DT patches, so they are not mentioned in this diagram.

Normally tegra would require 1, 2, 3, 4, 5 and 8, so ideally, with the respective maintainers ACKs, Jason Cooper could take them in a specific topic stable branch that would not be rebased, on top of which both the Marvell work and Tegra work could be done.

I really would like to see those patches very soon in linux-next, in order to get some build coverage, especially for the 2, 3 and 4 patches that touch a number of architectures.

Thanks,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#45 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Quoted 24 lines · Thomas Petazzoni

Dear Stephen Warren,

Quoted 6 lines · Stephen Warren
Quoted 4 lines

This patch set is intended for merging in 3.12, so the respective maintainers of the different areas are invited to review/ack the patches, see below for the details. This set of patches applies on top of 3.11-rc1.

Thomas, who is going to merge this series?

I don't know. There are quite a few build dependencies in there:

* PATCH 7 build depends on PATCH 1 and PATCH 5, and obviously depends on PATCH 6.

* PATCH 2 to 5 really are one thing, they depend on each other.

* PATCH 10 build depends on PATCH 5 and PATCH 8.

A quick diagram of the dependencies, best viewed with a fixed-size font mailer.

kernel/irq/irqdomain drivers/pci arch/arm/kernel

Quoted 11 lines
     patch 1           patch 2, 3, 4           patch 8
        ||                  ||                   ||
        ||                  \/                   \/
        ||               drivers/of   ==> drivers/pci/host
        ||                patch 5           patch 10
        ||                  ||
        \\__________________//
                  ||
                  \/
            drivers/irqchip
              patch 6, 7

Well, that got more complicated. :( No cookie for you.

Quoted 7 lines

Patches 9 and 11 are DT patches, so they are not mentioned in this diagram.

Normally tegra would require 1, 2, 3, 4, 5 and 8, so ideally, with the respective maintainers ACKs, Jason Cooper could take them in a specific topic stable branch that would not be rebased, on top of which both the Marvell work and Tegra work could be done.

After my recent discussions with tglx, here's my proposal:

- rmk creates a dedicated topic branch with patch 8

- Bjorn creates a dedicated topic branch based on rmk's with 2, 3, 4, 5, and 10

- tglx creates a dedicated topic branch based on Bjorn's with 1, 6, 7

- I take 9 and 11.

For Tegra, tglx can tag patch 1 for merging. Tegra will 'adopt' patch 10, but that shouldn't hurt anything.

thx,

Jason.

#46 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Dear Jason Cooper,

Quoted 16 lines · Jason Cooper
Quoted 4 lines

A quick diagram of the dependencies, best viewed with a fixed-size font mailer.

kernel/irq/irqdomain drivers/pci arch/arm/kernel

Quoted 11 lines
     patch 1           patch 2, 3, 4           patch 8
        ||                  ||                   ||
        ||                  \/                   \/
        ||               drivers/of   ==> drivers/pci/host
        ||                patch 5           patch 10
        ||                  ||
        \\__________________//
                  ||
                  \/
            drivers/irqchip
              patch 6, 7
Quoted 1 line

Well, that got more complicated. :( No cookie for you.

Yeah, sorry about this. I'm not sure how to handle that differently.

Quoted 8 lines
Quoted 7 lines

Patches 9 and 11 are DT patches, so they are not mentioned in this diagram.

Normally tegra would require 1, 2, 3, 4, 5 and 8, so ideally, with the respective maintainers ACKs, Jason Cooper could take them in a specific topic stable branch that would not be rebased, on top of which both the Marvell work and Tegra work could be done.

Quoted 8 lines

After my recent discussions with tglx, here's my proposal:

- rmk creates a dedicated topic branch with patch 8

- Bjorn creates a dedicated topic branch based on rmk's with 2, 3, 4, 5, and 10

- tglx creates a dedicated topic branch based on Bjorn's with 1, 6, 7

I am wondering if this merge strategy isn't too complicated to work nicely. Would it be easier if one person took all of those patches in a stable topic branch, with the ACKs from the proper maintainers?

But anyway, as long as things get merged, I don't really mind what merge strategy is used, so I'll trust on what will be the best option on this.

Thanks a lot for taking care of this!

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#47 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Quoted 45 lines · Thomas Petazzoni

Dear Jason Cooper,

Quoted 16 lines · Jason Cooper
Quoted 4 lines

A quick diagram of the dependencies, best viewed with a fixed-size font mailer.

kernel/irq/irqdomain drivers/pci arch/arm/kernel

Quoted 11 lines
     patch 1           patch 2, 3, 4           patch 8
        ||                  ||                   ||
        ||                  \/                   \/
        ||               drivers/of   ==> drivers/pci/host
        ||                patch 5           patch 10
        ||                  ||
        \\__________________//
                  ||
                  \/
            drivers/irqchip
              patch 6, 7
Quoted 1 line

Well, that got more complicated. :( No cookie for you.

Yeah, sorry about this. I'm not sure how to handle that differently.

Quoted 8 lines
Quoted 7 lines

Patches 9 and 11 are DT patches, so they are not mentioned in this diagram.

Normally tegra would require 1, 2, 3, 4, 5 and 8, so ideally, with the respective maintainers ACKs, Jason Cooper could take them in a specific topic stable branch that would not be rebased, on top of which both the Marvell work and Tegra work could be done.

Quoted 8 lines

After my recent discussions with tglx, here's my proposal:

- rmk creates a dedicated topic branch with patch 8

- Bjorn creates a dedicated topic branch based on rmk's with 2, 3, 4, 5, and 10

- tglx creates a dedicated topic branch based on Bjorn's with 1, 6, 7

I am wondering if this merge strategy isn't too complicated to work nicely. Would it be easier if one person took all of those patches in a stable topic branch, with the ACKs from the proper maintainers?

Quoted 5 lines

But anyway, as long as things get merged, I don't really mind what merge strategy is used, so I'll trust on what will be the best option on this.

Thanks a lot for taking care of this!

Hi Thomas, Jason,

I've talked this over with Stephen and he'd be willing to create the stable branch with patches 2, 4 and 8. That could serve as the basis for both Tegra and Marvell.

Given that there are no cross-dependencies for any of the other patches (that I'm aware of) it would probably be easier to take them through the Marvell tree if Bjorn and Thomas (tglx) agree to Ack the patches.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130725/a1eb8ff1/attachment.sig>

#48 lore raw

v5 cover MSI support for Marvell EBU PCIe driver

Thomas (tglx), Russell (rmk),

Please see my request below.

Quoted 54 lines · Thierry Reding
Quoted 45 lines · Thomas Petazzoni

Dear Jason Cooper,

Quoted 16 lines · Jason Cooper
Quoted 4 lines

A quick diagram of the dependencies, best viewed with a fixed-size font mailer.

kernel/irq/irqdomain drivers/pci arch/arm/kernel

Quoted 11 lines
     patch 1           patch 2, 3, 4           patch 8
        ||                  ||                   ||
        ||                  \/                   \/
        ||               drivers/of   ==> drivers/pci/host
        ||                patch 5           patch 10
        ||                  ||
        \\__________________//
                  ||
                  \/
            drivers/irqchip
              patch 6, 7
Quoted 1 line

Well, that got more complicated. :( No cookie for you.

Yeah, sorry about this. I'm not sure how to handle that differently.

Quoted 8 lines
Quoted 7 lines

Patches 9 and 11 are DT patches, so they are not mentioned in this diagram.

Normally tegra would require 1, 2, 3, 4, 5 and 8, so ideally, with the respective maintainers ACKs, Jason Cooper could take them in a specific topic stable branch that would not be rebased, on top of which both the Marvell work and Tegra work could be done.

Quoted 8 lines

After my recent discussions with tglx, here's my proposal:

- rmk creates a dedicated topic branch with patch 8

- Bjorn creates a dedicated topic branch based on rmk's with 2, 3, 4, 5, and 10

- tglx creates a dedicated topic branch based on Bjorn's with 1, 6, 7

I am wondering if this merge strategy isn't too complicated to work nicely. Would it be easier if one person took all of those patches in a stable topic branch, with the ACKs from the proper maintainers?

Quoted 5 lines

But anyway, as long as things get merged, I don't really mind what merge strategy is used, so I'll trust on what will be the best option on this.

Thanks a lot for taking care of this!

Hi Thomas, Jason,

Quoted 7 lines

I've talked this over with Stephen and he'd be willing to create the stable branch with patches 2, 4 and 8. That could serve as the basis for both Tegra and Marvell.

Given that there are no cross-dependencies for any of the other patches (that I'm aware of) it would probably be easier to take them through the Marvell tree if Bjorn and Thomas (tglx) agree to Ack the patches.

Ok, this is getting complicated again. :( I'm all for adhering to Thomas' (tglx) request that all clocksource and irqchip patches go through his tree. However, this series is just a hot-dependency mess.

Thomas, Russell, can you please cut me a little slack on this series and Ack your respective patches (tglx: #1, #6, #7; rmk: #8) for going through arm-soc?

I know it's not the proper way, but I could have this series in -next tomorrow with a public branch for Thierry. The alternative is turning into a Rube Goldberg machine [1].

thx,

Jason.

[1] https://en.wikipedia.org/wiki/Rube_Goldberg_machine