diff options
| -rw-r--r-- | drivers/pnp/quirks.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 258fef272ea7..3736bc408adb 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
| 17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
| 18 | #include <linux/pci.h> | ||
| 18 | #include <linux/string.h> | 19 | #include <linux/string.h> |
| 19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 20 | #include <linux/pnp.h> | 21 | #include <linux/pnp.h> |
| @@ -334,6 +335,81 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev) | |||
| 334 | } | 335 | } |
| 335 | #endif | 336 | #endif |
| 336 | 337 | ||
| 338 | #ifdef CONFIG_X86 | ||
| 339 | /* Device IDs of parts that have 32KB MCH space */ | ||
| 340 | static const unsigned int mch_quirk_devices[] = { | ||
| 341 | 0x0154, /* Ivy Bridge */ | ||
| 342 | 0x0c00, /* Haswell */ | ||
| 343 | }; | ||
| 344 | |||
| 345 | static struct pci_dev *get_intel_host(void) | ||
| 346 | { | ||
| 347 | int i; | ||
| 348 | struct pci_dev *host; | ||
| 349 | |||
| 350 | for (i = 0; i < ARRAY_SIZE(mch_quirk_devices); i++) { | ||
| 351 | host = pci_get_device(PCI_VENDOR_ID_INTEL, mch_quirk_devices[i], | ||
| 352 | NULL); | ||
| 353 | if (host) | ||
| 354 | return host; | ||
| 355 | } | ||
| 356 | return NULL; | ||
| 357 | } | ||
| 358 | |||
| 359 | static void quirk_intel_mch(struct pnp_dev *dev) | ||
| 360 | { | ||
| 361 | struct pci_dev *host; | ||
| 362 | u32 addr_lo, addr_hi; | ||
| 363 | struct pci_bus_region region; | ||
| 364 | struct resource mch; | ||
| 365 | struct pnp_resource *pnp_res; | ||
| 366 | struct resource *res; | ||
| 367 | |||
| 368 | host = get_intel_host(); | ||
| 369 | if (!host) | ||
| 370 | return; | ||
| 371 | |||
| 372 | /* | ||
| 373 | * MCHBAR is not an architected PCI BAR, so MCH space is usually | ||
| 374 | * reported as a PNP0C02 resource. The MCH space was originally | ||
| 375 | * 16KB, but is 32KB in newer parts. Some BIOSes still report a | ||
| 376 | * PNP0C02 resource that is only 16KB, which means the rest of the | ||
| 377 | * MCH space is consumed but unreported. | ||
| 378 | */ | ||
| 379 | |||
| 380 | /* | ||
| 381 | * Read MCHBAR for Host Member Mapped Register Range Base | ||
| 382 | * https://www-ssl.intel.com/content/www/us/en/processors/core/4th-gen-core-family-desktop-vol-2-datasheet | ||
| 383 | * Sec 3.1.12. | ||
| 384 | */ | ||
| 385 | pci_read_config_dword(host, 0x48, &addr_lo); | ||
| 386 | region.start = addr_lo & ~0x7fff; | ||
| 387 | pci_read_config_dword(host, 0x4c, &addr_hi); | ||
| 388 | region.start |= (u64) addr_hi << 32; | ||
| 389 | region.end = region.start + 32*1024 - 1; | ||
| 390 | |||
| 391 | memset(&mch, 0, sizeof(mch)); | ||
| 392 | mch.flags = IORESOURCE_MEM; | ||
| 393 | pcibios_bus_to_resource(host->bus, &mch, ®ion); | ||
| 394 | |||
| 395 | list_for_each_entry(pnp_res, &dev->resources, list) { | ||
| 396 | res = &pnp_res->res; | ||
| 397 | if (res->end < mch.start || res->start > mch.end) | ||
| 398 | continue; /* no overlap */ | ||
| 399 | if (res->start == mch.start && res->end == mch.end) | ||
| 400 | continue; /* exact match */ | ||
| 401 | |||
| 402 | dev_info(&dev->dev, FW_BUG "PNP resource %pR covers only part of %s Intel MCH; extending to %pR\n", | ||
| 403 | res, pci_name(host), &mch); | ||
| 404 | res->start = mch.start; | ||
| 405 | res->end = mch.end; | ||
| 406 | break; | ||
| 407 | } | ||
| 408 | |||
| 409 | pci_dev_put(host); | ||
| 410 | } | ||
| 411 | #endif | ||
| 412 | |||
| 337 | /* | 413 | /* |
| 338 | * PnP Quirks | 414 | * PnP Quirks |
| 339 | * Cards or devices that need some tweaking due to incomplete resource info | 415 | * Cards or devices that need some tweaking due to incomplete resource info |
| @@ -364,6 +440,9 @@ static struct pnp_fixup pnp_fixups[] = { | |||
| 364 | #ifdef CONFIG_AMD_NB | 440 | #ifdef CONFIG_AMD_NB |
| 365 | {"PNP0c01", quirk_amd_mmconfig_area}, | 441 | {"PNP0c01", quirk_amd_mmconfig_area}, |
| 366 | #endif | 442 | #endif |
| 443 | #ifdef CONFIG_X86 | ||
| 444 | {"PNP0c02", quirk_intel_mch}, | ||
| 445 | #endif | ||
| 367 | {""} | 446 | {""} |
| 368 | }; | 447 | }; |
| 369 | 448 | ||
