diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 34b8dae..51ef450 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -180,11 +180,26 @@ static inline int is_64bit_memory(u32 mask) return 0; } +/* + * Sizing PCI BARs requires us to disable decoding, otherwise we may run + * into conflicts with other devices while trying to size the BAR. Normally + * this isn't a problem, but it happens on some machines normally, and can + * happen on others during PCI device hotplug. Don't disable BARs for host + * bridges, though. Some of them do silly things like disable accesses to + * RAM from the CPU + */ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) { unsigned int pos, reg, next; u32 l, sz; struct resource *res; + u16 orig_cmd; + + if ((dev->class >> 8) != PCI_CLASS_BRIDGE_HOST) { + pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); + pci_write_config_word(dev, PCI_COMMAND, + orig_cmd & ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO)); + } for(pos=0; posclass >> 8) != PCI_CLASS_BRIDGE_HOST) + pci_write_config_word(dev, PCI_COMMAND, orig_cmd); } void __devinit pci_read_bridge_bases(struct pci_bus *child)