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 | { |
