* [PATCHv8 01/10] PCI: use weak functions for MSI arch-specific functions
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-08 22:39 ` Benjamin Herrenschmidt
2013-08-08 22:17 ` [PATCHv8 02/10] PCI: remove ARCH_SUPPORTS_MSI kconfig option Thomas Petazzoni
` (9 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
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 two separate, non-weak, functions
default_teardown_msi_irqs() and default_restore_msi_irqs() for the
default behavior of the arch_teardown_msi_irqs() and
arch_restore_msi_irqs(), as the default behavior is needed by x86 PCI
code.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Daniel Price <daniel.price@gmail.com>
Tested-by: Thierry Reding <thierry.reding@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev at lists.ozlabs.org
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux390 at de.ibm.com
Cc: linux-s390 at vger.kernel.org
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: x86 at kernel.org
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64 at vger.kernel.org
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips at linux-mips.org
Cc: David S. Miller <davem@davemloft.net>
Cc: sparclinux at vger.kernel.org
Cc: Chris Metcalf <cmetcalf@tilera.com>
---
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 | 48 +++++++++++++++++++++---------------------
include/linux/msi.h | 8 ++++++-
7 files changed, 52 insertions(+), 67 deletions(-)
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index fa8e0aa..f194c08 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -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
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 6653f27..95145a1 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -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,
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 6e577ba..262b91b 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -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 */
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index d9e9e6c..8c61de0 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -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
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 5f24c71..4c374a9 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -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,
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index aca7578..823c386 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -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,14 +87,12 @@ 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)
{
struct msi_desc *entry;
@@ -114,7 +110,11 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)
if (entry)
write_msi_msg(irq, &entry->msg);
}
-#endif
+
+void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq)
+{
+ return default_restore_msi_irqs(dev, irq);
+}
static void msi_set_enable(struct pci_dev *dev, int enable)
{
diff --git a/include/linux/msi.h b/include/linux/msi.h
index ee66f3a..271dfd1 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -51,12 +51,18 @@ 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);
+void default_restore_msi_irqs(struct pci_dev *dev, int irq);
#endif /* LINUX_MSI_H */
--
1.8.1.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 01/10] PCI: use weak functions for MSI arch-specific functions
2013-08-08 22:17 ` [PATCHv8 01/10] PCI: use weak functions for MSI arch-specific functions Thomas Petazzoni
@ 2013-08-08 22:39 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-08 22:39 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
> 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 two separate, non-weak, functions
> default_teardown_msi_irqs() and default_restore_msi_irqs() for the
> default behavior of the arch_teardown_msi_irqs() and
> arch_restore_msi_irqs(), as the default behavior is needed by x86 PCI
> code.
Looks good, I'll give it a quick spin to make sure there is no
accidental breakage on ppc today.
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> Tested-by: Daniel Price <daniel.price@gmail.com>
> Tested-by: Thierry Reding <thierry.reding@gmail.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: linuxppc-dev at lists.ozlabs.org
> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
> Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
> Cc: linux390 at de.ibm.com
> Cc: linux-s390 at vger.kernel.org
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: H. Peter Anvin <hpa@zytor.com>
> Cc: x86 at kernel.org
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Tony Luck <tony.luck@intel.com>
> Cc: Fenghua Yu <fenghua.yu@intel.com>
> Cc: linux-ia64 at vger.kernel.org
> Cc: Ralf Baechle <ralf@linux-mips.org>
> Cc: linux-mips at linux-mips.org
> Cc: David S. Miller <davem@davemloft.net>
> Cc: sparclinux at vger.kernel.org
> Cc: Chris Metcalf <cmetcalf@tilera.com>
> ---
> 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 | 48 +++++++++++++++++++++---------------------
> include/linux/msi.h | 8 ++++++-
> 7 files changed, 52 insertions(+), 67 deletions(-)
>
> diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
> index fa8e0aa..f194c08 100644
> --- a/arch/mips/include/asm/pci.h
> +++ b/arch/mips/include/asm/pci.h
> @@ -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
> diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
> index 6653f27..95145a1 100644
> --- a/arch/powerpc/include/asm/pci.h
> +++ b/arch/powerpc/include/asm/pci.h
> @@ -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,
> diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
> index 6e577ba..262b91b 100644
> --- a/arch/s390/include/asm/pci.h
> +++ b/arch/s390/include/asm/pci.h
> @@ -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 */
>
> diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> index d9e9e6c..8c61de0 100644
> --- a/arch/x86/include/asm/pci.h
> +++ b/arch/x86/include/asm/pci.h
> @@ -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
> diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
> index 5f24c71..4c374a9 100644
> --- a/arch/x86/kernel/x86_init.c
> +++ b/arch/x86/kernel/x86_init.c
> @@ -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,
> diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
> index aca7578..823c386 100644
> --- a/drivers/pci/msi.c
> +++ b/drivers/pci/msi.c
> @@ -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,14 +87,12 @@ 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)
> {
> struct msi_desc *entry;
> @@ -114,7 +110,11 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)
> if (entry)
> write_msi_msg(irq, &entry->msg);
> }
> -#endif
> +
> +void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq)
> +{
> + return default_restore_msi_irqs(dev, irq);
> +}
>
> static void msi_set_enable(struct pci_dev *dev, int enable)
> {
> diff --git a/include/linux/msi.h b/include/linux/msi.h
> index ee66f3a..271dfd1 100644
> --- a/include/linux/msi.h
> +++ b/include/linux/msi.h
> @@ -51,12 +51,18 @@ 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);
> +void default_restore_msi_irqs(struct pci_dev *dev, int irq);
>
> #endif /* LINUX_MSI_H */
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 02/10] PCI: remove ARCH_SUPPORTS_MSI kconfig option
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
2013-08-08 22:17 ` [PATCHv8 01/10] PCI: use weak functions for MSI arch-specific functions Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-08 22:39 ` Benjamin Herrenschmidt
2013-08-08 22:17 ` [PATCHv8 03/10] PCI: Introduce new MSI chip infrastructure Thomas Petazzoni
` (8 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
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.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Daniel Price <daniel.price@gmail.com>
Tested-by: Thierry Reding <thierry.reding@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev at lists.ozlabs.org
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux390 at de.ibm.com
Cc: linux-s390 at vger.kernel.org
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: x86 at kernel.org
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64 at vger.kernel.org
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips at linux-mips.org
Cc: David S. Miller <davem@davemloft.net>
Cc: sparclinux at vger.kernel.org
Cc: Chris Metcalf <cmetcalf@tilera.com>
---
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(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 37c0f4e..41b6c96 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 5a768ad..098602b 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -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
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c3abed3..01b5f5a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -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
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3bf72cd..183a165 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -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
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 22f75b5..e9982a3 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -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.
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index a00cbd3..1570ad2 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -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
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 24565a7..74dff90 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -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
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b32ebf9..5db62ef 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -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
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 81944fb..b6a99f7 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -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
--
1.8.1.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 02/10] PCI: remove ARCH_SUPPORTS_MSI kconfig option
2013-08-08 22:17 ` [PATCHv8 02/10] PCI: remove ARCH_SUPPORTS_MSI kconfig option Thomas Petazzoni
@ 2013-08-08 22:39 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-08 22:39 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
> 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.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> Tested-by: Daniel Price <daniel.price@gmail.com>
> Tested-by: Thierry Reding <thierry.reding@gmail.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: linuxppc-dev at lists.ozlabs.org
> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
> Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
> Cc: linux390 at de.ibm.com
> Cc: linux-s390 at vger.kernel.org
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: H. Peter Anvin <hpa@zytor.com>
> Cc: x86 at kernel.org
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Tony Luck <tony.luck@intel.com>
> Cc: Fenghua Yu <fenghua.yu@intel.com>
> Cc: linux-ia64 at vger.kernel.org
> Cc: Ralf Baechle <ralf@linux-mips.org>
> Cc: linux-mips at linux-mips.org
> Cc: David S. Miller <davem@davemloft.net>
> Cc: sparclinux at vger.kernel.org
> Cc: Chris Metcalf <cmetcalf@tilera.com>
> ---
> 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(-)
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 37c0f4e..41b6c96 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -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
> diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
> index 5a768ad..098602b 100644
> --- a/arch/ia64/Kconfig
> +++ b/arch/ia64/Kconfig
> @@ -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
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index c3abed3..01b5f5a 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -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
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 3bf72cd..183a165 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -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
> diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
> index 22f75b5..e9982a3 100644
> --- a/arch/s390/Kconfig
> +++ b/arch/s390/Kconfig
> @@ -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.
> diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
> index a00cbd3..1570ad2 100644
> --- a/arch/sparc/Kconfig
> +++ b/arch/sparc/Kconfig
> @@ -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
> diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
> index 24565a7..74dff90 100644
> --- a/arch/tile/Kconfig
> +++ b/arch/tile/Kconfig
> @@ -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
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index b32ebf9..5db62ef 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -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
> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> index 81944fb..b6a99f7 100644
> --- a/drivers/pci/Kconfig
> +++ b/drivers/pci/Kconfig
> @@ -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
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 03/10] PCI: Introduce new MSI chip infrastructure
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
2013-08-08 22:17 ` [PATCHv8 01/10] PCI: use weak functions for MSI arch-specific functions Thomas Petazzoni
2013-08-08 22:17 ` [PATCHv8 02/10] PCI: remove ARCH_SUPPORTS_MSI kconfig option Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-08 22:17 ` [PATCHv8 04/10] of: pci: add registry of MSI chips Thomas Petazzoni
` (7 subsequent siblings)
10 siblings, 0 replies; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
From: Thierry Reding <thierry.reding@avionic-design.de>
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.
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Daniel Price <daniel.price@gmail.com>
Tested-by: Thierry Reding <thierry.reding@gmail.com>
---
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(-)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 823c386..2837285 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -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)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 46ada5c..b8eaa81 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -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;
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 271dfd1..090ddad 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -65,4 +65,15 @@ void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
void default_teardown_msi_irqs(struct pci_dev *dev);
void default_restore_msi_irqs(struct pci_dev *dev, int irq);
+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 */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0fd1f15..4044e3c 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -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
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 04/10] of: pci: add registry of MSI chips
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
` (2 preceding siblings ...)
2013-08-08 22:17 ` [PATCHv8 03/10] PCI: Introduce new MSI chip infrastructure Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-09 5:49 ` Benjamin Herrenschmidt
2013-08-09 5:59 ` Benjamin Herrenschmidt
2013-08-08 22:17 ` [PATCHv8 05/10] irqchip: armada-370-xp: properly request resources Thomas Petazzoni
` (6 subsequent siblings)
10 siblings, 2 replies; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
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'.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/of/of_pci.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/msi.h | 2 ++
include/linux/of_pci.h | 12 ++++++++++++
3 files changed, 59 insertions(+)
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 42c687a..e5ca008 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -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 */
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 090ddad..b17ead8 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -68,6 +68,8 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq);
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);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 7a04826..29631eb 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -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
--
1.8.1.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 04/10] of: pci: add registry of MSI chips
2013-08-08 22:17 ` [PATCHv8 04/10] of: pci: add registry of MSI chips Thomas Petazzoni
@ 2013-08-09 5:49 ` Benjamin Herrenschmidt
2013-08-09 11:42 ` Jason Cooper
2013-08-09 13:44 ` Jason Cooper
2013-08-09 5:59 ` Benjamin Herrenschmidt
1 sibling, 2 replies; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-09 5:49 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
>
> +#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) { }
Missing a ; at the end of the above line... breaks the build of
CONFIG_PCI_MSI is not set.
> +static inline struct msi_chip *
> +of_pci_find_msi_chip_by_node(struct device_node *of_node) { return
> NULL };
> +#endif
> +
> #endif
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 04/10] of: pci: add registry of MSI chips
2013-08-09 5:49 ` Benjamin Herrenschmidt
@ 2013-08-09 11:42 ` Jason Cooper
2013-08-09 13:44 ` Jason Cooper
1 sibling, 0 replies; 26+ messages in thread
From: Jason Cooper @ 2013-08-09 11:42 UTC (permalink / raw)
To: linux-arm-kernel
Thomas,
On Fri, Aug 09, 2013 at 03:49:06PM +1000, Benjamin Herrenschmidt wrote:
> On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
> >
> > +#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) { }
>
> Missing a ; at the end of the above line... breaks the build of
> CONFIG_PCI_MSI is not set.
If this is the same error Randy reported yesterday from -next, I'll just
fix it up when I pull it in.
thx,
Jason.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 04/10] of: pci: add registry of MSI chips
2013-08-09 5:49 ` Benjamin Herrenschmidt
2013-08-09 11:42 ` Jason Cooper
@ 2013-08-09 13:44 ` Jason Cooper
2013-08-09 14:18 ` Thierry Reding
1 sibling, 1 reply; 26+ messages in thread
From: Jason Cooper @ 2013-08-09 13:44 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Aug 09, 2013 at 03:49:06PM +1000, Benjamin Herrenschmidt wrote:
> On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
> >
> > +#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) { }
>
> Missing a ; at the end of the above line... breaks the build of
> CONFIG_PCI_MSI is not set.
>
> > +static inline struct msi_chip *
> > +of_pci_find_msi_chip_by_node(struct device_node *of_node) { return
> > NULL };
> > +#endif
> > +
> > #endif
Reproduced, fixed and builds clean !CONFIG_OF and !CONFIG_PCI_MSI with:
---------------->8----------------
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 29631eb..9f69507 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -19,10 +19,11 @@ 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 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 };
+of_pci_find_msi_chip_by_node(struct device_node *of_node) { return NULL; };
#endif
#endif
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 04/10] of: pci: add registry of MSI chips
2013-08-09 13:44 ` Jason Cooper
@ 2013-08-09 14:18 ` Thierry Reding
2013-08-09 14:27 ` Jason Cooper
0 siblings, 1 reply; 26+ messages in thread
From: Thierry Reding @ 2013-08-09 14:18 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Aug 09, 2013 at 09:44:27AM -0400, Jason Cooper wrote:
> On Fri, Aug 09, 2013 at 03:49:06PM +1000, Benjamin Herrenschmidt wrote:
> > On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
> > >
> > > +#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) { }
> >
> > Missing a ; at the end of the above line... breaks the build of
> > CONFIG_PCI_MSI is not set.
> >
> > > +static inline struct msi_chip *
> > > +of_pci_find_msi_chip_by_node(struct device_node *of_node) { return
> > > NULL };
> > > +#endif
> > > +
> > > #endif
>
> Reproduced, fixed and builds clean !CONFIG_OF and !CONFIG_PCI_MSI with:
>
> ---------------->8----------------
> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
> index 29631eb..9f69507 100644
> --- a/include/linux/of_pci.h
> +++ b/include/linux/of_pci.h
> @@ -19,10 +19,11 @@ 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 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 };
> +of_pci_find_msi_chip_by_node(struct device_node *of_node) { return NULL; };
> #endif
>
> #endif
So why do we need a semi-colon after a closing brace? I can understand
how the missing semi-colon after NULL would cause the compiler to flag
an error, but all the other changes look unnecessary to me.
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/20130809/78740b22/attachment.sig>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 04/10] of: pci: add registry of MSI chips
2013-08-09 14:18 ` Thierry Reding
@ 2013-08-09 14:27 ` Jason Cooper
2013-08-09 21:54 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 26+ messages in thread
From: Jason Cooper @ 2013-08-09 14:27 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Aug 09, 2013 at 04:18:07PM +0200, Thierry Reding wrote:
> On Fri, Aug 09, 2013 at 09:44:27AM -0400, Jason Cooper wrote:
> > On Fri, Aug 09, 2013 at 03:49:06PM +1000, Benjamin Herrenschmidt wrote:
> > > On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
> > > >
> > > > +#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) { }
> > >
> > > Missing a ; at the end of the above line... breaks the build of
> > > CONFIG_PCI_MSI is not set.
> > >
> > > > +static inline struct msi_chip *
> > > > +of_pci_find_msi_chip_by_node(struct device_node *of_node) { return
> > > > NULL };
> > > > +#endif
> > > > +
> > > > #endif
> >
> > Reproduced, fixed and builds clean !CONFIG_OF and !CONFIG_PCI_MSI with:
> >
> > ---------------->8----------------
> > diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
> > index 29631eb..9f69507 100644
> > --- a/include/linux/of_pci.h
> > +++ b/include/linux/of_pci.h
> > @@ -19,10 +19,11 @@ 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 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 };
> > +of_pci_find_msi_chip_by_node(struct device_node *of_node) { return NULL; };
> > #endif
> >
> > #endif
>
> So why do we need a semi-colon after a closing brace? I can understand
> how the missing semi-colon after NULL would cause the compiler to flag
> an error, but all the other changes look unnecessary to me.
You're correct, I sent this a little too hastily. I thought Ben knew
something I didn't (see above), but the error was only where you
indicated. I'm revising my fix to just append the semi-colon after the
NULL.
thx,
Jason.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 04/10] of: pci: add registry of MSI chips
2013-08-09 14:27 ` Jason Cooper
@ 2013-08-09 21:54 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-09 21:54 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-08-09 at 10:27 -0400, Jason Cooper wrote:
>
> You're correct, I sent this a little too hastily. I thought Ben knew
> something I didn't (see above), but the error was only where you
> indicated. I'm revising my fix to just append the semi-colon after
> the
> NULL.
I messed up in my reply, I was talking about the one after the NULL.
Cheers,
Ben.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 04/10] of: pci: add registry of MSI chips
2013-08-08 22:17 ` [PATCHv8 04/10] of: pci: add registry of MSI chips Thomas Petazzoni
2013-08-09 5:49 ` Benjamin Herrenschmidt
@ 2013-08-09 5:59 ` Benjamin Herrenschmidt
1 sibling, 0 replies; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-09 5:59 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
> 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'.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> drivers/of/of_pci.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
> include/linux/msi.h | 2 ++
> include/linux/of_pci.h | 12 ++++++++++++
> 3 files changed, 59 insertions(+)
>
> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> index 42c687a..e5ca008 100644
> --- a/drivers/of/of_pci.c
> +++ b/drivers/of/of_pci.c
> @@ -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 */
> diff --git a/include/linux/msi.h b/include/linux/msi.h
> index 090ddad..b17ead8 100644
> --- a/include/linux/msi.h
> +++ b/include/linux/msi.h
> @@ -68,6 +68,8 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq);
> 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);
> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
> index 7a04826..29631eb 100644
> --- a/include/linux/of_pci.h
> +++ b/include/linux/of_pci.h
> @@ -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
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 05/10] irqchip: armada-370-xp: properly request resources
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
` (3 preceding siblings ...)
2013-08-08 22:17 ` [PATCHv8 04/10] of: pci: add registry of MSI chips Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-09 6:44 ` Gregory CLEMENT
2013-08-08 22:17 ` [PATCHv8 06/10] irqchip: armada-370-xp: implement MSI support Thomas Petazzoni
` (5 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
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.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Tested-by: Daniel Price <daniel.price@gmail.com>
---
drivers/irqchip/irq-armada-370-xp.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index bb328a3..26adc74 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -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);
--
1.8.1.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 05/10] irqchip: armada-370-xp: properly request resources
2013-08-08 22:17 ` [PATCHv8 05/10] irqchip: armada-370-xp: properly request resources Thomas Petazzoni
@ 2013-08-09 6:44 ` Gregory CLEMENT
0 siblings, 0 replies; 26+ messages in thread
From: Gregory CLEMENT @ 2013-08-09 6:44 UTC (permalink / raw)
To: linux-arm-kernel
On 09/08/2013 00:17, Thomas Petazzoni wrote:
> 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.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Tested-by: Daniel Price <daniel.price@gmail.com>
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/irqchip/irq-armada-370-xp.c | 20 ++++++++++++++++----
> 1 file changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
> index bb328a3..26adc74 100644
> --- a/drivers/irqchip/irq-armada-370-xp.c
> +++ b/drivers/irqchip/irq-armada-370-xp.c
> @@ -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);
>
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 06/10] irqchip: armada-370-xp: implement MSI support
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
` (4 preceding siblings ...)
2013-08-08 22:17 ` [PATCHv8 05/10] irqchip: armada-370-xp: properly request resources Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-09 5:56 ` Benjamin Herrenschmidt
2013-08-09 6:44 ` Gregory CLEMENT
2013-08-08 22:17 ` [PATCHv8 07/10] ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci Thomas Petazzoni
` (4 subsequent siblings)
10 siblings, 2 replies; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
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.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
.../devicetree/bindings/arm/armada-370-xp-mpic.txt | 3 +
drivers/irqchip/irq-armada-370-xp.c | 182 ++++++++++++++++++++-
2 files changed, 184 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
index 61df564..d74091a 100644
--- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
+++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
@@ -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>;
};
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 26adc74..433cc85 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -21,7 +21,10 @@
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/of_pci.h>
#include <linux/irqdomain.h>
+#include <linux/slab.h>
+#include <linux/msi.h>
#include <asm/mach/arch.h>
#include <asm/exception.h>
#include <asm/smp_plat.h>
@@ -51,12 +54,22 @@
#define IPI_DOORBELL_START (0)
#define IPI_DOORBELL_END (8)
#define IPI_DOORBELL_MASK 0xFF
+#define PCI_MSI_DOORBELL_START (16)
+#define PCI_MSI_DOORBELL_NR (16)
+#define PCI_MSI_DOORBELL_END (32)
+#define PCI_MSI_DOORBELL_MASK 0xFFFF0000
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
static void __iomem *per_cpu_int_base;
static void __iomem *main_int_base;
static struct irq_domain *armada_370_xp_mpic_domain;
+#ifdef CONFIG_PCI_MSI
+static struct irq_domain *armada_370_xp_msi_domain;
+static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
+static DEFINE_MUTEX(msi_used_lock);
+static phys_addr_t msi_doorbell_addr;
+#endif
/*
* In SMP mode:
@@ -87,6 +100,144 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
}
+#ifdef CONFIG_PCI_MSI
+
+static int armada_370_xp_alloc_msi(void)
+{
+ int hwirq;
+
+ mutex_lock(&msi_used_lock);
+ hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR);
+ if (hwirq >= PCI_MSI_DOORBELL_NR)
+ hwirq = -ENOSPC;
+ else
+ set_bit(hwirq, msi_used);
+ mutex_unlock(&msi_used_lock);
+
+ return hwirq;
+}
+
+static void armada_370_xp_free_msi(int hwirq)
+{
+ mutex_lock(&msi_used_lock);
+ if (!test_bit(hwirq, msi_used))
+ pr_err("trying to free unused MSI#%d\n", hwirq);
+ else
+ clear_bit(hwirq, msi_used);
+ mutex_unlock(&msi_used_lock);
+}
+
+static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
+ struct pci_dev *pdev,
+ struct msi_desc *desc)
+{
+ struct msi_msg msg;
+ irq_hw_number_t hwirq;
+ int virq;
+
+ hwirq = armada_370_xp_alloc_msi();
+ if (hwirq < 0)
+ return hwirq;
+
+ virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq);
+ if (!virq) {
+ armada_370_xp_free_msi(hwirq);
+ return -EINVAL;
+ }
+
+ irq_set_msi_desc(virq, desc);
+
+ msg.address_lo = msi_doorbell_addr;
+ msg.address_hi = 0;
+ msg.data = 0xf00 | (hwirq + 16);
+
+ write_msi_msg(virq, &msg);
+ return 0;
+}
+
+static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
+ unsigned int irq)
+{
+ struct irq_data *d = irq_get_irq_data(irq);
+ irq_dispose_mapping(irq);
+ armada_370_xp_free_msi(d->hwirq);
+}
+
+static struct irq_chip armada_370_xp_msi_irq_chip = {
+ .name = "armada_370_xp_msi_irq",
+ .irq_enable = unmask_msi_irq,
+ .irq_disable = mask_msi_irq,
+ .irq_mask = mask_msi_irq,
+ .irq_unmask = unmask_msi_irq,
+};
+
+static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
+ handle_simple_irq);
+ set_irq_flags(virq, IRQF_VALID);
+
+ return 0;
+}
+
+static const struct irq_domain_ops armada_370_xp_msi_irq_ops = {
+ .map = armada_370_xp_msi_map,
+};
+
+static int armada_370_xp_msi_init(struct device_node *node,
+ phys_addr_t main_int_phys_base)
+{
+ struct msi_chip *msi_chip;
+ u32 reg;
+ int ret;
+
+ msi_doorbell_addr = main_int_phys_base +
+ ARMADA_370_XP_SW_TRIG_INT_OFFS;
+
+ msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL);
+ if (!msi_chip)
+ return -ENOMEM;
+
+ msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
+ msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
+ msi_chip->of_node = node;
+
+ armada_370_xp_msi_domain =
+ irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
+ &armada_370_xp_msi_irq_ops,
+ NULL);
+ if (!armada_370_xp_msi_domain) {
+ kfree(msi_chip);
+ return -ENOMEM;
+ }
+
+ ret = of_pci_msi_chip_add(msi_chip);
+ if (ret < 0) {
+ irq_domain_remove(armada_370_xp_msi_domain);
+ kfree(msi_chip);
+ return ret;
+ }
+
+ reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
+ | PCI_MSI_DOORBELL_MASK;
+
+ writel(reg, per_cpu_int_base +
+ ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+
+ /* Unmask IPI interrupt */
+ writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+
+ return 0;
+}
+#else
+static inline int armada_370_xp_msi_init(struct device_node *node,
+ phys_addr_t main_int_phys_base)
+{
+ return 0;
+}
+#endif
+
#ifdef CONFIG_SMP
static int armada_xp_set_affinity(struct irq_data *d,
const struct cpumask *mask_val, bool force)
@@ -214,12 +365,39 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
if (irqnr > 1022)
break;
- if (irqnr > 0) {
+ if (irqnr > 1) {
irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
irqnr);
handle_IRQ(irqnr, regs);
continue;
}
+
+#ifdef CONFIG_PCI_MSI
+ /* MSI handling */
+ if (irqnr == 1) {
+ u32 msimask, msinr;
+
+ msimask = readl_relaxed(per_cpu_int_base +
+ ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
+ & PCI_MSI_DOORBELL_MASK;
+
+ writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base +
+ ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
+
+ for (msinr = PCI_MSI_DOORBELL_START;
+ msinr < PCI_MSI_DOORBELL_END; msinr++) {
+ int irq;
+
+ if (!(msimask & BIT(msinr)))
+ continue;
+
+ irq = irq_find_mapping(armada_370_xp_msi_domain,
+ msinr - 16);
+ handle_IRQ(irq, regs);
+ }
+ }
+#endif
+
#ifdef CONFIG_SMP
/* IPI Handling */
if (irqnr == 0) {
@@ -292,6 +470,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
#endif
+ armada_370_xp_msi_init(node, main_int_res.start);
+
set_handle_irq(armada_370_xp_handle_irq);
return 0;
--
1.8.1.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 06/10] irqchip: armada-370-xp: implement MSI support
2013-08-08 22:17 ` [PATCHv8 06/10] irqchip: armada-370-xp: implement MSI support Thomas Petazzoni
@ 2013-08-09 5:56 ` Benjamin Herrenschmidt
2013-08-09 6:44 ` Gregory CLEMENT
1 sibling, 0 replies; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-09 5:56 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
> 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.
When you have a bit of time, have a look at
arch/powerpc/sysdev/msi_bitmap.c
This should be usable pretty-much as-is and thus could be moved to
a generic place and replace your custom bitmap allocator.
Cheers,
Ben.
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
> .../devicetree/bindings/arm/armada-370-xp-mpic.txt | 3 +
> drivers/irqchip/irq-armada-370-xp.c | 182 ++++++++++++++++++++-
> 2 files changed, 184 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
> index 61df564..d74091a 100644
> --- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
> +++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
> @@ -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>;
> };
> diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
> index 26adc74..433cc85 100644
> --- a/drivers/irqchip/irq-armada-370-xp.c
> +++ b/drivers/irqchip/irq-armada-370-xp.c
> @@ -21,7 +21,10 @@
> #include <linux/io.h>
> #include <linux/of_address.h>
> #include <linux/of_irq.h>
> +#include <linux/of_pci.h>
> #include <linux/irqdomain.h>
> +#include <linux/slab.h>
> +#include <linux/msi.h>
> #include <asm/mach/arch.h>
> #include <asm/exception.h>
> #include <asm/smp_plat.h>
> @@ -51,12 +54,22 @@
> #define IPI_DOORBELL_START (0)
> #define IPI_DOORBELL_END (8)
> #define IPI_DOORBELL_MASK 0xFF
> +#define PCI_MSI_DOORBELL_START (16)
> +#define PCI_MSI_DOORBELL_NR (16)
> +#define PCI_MSI_DOORBELL_END (32)
> +#define PCI_MSI_DOORBELL_MASK 0xFFFF0000
>
> static DEFINE_RAW_SPINLOCK(irq_controller_lock);
>
> static void __iomem *per_cpu_int_base;
> static void __iomem *main_int_base;
> static struct irq_domain *armada_370_xp_mpic_domain;
> +#ifdef CONFIG_PCI_MSI
> +static struct irq_domain *armada_370_xp_msi_domain;
> +static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
> +static DEFINE_MUTEX(msi_used_lock);
> +static phys_addr_t msi_doorbell_addr;
> +#endif
>
> /*
> * In SMP mode:
> @@ -87,6 +100,144 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
> ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
> }
>
> +#ifdef CONFIG_PCI_MSI
> +
> +static int armada_370_xp_alloc_msi(void)
> +{
> + int hwirq;
> +
> + mutex_lock(&msi_used_lock);
> + hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR);
> + if (hwirq >= PCI_MSI_DOORBELL_NR)
> + hwirq = -ENOSPC;
> + else
> + set_bit(hwirq, msi_used);
> + mutex_unlock(&msi_used_lock);
> +
> + return hwirq;
> +}
> +
> +static void armada_370_xp_free_msi(int hwirq)
> +{
> + mutex_lock(&msi_used_lock);
> + if (!test_bit(hwirq, msi_used))
> + pr_err("trying to free unused MSI#%d\n", hwirq);
> + else
> + clear_bit(hwirq, msi_used);
> + mutex_unlock(&msi_used_lock);
> +}
> +
> +static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
> + struct pci_dev *pdev,
> + struct msi_desc *desc)
> +{
> + struct msi_msg msg;
> + irq_hw_number_t hwirq;
> + int virq;
> +
> + hwirq = armada_370_xp_alloc_msi();
> + if (hwirq < 0)
> + return hwirq;
> +
> + virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq);
> + if (!virq) {
> + armada_370_xp_free_msi(hwirq);
> + return -EINVAL;
> + }
> +
> + irq_set_msi_desc(virq, desc);
> +
> + msg.address_lo = msi_doorbell_addr;
> + msg.address_hi = 0;
> + msg.data = 0xf00 | (hwirq + 16);
> +
> + write_msi_msg(virq, &msg);
> + return 0;
> +}
> +
> +static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
> + unsigned int irq)
> +{
> + struct irq_data *d = irq_get_irq_data(irq);
> + irq_dispose_mapping(irq);
> + armada_370_xp_free_msi(d->hwirq);
> +}
> +
> +static struct irq_chip armada_370_xp_msi_irq_chip = {
> + .name = "armada_370_xp_msi_irq",
> + .irq_enable = unmask_msi_irq,
> + .irq_disable = mask_msi_irq,
> + .irq_mask = mask_msi_irq,
> + .irq_unmask = unmask_msi_irq,
> +};
> +
> +static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
> + irq_hw_number_t hw)
> +{
> + irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
> + handle_simple_irq);
> + set_irq_flags(virq, IRQF_VALID);
> +
> + return 0;
> +}
> +
> +static const struct irq_domain_ops armada_370_xp_msi_irq_ops = {
> + .map = armada_370_xp_msi_map,
> +};
> +
> +static int armada_370_xp_msi_init(struct device_node *node,
> + phys_addr_t main_int_phys_base)
> +{
> + struct msi_chip *msi_chip;
> + u32 reg;
> + int ret;
> +
> + msi_doorbell_addr = main_int_phys_base +
> + ARMADA_370_XP_SW_TRIG_INT_OFFS;
> +
> + msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL);
> + if (!msi_chip)
> + return -ENOMEM;
> +
> + msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
> + msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
> + msi_chip->of_node = node;
> +
> + armada_370_xp_msi_domain =
> + irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
> + &armada_370_xp_msi_irq_ops,
> + NULL);
> + if (!armada_370_xp_msi_domain) {
> + kfree(msi_chip);
> + return -ENOMEM;
> + }
> +
> + ret = of_pci_msi_chip_add(msi_chip);
> + if (ret < 0) {
> + irq_domain_remove(armada_370_xp_msi_domain);
> + kfree(msi_chip);
> + return ret;
> + }
> +
> + reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
> + | PCI_MSI_DOORBELL_MASK;
> +
> + writel(reg, per_cpu_int_base +
> + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
> +
> + /* Unmask IPI interrupt */
> + writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
> +
> + return 0;
> +}
> +#else
> +static inline int armada_370_xp_msi_init(struct device_node *node,
> + phys_addr_t main_int_phys_base)
> +{
> + return 0;
> +}
> +#endif
> +
> #ifdef CONFIG_SMP
> static int armada_xp_set_affinity(struct irq_data *d,
> const struct cpumask *mask_val, bool force)
> @@ -214,12 +365,39 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
> if (irqnr > 1022)
> break;
>
> - if (irqnr > 0) {
> + if (irqnr > 1) {
> irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
> irqnr);
> handle_IRQ(irqnr, regs);
> continue;
> }
> +
> +#ifdef CONFIG_PCI_MSI
> + /* MSI handling */
> + if (irqnr == 1) {
> + u32 msimask, msinr;
> +
> + msimask = readl_relaxed(per_cpu_int_base +
> + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
> + & PCI_MSI_DOORBELL_MASK;
> +
> + writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base +
> + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
> +
> + for (msinr = PCI_MSI_DOORBELL_START;
> + msinr < PCI_MSI_DOORBELL_END; msinr++) {
> + int irq;
> +
> + if (!(msimask & BIT(msinr)))
> + continue;
> +
> + irq = irq_find_mapping(armada_370_xp_msi_domain,
> + msinr - 16);
> + handle_IRQ(irq, regs);
> + }
> + }
> +#endif
> +
> #ifdef CONFIG_SMP
> /* IPI Handling */
> if (irqnr == 0) {
> @@ -292,6 +470,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
>
> #endif
>
> + armada_370_xp_msi_init(node, main_int_res.start);
> +
> set_handle_irq(armada_370_xp_handle_irq);
>
> return 0;
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 06/10] irqchip: armada-370-xp: implement MSI support
2013-08-08 22:17 ` [PATCHv8 06/10] irqchip: armada-370-xp: implement MSI support Thomas Petazzoni
2013-08-09 5:56 ` Benjamin Herrenschmidt
@ 2013-08-09 6:44 ` Gregory CLEMENT
1 sibling, 0 replies; 26+ messages in thread
From: Gregory CLEMENT @ 2013-08-09 6:44 UTC (permalink / raw)
To: linux-arm-kernel
On 09/08/2013 00:17, Thomas Petazzoni wrote:
> 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.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> .../devicetree/bindings/arm/armada-370-xp-mpic.txt | 3 +
> drivers/irqchip/irq-armada-370-xp.c | 182 ++++++++++++++++++++-
> 2 files changed, 184 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
> index 61df564..d74091a 100644
> --- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
> +++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
> @@ -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>;
> };
> diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
> index 26adc74..433cc85 100644
> --- a/drivers/irqchip/irq-armada-370-xp.c
> +++ b/drivers/irqchip/irq-armada-370-xp.c
> @@ -21,7 +21,10 @@
> #include <linux/io.h>
> #include <linux/of_address.h>
> #include <linux/of_irq.h>
> +#include <linux/of_pci.h>
> #include <linux/irqdomain.h>
> +#include <linux/slab.h>
> +#include <linux/msi.h>
> #include <asm/mach/arch.h>
> #include <asm/exception.h>
> #include <asm/smp_plat.h>
> @@ -51,12 +54,22 @@
> #define IPI_DOORBELL_START (0)
> #define IPI_DOORBELL_END (8)
> #define IPI_DOORBELL_MASK 0xFF
> +#define PCI_MSI_DOORBELL_START (16)
> +#define PCI_MSI_DOORBELL_NR (16)
> +#define PCI_MSI_DOORBELL_END (32)
> +#define PCI_MSI_DOORBELL_MASK 0xFFFF0000
>
> static DEFINE_RAW_SPINLOCK(irq_controller_lock);
>
> static void __iomem *per_cpu_int_base;
> static void __iomem *main_int_base;
> static struct irq_domain *armada_370_xp_mpic_domain;
> +#ifdef CONFIG_PCI_MSI
> +static struct irq_domain *armada_370_xp_msi_domain;
> +static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
> +static DEFINE_MUTEX(msi_used_lock);
> +static phys_addr_t msi_doorbell_addr;
> +#endif
>
> /*
> * In SMP mode:
> @@ -87,6 +100,144 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
> ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
> }
>
> +#ifdef CONFIG_PCI_MSI
> +
> +static int armada_370_xp_alloc_msi(void)
> +{
> + int hwirq;
> +
> + mutex_lock(&msi_used_lock);
> + hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR);
> + if (hwirq >= PCI_MSI_DOORBELL_NR)
> + hwirq = -ENOSPC;
> + else
> + set_bit(hwirq, msi_used);
> + mutex_unlock(&msi_used_lock);
> +
> + return hwirq;
> +}
> +
> +static void armada_370_xp_free_msi(int hwirq)
> +{
> + mutex_lock(&msi_used_lock);
> + if (!test_bit(hwirq, msi_used))
> + pr_err("trying to free unused MSI#%d\n", hwirq);
> + else
> + clear_bit(hwirq, msi_used);
> + mutex_unlock(&msi_used_lock);
> +}
> +
> +static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
> + struct pci_dev *pdev,
> + struct msi_desc *desc)
> +{
> + struct msi_msg msg;
> + irq_hw_number_t hwirq;
> + int virq;
> +
> + hwirq = armada_370_xp_alloc_msi();
> + if (hwirq < 0)
> + return hwirq;
> +
> + virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq);
> + if (!virq) {
> + armada_370_xp_free_msi(hwirq);
> + return -EINVAL;
> + }
> +
> + irq_set_msi_desc(virq, desc);
> +
> + msg.address_lo = msi_doorbell_addr;
> + msg.address_hi = 0;
> + msg.data = 0xf00 | (hwirq + 16);
> +
> + write_msi_msg(virq, &msg);
> + return 0;
> +}
> +
> +static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
> + unsigned int irq)
> +{
> + struct irq_data *d = irq_get_irq_data(irq);
> + irq_dispose_mapping(irq);
> + armada_370_xp_free_msi(d->hwirq);
> +}
> +
> +static struct irq_chip armada_370_xp_msi_irq_chip = {
> + .name = "armada_370_xp_msi_irq",
> + .irq_enable = unmask_msi_irq,
> + .irq_disable = mask_msi_irq,
> + .irq_mask = mask_msi_irq,
> + .irq_unmask = unmask_msi_irq,
> +};
> +
> +static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
> + irq_hw_number_t hw)
> +{
> + irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
> + handle_simple_irq);
> + set_irq_flags(virq, IRQF_VALID);
> +
> + return 0;
> +}
> +
> +static const struct irq_domain_ops armada_370_xp_msi_irq_ops = {
> + .map = armada_370_xp_msi_map,
> +};
> +
> +static int armada_370_xp_msi_init(struct device_node *node,
> + phys_addr_t main_int_phys_base)
> +{
> + struct msi_chip *msi_chip;
> + u32 reg;
> + int ret;
> +
> + msi_doorbell_addr = main_int_phys_base +
> + ARMADA_370_XP_SW_TRIG_INT_OFFS;
> +
> + msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL);
> + if (!msi_chip)
> + return -ENOMEM;
> +
> + msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
> + msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
> + msi_chip->of_node = node;
> +
> + armada_370_xp_msi_domain =
> + irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
> + &armada_370_xp_msi_irq_ops,
> + NULL);
> + if (!armada_370_xp_msi_domain) {
> + kfree(msi_chip);
> + return -ENOMEM;
> + }
> +
> + ret = of_pci_msi_chip_add(msi_chip);
> + if (ret < 0) {
> + irq_domain_remove(armada_370_xp_msi_domain);
> + kfree(msi_chip);
> + return ret;
> + }
> +
> + reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
> + | PCI_MSI_DOORBELL_MASK;
> +
> + writel(reg, per_cpu_int_base +
> + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
> +
> + /* Unmask IPI interrupt */
> + writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
> +
> + return 0;
> +}
> +#else
> +static inline int armada_370_xp_msi_init(struct device_node *node,
> + phys_addr_t main_int_phys_base)
> +{
> + return 0;
> +}
> +#endif
> +
> #ifdef CONFIG_SMP
> static int armada_xp_set_affinity(struct irq_data *d,
> const struct cpumask *mask_val, bool force)
> @@ -214,12 +365,39 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
> if (irqnr > 1022)
> break;
>
> - if (irqnr > 0) {
> + if (irqnr > 1) {
> irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
> irqnr);
> handle_IRQ(irqnr, regs);
> continue;
> }
> +
> +#ifdef CONFIG_PCI_MSI
> + /* MSI handling */
> + if (irqnr == 1) {
> + u32 msimask, msinr;
> +
> + msimask = readl_relaxed(per_cpu_int_base +
> + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
> + & PCI_MSI_DOORBELL_MASK;
> +
> + writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base +
> + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
> +
> + for (msinr = PCI_MSI_DOORBELL_START;
> + msinr < PCI_MSI_DOORBELL_END; msinr++) {
> + int irq;
> +
> + if (!(msimask & BIT(msinr)))
> + continue;
> +
> + irq = irq_find_mapping(armada_370_xp_msi_domain,
> + msinr - 16);
> + handle_IRQ(irq, regs);
> + }
> + }
> +#endif
> +
> #ifdef CONFIG_SMP
> /* IPI Handling */
> if (irqnr == 0) {
> @@ -292,6 +470,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
>
> #endif
>
> + armada_370_xp_msi_init(node, main_int_res.start);
> +
> set_handle_irq(armada_370_xp_handle_irq);
>
> return 0;
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 07/10] ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
` (5 preceding siblings ...)
2013-08-08 22:17 ` [PATCHv8 06/10] irqchip: armada-370-xp: implement MSI support Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-08 22:17 ` [PATCHv8 08/10] ARM: mvebu: the MPIC now provides MSI controller features Thomas Petazzoni
` (3 subsequent siblings)
10 siblings, 0 replies; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
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.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Reviewed-by: Thierry Reding <thierry.reding@gmail.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Tested-by: Daniel Price <daniel.price@gmail.com>
Tested-by: Thierry Reding <thierry.reding@gmail.com>
---
arch/arm/include/asm/mach/pci.h | 4 ++++
arch/arm/kernel/bios32.c | 16 ++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index a1c90d7..454d642 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -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 */
};
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 261fcc8..1ec9c87 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -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)
--
1.8.1.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 08/10] ARM: mvebu: the MPIC now provides MSI controller features
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
` (6 preceding siblings ...)
2013-08-08 22:17 ` [PATCHv8 07/10] ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-09 6:45 ` Gregory CLEMENT
2013-08-08 22:17 ` [PATCHv8 09/10] PCI: mvebu: add support for MSI Thomas Petazzoni
` (2 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
Adds the 'msi-controller' property to the main interrupt controller
Device Tree node, to indicate that it can now behave as a MSI
controller.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Reviewed-by: Thierry Reding <thierry.reding@gmail.com>
Tested-by: Daniel Price <daniel.price@gmail.com>
---
arch/arm/boot/dts/armada-370-xp.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 90b1176..ac0bbc0 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -56,6 +56,7 @@
#interrupt-cells = <1>;
#size-cells = <1>;
interrupt-controller;
+ msi-controller;
};
coherency-fabric at 20200 {
--
1.8.1.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 08/10] ARM: mvebu: the MPIC now provides MSI controller features
2013-08-08 22:17 ` [PATCHv8 08/10] ARM: mvebu: the MPIC now provides MSI controller features Thomas Petazzoni
@ 2013-08-09 6:45 ` Gregory CLEMENT
0 siblings, 0 replies; 26+ messages in thread
From: Gregory CLEMENT @ 2013-08-09 6:45 UTC (permalink / raw)
To: linux-arm-kernel
On 09/08/2013 00:17, Thomas Petazzoni wrote:
> Adds the 'msi-controller' property to the main interrupt controller
> Device Tree node, to indicate that it can now behave as a MSI
> controller.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Reviewed-by: Thierry Reding <thierry.reding@gmail.com>
> Tested-by: Daniel Price <daniel.price@gmail.com>
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> arch/arm/boot/dts/armada-370-xp.dtsi | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
> index 90b1176..ac0bbc0 100644
> --- a/arch/arm/boot/dts/armada-370-xp.dtsi
> +++ b/arch/arm/boot/dts/armada-370-xp.dtsi
> @@ -56,6 +56,7 @@
> #interrupt-cells = <1>;
> #size-cells = <1>;
> interrupt-controller;
> + msi-controller;
> };
>
> coherency-fabric at 20200 {
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 09/10] PCI: mvebu: add support for MSI
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
` (7 preceding siblings ...)
2013-08-08 22:17 ` [PATCHv8 08/10] ARM: mvebu: the MPIC now provides MSI controller features Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-08 22:17 ` [PATCHv8 10/10] ARM: mvebu: link PCIe controllers to the MSI controller Thomas Petazzoni
2013-08-09 5:58 ` [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Benjamin Herrenschmidt
10 siblings, 0 replies; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
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.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Reviewed-by: Thierry Reding <thierry.reding@gmail.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
---
.../devicetree/bindings/pci/mvebu-pci.txt | 3 +++
drivers/pci/host/pci-mvebu.c | 26 ++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index f8d4058..77e0ffe 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -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 */
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 13a633b..5715a97 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -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, ®s);
}
+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;
--
1.8.1.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 10/10] ARM: mvebu: link PCIe controllers to the MSI controller
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
` (8 preceding siblings ...)
2013-08-08 22:17 ` [PATCHv8 09/10] PCI: mvebu: add support for MSI Thomas Petazzoni
@ 2013-08-08 22:17 ` Thomas Petazzoni
2013-08-09 6:45 ` Gregory CLEMENT
2013-08-09 5:58 ` [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Benjamin Herrenschmidt
10 siblings, 1 reply; 26+ messages in thread
From: Thomas Petazzoni @ 2013-08-08 22:17 UTC (permalink / raw)
To: linux-arm-kernel
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.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Tested-by: Daniel Price <daniel.price@gmail.com>
---
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(+)
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index fa3dfc6..a60018d 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -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 */
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
index f8eaa38..4a9a305 100644
--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -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 */
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
index 2d9335d..dd23e96 100644
--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -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 */
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
index c7b1f4d..77db2bc 100644
--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
@@ -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 */
--
1.8.1.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCHv8 10/10] ARM: mvebu: link PCIe controllers to the MSI controller
2013-08-08 22:17 ` [PATCHv8 10/10] ARM: mvebu: link PCIe controllers to the MSI controller Thomas Petazzoni
@ 2013-08-09 6:45 ` Gregory CLEMENT
0 siblings, 0 replies; 26+ messages in thread
From: Gregory CLEMENT @ 2013-08-09 6:45 UTC (permalink / raw)
To: linux-arm-kernel
On 09/08/2013 00:17, Thomas Petazzoni wrote:
> 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.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Tested-by: Daniel Price <daniel.price@gmail.com>
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> 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(+)
>
> diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
> index fa3dfc6..a60018d 100644
> --- a/arch/arm/boot/dts/armada-370.dtsi
> +++ b/arch/arm/boot/dts/armada-370.dtsi
> @@ -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 */
> diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
> index f8eaa38..4a9a305 100644
> --- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
> +++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
> @@ -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 */
> diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
> index 2d9335d..dd23e96 100644
> --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
> +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
> @@ -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 */
> diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
> index c7b1f4d..77db2bc 100644
> --- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
> +++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
> @@ -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 */
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver
2013-08-08 22:17 [PATCHv8 00/10] MSI support for Marvell EBU PCIe driver Thomas Petazzoni
` (9 preceding siblings ...)
2013-08-08 22:17 ` [PATCHv8 10/10] ARM: mvebu: link PCIe controllers to the MSI controller Thomas Petazzoni
@ 2013-08-09 5:58 ` Benjamin Herrenschmidt
10 siblings, 0 replies; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-09 5:58 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-08-09 at 00:17 +0200, Thomas Petazzoni wrote:
> 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.
Appart from the build breakage when not using CONFIG_PCI_MSI which
I reported in a previous email, I'm fine with the series. No need
to add my acks to all of the ARM specific stuff.
Cheers,
Ben.
^ permalink raw reply [flat|nested] 26+ messages in thread