diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2010-03-19 14:56:27 -0600 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-03-24 13:21:36 -0700 |
commit | c519a5a7dab2d8e9a114f003e2d369bcf8e913f3 (patch) | |
tree | 2f0ebf4123b9b66b8068b8532334bad0f5cd0d84 /drivers/pci/probe.c | |
parent | e1944c6b0fba80a7837c1cbc47dfbf46e1274a4b (diff) | |
download | blackbird-op-linux-c519a5a7dab2d8e9a114f003e2d369bcf8e913f3.tar.gz blackbird-op-linux-c519a5a7dab2d8e9a114f003e2d369bcf8e913f3.zip |
PCI: complain about devices that seem to be broken
If we can tell that a device isn't working correctly, we should tell
the user to make debugging easier. Otherwise, it can take a lot of
work to determine whether the problem is in the driver, PCMCIA, PCI,
hardware, etc., as in http://bugzilla.kernel.org/show_bug.cgi?id=12006
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c82548afcd5c..882bd8d29fe3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -174,14 +174,19 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, pci_read_config_dword(dev, pos, &sz); pci_write_config_dword(dev, pos, l); + if (!sz) + goto fail; /* BAR not implemented */ + /* * All bits set in sz means the device isn't working properly. - * If the BAR isn't implemented, all bits must be 0. If it's a - * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit - * 1 must be clear. + * If it's a memory BAR or a ROM, bit 0 must be clear; if it's + * an io BAR, bit 1 must be clear. */ - if (!sz || sz == 0xffffffff) + if (sz == 0xffffffff) { + dev_err(&dev->dev, "reg %x: invalid size %#x; broken device?\n", + pos, sz); goto fail; + } /* * I don't know how l can have all bits set. Copied from old code. @@ -244,13 +249,17 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, pos, res); } } else { - sz = pci_size(l, sz, mask); + u32 size = pci_size(l, sz, mask); - if (!sz) + if (!size) { + dev_err(&dev->dev, "reg %x: invalid size " + "(l %#x sz %#x mask %#x); broken device?", + pos, l, sz, mask); goto fail; + } res->start = l; - res->end = l + sz; + res->end = l + size; dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); } |