diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/setup-res.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index eea85dafc76..1a0e60e265e 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
@@ -30,6 +30,8 @@ | |||
30 | void pci_update_resource(struct pci_dev *dev, int resno) | 30 | void pci_update_resource(struct pci_dev *dev, int resno) |
31 | { | 31 | { |
32 | struct pci_bus_region region; | 32 | struct pci_bus_region region; |
33 | bool disable; | ||
34 | u16 cmd; | ||
33 | u32 new, check, mask; | 35 | u32 new, check, mask; |
34 | int reg; | 36 | int reg; |
35 | enum pci_bar_type type; | 37 | enum pci_bar_type type; |
@@ -67,6 +69,18 @@ void pci_update_resource(struct pci_dev *dev, int resno) | |||
67 | new |= PCI_ROM_ADDRESS_ENABLE; | 69 | new |= PCI_ROM_ADDRESS_ENABLE; |
68 | } | 70 | } |
69 | 71 | ||
72 | /* | ||
73 | * We can't update a 64-bit BAR atomically, so when possible, | ||
74 | * disable decoding so that a half-updated BAR won't conflict | ||
75 | * with another device. | ||
76 | */ | ||
77 | disable = (res->flags & IORESOURCE_MEM_64) && !dev->mmio_always_on; | ||
78 | if (disable) { | ||
79 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
80 | pci_write_config_word(dev, PCI_COMMAND, | ||
81 | cmd & ~PCI_COMMAND_MEMORY); | ||
82 | } | ||
83 | |||
70 | pci_write_config_dword(dev, reg, new); | 84 | pci_write_config_dword(dev, reg, new); |
71 | pci_read_config_dword(dev, reg, &check); | 85 | pci_read_config_dword(dev, reg, &check); |
72 | 86 | ||
@@ -84,6 +98,10 @@ void pci_update_resource(struct pci_dev *dev, int resno) | |||
84 | "(high %#08x != %#08x)\n", resno, new, check); | 98 | "(high %#08x != %#08x)\n", resno, new, check); |
85 | } | 99 | } |
86 | } | 100 | } |
101 | |||
102 | if (disable) | ||
103 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
104 | |||
87 | res->flags &= ~IORESOURCE_UNSET; | 105 | res->flags &= ~IORESOURCE_UNSET; |
88 | dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n", | 106 | dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n", |
89 | resno, res, (unsigned long long)region.start, | 107 | resno, res, (unsigned long long)region.start, |