Commit 06cf35f903aa6da0cc8d9f81e9bcd1f7e1b534bb

Authored by Myron Stowe
Committed by Bjorn Helgaas
1 parent 51ac3d2f0c

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+

Showing 1 changed file with 37 additions and 3 deletions Side-by-side Diff

drivers/pci/quirks.c
... ... @@ -324,18 +324,52 @@
324 324 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
325 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), &region);
  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 355 * Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS
329 356 * ver. 1.33 20070103) don't set the correct ISA PCI region header info.
330 357 * BAR0 should be 8 bytes; instead, it may be set to something like 8k
331 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 363 static void quirk_cs5536_vsa(struct pci_dev *dev)
334 364 {
  365 + static char *name = "CS5536 ISA bridge";
  366 +
335 367 if (pci_resource_len(dev, 0) != 8) {
336   - struct resource *res = &dev->resource[0];
337   - res->end = res->start + 8 - 1;
338   - dev_info(&dev->dev, "CS5536 ISA bridge bug detected (incorrect header); workaround applied\n");
  368 + quirk_io(dev, 0, 8, name); /* SMB */
  369 + quirk_io(dev, 1, 256, name); /* GPIO */
  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 375 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);