Re: small PCI probe patch for odd 64 bit BARs

From: Tim Hockin
Date: Thu Nov 11 2004 - 16:00:25 EST


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.

Tim

Signed-Off-By: Tim Hockin <thockin@xxxxxxxxxx>



--- linux-2.6.9/drivers/pci/probe.c.orig 2004-11-11 12:50:06.000000000 -0800
+++ linux-2.6.9/drivers/pci/probe.c 2004-11-11 12:53:33.000000000 -0800
@@ -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;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/