aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/quirks.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp/quirks.c')
-rw-r--r--drivers/pnp/quirks.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 258fef272ea7..ebf0d6710b5a 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_PCI
339/* Device IDs of parts that have 32KB MCH space */
340static const unsigned int mch_quirk_devices[] = {
341 0x0154, /* Ivy Bridge */
342 0x0c00, /* Haswell */
343};
344
345static 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
359static 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, &region);
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_PCI
444 {"PNP0c02", quirk_intel_mch},
445#endif
367 {""} 446 {""}
368}; 447};
369 448