diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e48fcf0..a5fdd83 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -170,6 +170,33 @@ static inline int is_64bit_memory(u32 mask) return 0; } +static u32 pci_base_size(struct pci_dev *dev, unsigned int reg, bool memory) +{ + u32 orig_reg, sz; + u16 orig_cmd; + + pci_read_config_dword(dev, reg, &orig_reg); + pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); + + if (memory) + pci_write_config_word(dev, PCI_COMMAND, + orig_cmd & ~PCI_COMMAND_MEMORY); + else + pci_write_config_word(dev, PCI_COMMAND, + orig_cmd & ~PCI_COMMAND_IO); + + pci_write_config_dword(dev, reg, ~0); + pci_read_config_dword(dev, reg, &sz); + pci_write_config_dword(dev, reg, orig_reg); + + pci_write_config_word(dev, reg, orig_cmd); + + return sz; +} + +#define BAR_IS_MEMORY(bar) (((bar) & PCI_BASE_ADDRESS_SPACE) == \ + PCI_BASE_ADDRESS_SPACE_MEMORY) + static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) { unsigned int pos, reg, next; @@ -186,16 +213,14 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) res->name = pci_name(dev); reg = PCI_BASE_ADDRESS_0 + (pos << 2); pci_read_config_dword(dev, reg, &l); - pci_write_config_dword(dev, reg, ~0); - pci_read_config_dword(dev, reg, &sz); + sz = pci_base_size(dev, reg, BAR_IS_MEMORY(l)); pci_write_config_dword(dev, reg, l); if (!sz || sz == 0xffffffff) continue; if (l == 0xffffffff) l = 0; raw_sz = sz; - if ((l & PCI_BASE_ADDRESS_SPACE) == - PCI_BASE_ADDRESS_SPACE_MEMORY) { + if (BAR_IS_MEMORY(l)) { sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK); /* * For 64bit prefetchable memory sz could be 0, if the