From 44c8bdbe32aa51fe673c7a86b1e8f45b952d7759 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Apr 2014 15:35:21 -0600 Subject: x86/PCI: Mark ATI SBx00 HPET BAR as IORESOURCE_PCI_FIXED Bodo reported that on the Asrock M3A UCC, v3.12.6 hangs during boot unless he uses "pci=nocrs". This regression was caused by 7bc5e3f2be32 ("x86/PCI: use host bridge _CRS info by default on 2008 and newer machines"), which appeared in v2.6.34. The reason is that the HPET address appears in a PCI device BAR, and this address is not contained in any of the host bridge windows. Linux moves the PCI BAR into a window, but the original address was published via the HPET table and an ACPI device, so changing the BAR is a bad idea. Here's the dmesg info: ACPI: HPET id: 0x43538301 base: 0xfed00000 pci_root PNP0A03:00: host bridge window [mem 0xd0000000-0xdfffffff] pci_root PNP0A03:00: host bridge window [mem 0xf0000000-0xfebfffff] pci 0000:00:14.0: [1002:4385] type 0 class 0x000c05 pci 0000:00:14.0: reg 14: [mem 0xfed00000-0xfed003ff] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0, 0 pnp 00:06: Plug and Play ACPI device, IDs PNP0103 (active) pnp 00:06: [mem 0xfed00000-0xfed003ff] When we notice the BAR is not in a host bridge window, we try to move it, but that causes a hang shortly thereafter: pci 0000:00:14.0: no compatible bridge window for [mem 0xfed00000-0xfed003ff] pci 0000:00:14.0: BAR 1: assigned [mem 0xf0000000-0xf00003ff] This patch marks the BAR as IORESOURCE_PCI_FIXED to prevent Linux from moving it. This depends on a previous patch ("x86/PCI: Don't try to move IORESOURCE_PCI_FIXED resources") to check for this flag when pci_claim_resource() fails. Link: https://bugzilla.kernel.org/show_bug.cgi?id=68591 Reported-and-tested-by: Bodo Eggert <7eggert@gmx.de> Signed-off-by: Bjorn Helgaas --- arch/x86/pci/fixup.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 94ae9ae9574f..ef334a003f3c 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -6,6 +6,7 @@ #include #include #include +#include #include static void pci_fixup_i450nx(struct pci_dev *d) @@ -526,6 +527,19 @@ static void sb600_disable_hpet_bar(struct pci_dev *dev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar); +#ifdef CONFIG_HPET_TIMER +static void sb600_hpet_quirk(struct pci_dev *dev) +{ + struct resource *r = &dev->resource[1]; + + if (r->flags & IORESOURCE_MEM && r->start == hpet_address) { + r->flags |= IORESOURCE_PCI_FIXED; + dev_info(&dev->dev, "reg 0x14 contains HPET; making it immovable\n"); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, 0x4385, sb600_hpet_quirk); +#endif + /* * Twinhead H12Y needs us to block out a region otherwise we map devices * there and any access kills the box. -- cgit v1.2.3