aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2013-08-13 14:07:26 -0400
committerStephen Warren <swarren@nvidia.com>2013-08-13 14:07:26 -0400
commit734a0f6bb93d6f2c27a2b2976e9da1e31905facd (patch)
tree9bfd05c893da5c37318f5ca0147898f1d9f1fe09
parente9f624499cc84a625648ccfbd550b74d17d52fb2 (diff)
parent6a4324ebf5cf412d55fd1ea259d4dd29fb8f90e8 (diff)
Merge tag 'msi-3.12-2' into for-3.12/soc
pci msi changes for v3.12 (round 2) - fix build breakage for s390 allyesconfig due to !HAVE_GENERIC_HARDIRQS
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/include/asm/mach/pci.h4
-rw-r--r--arch/arm/kernel/bios32.c16
-rw-r--r--arch/ia64/Kconfig1
-rw-r--r--arch/mips/Kconfig2
-rw-r--r--arch/mips/include/asm/pci.h5
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/include/asm/pci.h5
-rw-r--r--arch/s390/Kconfig1
-rw-r--r--arch/s390/include/asm/pci.h4
-rw-r--r--arch/sparc/Kconfig1
-rw-r--r--arch/tile/Kconfig1
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/include/asm/pci.h30
-rw-r--r--arch/x86/kernel/x86_init.c24
-rw-r--r--drivers/of/of_pci.c45
-rw-r--r--drivers/pci/Kconfig4
-rw-r--r--drivers/pci/msi.c85
-rw-r--r--drivers/pci/probe.c1
-rw-r--r--include/linux/msi.h21
-rw-r--r--include/linux/of_pci.h12
-rw-r--r--include/linux/pci.h1
22 files changed, 185 insertions, 81 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ba412e02ec0c..b173c1d8721f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -441,7 +441,6 @@ config ARCH_NETX
441config ARCH_IOP13XX 441config ARCH_IOP13XX
442 bool "IOP13xx-based" 442 bool "IOP13xx-based"
443 depends on MMU 443 depends on MMU
444 select ARCH_SUPPORTS_MSI
445 select CPU_XSC3 444 select CPU_XSC3
446 select NEED_MACH_MEMORY_H 445 select NEED_MACH_MEMORY_H
447 select NEED_RET_TO_USER 446 select NEED_RET_TO_USER
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index a1c90d7feb0e..454d642a4070 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -36,6 +36,8 @@ struct hw_pci {
36 resource_size_t start, 36 resource_size_t start,
37 resource_size_t size, 37 resource_size_t size,
38 resource_size_t align); 38 resource_size_t align);
39 void (*add_bus)(struct pci_bus *bus);
40 void (*remove_bus)(struct pci_bus *bus);
39}; 41};
40 42
41/* 43/*
@@ -63,6 +65,8 @@ struct pci_sys_data {
63 resource_size_t start, 65 resource_size_t start,
64 resource_size_t size, 66 resource_size_t size,
65 resource_size_t align); 67 resource_size_t align);
68 void (*add_bus)(struct pci_bus *bus);
69 void (*remove_bus)(struct pci_bus *bus);
66 void *private_data; /* platform controller private data */ 70 void *private_data; /* platform controller private data */
67}; 71};
68 72
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 261fcc826169..1ec9c8701c26 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)
363} 363}
364EXPORT_SYMBOL(pcibios_fixup_bus); 364EXPORT_SYMBOL(pcibios_fixup_bus);
365 365
366void pcibios_add_bus(struct pci_bus *bus)
367{
368 struct pci_sys_data *sys = bus->sysdata;
369 if (sys->add_bus)
370 sys->add_bus(bus);
371}
372
373void pcibios_remove_bus(struct pci_bus *bus)
374{
375 struct pci_sys_data *sys = bus->sysdata;
376 if (sys->remove_bus)
377 sys->remove_bus(bus);
378}
379
366/* 380/*
367 * Swizzle the device pin each time we cross a bridge. If a platform does 381 * Swizzle the device pin each time we cross a bridge. If a platform does
368 * not provide a swizzle function, we perform the standard PCI swizzling. 382 * 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,
464 sys->swizzle = hw->swizzle; 478 sys->swizzle = hw->swizzle;
465 sys->map_irq = hw->map_irq; 479 sys->map_irq = hw->map_irq;
466 sys->align_resource = hw->align_resource; 480 sys->align_resource = hw->align_resource;
481 sys->add_bus = hw->add_bus;
482 sys->remove_bus = hw->remove_bus;
467 INIT_LIST_HEAD(&sys->resources); 483 INIT_LIST_HEAD(&sys->resources);
468 484
469 if (hw->private_data) 485 if (hw->private_data)
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 5a768ad8e893..098602b939a9 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -9,7 +9,6 @@ config IA64
9 select PCI if (!IA64_HP_SIM) 9 select PCI if (!IA64_HP_SIM)
10 select ACPI if (!IA64_HP_SIM) 10 select ACPI if (!IA64_HP_SIM)
11 select PM if (!IA64_HP_SIM) 11 select PM if (!IA64_HP_SIM)
12 select ARCH_SUPPORTS_MSI
13 select HAVE_UNSTABLE_SCHED_CLOCK 12 select HAVE_UNSTABLE_SCHED_CLOCK
14 select HAVE_IDE 13 select HAVE_IDE
15 select HAVE_OPROFILE 14 select HAVE_OPROFILE
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4758a8fd3e99..00b26986cd05 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -726,7 +726,6 @@ config CAVIUM_OCTEON_SOC
726 select SYS_HAS_CPU_CAVIUM_OCTEON 726 select SYS_HAS_CPU_CAVIUM_OCTEON
727 select SWAP_IO_SPACE 727 select SWAP_IO_SPACE
728 select HW_HAS_PCI 728 select HW_HAS_PCI
729 select ARCH_SUPPORTS_MSI
730 select ZONE_DMA32 729 select ZONE_DMA32
731 select USB_ARCH_HAS_OHCI 730 select USB_ARCH_HAS_OHCI
732 select USB_ARCH_HAS_EHCI 731 select USB_ARCH_HAS_EHCI
@@ -762,7 +761,6 @@ config NLM_XLR_BOARD
762 select CEVT_R4K 761 select CEVT_R4K
763 select CSRC_R4K 762 select CSRC_R4K
764 select IRQ_CPU 763 select IRQ_CPU
765 select ARCH_SUPPORTS_MSI
766 select ZONE_DMA32 if 64BIT 764 select ZONE_DMA32 if 64BIT
767 select SYNC_R4K 765 select SYNC_R4K
768 select SYS_HAS_EARLY_PRINTK 766 select SYS_HAS_EARLY_PRINTK
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index fa8e0aa250ca..f194c08bd057 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)
136 return channel ? 15 : 14; 136 return channel ? 15 : 14;
137} 137}
138 138
139#ifdef CONFIG_CPU_CAVIUM_OCTEON
140/* MSI arch hook for OCTEON */
141#define arch_setup_msi_irqs arch_setup_msi_irqs
142#endif
143
144extern char * (*pcibios_plat_setup)(char *str); 139extern char * (*pcibios_plat_setup)(char *str);
145 140
146#ifdef CONFIG_OF 141#ifdef CONFIG_OF
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3bf72cd2c8fc..183a16509e8f 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -727,7 +727,6 @@ config PCI
727 default y if !40x && !CPM2 && !8xx && !PPC_83xx \ 727 default y if !40x && !CPM2 && !8xx && !PPC_83xx \
728 && !PPC_85xx && !PPC_86xx && !GAMECUBE_COMMON 728 && !PPC_85xx && !PPC_86xx && !GAMECUBE_COMMON
729 default PCI_QSPAN if !4xx && !CPM2 && 8xx 729 default PCI_QSPAN if !4xx && !CPM2 && 8xx
730 select ARCH_SUPPORTS_MSI
731 select GENERIC_PCI_IOMAP 730 select GENERIC_PCI_IOMAP
732 help 731 help
733 Find out whether your system includes a PCI bus. PCI is the name of 732 Find out whether your system includes a PCI bus. PCI is the name of
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 6653f2743c4e..95145a15c708 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);
113/* Decide whether to display the domain number in /proc */ 113/* Decide whether to display the domain number in /proc */
114extern int pci_proc_domain(struct pci_bus *bus); 114extern int pci_proc_domain(struct pci_bus *bus);
115 115
116/* MSI arch hooks */
117#define arch_setup_msi_irqs arch_setup_msi_irqs
118#define arch_teardown_msi_irqs arch_teardown_msi_irqs
119#define arch_msi_check_device arch_msi_check_device
120
121struct vm_area_struct; 116struct vm_area_struct;
122/* Map a range of PCI memory or I/O space for a device into user space */ 117/* Map a range of PCI memory or I/O space for a device into user space */
123int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, 118int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 22f75b504f7f..e9982a353b55 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -428,7 +428,6 @@ menuconfig PCI
428 bool "PCI support" 428 bool "PCI support"
429 default n 429 default n
430 depends on 64BIT 430 depends on 64BIT
431 select ARCH_SUPPORTS_MSI
432 select PCI_MSI 431 select PCI_MSI
433 help 432 help
434 Enable PCI support. 433 Enable PCI support.
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 6e577ba0e5da..262b91bb8811 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 *);
21int pci_domain_nr(struct pci_bus *); 21int pci_domain_nr(struct pci_bus *);
22int pci_proc_domain(struct pci_bus *); 22int pci_proc_domain(struct pci_bus *);
23 23
24/* MSI arch hooks */
25#define arch_setup_msi_irqs arch_setup_msi_irqs
26#define arch_teardown_msi_irqs arch_teardown_msi_irqs
27
28#define ZPCI_BUS_NR 0 /* default bus number */ 24#define ZPCI_BUS_NR 0 /* default bus number */
29#define ZPCI_DEVFN 0 /* default device number */ 25#define ZPCI_DEVFN 0 /* default device number */
30 26
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index a00cbd356db5..1570ad2802b3 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -52,7 +52,6 @@ config SPARC32
52 52
53config SPARC64 53config SPARC64
54 def_bool 64BIT 54 def_bool 64BIT
55 select ARCH_SUPPORTS_MSI
56 select HAVE_FUNCTION_TRACER 55 select HAVE_FUNCTION_TRACER
57 select HAVE_FUNCTION_GRAPH_TRACER 56 select HAVE_FUNCTION_GRAPH_TRACER
58 select HAVE_FUNCTION_GRAPH_FP_TEST 57 select HAVE_FUNCTION_GRAPH_FP_TEST
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 24565a7ffe6d..74dff908a70f 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -380,7 +380,6 @@ config PCI
380 select PCI_DOMAINS 380 select PCI_DOMAINS
381 select GENERIC_PCI_IOMAP 381 select GENERIC_PCI_IOMAP
382 select TILE_GXIO_TRIO if TILEGX 382 select TILE_GXIO_TRIO if TILEGX
383 select ARCH_SUPPORTS_MSI if TILEGX
384 select PCI_MSI if TILEGX 383 select PCI_MSI if TILEGX
385 ---help--- 384 ---help---
386 Enable PCI root complex support, so PCIe endpoint devices can 385 Enable PCI root complex support, so PCIe endpoint devices can
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b32ebf92b0ce..5db62ef37804 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2014,7 +2014,6 @@ menu "Bus options (PCI etc.)"
2014config PCI 2014config PCI
2015 bool "PCI support" 2015 bool "PCI support"
2016 default y 2016 default y
2017 select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
2018 ---help--- 2017 ---help---
2019 Find out whether you have a PCI motherboard. PCI is the name of a 2018 Find out whether you have a PCI motherboard. PCI is the name of a
2020 bus system, i.e. the way the CPU talks to the other stuff inside 2019 bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index d9e9e6c7ed32..7d7443283a9d 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) { }
100extern void pci_iommu_alloc(void); 100extern void pci_iommu_alloc(void);
101 101
102#ifdef CONFIG_PCI_MSI 102#ifdef CONFIG_PCI_MSI
103/* MSI arch specific hooks */
104static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
105{
106 return x86_msi.setup_msi_irqs(dev, nvec, type);
107}
108
109static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
110{
111 x86_msi.teardown_msi_irqs(dev);
112}
113
114static inline void x86_teardown_msi_irq(unsigned int irq)
115{
116 x86_msi.teardown_msi_irq(irq);
117}
118static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq)
119{
120 x86_msi.restore_msi_irqs(dev, irq);
121}
122#define arch_setup_msi_irqs x86_setup_msi_irqs
123#define arch_teardown_msi_irqs x86_teardown_msi_irqs
124#define arch_teardown_msi_irq x86_teardown_msi_irq
125#define arch_restore_msi_irqs x86_restore_msi_irqs
126/* implemented in arch/x86/kernel/apic/io_apic. */ 103/* implemented in arch/x86/kernel/apic/io_apic. */
127struct msi_desc; 104struct msi_desc;
128int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); 105int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
@@ -130,16 +107,9 @@ void native_teardown_msi_irq(unsigned int irq);
130void native_restore_msi_irqs(struct pci_dev *dev, int irq); 107void native_restore_msi_irqs(struct pci_dev *dev, int irq);
131int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, 108int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
132 unsigned int irq_base, unsigned int irq_offset); 109 unsigned int irq_base, unsigned int irq_offset);
133/* default to the implementation in drivers/lib/msi.c */
134#define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
135#define HAVE_DEFAULT_MSI_RESTORE_IRQS
136void default_teardown_msi_irqs(struct pci_dev *dev);
137void default_restore_msi_irqs(struct pci_dev *dev, int irq);
138#else 110#else
139#define native_setup_msi_irqs NULL 111#define native_setup_msi_irqs NULL
140#define native_teardown_msi_irq NULL 112#define native_teardown_msi_irq NULL
141#define default_teardown_msi_irqs NULL
142#define default_restore_msi_irqs NULL
143#endif 113#endif
144 114
145#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) 115#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 45a14dbbddaf..5587f991d111 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -107,6 +107,8 @@ struct x86_platform_ops x86_platform = {
107}; 107};
108 108
109EXPORT_SYMBOL_GPL(x86_platform); 109EXPORT_SYMBOL_GPL(x86_platform);
110
111#if defined(CONFIG_PCI_MSI)
110struct x86_msi_ops x86_msi = { 112struct x86_msi_ops x86_msi = {
111 .setup_msi_irqs = native_setup_msi_irqs, 113 .setup_msi_irqs = native_setup_msi_irqs,
112 .compose_msi_msg = native_compose_msi_msg, 114 .compose_msi_msg = native_compose_msi_msg,
@@ -116,6 +118,28 @@ struct x86_msi_ops x86_msi = {
116 .setup_hpet_msi = default_setup_hpet_msi, 118 .setup_hpet_msi = default_setup_hpet_msi,
117}; 119};
118 120
121/* MSI arch specific hooks */
122int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
123{
124 return x86_msi.setup_msi_irqs(dev, nvec, type);
125}
126
127void arch_teardown_msi_irqs(struct pci_dev *dev)
128{
129 x86_msi.teardown_msi_irqs(dev);
130}
131
132void arch_teardown_msi_irq(unsigned int irq)
133{
134 x86_msi.teardown_msi_irq(irq);
135}
136
137void arch_restore_msi_irqs(struct pci_dev *dev, int irq)
138{
139 x86_msi.restore_msi_irqs(dev, irq);
140}
141#endif
142
119struct x86_io_apic_ops x86_io_apic_ops = { 143struct x86_io_apic_ops x86_io_apic_ops = {
120 .init = native_io_apic_init_mappings, 144 .init = native_io_apic_init_mappings,
121 .read = native_io_apic_read, 145 .read = native_io_apic_read,
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 42c687a820ac..e5ca00893c0c 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)
89 return 0; 89 return 0;
90} 90}
91EXPORT_SYMBOL_GPL(of_pci_parse_bus_range); 91EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
92
93#ifdef CONFIG_PCI_MSI
94
95static LIST_HEAD(of_pci_msi_chip_list);
96static DEFINE_MUTEX(of_pci_msi_chip_mutex);
97
98int of_pci_msi_chip_add(struct msi_chip *chip)
99{
100 if (!of_property_read_bool(chip->of_node, "msi-controller"))
101 return -EINVAL;
102
103 mutex_lock(&of_pci_msi_chip_mutex);
104 list_add(&chip->list, &of_pci_msi_chip_list);
105 mutex_unlock(&of_pci_msi_chip_mutex);
106
107 return 0;
108}
109EXPORT_SYMBOL_GPL(of_pci_msi_chip_add);
110
111void of_pci_msi_chip_remove(struct msi_chip *chip)
112{
113 mutex_lock(&of_pci_msi_chip_mutex);
114 list_del(&chip->list);
115 mutex_unlock(&of_pci_msi_chip_mutex);
116}
117EXPORT_SYMBOL_GPL(of_pci_msi_chip_remove);
118
119struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node)
120{
121 struct msi_chip *c;
122
123 mutex_lock(&of_pci_msi_chip_mutex);
124 list_for_each_entry(c, &of_pci_msi_chip_list, list) {
125 if (c->of_node == of_node) {
126 mutex_unlock(&of_pci_msi_chip_mutex);
127 return c;
128 }
129 }
130 mutex_unlock(&of_pci_msi_chip_mutex);
131
132 return NULL;
133}
134EXPORT_SYMBOL_GPL(of_pci_find_msi_chip_by_node);
135
136#endif /* CONFIG_PCI_MSI */
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 81944fb73116..b6a99f7a9b20 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -1,13 +1,9 @@
1# 1#
2# PCI configuration 2# PCI configuration
3# 3#
4config ARCH_SUPPORTS_MSI
5 bool
6
7config PCI_MSI 4config PCI_MSI
8 bool "Message Signaled Interrupts (MSI and MSI-X)" 5 bool "Message Signaled Interrupts (MSI and MSI-X)"
9 depends on PCI 6 depends on PCI
10 depends on ARCH_SUPPORTS_MSI
11 help 7 help
12 This allows device drivers to enable MSI (Message Signaled 8 This allows device drivers to enable MSI (Message Signaled
13 Interrupts). Message Signaled Interrupts enable a device to 9 Interrupts). Message Signaled Interrupts enable a device to
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index aca7578b05e5..b35f93c232cf 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -30,20 +30,60 @@ static int pci_msi_enable = 1;
30 30
31/* Arch hooks */ 31/* Arch hooks */
32 32
33#ifndef arch_msi_check_device 33#if defined(CONFIG_GENERIC_HARDIRQS)
34int arch_msi_check_device(struct pci_dev *dev, int nvec, int type) 34int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
35{ 35{
36 struct msi_chip *chip = dev->bus->msi;
37 int err;
38
39 if (!chip || !chip->setup_irq)
40 return -EINVAL;
41
42 err = chip->setup_irq(chip, dev, desc);
43 if (err < 0)
44 return err;
45
46 irq_set_chip_data(desc->irq, chip);
47
36 return 0; 48 return 0;
37} 49}
38#endif
39 50
40#ifndef arch_setup_msi_irqs 51void __weak arch_teardown_msi_irq(unsigned int irq)
41# define arch_setup_msi_irqs default_setup_msi_irqs 52{
42# define HAVE_DEFAULT_MSI_SETUP_IRQS 53 struct msi_chip *chip = irq_get_chip_data(irq);
43#endif
44 54
45#ifdef HAVE_DEFAULT_MSI_SETUP_IRQS 55 if (!chip || !chip->teardown_irq)
46int default_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 56 return;
57
58 chip->teardown_irq(chip, irq);
59}
60
61int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
62{
63 struct msi_chip *chip = dev->bus->msi;
64
65 if (!chip || !chip->check_device)
66 return 0;
67
68 return chip->check_device(chip, dev, nvec, type);
69}
70#else
71int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
72{
73 return -ENOSYS;
74}
75
76void __weak arch_teardown_msi_irq(unsigned int irq)
77{
78}
79
80int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
81{
82 return 0;
83}
84#endif /* CONFIG_GENERIC_HARDIRQS */
85
86int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
47{ 87{
48 struct msi_desc *entry; 88 struct msi_desc *entry;
49 int ret; 89 int ret;
@@ -65,14 +105,11 @@ int default_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
65 105
66 return 0; 106 return 0;
67} 107}
68#endif
69
70#ifndef arch_teardown_msi_irqs
71# define arch_teardown_msi_irqs default_teardown_msi_irqs
72# define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
73#endif
74 108
75#ifdef HAVE_DEFAULT_MSI_TEARDOWN_IRQS 109/*
110 * We have a default implementation available as a separate non-weak
111 * function, as it is used by the Xen x86 PCI code
112 */
76void default_teardown_msi_irqs(struct pci_dev *dev) 113void default_teardown_msi_irqs(struct pci_dev *dev)
77{ 114{
78 struct msi_desc *entry; 115 struct msi_desc *entry;
@@ -89,14 +126,12 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
89 arch_teardown_msi_irq(entry->irq + i); 126 arch_teardown_msi_irq(entry->irq + i);
90 } 127 }
91} 128}
92#endif
93 129
94#ifndef arch_restore_msi_irqs 130void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
95# define arch_restore_msi_irqs default_restore_msi_irqs 131{
96# define HAVE_DEFAULT_MSI_RESTORE_IRQS 132 return default_teardown_msi_irqs(dev);
97#endif 133}
98 134
99#ifdef HAVE_DEFAULT_MSI_RESTORE_IRQS
100void default_restore_msi_irqs(struct pci_dev *dev, int irq) 135void default_restore_msi_irqs(struct pci_dev *dev, int irq)
101{ 136{
102 struct msi_desc *entry; 137 struct msi_desc *entry;
@@ -114,7 +149,11 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)
114 if (entry) 149 if (entry)
115 write_msi_msg(irq, &entry->msg); 150 write_msi_msg(irq, &entry->msg);
116} 151}
117#endif 152
153void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq)
154{
155 return default_restore_msi_irqs(dev, irq);
156}
118 157
119static void msi_set_enable(struct pci_dev *dev, int enable) 158static void msi_set_enable(struct pci_dev *dev, int enable)
120{ 159{
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 46ada5c098eb..b8eaa8167849 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,
666 666
667 child->parent = parent; 667 child->parent = parent;
668 child->ops = parent->ops; 668 child->ops = parent->ops;
669 child->msi = parent->msi;
669 child->sysdata = parent->sysdata; 670 child->sysdata = parent->sysdata;
670 child->bus_flags = parent->bus_flags; 671 child->bus_flags = parent->bus_flags;
671 672
diff --git a/include/linux/msi.h b/include/linux/msi.h
index ee66f3a12fb6..b17ead818aec 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -51,12 +51,31 @@ struct msi_desc {
51}; 51};
52 52
53/* 53/*
54 * The arch hook for setup up msi irqs 54 * The arch hooks to setup up msi irqs. Those functions are
55 * implemented as weak symbols so that they /can/ be overriden by
56 * architecture specific code if needed.
55 */ 57 */
56int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc); 58int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
57void arch_teardown_msi_irq(unsigned int irq); 59void arch_teardown_msi_irq(unsigned int irq);
58int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); 60int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
59void arch_teardown_msi_irqs(struct pci_dev *dev); 61void arch_teardown_msi_irqs(struct pci_dev *dev);
60int arch_msi_check_device(struct pci_dev* dev, int nvec, int type); 62int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
63void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
64
65void default_teardown_msi_irqs(struct pci_dev *dev);
66void default_restore_msi_irqs(struct pci_dev *dev, int irq);
67
68struct msi_chip {
69 struct module *owner;
70 struct device *dev;
71 struct device_node *of_node;
72 struct list_head list;
73
74 int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
75 struct msi_desc *desc);
76 void (*teardown_irq)(struct msi_chip *chip, unsigned int irq);
77 int (*check_device)(struct msi_chip *chip, struct pci_dev *dev,
78 int nvec, int type);
79};
61 80
62#endif /* LINUX_MSI_H */ 81#endif /* LINUX_MSI_H */
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 7a04826018c0..fd9c408631a0 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -2,6 +2,7 @@
2#define __OF_PCI_H 2#define __OF_PCI_H
3 3
4#include <linux/pci.h> 4#include <linux/pci.h>
5#include <linux/msi.h>
5 6
6struct pci_dev; 7struct pci_dev;
7struct of_irq; 8struct of_irq;
@@ -13,4 +14,15 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
13int of_pci_get_devfn(struct device_node *np); 14int of_pci_get_devfn(struct device_node *np);
14int of_pci_parse_bus_range(struct device_node *node, struct resource *res); 15int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
15 16
17#if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
18int of_pci_msi_chip_add(struct msi_chip *chip);
19void of_pci_msi_chip_remove(struct msi_chip *chip);
20struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node);
21#else
22static inline int of_pci_msi_chip_add(struct msi_chip *chip) { return -EINVAL; }
23static inline void of_pci_msi_chip_remove(struct msi_chip *chip) { }
24static inline struct msi_chip *
25of_pci_find_msi_chip_by_node(struct device_node *of_node) { return NULL; }
26#endif
27
16#endif 28#endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0fd1f1582fa1..4044e3c00609 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -433,6 +433,7 @@ struct pci_bus {
433 struct resource busn_res; /* bus numbers routed to this bus */ 433 struct resource busn_res; /* bus numbers routed to this bus */
434 434
435 struct pci_ops *ops; /* configuration access functions */ 435 struct pci_ops *ops; /* configuration access functions */
436 struct msi_chip *msi; /* MSI controller */
436 void *sysdata; /* hook for sys-specific extension */ 437 void *sysdata; /* hook for sys-specific extension */
437 struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */ 438 struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */
438 439