The current PCI probe code breaks for 64 bit BARs that do not decode a
full 64 bits. Example:
We have a device that uses a 64 bit BAR. When you write all Fs to the
BARs, you get:
000000ff ffff0000
It wants 64k, in the first TB of RAM. The current code totally borks on
this.
Simple patch against 2.6.9:
Signed-Off-By: Tim Hockin <[email protected]>
--- drivers/pci/probe.c.orig 2004-11-10 20:42:03.000000000 -0800
+++ drivers/pci/probe.c 2004-11-10 20:42:07.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(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));
Tim Hockin <[email protected]> wrote:
>
> + sz = pci_size(sz, 0xffffffff);
pci_size() takes three arguments, so this patch appears to not have been
runtime tested :(
On Thu, Nov 11, 2004 at 09:22:21AM -0800, Greg KH wrote:
> On Wed, Nov 10, 2004 at 08:48:09PM -0800, Tim Hockin wrote:
> > The current PCI probe code breaks for 64 bit BARs that do not decode a
> > full 64 bits. Example:
> >
> > We have a device that uses a 64 bit BAR. When you write all Fs to the
> > BARs, you get:
> >
> > 000000ff ffff0000
> >
> > It wants 64k, in the first TB of RAM. The current code totally borks on
> > this.
> >
> > Simple patch against 2.6.9:
>
> As Andrew pointed out, you didn't even compile test this patch, not nice.
Yeah, I sent the 2.4 patch and called it 2.6, bny mistake. The one that
actually came out of the 2.6.9 tree here was sent a few minutes ago, and
here again.
I was in a rush, I screwed up. This version has been compile tested,
and run tested under 2.4.
Sorry, again.
--- linux-2.6.9/drivers/pci/probe.c.orig 2004-11-10 20:42:03.000000000 -0800
+++ linux-2.6.9/drivers/pci/probe.c 2004-11-11 09:30:07.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));
On Thu, Nov 11, 2004 at 09:39:01AM -0800, Tim Hockin wrote:
> On Wed, Nov 10, 2004 at 09:51:42PM -0800, Andrew Morton wrote:
> > Tim Hockin <[email protected]> wrote:
> > >
> > > + sz = pci_size(sz, 0xffffffff);
> >
> > pci_size() takes three arguments, so this patch appears to not have been
> > runtime tested :(
>
> Doh, I sent the 2.4 patch. This one should work on 2.6.9, though I do
> not have 2.6.9 running on this hardware, yet. It was definitely runtime
> tested on 2.4.
I'll wait till you test this on 2.6 before applying it. What kind of
hardware is this patch needed for?
thanks,
greg k-h
On Wed, Nov 10, 2004 at 09:51:42PM -0800, Andrew Morton wrote:
> Tim Hockin <[email protected]> wrote:
> >
> > + sz = pci_size(sz, 0xffffffff);
>
> pci_size() takes three arguments, so this patch appears to not have been
> runtime tested :(
Doh, I sent the 2.4 patch. This one should work on 2.6.9, though I do
not have 2.6.9 running on this hardware, yet. It was definitely runtime
tested on 2.4.
--- linux-2.6.9/drivers/pci/probe.c.orig 2004-11-10 20:42:03.000000000 -0800
+++ linux-2.6.9/drivers/pci/probe.c 2004-11-11 09:30:07.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));
On Wed, Nov 10, 2004 at 08:48:09PM -0800, Tim Hockin wrote:
> The current PCI probe code breaks for 64 bit BARs that do not decode a
> full 64 bits. Example:
>
> We have a device that uses a 64 bit BAR. When you write all Fs to the
> BARs, you get:
>
> 000000ff ffff0000
>
> It wants 64k, in the first TB of RAM. The current code totally borks on
> this.
>
> Simple patch against 2.6.9:
As Andrew pointed out, you didn't even compile test this patch, not nice.
thanks,
greg k-h
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 <[email protected]>
--- 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;
On Thu, Nov 11, 2004 at 12:58:52PM -0800, Tim Hockin wrote:
> 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 <[email protected]>
Applied, thanks.
greg k-h