aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMyron Stowe <myron.stowe@redhat.com>2014-10-30 13:54:43 -0400
committerBjorn Helgaas <bhelgaas@google.com>2014-11-10 22:28:17 -0500
commitf795d86aaa578501551a2d1b463eac4bbea84db2 (patch)
tree797faaa59809689b0b688f6bff10b016c35ad329
parent36e8164882ca6d3c41cb91e6f09a3ed236841f80 (diff)
PCI: Shrink decoding-disabled window while sizing BARs
__pci_read_base() disables decoding while sizing device BARs. We can't print while decoding is disabled, which leads to some rather messy exit logic. Coalesce the sizing logic to minimize the time decoding is disabled. This lets us print errors where they're detected. The refactoring also takes advantage of the symmetry of obtaining the BAR's extent (pci_size) and storing the result as the 'region' for both the 32-bit and 64-bit BARs, consolidating both cases. No functional change intended. [bhelgaas: move pci_size() up, per Thomas Petazzoni, Thierry Reding, Kevin Hilman] Signed-off-by: Myron Stowe <myron.stowe@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> CC: Matthew Wilcox <willy@linux.intel.com>
-rw-r--r--drivers/pci/probe.c77
1 files changed, 31 insertions, 46 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 19dc247618f8..529fcd782e43 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -175,7 +175,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
175 u64 l64, sz64, mask64; 175 u64 l64, sz64, mask64;
176 u16 orig_cmd; 176 u16 orig_cmd;
177 struct pci_bus_region region, inverted_region; 177 struct pci_bus_region region, inverted_region;
178 bool bar_too_big = false, bar_too_high = false, bar_invalid = false;
179 178
180 mask = type ? PCI_ROM_ADDRESS_MASK : ~0; 179 mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
181 180
@@ -201,8 +200,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
201 * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit 200 * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit
202 * 1 must be clear. 201 * 1 must be clear.
203 */ 202 */
204 if (!sz || sz == 0xffffffff) 203 if (sz == 0xffffffff)
205 goto fail; 204 sz = 0;
206 205
207 /* 206 /*
208 * I don't know how l can have all bits set. Copied from old code. 207 * I don't know how l can have all bits set. Copied from old code.
@@ -215,26 +214,22 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
215 res->flags = decode_bar(dev, l); 214 res->flags = decode_bar(dev, l);
216 res->flags |= IORESOURCE_SIZEALIGN; 215 res->flags |= IORESOURCE_SIZEALIGN;
217 if (res->flags & IORESOURCE_IO) { 216 if (res->flags & IORESOURCE_IO) {
218 l &= PCI_BASE_ADDRESS_IO_MASK; 217 l64 = l & PCI_BASE_ADDRESS_IO_MASK;
219 sz &= PCI_BASE_ADDRESS_IO_MASK; 218 sz64 = sz & PCI_BASE_ADDRESS_IO_MASK;
220 mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; 219 mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT;
221 } else { 220 } else {
222 l &= PCI_BASE_ADDRESS_MEM_MASK; 221 l64 = l & PCI_BASE_ADDRESS_MEM_MASK;
223 sz &= PCI_BASE_ADDRESS_MEM_MASK; 222 sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK;
224 mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; 223 mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
225 } 224 }
226 } else { 225 } else {
227 res->flags |= (l & IORESOURCE_ROM_ENABLE); 226 res->flags |= (l & IORESOURCE_ROM_ENABLE);
228 l &= PCI_ROM_ADDRESS_MASK; 227 l64 = l & PCI_ROM_ADDRESS_MASK;
229 sz &= PCI_ROM_ADDRESS_MASK; 228 sz64 = sz & PCI_ROM_ADDRESS_MASK;
230 mask = (u32)PCI_ROM_ADDRESS_MASK; 229 mask64 = (u32)PCI_ROM_ADDRESS_MASK;
231 } 230 }
232 231
233 if (res->flags & IORESOURCE_MEM_64) { 232 if (res->flags & IORESOURCE_MEM_64) {
234 l64 = l;
235 sz64 = sz;
236 mask64 = mask | (u64)~0 << 32;
237
238 pci_read_config_dword(dev, pos + 4, &l); 233 pci_read_config_dword(dev, pos + 4, &l);
239 pci_write_config_dword(dev, pos + 4, ~0); 234 pci_write_config_dword(dev, pos + 4, ~0);
240 pci_read_config_dword(dev, pos + 4, &sz); 235 pci_read_config_dword(dev, pos + 4, &sz);
@@ -242,18 +237,27 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
242 237
243 l64 |= ((u64)l << 32); 238 l64 |= ((u64)l << 32);
244 sz64 |= ((u64)sz << 32); 239 sz64 |= ((u64)sz << 32);
240 mask64 |= ((u64)~0 << 32);
241 }
245 242
246 sz64 = pci_size(l64, sz64, mask64); 243 if (!dev->mmio_always_on && (orig_cmd & PCI_COMMAND_DECODE_ENABLE))
244 pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
247 245
248 if (!sz64) 246 if (!sz64)
249 goto fail; 247 goto fail;
248
249 sz64 = pci_size(l64, sz64, mask64);
250 if (!sz64)
251 goto fail;
250 252
253 if (res->flags & IORESOURCE_MEM_64) {
251 if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && 254 if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) &&
252 sz64 > 0x100000000ULL) { 255 sz64 > 0x100000000ULL) {
253 res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; 256 res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
254 res->start = 0; 257 res->start = 0;
255 res->end = 0; 258 res->end = 0;
256 bar_too_big = true; 259 dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
260 pos, (unsigned long long)sz64);
257 goto out; 261 goto out;
258 } 262 }
259 263
@@ -262,22 +266,15 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
262 res->flags |= IORESOURCE_UNSET; 266 res->flags |= IORESOURCE_UNSET;
263 res->start = 0; 267 res->start = 0;
264 res->end = sz64; 268 res->end = sz64;
265 bar_too_high = true; 269 dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4GB (bus address %#010llx)\n",
270 pos, (unsigned long long)l64);
266 goto out; 271 goto out;
267 } else {
268 region.start = l64;
269 region.end = l64 + sz64;
270 } 272 }
271 } else {
272 sz = pci_size(l, sz, mask);
273
274 if (!sz)
275 goto fail;
276
277 region.start = l;
278 region.end = l + sz;
279 } 273 }
280 274
275 region.start = l64;
276 region.end = l64 + sz64;
277
281 pcibios_bus_to_resource(dev->bus, res, &region); 278 pcibios_bus_to_resource(dev->bus, res, &region);
282 pcibios_resource_to_bus(dev->bus, &inverted_region, res); 279 pcibios_resource_to_bus(dev->bus, &inverted_region, res);
283 280
@@ -296,7 +293,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
296 res->flags |= IORESOURCE_UNSET; 293 res->flags |= IORESOURCE_UNSET;
297 res->start = 0; 294 res->start = 0;
298 res->end = region.end - region.start; 295 res->end = region.end - region.start;
299 bar_invalid = true; 296 dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n",
297 pos, (unsigned long long)region.start);
300 } 298 }
301 299
302 goto out; 300 goto out;
@@ -305,19 +303,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
305fail: 303fail:
306 res->flags = 0; 304 res->flags = 0;
307out: 305out:
308 if (!dev->mmio_always_on &&
309 (orig_cmd & PCI_COMMAND_DECODE_ENABLE))
310 pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
311
312 if (bar_too_big)
313 dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
314 pos, (unsigned long long) sz64);
315 if (bar_too_high)
316 dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4G (bus address %#010llx)\n",
317 pos, (unsigned long long) l64);
318 if (bar_invalid)
319 dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n",
320 pos, (unsigned long long) region.start);
321 if (res->flags) 306 if (res->flags)
322 dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); 307 dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
323 308