diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 23:58:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 23:58:52 -0500 |
commit | c75059c46293adf1560162c17148ab94624f5ed2 (patch) | |
tree | 75847b97da3477ce5c7aa32d81d0861f992e61ce /drivers/pci/probe.c | |
parent | f74ea36848ad49cb011aae55f56b0475702ffb79 (diff) | |
parent | 149792795d2bab33954bc025fcf145a8009683f6 (diff) |
Merge tag 'pci-v3.19-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI changes from Bjorn Helgaas:
"Here are the PCI changes intended for v3.19. I don't think there's
anything very exciting here, but there was a lot of MSI-related stuff
coming via Thomas.
Details:
NUMA
- Allow numa_node override via sysfs (Prarit Bhargava)
Resource management
- Restore detection of read-only BARs (Myron Stowe)
- Shrink decoding-disabled window while sizing BARs (Myron Stowe)
- Add informational printk for invalid BARs (Myron Stowe)
- Remove fixed parameter in pci_iov_resource_bar() (Myron Stowe)
MSI
- Add pci_msi_ignore_mask to prevent writes to MSI/MSI-X Mask Bits (Yijing Wang)
- Revert "PCI: Add x86_msi.msi_mask_irq() and msix_mask_irq()" (Yijing Wang)
- s390/MSI: Use __msi_mask_irq() instead of default_msi_mask_irq() (Yijing Wang)
Virtualization
- xen: Process failure for pcifront_(re)scan_root() (Chen Gang)
- Make FLR and AF FLR reset warning messages different (Gavin Shan)
Generic host bridge driver
- Allocate config space windows after limiting bus number range (Lorenzo Pieralisi)
- Convert to DT resource parsing API (Lorenzo Pieralisi)
Freescale Layerscape
- Add Freescale Layerscape PCIe driver (Minghuan Lian)
NVIDIA Tegra
- Do not build on 64-bit ARM (Thierry Reding)
- Add Kconfig help text (Thierry Reding)
Renesas R-Car
- Make rcar_pci static (Jingoo Han)
Samsung Exynos
- Add exynos prefix to add_pcie_port(), pcie_init() (Jingoo Han)
ST Microelectronics SPEAr13xx
- Add spear prefix to add_pcie_port(), pcie_init() (Jingoo Han)
- Make spear13xx_add_pcie_port() __init (Jingoo Han)
- Remove unnecessary OOM message (Jingoo Han)
TI DRA7xx
- Add dra7xx prefix to add_pcie_port() (Jingoo Han)
- Make dra7xx_add_pcie_port() __init (Jingoo Han)
TI Keystone
- Make ks_dw_pcie_msi_domain_ops static (Jingoo Han)
- Remove unnecessary OOM message (Jingoo Han)
Miscellaneous
- Delete unnecessary NULL pointer checks (Markus Elfring)
- Remove unused to_hotplug_slot() (Gavin Shan)
- Whitespace cleanup (Jingoo Han)
- Simplify if-return sequences (Quentin Lambert)"
* tag 'pci-v3.19-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (28 commits)
PCI: Remove fixed parameter in pci_iov_resource_bar()
PCI: Add informational printk for invalid BARs
PCI: tegra: Add Kconfig help text
PCI: tegra: Do not build on 64-bit ARM
PCI: spear: Remove unnecessary OOM message
PCI: mvebu: Add a blank line after declarations
PCI: designware: Add a blank line after declarations
PCI: exynos: Remove unnecessary return statement
PCI: imx6: Use tabs for indentation
PCI: keystone: Remove unnecessary OOM message
PCI: Remove unused and broken to_hotplug_slot()
PCI: Make FLR and AF FLR reset warning messages different
PCI: dra7xx: Add __init annotation to dra7xx_add_pcie_port()
PCI: spear: Add __init annotation to spear13xx_add_pcie_port()
PCI: spear: Rename add_pcie_port(), pcie_init() to spear13xx_add_pcie_port(), etc.
PCI: dra7xx: Rename add_pcie_port() to dra7xx_add_pcie_port()
PCI: layerscape: Add Freescale Layerscape PCIe driver
PCI: Simplify if-return sequences
PCI: Delete unnecessary NULL pointer checks
PCI: Shrink decoding-disabled window while sizing BARs
...
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 80 |
1 files changed, 35 insertions, 45 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c8ca98c2b480..23212f8ae09b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -87,8 +87,7 @@ static void release_pcibus_dev(struct device *dev) | |||
87 | { | 87 | { |
88 | struct pci_bus *pci_bus = to_pci_bus(dev); | 88 | struct pci_bus *pci_bus = to_pci_bus(dev); |
89 | 89 | ||
90 | if (pci_bus->bridge) | 90 | put_device(pci_bus->bridge); |
91 | put_device(pci_bus->bridge); | ||
92 | pci_bus_remove_resources(pci_bus); | 91 | pci_bus_remove_resources(pci_bus); |
93 | pci_release_bus_of_node(pci_bus); | 92 | pci_release_bus_of_node(pci_bus); |
94 | kfree(pci_bus); | 93 | kfree(pci_bus); |
@@ -175,7 +174,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
175 | u64 l64, sz64, mask64; | 174 | u64 l64, sz64, mask64; |
176 | u16 orig_cmd; | 175 | u16 orig_cmd; |
177 | struct pci_bus_region region, inverted_region; | 176 | struct pci_bus_region region, inverted_region; |
178 | bool bar_too_big = false, bar_too_high = false, bar_invalid = false; | ||
179 | 177 | ||
180 | mask = type ? PCI_ROM_ADDRESS_MASK : ~0; | 178 | mask = type ? PCI_ROM_ADDRESS_MASK : ~0; |
181 | 179 | ||
@@ -201,8 +199,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 | 199 | * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit |
202 | * 1 must be clear. | 200 | * 1 must be clear. |
203 | */ | 201 | */ |
204 | if (!sz || sz == 0xffffffff) | 202 | if (sz == 0xffffffff) |
205 | goto fail; | 203 | sz = 0; |
206 | 204 | ||
207 | /* | 205 | /* |
208 | * I don't know how l can have all bits set. Copied from old code. | 206 | * I don't know how l can have all bits set. Copied from old code. |
@@ -215,23 +213,22 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
215 | res->flags = decode_bar(dev, l); | 213 | res->flags = decode_bar(dev, l); |
216 | res->flags |= IORESOURCE_SIZEALIGN; | 214 | res->flags |= IORESOURCE_SIZEALIGN; |
217 | if (res->flags & IORESOURCE_IO) { | 215 | if (res->flags & IORESOURCE_IO) { |
218 | l &= PCI_BASE_ADDRESS_IO_MASK; | 216 | l64 = l & PCI_BASE_ADDRESS_IO_MASK; |
219 | mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; | 217 | sz64 = sz & PCI_BASE_ADDRESS_IO_MASK; |
218 | mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT; | ||
220 | } else { | 219 | } else { |
221 | l &= PCI_BASE_ADDRESS_MEM_MASK; | 220 | l64 = l & PCI_BASE_ADDRESS_MEM_MASK; |
222 | mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; | 221 | sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK; |
222 | mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK; | ||
223 | } | 223 | } |
224 | } else { | 224 | } else { |
225 | res->flags |= (l & IORESOURCE_ROM_ENABLE); | 225 | res->flags |= (l & IORESOURCE_ROM_ENABLE); |
226 | l &= PCI_ROM_ADDRESS_MASK; | 226 | l64 = l & PCI_ROM_ADDRESS_MASK; |
227 | mask = (u32)PCI_ROM_ADDRESS_MASK; | 227 | sz64 = sz & PCI_ROM_ADDRESS_MASK; |
228 | mask64 = (u32)PCI_ROM_ADDRESS_MASK; | ||
228 | } | 229 | } |
229 | 230 | ||
230 | if (res->flags & IORESOURCE_MEM_64) { | 231 | if (res->flags & IORESOURCE_MEM_64) { |
231 | l64 = l; | ||
232 | sz64 = sz; | ||
233 | mask64 = mask | (u64)~0 << 32; | ||
234 | |||
235 | pci_read_config_dword(dev, pos + 4, &l); | 232 | pci_read_config_dword(dev, pos + 4, &l); |
236 | pci_write_config_dword(dev, pos + 4, ~0); | 233 | pci_write_config_dword(dev, pos + 4, ~0); |
237 | pci_read_config_dword(dev, pos + 4, &sz); | 234 | pci_read_config_dword(dev, pos + 4, &sz); |
@@ -239,18 +236,30 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
239 | 236 | ||
240 | l64 |= ((u64)l << 32); | 237 | l64 |= ((u64)l << 32); |
241 | sz64 |= ((u64)sz << 32); | 238 | sz64 |= ((u64)sz << 32); |
239 | mask64 |= ((u64)~0 << 32); | ||
240 | } | ||
242 | 241 | ||
243 | sz64 = pci_size(l64, sz64, mask64); | 242 | if (!dev->mmio_always_on && (orig_cmd & PCI_COMMAND_DECODE_ENABLE)) |
243 | pci_write_config_word(dev, PCI_COMMAND, orig_cmd); | ||
244 | 244 | ||
245 | if (!sz64) | 245 | if (!sz64) |
246 | goto fail; | 246 | goto fail; |
247 | 247 | ||
248 | sz64 = pci_size(l64, sz64, mask64); | ||
249 | if (!sz64) { | ||
250 | dev_info(&dev->dev, FW_BUG "reg 0x%x: invalid BAR (can't size)\n", | ||
251 | pos); | ||
252 | goto fail; | ||
253 | } | ||
254 | |||
255 | if (res->flags & IORESOURCE_MEM_64) { | ||
248 | if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && | 256 | if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && |
249 | sz64 > 0x100000000ULL) { | 257 | sz64 > 0x100000000ULL) { |
250 | res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; | 258 | res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; |
251 | res->start = 0; | 259 | res->start = 0; |
252 | res->end = 0; | 260 | res->end = 0; |
253 | bar_too_big = true; | 261 | dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n", |
262 | pos, (unsigned long long)sz64); | ||
254 | goto out; | 263 | goto out; |
255 | } | 264 | } |
256 | 265 | ||
@@ -259,22 +268,15 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
259 | res->flags |= IORESOURCE_UNSET; | 268 | res->flags |= IORESOURCE_UNSET; |
260 | res->start = 0; | 269 | res->start = 0; |
261 | res->end = sz64; | 270 | res->end = sz64; |
262 | bar_too_high = true; | 271 | dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4GB (bus address %#010llx)\n", |
272 | pos, (unsigned long long)l64); | ||
263 | goto out; | 273 | goto out; |
264 | } else { | ||
265 | region.start = l64; | ||
266 | region.end = l64 + sz64; | ||
267 | } | 274 | } |
268 | } else { | ||
269 | sz = pci_size(l, sz, mask); | ||
270 | |||
271 | if (!sz) | ||
272 | goto fail; | ||
273 | |||
274 | region.start = l; | ||
275 | region.end = l + sz; | ||
276 | } | 275 | } |
277 | 276 | ||
277 | region.start = l64; | ||
278 | region.end = l64 + sz64; | ||
279 | |||
278 | pcibios_bus_to_resource(dev->bus, res, ®ion); | 280 | pcibios_bus_to_resource(dev->bus, res, ®ion); |
279 | pcibios_resource_to_bus(dev->bus, &inverted_region, res); | 281 | pcibios_resource_to_bus(dev->bus, &inverted_region, res); |
280 | 282 | ||
@@ -293,7 +295,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
293 | res->flags |= IORESOURCE_UNSET; | 295 | res->flags |= IORESOURCE_UNSET; |
294 | res->start = 0; | 296 | res->start = 0; |
295 | res->end = region.end - region.start; | 297 | res->end = region.end - region.start; |
296 | bar_invalid = true; | 298 | dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n", |
299 | pos, (unsigned long long)region.start); | ||
297 | } | 300 | } |
298 | 301 | ||
299 | goto out; | 302 | goto out; |
@@ -302,19 +305,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
302 | fail: | 305 | fail: |
303 | res->flags = 0; | 306 | res->flags = 0; |
304 | out: | 307 | out: |
305 | if (!dev->mmio_always_on && | ||
306 | (orig_cmd & PCI_COMMAND_DECODE_ENABLE)) | ||
307 | pci_write_config_word(dev, PCI_COMMAND, orig_cmd); | ||
308 | |||
309 | if (bar_too_big) | ||
310 | dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n", | ||
311 | pos, (unsigned long long) sz64); | ||
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 (bar_invalid) | ||
316 | dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n", | ||
317 | pos, (unsigned long long) region.start); | ||
318 | if (res->flags) | 308 | if (res->flags) |
319 | dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); | 309 | dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); |
320 | 310 | ||