| From eb31aae8cb5eb54e234ed2d857ddac868195d911 Mon Sep 17 00:00:00 2001 |
| From: Bjorn Helgaas <bhelgaas@google.com> |
| Date: Thu, 5 Jan 2012 14:27:24 -0700 |
| Subject: PNP: work around Dell 1536/1546 BIOS MMCONFIG bug that breaks USB |
| |
| From: Bjorn Helgaas <bhelgaas@google.com> |
| |
| commit eb31aae8cb5eb54e234ed2d857ddac868195d911 upstream. |
| |
| Some Dell BIOSes have MCFG tables that don't report the entire |
| MMCONFIG area claimed by the chipset. If we move PCI devices into |
| that claimed-but-unreported area, they don't work. |
| |
| This quirk reads the AMD MMCONFIG MSRs and adds PNP0C01 resources as |
| needed to cover the entire area. |
| |
| Example problem scenario: |
| |
| BIOS-e820: 00000000cfec5400 - 00000000d4000000 (reserved) |
| Fam 10h mmconf [d0000000, dfffffff] |
| PCI: MMCONFIG for domain 0000 [bus 00-3f] at [mem 0xd0000000-0xd3ffffff] (base 0xd0000000) |
| pnp 00:0c: [mem 0xd0000000-0xd3ffffff] |
| pci 0000:00:12.0: reg 10: [mem 0xffb00000-0xffb00fff] |
| pci 0000:00:12.0: no compatible bridge window for [mem 0xffb00000-0xffb00fff] |
| pci 0000:00:12.0: BAR 0: assigned [mem 0xd4000000-0xd40000ff] |
| |
| Reported-by: Lisa Salimbas <lisa.salimbas@canonical.com> |
| Reported-by: <thuban@singularity.fr> |
| Tested-by: dann frazier <dann.frazier@canonical.com> |
| References: https://bugzilla.kernel.org/show_bug.cgi?id=31602 |
| References: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/647043 |
| References: https://bugzilla.redhat.com/show_bug.cgi?id=770308 |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/pnp/quirks.c | 42 ++++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 42 insertions(+) |
| |
| --- a/drivers/pnp/quirks.c |
| +++ b/drivers/pnp/quirks.c |
| @@ -300,6 +300,45 @@ static void quirk_system_pci_resources(s |
| } |
| } |
| |
| +#ifdef CONFIG_AMD_NB |
| + |
| +#include <asm/amd_nb.h> |
| + |
| +static void quirk_amd_mmconfig_area(struct pnp_dev *dev) |
| +{ |
| + resource_size_t start, end; |
| + struct pnp_resource *pnp_res; |
| + struct resource *res; |
| + struct resource mmconfig_res, *mmconfig; |
| + |
| + mmconfig = amd_get_mmconfig_range(&mmconfig_res); |
| + if (!mmconfig) |
| + return; |
| + |
| + list_for_each_entry(pnp_res, &dev->resources, list) { |
| + res = &pnp_res->res; |
| + if (res->end < mmconfig->start || res->start > mmconfig->end || |
| + (res->start == mmconfig->start && res->end == mmconfig->end)) |
| + continue; |
| + |
| + dev_info(&dev->dev, FW_BUG |
| + "%pR covers only part of AMD MMCONFIG area %pR; adding more reservations\n", |
| + res, mmconfig); |
| + if (mmconfig->start < res->start) { |
| + start = mmconfig->start; |
| + end = res->start - 1; |
| + pnp_add_mem_resource(dev, start, end, 0); |
| + } |
| + if (mmconfig->end > res->end) { |
| + start = res->end + 1; |
| + end = mmconfig->end; |
| + pnp_add_mem_resource(dev, start, end, 0); |
| + } |
| + break; |
| + } |
| +} |
| +#endif |
| + |
| /* |
| * PnP Quirks |
| * Cards or devices that need some tweaking due to incomplete resource info |
| @@ -327,6 +366,9 @@ static struct pnp_fixup pnp_fixups[] = { |
| /* PnP resources that might overlap PCI BARs */ |
| {"PNP0c01", quirk_system_pci_resources}, |
| {"PNP0c02", quirk_system_pci_resources}, |
| +#ifdef CONFIG_AMD_NB |
| + {"PNP0c01", quirk_amd_mmconfig_area}, |
| +#endif |
| {""} |
| }; |
| |