aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-08-29 13:06:50 -0400
committerOlof Johansson <olof@lixom.net>2013-08-29 13:06:50 -0400
commit158a71f83800f07c0da0f0159d2670bdf4bdd852 (patch)
treed71c9a520d7a968cf221c4a65fe67003de3e1f5a /drivers
parentaaf75e454cc5e16e7f24bd87590b2d882ddb1671 (diff)
parent6a4324ebf5cf412d55fd1ea259d4dd29fb8f90e8 (diff)
Merge tag 'msi-3.12' of git://git.infradead.org/linux-mvebu into next/drivers
From Jason Cooper: mvebu msi pci changes for v3.12 - introduce support for MSI on PCI - fix s390 build breakage when !HAVE_GENERIC_HARDIRQS NOTE: This branch is a dependency for changes going though arm-soc from both Thomas Petazzoni and Thierry Reding. * tag 'msi-3.12' of git://git.infradead.org/linux-mvebu: PCI: msi: add default MSI operations for !HAVE_GENERIC_HARDIRQS platforms ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci of: pci: add registry of MSI chips PCI: Introduce new MSI chip infrastructure PCI: remove ARCH_SUPPORTS_MSI kconfig option PCI: use weak functions for MSI arch-specific functions Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers')
-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
4 files changed, 108 insertions, 27 deletions
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