aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2014-04-29 20:37:47 -0400
committerBjorn Helgaas <bhelgaas@google.com>2014-05-23 12:47:20 -0400
commit31e9dd2565a6e27a3e698d7e3adf929db8d6c767 (patch)
tree7d3eefcac66a13eab42540e4a491b67dedde0b95
parent72dc5601fe5fec37cc1bd0efb19d99948fe7e54c (diff)
PCI: Don't set BAR to zero if dma_addr_t is too small
If a BAR is above 4GB and our dma_addr_t is too small, don't clear the BAR to zero: that doesn't disable the BAR, and it makes it more likely that the BAR will conflict with things if we turn on the memory enable bit (as we will at "out:" if the device was already enabled at the handoff). We should also print the BAR info and its original size so we can follow the process when we try to assign space to it. Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/probe.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 82cd75f6118a..dd710b12d34c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -174,7 +174,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
174 u64 l64, sz64, mask64; 174 u64 l64, sz64, mask64;
175 u16 orig_cmd; 175 u16 orig_cmd;
176 struct pci_bus_region region, inverted_region; 176 struct pci_bus_region region, inverted_region;
177 bool bar_too_big = false, bar_disabled = false; 177 bool bar_too_big = false, bar_too_high = false;
178 178
179 mask = type ? PCI_ROM_ADDRESS_MASK : ~0; 179 mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
180 180
@@ -254,13 +254,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
254 } 254 }
255 255
256 if ((sizeof(dma_addr_t) < 8) && l) { 256 if ((sizeof(dma_addr_t) < 8) && l) {
257 /* Address above 32-bit boundary; disable the BAR */ 257 /* Above 32-bit boundary; try to reallocate */
258 pci_write_config_dword(dev, pos, 0);
259 pci_write_config_dword(dev, pos + 4, 0);
260 res->flags |= IORESOURCE_UNSET; 258 res->flags |= IORESOURCE_UNSET;
261 res->start = 0; 259 res->start = 0;
262 res->end = sz64; 260 res->end = sz64;
263 bar_disabled = true; 261 bar_too_high = true;
264 goto out; 262 goto out;
265 } else { 263 } else {
266 region.start = l64; 264 region.start = l64;
@@ -311,7 +309,10 @@ out:
311 if (bar_too_big) 309 if (bar_too_big)
312 dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n", 310 dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
313 pos, (unsigned long long) sz64); 311 pos, (unsigned long long) sz64);
314 if (res->flags && !bar_disabled) 312 if (bar_too_high)
313 dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4G (bus address %#010llx)\n",
314 pos, (unsigned long long) l64);
315 if (res->flags)
315 dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); 316 dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
316 317
317 return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; 318 return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;