aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/quirks.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2010-09-21 13:54:39 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-10-15 16:09:50 -0400
commit66db60eaf158aa953651d03e43e931e757e87262 (patch)
treeac095123c1c92b4a646d8e908cbca835b63ac611 /drivers/pci/quirks.c
parentb22c3d82757109fa107ce17ba9484d45273eed05 (diff)
PCI: add quirk for non-symmetric-mode irq routing to versions 0 and 4 of the MCP55 northbridge
A long time ago I worked on a RHEL5 bug in which kdump hung during boot on a set of systems. The systems hung because they never received timer interrupts during calibrate_delay. These systems also all had Opteron processors on a hypertransport bus, bridged to a pci bus via an Nvidia MCP55 northbridge chip. After much wrangling I managed to learn from Nvidia that they have an undocumented register in some versions of that chip which control how legacy interrupts are send to the cpu complex when the ioapic isn't active. Nvidia defaults this register to only send legacy interrupts to the BSP, so if kdump happens to boot on an AP, we never get timer interrupts and boom. I had initially used this quirk as a workaround, with my intent being to move apic initalization to an earlier point in the boot process, so the setting of the register would be irrelevant. Given the work involved in doing that however, the fragile nature of the apic initalization code, and the fact that, over the 2 years since we found this bug, the MCP55 is the only chip which seems to have this issue, I've figure at this point its likely safer to just carry the quirk around. By setting the referenced bits in this hidden register, interrupts will be broadcast to all cpus when the ioapic isn't active on the above described systems. Acked-by: Simon Horman <horms@verge.net.au> Acked-by: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r--drivers/pci/quirks.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 857ae01734a6..034430690a5b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2296,6 +2296,37 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
2296 PCI_DEVICE_ID_NVIDIA_NVENET_15, 2296 PCI_DEVICE_ID_NVIDIA_NVENET_15,
2297 nvenet_msi_disable); 2297 nvenet_msi_disable);
2298 2298
2299/*
2300 * Some versions of the MCP55 bridge from nvidia have a legacy irq routing
2301 * config register. This register controls the routing of legacy interrupts
2302 * from devices that route through the MCP55. If this register is misprogramed
2303 * interrupts are only sent to the bsp, unlike conventional systems where the
2304 * irq is broadxast to all online cpus. Not having this register set
2305 * properly prevents kdump from booting up properly, so lets make sure that
2306 * we have it set correctly.
2307 * Note this is an undocumented register.
2308 */
2309static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
2310{
2311 u32 cfg;
2312
2313 pci_read_config_dword(dev, 0x74, &cfg);
2314
2315 if (cfg & ((1 << 2) | (1 << 15))) {
2316 printk(KERN_INFO "Rewriting irq routing register on MCP55\n");
2317 cfg &= ~((1 << 2) | (1 << 15));
2318 pci_write_config_dword(dev, 0x74, cfg);
2319 }
2320}
2321
2322DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
2323 PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V0,
2324 nvbridge_check_legacy_irq_routing);
2325
2326DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
2327 PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V4,
2328 nvbridge_check_legacy_irq_routing);
2329
2299static int __devinit ht_check_msi_mapping(struct pci_dev *dev) 2330static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
2300{ 2331{
2301 int pos, ttl = 48; 2332 int pos, ttl = 48;