Skip to content

Commit

Permalink
PNP: Work around BIOS defects in Intel MCH area reporting
Browse files Browse the repository at this point in the history
Work around BIOSes that don't report the entire Intel MCH area.

MCHBAR is not an architected PCI BAR, so MCH space is usually reported as a
PNP0C02 resource.  The MCH space was once 16KB, but is 32KB in newer parts.
Some BIOSes still report a PNP0C02 resource that is only 16KB, which means
the rest of the MCH space is consumed but unreported.

This can cause resource map sanity check warnings or (theoretically) a
device conflict if we assigned the unreported space to another device.

The Intel perf event uncore driver tripped over this when it claimed the
MCH region:

  resource map sanity check conflict: 0xfed10000 0xfed15fff 0xfed10000 0xfed13fff pnp 00:01
  Info: mapping multiple BARs. Your kernel is fine.

To prevent this, if we find a PNP0C02 resource that covers part of the MCH
space, extend it to cover the entire space.

References: http://lkml.kernel.org/r/20140224162400.GE16457@pd.tnic
Reported-and-tested-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Borislav Petkov <bp@suse.de>
Acked-by: Stephane Eranian <eranian@google.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
bjorn-helgaas authored and rafaeljw committed Apr 24, 2014
1 parent a798c10 commit cb171f7
Showing 1 changed file with 79 additions and 0 deletions.
79 changes: 79 additions & 0 deletions drivers/pnp/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/pnp.h>
Expand Down Expand Up @@ -334,6 +335,81 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
}
#endif

#ifdef CONFIG_X86
/* Device IDs of parts that have 32KB MCH space */
static const unsigned int mch_quirk_devices[] = {
0x0154, /* Ivy Bridge */
0x0c00, /* Haswell */
};

static struct pci_dev *get_intel_host(void)
{
int i;
struct pci_dev *host;

for (i = 0; i < ARRAY_SIZE(mch_quirk_devices); i++) {
host = pci_get_device(PCI_VENDOR_ID_INTEL, mch_quirk_devices[i],
NULL);
if (host)
return host;
}
return NULL;
}

static void quirk_intel_mch(struct pnp_dev *dev)
{
struct pci_dev *host;
u32 addr_lo, addr_hi;
struct pci_bus_region region;
struct resource mch;
struct pnp_resource *pnp_res;
struct resource *res;

host = get_intel_host();
if (!host)
return;

/*
* MCHBAR is not an architected PCI BAR, so MCH space is usually
* reported as a PNP0C02 resource. The MCH space was originally
* 16KB, but is 32KB in newer parts. Some BIOSes still report a
* PNP0C02 resource that is only 16KB, which means the rest of the
* MCH space is consumed but unreported.
*/

/*
* Read MCHBAR for Host Member Mapped Register Range Base
* https://www-ssl.intel.com/content/www/us/en/processors/core/4th-gen-core-family-desktop-vol-2-datasheet
* Sec 3.1.12.
*/
pci_read_config_dword(host, 0x48, &addr_lo);
region.start = addr_lo & ~0x7fff;
pci_read_config_dword(host, 0x4c, &addr_hi);
region.start |= (u64) addr_hi << 32;
region.end = region.start + 32*1024 - 1;

memset(&mch, 0, sizeof(mch));
mch.flags = IORESOURCE_MEM;
pcibios_bus_to_resource(host->bus, &mch, &region);

list_for_each_entry(pnp_res, &dev->resources, list) {
res = &pnp_res->res;
if (res->end < mch.start || res->start > mch.end)
continue; /* no overlap */
if (res->start == mch.start && res->end == mch.end)
continue; /* exact match */

dev_info(&dev->dev, FW_BUG "PNP resource %pR covers only part of %s Intel MCH; extending to %pR\n",
res, pci_name(host), &mch);
res->start = mch.start;
res->end = mch.end;
break;
}

pci_dev_put(host);
}
#endif

/*
* PnP Quirks
* Cards or devices that need some tweaking due to incomplete resource info
Expand Down Expand Up @@ -363,6 +439,9 @@ static struct pnp_fixup pnp_fixups[] = {
{"PNP0c02", quirk_system_pci_resources},
#ifdef CONFIG_AMD_NB
{"PNP0c01", quirk_amd_mmconfig_area},
#endif
#ifdef CONFIG_X86
{"PNP0c02", quirk_intel_mch},
#endif
{""}
};
Expand Down

0 comments on commit cb171f7

Please sign in to comment.