diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2013-11-07 17:02:04 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-11-07 17:02:04 -0500 |
commit | eaaeb1cb33310dea6c3fa45d8bfc63e5a1d0a846 (patch) | |
tree | a76b60ff193a29b521e1bd63943a6d1969fe9af4 | |
parent | c245f2422031fec447e4d9e35fb0ef0fd5e42ab9 (diff) | |
parent | 79272138bd5c35edb9be5ae7b473a2741751a706 (diff) |
Merge branch 'pci/misc' into next
* pci/misc:
PCI: Enable upstream bridges even for VFs on virtual buses
PCI: Add pci_upstream_bridge()
PCI: Add x86_msi.msi_mask_irq() and msix_mask_irq()
-rw-r--r-- | arch/x86/include/asm/x86_init.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/x86_init.c | 10 | ||||
-rw-r--r-- | arch/x86/pci/xen.c | 13 | ||||
-rw-r--r-- | drivers/pci/msi.c | 22 | ||||
-rw-r--r-- | drivers/pci/pci.c | 13 | ||||
-rw-r--r-- | include/linux/msi.h | 2 | ||||
-rw-r--r-- | include/linux/pci.h | 9 |
7 files changed, 60 insertions, 12 deletions
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 828a1565ba57..0f1be11e43d2 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h | |||
@@ -172,6 +172,7 @@ struct x86_platform_ops { | |||
172 | 172 | ||
173 | struct pci_dev; | 173 | struct pci_dev; |
174 | struct msi_msg; | 174 | struct msi_msg; |
175 | struct msi_desc; | ||
175 | 176 | ||
176 | struct x86_msi_ops { | 177 | struct x86_msi_ops { |
177 | int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); | 178 | int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); |
@@ -182,6 +183,8 @@ struct x86_msi_ops { | |||
182 | void (*teardown_msi_irqs)(struct pci_dev *dev); | 183 | void (*teardown_msi_irqs)(struct pci_dev *dev); |
183 | void (*restore_msi_irqs)(struct pci_dev *dev, int irq); | 184 | void (*restore_msi_irqs)(struct pci_dev *dev, int irq); |
184 | int (*setup_hpet_msi)(unsigned int irq, unsigned int id); | 185 | int (*setup_hpet_msi)(unsigned int irq, unsigned int id); |
186 | u32 (*msi_mask_irq)(struct msi_desc *desc, u32 mask, u32 flag); | ||
187 | u32 (*msix_mask_irq)(struct msi_desc *desc, u32 flag); | ||
185 | }; | 188 | }; |
186 | 189 | ||
187 | struct IO_APIC_route_entry; | 190 | struct IO_APIC_route_entry; |
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 8ce0072cd700..021783b1f46a 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c | |||
@@ -116,6 +116,8 @@ struct x86_msi_ops x86_msi = { | |||
116 | .teardown_msi_irqs = default_teardown_msi_irqs, | 116 | .teardown_msi_irqs = default_teardown_msi_irqs, |
117 | .restore_msi_irqs = default_restore_msi_irqs, | 117 | .restore_msi_irqs = default_restore_msi_irqs, |
118 | .setup_hpet_msi = default_setup_hpet_msi, | 118 | .setup_hpet_msi = default_setup_hpet_msi, |
119 | .msi_mask_irq = default_msi_mask_irq, | ||
120 | .msix_mask_irq = default_msix_mask_irq, | ||
119 | }; | 121 | }; |
120 | 122 | ||
121 | /* MSI arch specific hooks */ | 123 | /* MSI arch specific hooks */ |
@@ -138,6 +140,14 @@ void arch_restore_msi_irqs(struct pci_dev *dev, int irq) | |||
138 | { | 140 | { |
139 | x86_msi.restore_msi_irqs(dev, irq); | 141 | x86_msi.restore_msi_irqs(dev, irq); |
140 | } | 142 | } |
143 | u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | ||
144 | { | ||
145 | return x86_msi.msi_mask_irq(desc, mask, flag); | ||
146 | } | ||
147 | u32 arch_msix_mask_irq(struct msi_desc *desc, u32 flag) | ||
148 | { | ||
149 | return x86_msi.msix_mask_irq(desc, flag); | ||
150 | } | ||
141 | #endif | 151 | #endif |
142 | 152 | ||
143 | struct x86_io_apic_ops x86_io_apic_ops = { | 153 | struct x86_io_apic_ops x86_io_apic_ops = { |
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 48e8461057ba..5eee4959785d 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -382,7 +382,14 @@ static void xen_teardown_msi_irq(unsigned int irq) | |||
382 | { | 382 | { |
383 | xen_destroy_irq(irq); | 383 | xen_destroy_irq(irq); |
384 | } | 384 | } |
385 | 385 | static u32 xen_nop_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | |
386 | { | ||
387 | return 0; | ||
388 | } | ||
389 | static u32 xen_nop_msix_mask_irq(struct msi_desc *desc, u32 flag) | ||
390 | { | ||
391 | return 0; | ||
392 | } | ||
386 | #endif | 393 | #endif |
387 | 394 | ||
388 | int __init pci_xen_init(void) | 395 | int __init pci_xen_init(void) |
@@ -406,6 +413,8 @@ int __init pci_xen_init(void) | |||
406 | x86_msi.setup_msi_irqs = xen_setup_msi_irqs; | 413 | x86_msi.setup_msi_irqs = xen_setup_msi_irqs; |
407 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; | 414 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; |
408 | x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; | 415 | x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; |
416 | x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; | ||
417 | x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; | ||
409 | #endif | 418 | #endif |
410 | return 0; | 419 | return 0; |
411 | } | 420 | } |
@@ -485,6 +494,8 @@ int __init pci_xen_initial_domain(void) | |||
485 | x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; | 494 | x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; |
486 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; | 495 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; |
487 | x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; | 496 | x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; |
497 | x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; | ||
498 | x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; | ||
488 | #endif | 499 | #endif |
489 | xen_setup_acpi_sci(); | 500 | xen_setup_acpi_sci(); |
490 | __acpi_register_gsi = acpi_register_gsi_xen; | 501 | __acpi_register_gsi = acpi_register_gsi_xen; |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 604265c40853..5e63645a7abe 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -185,7 +185,7 @@ static inline __attribute_const__ u32 msi_enabled_mask(u16 control) | |||
185 | * reliably as devices without an INTx disable bit will then generate a | 185 | * reliably as devices without an INTx disable bit will then generate a |
186 | * level IRQ which will never be cleared. | 186 | * level IRQ which will never be cleared. |
187 | */ | 187 | */ |
188 | static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | 188 | u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) |
189 | { | 189 | { |
190 | u32 mask_bits = desc->masked; | 190 | u32 mask_bits = desc->masked; |
191 | 191 | ||
@@ -199,9 +199,14 @@ static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | |||
199 | return mask_bits; | 199 | return mask_bits; |
200 | } | 200 | } |
201 | 201 | ||
202 | __weak u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | ||
203 | { | ||
204 | return default_msi_mask_irq(desc, mask, flag); | ||
205 | } | ||
206 | |||
202 | static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | 207 | static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) |
203 | { | 208 | { |
204 | desc->masked = __msi_mask_irq(desc, mask, flag); | 209 | desc->masked = arch_msi_mask_irq(desc, mask, flag); |
205 | } | 210 | } |
206 | 211 | ||
207 | /* | 212 | /* |
@@ -211,7 +216,7 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | |||
211 | * file. This saves a few milliseconds when initialising devices with lots | 216 | * file. This saves a few milliseconds when initialising devices with lots |
212 | * of MSI-X interrupts. | 217 | * of MSI-X interrupts. |
213 | */ | 218 | */ |
214 | static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag) | 219 | u32 default_msix_mask_irq(struct msi_desc *desc, u32 flag) |
215 | { | 220 | { |
216 | u32 mask_bits = desc->masked; | 221 | u32 mask_bits = desc->masked; |
217 | unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 222 | unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
@@ -224,9 +229,14 @@ static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag) | |||
224 | return mask_bits; | 229 | return mask_bits; |
225 | } | 230 | } |
226 | 231 | ||
232 | __weak u32 arch_msix_mask_irq(struct msi_desc *desc, u32 flag) | ||
233 | { | ||
234 | return default_msix_mask_irq(desc, flag); | ||
235 | } | ||
236 | |||
227 | static void msix_mask_irq(struct msi_desc *desc, u32 flag) | 237 | static void msix_mask_irq(struct msi_desc *desc, u32 flag) |
228 | { | 238 | { |
229 | desc->masked = __msix_mask_irq(desc, flag); | 239 | desc->masked = arch_msix_mask_irq(desc, flag); |
230 | } | 240 | } |
231 | 241 | ||
232 | static void msi_set_mask_bit(struct irq_data *data, u32 flag) | 242 | static void msi_set_mask_bit(struct irq_data *data, u32 flag) |
@@ -902,7 +912,7 @@ void pci_msi_shutdown(struct pci_dev *dev) | |||
902 | pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl); | 912 | pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl); |
903 | mask = msi_capable_mask(ctrl); | 913 | mask = msi_capable_mask(ctrl); |
904 | /* Keep cached state to be restored */ | 914 | /* Keep cached state to be restored */ |
905 | __msi_mask_irq(desc, mask, ~mask); | 915 | arch_msi_mask_irq(desc, mask, ~mask); |
906 | 916 | ||
907 | /* Restore dev->irq to its default pin-assertion irq */ | 917 | /* Restore dev->irq to its default pin-assertion irq */ |
908 | dev->irq = desc->msi_attrib.default_irq; | 918 | dev->irq = desc->msi_attrib.default_irq; |
@@ -998,7 +1008,7 @@ void pci_msix_shutdown(struct pci_dev *dev) | |||
998 | /* Return the device with MSI-X masked as initial states */ | 1008 | /* Return the device with MSI-X masked as initial states */ |
999 | list_for_each_entry(entry, &dev->msi_list, list) { | 1009 | list_for_each_entry(entry, &dev->msi_list, list) { |
1000 | /* Keep cached states to be restored */ | 1010 | /* Keep cached states to be restored */ |
1001 | __msix_mask_irq(entry, 1); | 1011 | arch_msix_mask_irq(entry, 1); |
1002 | } | 1012 | } |
1003 | 1013 | ||
1004 | msix_set_enable(dev, 0); | 1014 | msix_set_enable(dev, 0); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e485d92b3fa8..b127fbda6fc8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1148,12 +1148,12 @@ int pci_reenable_device(struct pci_dev *dev) | |||
1148 | 1148 | ||
1149 | static void pci_enable_bridge(struct pci_dev *dev) | 1149 | static void pci_enable_bridge(struct pci_dev *dev) |
1150 | { | 1150 | { |
1151 | struct pci_dev *bridge; | ||
1151 | int retval; | 1152 | int retval; |
1152 | 1153 | ||
1153 | if (!dev) | 1154 | bridge = pci_upstream_bridge(dev); |
1154 | return; | 1155 | if (bridge) |
1155 | 1156 | pci_enable_bridge(bridge); | |
1156 | pci_enable_bridge(dev->bus->self); | ||
1157 | 1157 | ||
1158 | if (pci_is_enabled(dev)) { | 1158 | if (pci_is_enabled(dev)) { |
1159 | if (!dev->is_busmaster) | 1159 | if (!dev->is_busmaster) |
@@ -1170,6 +1170,7 @@ static void pci_enable_bridge(struct pci_dev *dev) | |||
1170 | 1170 | ||
1171 | static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) | 1171 | static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) |
1172 | { | 1172 | { |
1173 | struct pci_dev *bridge; | ||
1173 | int err; | 1174 | int err; |
1174 | int i, bars = 0; | 1175 | int i, bars = 0; |
1175 | 1176 | ||
@@ -1188,7 +1189,9 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) | |||
1188 | if (atomic_inc_return(&dev->enable_cnt) > 1) | 1189 | if (atomic_inc_return(&dev->enable_cnt) > 1) |
1189 | return 0; /* already enabled */ | 1190 | return 0; /* already enabled */ |
1190 | 1191 | ||
1191 | pci_enable_bridge(dev->bus->self); | 1192 | bridge = pci_upstream_bridge(dev); |
1193 | if (bridge) | ||
1194 | pci_enable_bridge(bridge); | ||
1192 | 1195 | ||
1193 | /* only skip sriov related */ | 1196 | /* only skip sriov related */ |
1194 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) | 1197 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) |
diff --git a/include/linux/msi.h b/include/linux/msi.h index b17ead818aec..87cce50bd121 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h | |||
@@ -64,6 +64,8 @@ void arch_restore_msi_irqs(struct pci_dev *dev, int irq); | |||
64 | 64 | ||
65 | void default_teardown_msi_irqs(struct pci_dev *dev); | 65 | void default_teardown_msi_irqs(struct pci_dev *dev); |
66 | void default_restore_msi_irqs(struct pci_dev *dev, int irq); | 66 | void default_restore_msi_irqs(struct pci_dev *dev, int irq); |
67 | u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag); | ||
68 | u32 default_msix_mask_irq(struct msi_desc *desc, u32 flag); | ||
67 | 69 | ||
68 | struct msi_chip { | 70 | struct msi_chip { |
69 | struct module *owner; | 71 | struct module *owner; |
diff --git a/include/linux/pci.h b/include/linux/pci.h index d3a888ae4b2e..835ec7bf6c05 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -480,6 +480,15 @@ static inline bool pci_is_root_bus(struct pci_bus *pbus) | |||
480 | return !(pbus->parent); | 480 | return !(pbus->parent); |
481 | } | 481 | } |
482 | 482 | ||
483 | static inline struct pci_dev *pci_upstream_bridge(struct pci_dev *dev) | ||
484 | { | ||
485 | dev = pci_physfn(dev); | ||
486 | if (pci_is_root_bus(dev->bus)) | ||
487 | return NULL; | ||
488 | |||
489 | return dev->bus->self; | ||
490 | } | ||
491 | |||
483 | #ifdef CONFIG_PCI_MSI | 492 | #ifdef CONFIG_PCI_MSI |
484 | static inline bool pci_dev_msi_enabled(struct pci_dev *pci_dev) | 493 | static inline bool pci_dev_msi_enabled(struct pci_dev *pci_dev) |
485 | { | 494 | { |