diff options
| author | Myron Stowe <myron.stowe@redhat.com> | 2015-02-03 18:01:24 -0500 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2015-02-03 21:28:02 -0500 |
| commit | 06cf35f903aa6da0cc8d9f81e9bcd1f7e1b534bb (patch) | |
| tree | 27fde5e9789b9747378bf0eaa5a23b3e499c863b | |
| parent | 51ac3d2f0c505ca36ffc9715ffd518d756589ef8 (diff) | |
PCI: Handle read-only BARs on AMD CS553x devices
Some AMD CS553x devices have read-only BARs because of a firmware or
hardware defect. There's a workaround in quirk_cs5536_vsa(), but it no
longer works after 36e8164882ca ("PCI: Restore detection of read-only
BARs"). Prior to 36e8164882ca, we filled in res->start; afterwards we
leave it zeroed out. The quirk only updated the size, so the driver tried
to use a region starting at zero, which didn't work.
Expand quirk_cs5536_vsa() to read the base addresses from the BARs and
hard-code the sizes.
On Nix's system BAR 2's read-only value is 0x6200. Prior to 36e8164882ca,
we interpret that as a 512-byte BAR based on the lowest-order bit set. Per
datasheet sec 5.6.1, that BAR (MFGPT) requires only 64 bytes; use that to
avoid clearing any address bits if a platform uses only 64-byte alignment.
[bhelgaas: changelog, reduce BAR 2 size to 64]
Fixes: 36e8164882ca ("PCI: Restore detection of read-only BARs")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=85991#c4
Link: http://support.amd.com/TechDocs/31506_cs5535_databook.pdf
Link: http://support.amd.com/TechDocs/33238G_cs5536_db.pdf
Reported-and-tested-by: Nix <nix@esperi.org.uk>
Signed-off-by: Myron Stowe <myron.stowe@redhat.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
CC: stable@vger.kernel.org # v.2.6.27+
| -rw-r--r-- | drivers/pci/quirks.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e52356aa09b8..903d5078b5ed 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -324,18 +324,52 @@ static void quirk_s3_64M(struct pci_dev *dev) | |||
| 324 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M); | 324 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M); |
| 325 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M); | 325 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M); |
| 326 | 326 | ||
| 327 | static void quirk_io(struct pci_dev *dev, int pos, unsigned size, | ||
| 328 | const char *name) | ||
| 329 | { | ||
| 330 | u32 region; | ||
| 331 | struct pci_bus_region bus_region; | ||
| 332 | struct resource *res = dev->resource + pos; | ||
| 333 | |||
| 334 | pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (pos << 2), ®ion); | ||
| 335 | |||
| 336 | if (!region) | ||
| 337 | return; | ||
| 338 | |||
| 339 | res->name = pci_name(dev); | ||
| 340 | res->flags = region & ~PCI_BASE_ADDRESS_IO_MASK; | ||
| 341 | res->flags |= | ||
| 342 | (IORESOURCE_IO | IORESOURCE_PCI_FIXED | IORESOURCE_SIZEALIGN); | ||
| 343 | region &= ~(size - 1); | ||
| 344 | |||
| 345 | /* Convert from PCI bus to resource space */ | ||
| 346 | bus_region.start = region; | ||
| 347 | bus_region.end = region + size - 1; | ||
| 348 | pcibios_bus_to_resource(dev->bus, res, &bus_region); | ||
| 349 | |||
| 350 | dev_info(&dev->dev, FW_BUG "%s quirk: reg 0x%x: %pR\n", | ||
| 351 | name, PCI_BASE_ADDRESS_0 + (pos << 2), res); | ||
| 352 | } | ||
| 353 | |||
| 327 | /* | 354 | /* |
| 328 | * Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS | 355 | * Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS |
| 329 | * ver. 1.33 20070103) don't set the correct ISA PCI region header info. | 356 | * ver. 1.33 20070103) don't set the correct ISA PCI region header info. |
| 330 | * BAR0 should be 8 bytes; instead, it may be set to something like 8k | 357 | * BAR0 should be 8 bytes; instead, it may be set to something like 8k |
| 331 | * (which conflicts w/ BAR1's memory range). | 358 | * (which conflicts w/ BAR1's memory range). |
| 359 | * | ||
| 360 | * CS553x's ISA PCI BARs may also be read-only (ref: | ||
| 361 | * https://bugzilla.kernel.org/show_bug.cgi?id=85991 - Comment #4 forward). | ||
| 332 | */ | 362 | */ |
| 333 | static void quirk_cs5536_vsa(struct pci_dev *dev) | 363 | static void quirk_cs5536_vsa(struct pci_dev *dev) |
| 334 | { | 364 | { |
| 365 | static char *name = "CS5536 ISA bridge"; | ||
| 366 | |||
| 335 | if (pci_resource_len(dev, 0) != 8) { | 367 | if (pci_resource_len(dev, 0) != 8) { |
| 336 | struct resource *res = &dev->resource[0]; | 368 | quirk_io(dev, 0, 8, name); /* SMB */ |
| 337 | res->end = res->start + 8 - 1; | 369 | quirk_io(dev, 1, 256, name); /* GPIO */ |
| 338 | dev_info(&dev->dev, "CS5536 ISA bridge bug detected (incorrect header); workaround applied\n"); | 370 | quirk_io(dev, 2, 64, name); /* MFGPT */ |
| 371 | dev_info(&dev->dev, "%s bug detected (incorrect header); workaround applied\n", | ||
| 372 | name); | ||
| 339 | } | 373 | } |
| 340 | } | 374 | } |
| 341 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa); | 375 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa); |
