diff mbox

x86, pci: Add quirk for unsizeable Broadwell EP bar

Message ID 1455752728-29958-1-git-send-email-andi@firstfloor.org (mailing list archive)
State New, archived
Headers show

Commit Message

Andi Kleen Feb. 17, 2016, 11:45 p.m. UTC
From: Andi Kleen <ak@linux.intel.com>

The Home Agent and PCU PCI devices in Broadwell-EP have a BAR that returns a
non zero value when read, but is still not sizeable (because it doesn't
exist).  This causes several [Firmware error] messages at boot. It does
not cause any functional problems, as the devices really have no BARs.

Add a PCI quirk to shut off the messages.

v2: Handle all BARs, not just BAR0 (Chaohong Guo)
v3: Switch to patching bus ops
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 arch/x86/pci/fixup.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)
diff mbox

Patch

diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index e585655..4fcb5d5 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -540,3 +540,48 @@  static void twinhead_reserve_killing_zone(struct pci_dev *dev)
         }
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);
+
+/*
+ * Intel Broadwell EP. Prevent reading/updating BARs on Home Agent and PCU devices
+ * which are not real BARs, but still return non-null.
+ * This prevents a harmless warning message at boot.
+ */
+
+static inline bool bdwep_bad_bars(unsigned devfn, int where)
+{
+	return ((PCI_SLOT(devfn) == 0x12 && PCI_FUNC(devfn) == 0) ||
+		(PCI_SLOT(devfn) == 0x1e && PCI_FUNC(devfn) == 3)) &&
+		where >= 0x10 && where <= 0x24;
+}
+
+static int quirk_bdwep_bar_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+	if (bdwep_bad_bars(devfn, where)) {
+		*value = 0;
+		return 0;
+	}
+
+	return raw_pci_read(pci_domain_nr(bus), bus->number,
+			    devfn, where, size, value);
+}
+
+static int quirk_bdwep_bar_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+	if (bdwep_bad_bars(devfn, where))
+		return 0;
+
+	return raw_pci_write(pci_domain_nr(bus), bus->number,
+			     devfn, where, size, value);
+}
+
+static struct pci_ops quirk_bdwep_bar_ops = {
+	.read = quirk_bdwep_bar_read,
+	.write = quirk_bdwep_bar_write,
+};
+
+static void pci_bdwep_bar(struct pci_dev *dev)
+{
+	pci_bus_set_ops(dev->bus, &quirk_bdwep_bar_ops);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_bdwep_bar);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_bdwep_bar);