diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2012-07-09 23:02:44 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-07-09 23:02:44 -0400 |
commit | d68e70c6e59ad08feca291c2790164d3231c425e (patch) | |
tree | 17bd7b95ef577a5b2f1913be20e31c0f41390d1a | |
parent | 9349b44a459677e270ae19a373c58e5c3edbff04 (diff) | |
parent | 9aac537e0e33f4e4f28b8e7472c283fb6460c650 (diff) |
Merge branch 'pci/bjorn-disable-decode' into next
* pci/bjorn-disable-decode:
PCI: disable MEM decoding while updating 64-bit MEM BARs
PCI: leave MEM and IO decoding disabled during 64-bit BAR sizing, too
-rw-r--r-- | drivers/pci/probe.c | 6 | ||||
-rw-r--r-- | drivers/pci/setup-res.c | 18 |
2 files changed, 21 insertions, 3 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index cd06c8478267..5e5358a3dd92 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -189,9 +189,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
189 | pci_read_config_dword(dev, pos, &sz); | 189 | pci_read_config_dword(dev, pos, &sz); |
190 | pci_write_config_dword(dev, pos, l); | 190 | pci_write_config_dword(dev, pos, l); |
191 | 191 | ||
192 | if (!dev->mmio_always_on) | ||
193 | pci_write_config_word(dev, PCI_COMMAND, orig_cmd); | ||
194 | |||
195 | /* | 192 | /* |
196 | * All bits set in sz means the device isn't working properly. | 193 | * All bits set in sz means the device isn't working properly. |
197 | * If the BAR isn't implemented, all bits must be 0. If it's a | 194 | * If the BAR isn't implemented, all bits must be 0. If it's a |
@@ -276,6 +273,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
276 | } | 273 | } |
277 | 274 | ||
278 | out: | 275 | out: |
276 | if (!dev->mmio_always_on) | ||
277 | pci_write_config_word(dev, PCI_COMMAND, orig_cmd); | ||
278 | |||
279 | return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; | 279 | return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; |
280 | fail: | 280 | fail: |
281 | res->flags = 0; | 281 | res->flags = 0; |
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index eea85dafc763..1a0e60e265ea 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, |