Re: [PATCH] PCI fixes for 2.6.10-rc1

Greg KH
2004-11-12T23:25:57Z

ChangeSet 1.2091.1.4, 2004/11/12 14:01:32-08:00, thockin@google.com

[PATCH] PCI: small PCI probe patch for odd 64 bit BARs

On Thu, Nov 11, 2004 at 09:54:19AM -0800, Greg KH wrote:
> I'll wait till you test this on 2.6 before applying it.

OK. Tested now on real hardware in 32 bit and 64 bit kernels. 32 bit
found another dumbness, that we can fix up.

Some PCI bridges default their UPPER prefetch windows to an unused state
of base > limit. We should not use those values if we find that. It
might be nice to reprogram them to 0, in fact.

Yes, BIOS should fix that up, but apparently, some do not.

Signed-Off-By: Tim Hockin <thockin@google.com>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>

drivers/pci/probe.c | 28 +++++++++++++++++++---------
1 files changed, 19 insertions(+), 9 deletions(-)

diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c 2004-11-12 15:11:34 -08:00
+++ b/drivers/pci/probe.c 2004-11-12 15:11:34 -08:00
@@ -144,9 +144,11 @@
pci_write_config_dword(dev, reg+4, ~0);
pci_read_config_dword(dev, reg+4, &sz);
pci_write_config_dword(dev, reg+4, l);
- if (~sz)
- res->end = res->start + 0xffffffff +
- (((unsigned long) ~sz) << 32);
+ sz = pci_size(l, sz, 0xffffffff);
+ if (sz) {
+ /* This BAR needs > 4GB? Wow. */
+ res->end |= (unsigned long)sz<<32;
+ }
#else
if (l) {
printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", pci_name(dev));
@@ -243,15 +245,23 @@
u32 mem_base_hi, mem_limit_hi;
pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
+
+ /*
+ * Some bridges set the base > limit by default, and some
+ * (broken) BIOSes do not initialize them. If we find
+ * this, just assume they are not being used.
+ */
+ if (mem_base_hi <= mem_limit_hi) {
#if BITS_PER_LONG == 64
- base |= ((long) mem_base_hi) << 32;
- limit |= ((long) mem_limit_hi) << 32;
+ base |= ((long) mem_base_hi) << 32;
+ limit |= ((long) mem_limit_hi) << 32;
#else
- if (mem_base_hi || mem_limit_hi) {
- printk(KERN_ERR "PCI: Unable to handle 64-bit address space for %s\n", child->name);
- return;
- }
+ if (mem_base_hi || mem_limit_hi) {
+ printk(KERN_ERR "PCI: Unable to handle 64-bit address space for bridge %s\n", pci_name(dev));
+ return;
+ }
#endif
+ }
}
if (base <= limit) {
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;