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 after36e8164882
("PCI: Restore detection of read-only BARs"). Prior to36e8164882
, 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 to36e8164882
, 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:36e8164882
("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+
This commit is contained in:
committed by
Bjorn Helgaas
parent
51ac3d2f0c
commit
06cf35f903
@@ -324,18 +324,52 @@ static void quirk_s3_64M(struct pci_dev *dev)
|
|||||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
|
||||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M);
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M);
|
||||||
|
|
||||||
|
static void quirk_io(struct pci_dev *dev, int pos, unsigned size,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
u32 region;
|
||||||
|
struct pci_bus_region bus_region;
|
||||||
|
struct resource *res = dev->resource + pos;
|
||||||
|
|
||||||
|
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (pos << 2), ®ion);
|
||||||
|
|
||||||
|
if (!region)
|
||||||
|
return;
|
||||||
|
|
||||||
|
res->name = pci_name(dev);
|
||||||
|
res->flags = region & ~PCI_BASE_ADDRESS_IO_MASK;
|
||||||
|
res->flags |=
|
||||||
|
(IORESOURCE_IO | IORESOURCE_PCI_FIXED | IORESOURCE_SIZEALIGN);
|
||||||
|
region &= ~(size - 1);
|
||||||
|
|
||||||
|
/* Convert from PCI bus to resource space */
|
||||||
|
bus_region.start = region;
|
||||||
|
bus_region.end = region + size - 1;
|
||||||
|
pcibios_bus_to_resource(dev->bus, res, &bus_region);
|
||||||
|
|
||||||
|
dev_info(&dev->dev, FW_BUG "%s quirk: reg 0x%x: %pR\n",
|
||||||
|
name, PCI_BASE_ADDRESS_0 + (pos << 2), res);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS
|
* Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS
|
||||||
* ver. 1.33 20070103) don't set the correct ISA PCI region header info.
|
* ver. 1.33 20070103) don't set the correct ISA PCI region header info.
|
||||||
* BAR0 should be 8 bytes; instead, it may be set to something like 8k
|
* BAR0 should be 8 bytes; instead, it may be set to something like 8k
|
||||||
* (which conflicts w/ BAR1's memory range).
|
* (which conflicts w/ BAR1's memory range).
|
||||||
|
*
|
||||||
|
* CS553x's ISA PCI BARs may also be read-only (ref:
|
||||||
|
* https://bugzilla.kernel.org/show_bug.cgi?id=85991 - Comment #4 forward).
|
||||||
*/
|
*/
|
||||||
static void quirk_cs5536_vsa(struct pci_dev *dev)
|
static void quirk_cs5536_vsa(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
|
static char *name = "CS5536 ISA bridge";
|
||||||
|
|
||||||
if (pci_resource_len(dev, 0) != 8) {
|
if (pci_resource_len(dev, 0) != 8) {
|
||||||
struct resource *res = &dev->resource[0];
|
quirk_io(dev, 0, 8, name); /* SMB */
|
||||||
res->end = res->start + 8 - 1;
|
quirk_io(dev, 1, 256, name); /* GPIO */
|
||||||
dev_info(&dev->dev, "CS5536 ISA bridge bug detected (incorrect header); workaround applied\n");
|
quirk_io(dev, 2, 64, name); /* MFGPT */
|
||||||
|
dev_info(&dev->dev, "%s bug detected (incorrect header); workaround applied\n",
|
||||||
|
name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
|
||||||
|
Reference in New Issue
Block a user