Skip to content

Commit

Permalink
[PATCH] PCI: Ignore pre-set 64-bit BARs on 32-bit platforms
Browse files Browse the repository at this point in the history
[pci] Ignore pre-set 64-bit BARs on 32-bit platforms

Currently, Linux always rejects a device which has a pre-set 64-bit
address on a 32-bit platform.  On systems which do not do PCI
initialization in firmware, this causes some devices which don't
correctly power up with all BARs zero to fail.

This patch makes the kernel automatically zero out such an address
(thus treating it as if it had not been set at all, meaning it will
assign an address if necessary).

I have done this only for devices, not bridges.  It seems potentially
hazardous to do for bridges.

Signed-off-by: H. Peter Anvin <hpa@c2micro.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
H. Peter Anvin authored and Greg Kroah-Hartman committed Jun 21, 2006
1 parent 83821d3 commit 17d6dc8
Showing 1 changed file with 17 additions and 11 deletions.
28 changes: 17 additions & 11 deletions drivers/pci/probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,25 +180,31 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
res->flags |= pci_calc_resource_flags(l);
if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
== (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
pci_read_config_dword(dev, reg+4, &l);
u32 szhi, lhi;
pci_read_config_dword(dev, reg+4, &lhi);
pci_write_config_dword(dev, reg+4, ~0);
pci_read_config_dword(dev, reg+4, &szhi);
pci_write_config_dword(dev, reg+4, lhi);
szhi = pci_size(lhi, szhi, 0xffffffff);
next++;
#if BITS_PER_LONG == 64
res->start |= ((unsigned long) l) << 32;
res->start |= ((unsigned long) lhi) << 32;
res->end = res->start + sz;
pci_write_config_dword(dev, reg+4, ~0);
pci_read_config_dword(dev, reg+4, &sz);
pci_write_config_dword(dev, reg+4, l);
sz = pci_size(l, sz, 0xffffffff);
if (sz) {
if (szhi) {
/* This BAR needs > 4GB? Wow. */
res->end |= (unsigned long)sz<<32;
res->end |= (unsigned long)szhi<<32;
}
#else
if (l) {
printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", pci_name(dev));
if (szhi) {
printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev));
res->start = 0;
res->flags = 0;
continue;
} else if (l) {
/* 64-bit wide address, treat as disabled */
pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK);
pci_write_config_dword(dev, reg+4, 0);
res->start = 0;
res->end = sz;
}
#endif
}
Expand Down

0 comments on commit 17d6dc8

Please sign in to comment.