diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-09 15:03:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-09 15:03:49 -0400 |
commit | 80213c03c4151d900cf293ef0fc51f8d88495e14 (patch) | |
tree | af2422fa255aed96c23cef894e0adbf817f30c45 /drivers/pci/probe.c | |
parent | ea584595fc85e65796335033dfca25ed655cd0ed (diff) | |
parent | f92d9ee3ab39841d1f29f2d1aa96ff7c74b36ee1 (diff) |
Merge tag 'pci-v3.18-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
"The interesting things here are:
- Turn on Config Request Retry Status Software Visibility. This
caused hangs last time, but we included a fix this time.
- Rework PCI device configuration to use _HPP/_HPX more aggressively
- Allow PCI devices to be put into D3cold during system suspend
- Add arm64 PCI support
- Add APM X-Gene host bridge driver
- Add TI Keystone host bridge driver
- Add Xilinx AXI host bridge driver
More detailed summary:
Enumeration
- Check Vendor ID only for Config Request Retry Status (Rajat Jain)
- Enable Config Request Retry Status when supported (Rajat Jain)
- Add generic domain handling (Catalin Marinas)
- Generate uppercase hex for modalias interface class (Ricardo Ribalda Delgado)
Resource management
- Add missing MEM_64 mask in pci_assign_unassigned_bridge_resources() (Yinghai Lu)
- Increase IBM ipr SAS Crocodile BARs to at least system page size (Douglas Lehr)
PCI device hotplug
- Prevent NULL dereference during pciehp probe (Andreas Noever)
- Move _HPP & _HPX handling into core (Bjorn Helgaas)
- Apply _HPP to PCIe devices as well as PCI (Bjorn Helgaas)
- Apply _HPP/_HPX to display devices (Bjorn Helgaas)
- Preserve SERR & PARITY settings when applying _HPP/_HPX (Bjorn Helgaas)
- Preserve MPS and MRRS settings when applying _HPP/_HPX (Bjorn Helgaas)
- Apply _HPP/_HPX to all devices, not just hot-added ones (Bjorn Helgaas)
- Fix wait time in pciehp timeout message (Yinghai Lu)
- Add more pciehp Slot Control debug output (Yinghai Lu)
- Stop disabling pciehp notifications during init (Yinghai Lu)
MSI
- Remove arch_msi_check_device() (Alexander Gordeev)
- Rename pci_msi_check_device() to pci_msi_supported() (Alexander Gordeev)
- Move D0 check into pci_msi_check_device() (Alexander Gordeev)
- Remove unused kobject from struct msi_desc (Yijing Wang)
- Remove "pos" from the struct msi_desc msi_attrib (Yijing Wang)
- Add "msi_bus" sysfs MSI/MSI-X control for endpoints (Yijing Wang)
- Use __get_cached_msi_msg() instead of get_cached_msi_msg() (Yijing Wang)
- Use __read_msi_msg() instead of read_msi_msg() (Yijing Wang)
- Use __write_msi_msg() instead of write_msi_msg() (Yijing Wang)
Power management
- Drop unused runtime PM support code for PCIe ports (Rafael J. Wysocki)
- Allow PCI devices to be put into D3cold during system suspend (Rafael J. Wysocki)
AER
- Add additional AER error strings (Gong Chen)
- Make <linux/aer.h> standalone includable (Thierry Reding)
Virtualization
- Add ACS quirk for Solarflare SFC9120 & SFC9140 (Alex Williamson)
- Add ACS quirk for Intel 10G NICs (Alex Williamson)
- Add ACS quirk for AMD A88X southbridge (Marti Raudsepp)
- Remove unused pci_find_upstream_pcie_bridge(), pci_get_dma_source() (Alex Williamson)
- Add device flag helpers (Ethan Zhao)
- Assume all Mellanox devices have broken INTx masking (Gavin Shan)
Generic host bridge driver
- Fix ioport_map() for !CONFIG_GENERIC_IOMAP (Liviu Dudau)
- Add pci_register_io_range() and pci_pio_to_address() (Liviu Dudau)
- Define PCI_IOBASE as the base of virtual PCI IO space (Liviu Dudau)
- Fix the conversion of IO ranges into IO resources (Liviu Dudau)
- Add pci_get_new_domain_nr() and of_get_pci_domain_nr() (Liviu Dudau)
- Add support for parsing PCI host bridge resources from DT (Liviu Dudau)
- Add pci_remap_iospace() to map bus I/O resources (Liviu Dudau)
- Add arm64 architectural support for PCI (Liviu Dudau)
APM X-Gene
- Add APM X-Gene PCIe driver (Tanmay Inamdar)
- Add arm64 DT APM X-Gene PCIe device tree nodes (Tanmay Inamdar)
Freescale i.MX6
- Probe in module_init(), not fs_initcall() (Lucas Stach)
- Delay enabling reference clock for SS until it stabilizes (Tim Harvey)
Marvell MVEBU
- Fix uninitialized variable in mvebu_get_tgt_attr() (Thomas Petazzoni)
NVIDIA Tegra
- Make sure the PCIe PLL is really reset (Eric Yuen)
- Add error path tegra_msi_teardown_irq() cleanup (Jisheng Zhang)
- Fix extended configuration space mapping (Peter Daifuku)
- Implement resource hierarchy (Thierry Reding)
- Clear CLKREQ# enable on port disable (Thierry Reding)
- Add Tegra124 support (Thierry Reding)
ST Microelectronics SPEAr13xx
- Pass config resource through reg property (Pratyush Anand)
Synopsys DesignWare
- Use NULL instead of false (Fabio Estevam)
- Parse bus-range property from devicetree (Lucas Stach)
- Use pci_create_root_bus() instead of pci_scan_root_bus() (Lucas Stach)
- Remove pci_assign_unassigned_resources() (Lucas Stach)
- Check private_data validity in single place (Lucas Stach)
- Setup and clear exactly one MSI at a time (Lucas Stach)
- Remove open-coded bitmap operations (Lucas Stach)
- Fix configuration base address when using 'reg' (Minghuan Lian)
- Fix IO resource end address calculation (Minghuan Lian)
- Rename get_msi_data() to get_msi_addr() (Minghuan Lian)
- Add get_msi_data() to pcie_host_ops (Minghuan Lian)
- Add support for v3.65 hardware (Murali Karicheri)
- Fold struct pcie_port_info into struct pcie_port (Pratyush Anand)
TI Keystone
- Add TI Keystone PCIe driver (Murali Karicheri)
- Limit MRSS for all downstream devices (Murali Karicheri)
- Assume controller is already in RC mode (Murali Karicheri)
- Set device ID based on SoC to support multiple ports (Murali Karicheri)
Xilinx AXI
- Add Xilinx AXI PCIe driver (Srikanth Thokala)
- Fix xilinx_pcie_assign_msi() return value test (Dan Carpenter)
Miscellaneous
- Clean up whitespace (Quentin Lambert)
- Remove assignments from "if" conditions (Quentin Lambert)
- Move PCI_VENDOR_ID_VMWARE to pci_ids.h (Francesco Ruggeri)
- x86: Mark DMI tables as initialization data (Mathias Krause)
- x86: Move __init annotation to the correct place (Mathias Krause)
- x86: Mark constants of pci_mmcfg_nvidia_mcp55() as __initconst (Mathias Krause)
- x86: Constify pci_mmcfg_probes[] array (Mathias Krause)
- x86: Mark PCI BIOS initialization code as such (Mathias Krause)
- Parenthesize PCI_DEVID and PCI_VPD_LRDT_ID parameters (Megan Kamiya)
- Remove unnecessary variable in pci_add_dynid() (Tobias Klauser)"
* tag 'pci-v3.18-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (109 commits)
arm64: dts: Add APM X-Gene PCIe device tree nodes
PCI: Add ACS quirk for AMD A88X southbridge devices
PCI: xgene: Add APM X-Gene PCIe driver
PCI: designware: Remove open-coded bitmap operations
PCI/MSI: Remove unnecessary temporary variable
PCI/MSI: Use __write_msi_msg() instead of write_msi_msg()
MSI/powerpc: Use __read_msi_msg() instead of read_msi_msg()
PCI/MSI: Use __get_cached_msi_msg() instead of get_cached_msi_msg()
PCI/MSI: Add "msi_bus" sysfs MSI/MSI-X control for endpoints
PCI/MSI: Remove "pos" from the struct msi_desc msi_attrib
PCI/MSI: Remove unused kobject from struct msi_desc
PCI/MSI: Rename pci_msi_check_device() to pci_msi_supported()
PCI/MSI: Move D0 check into pci_msi_check_device()
PCI/MSI: Remove arch_msi_check_device()
irqchip: armada-370-xp: Remove arch_msi_check_device()
PCI/MSI/PPC: Remove arch_msi_check_device()
arm64: Add architectural support for PCI
PCI: Add pci_remap_iospace() to map bus I/O resources
of/pci: Add support for parsing PCI host bridge resources from DT
of/pci: Add pci_get_new_domain_nr() and of_get_pci_domain_nr()
...
Conflicts:
arch/arm64/boot/dts/apm-storm.dtsi
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 167 |
1 files changed, 162 insertions, 5 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 4170113cde61..5ed99309c758 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/pci.h> | 8 | #include <linux/pci.h> |
9 | #include <linux/pci_hotplug.h> | ||
9 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
10 | #include <linux/module.h> | 11 | #include <linux/module.h> |
11 | #include <linux/cpumask.h> | 12 | #include <linux/cpumask.h> |
@@ -485,7 +486,7 @@ void pci_read_bridge_bases(struct pci_bus *child) | |||
485 | } | 486 | } |
486 | } | 487 | } |
487 | 488 | ||
488 | static struct pci_bus *pci_alloc_bus(void) | 489 | static struct pci_bus *pci_alloc_bus(struct pci_bus *parent) |
489 | { | 490 | { |
490 | struct pci_bus *b; | 491 | struct pci_bus *b; |
491 | 492 | ||
@@ -500,6 +501,10 @@ static struct pci_bus *pci_alloc_bus(void) | |||
500 | INIT_LIST_HEAD(&b->resources); | 501 | INIT_LIST_HEAD(&b->resources); |
501 | b->max_bus_speed = PCI_SPEED_UNKNOWN; | 502 | b->max_bus_speed = PCI_SPEED_UNKNOWN; |
502 | b->cur_bus_speed = PCI_SPEED_UNKNOWN; | 503 | b->cur_bus_speed = PCI_SPEED_UNKNOWN; |
504 | #ifdef CONFIG_PCI_DOMAINS_GENERIC | ||
505 | if (parent) | ||
506 | b->domain_nr = parent->domain_nr; | ||
507 | #endif | ||
503 | return b; | 508 | return b; |
504 | } | 509 | } |
505 | 510 | ||
@@ -671,7 +676,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, | |||
671 | /* | 676 | /* |
672 | * Allocate a new bus, and inherit stuff from the parent.. | 677 | * Allocate a new bus, and inherit stuff from the parent.. |
673 | */ | 678 | */ |
674 | child = pci_alloc_bus(); | 679 | child = pci_alloc_bus(parent); |
675 | if (!child) | 680 | if (!child) |
676 | return NULL; | 681 | return NULL; |
677 | 682 | ||
@@ -740,6 +745,17 @@ struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, | |||
740 | } | 745 | } |
741 | EXPORT_SYMBOL(pci_add_new_bus); | 746 | EXPORT_SYMBOL(pci_add_new_bus); |
742 | 747 | ||
748 | static void pci_enable_crs(struct pci_dev *pdev) | ||
749 | { | ||
750 | u16 root_cap = 0; | ||
751 | |||
752 | /* Enable CRS Software Visibility if supported */ | ||
753 | pcie_capability_read_word(pdev, PCI_EXP_RTCAP, &root_cap); | ||
754 | if (root_cap & PCI_EXP_RTCAP_CRSVIS) | ||
755 | pcie_capability_set_word(pdev, PCI_EXP_RTCTL, | ||
756 | PCI_EXP_RTCTL_CRSSVE); | ||
757 | } | ||
758 | |||
743 | /* | 759 | /* |
744 | * If it's a bridge, configure it and scan the bus behind it. | 760 | * If it's a bridge, configure it and scan the bus behind it. |
745 | * For CardBus bridges, we don't scan behind as the devices will | 761 | * For CardBus bridges, we don't scan behind as the devices will |
@@ -787,6 +803,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) | |||
787 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, | 803 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, |
788 | bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); | 804 | bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); |
789 | 805 | ||
806 | pci_enable_crs(dev); | ||
807 | |||
790 | if ((secondary || subordinate) && !pcibios_assign_all_busses() && | 808 | if ((secondary || subordinate) && !pcibios_assign_all_busses() && |
791 | !is_cardbus && !broken) { | 809 | !is_cardbus && !broken) { |
792 | unsigned int cmax; | 810 | unsigned int cmax; |
@@ -1226,6 +1244,137 @@ int pci_setup_device(struct pci_dev *dev) | |||
1226 | return 0; | 1244 | return 0; |
1227 | } | 1245 | } |
1228 | 1246 | ||
1247 | static struct hpp_type0 pci_default_type0 = { | ||
1248 | .revision = 1, | ||
1249 | .cache_line_size = 8, | ||
1250 | .latency_timer = 0x40, | ||
1251 | .enable_serr = 0, | ||
1252 | .enable_perr = 0, | ||
1253 | }; | ||
1254 | |||
1255 | static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) | ||
1256 | { | ||
1257 | u16 pci_cmd, pci_bctl; | ||
1258 | |||
1259 | if (!hpp) | ||
1260 | hpp = &pci_default_type0; | ||
1261 | |||
1262 | if (hpp->revision > 1) { | ||
1263 | dev_warn(&dev->dev, | ||
1264 | "PCI settings rev %d not supported; using defaults\n", | ||
1265 | hpp->revision); | ||
1266 | hpp = &pci_default_type0; | ||
1267 | } | ||
1268 | |||
1269 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size); | ||
1270 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer); | ||
1271 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | ||
1272 | if (hpp->enable_serr) | ||
1273 | pci_cmd |= PCI_COMMAND_SERR; | ||
1274 | if (hpp->enable_perr) | ||
1275 | pci_cmd |= PCI_COMMAND_PARITY; | ||
1276 | pci_write_config_word(dev, PCI_COMMAND, pci_cmd); | ||
1277 | |||
1278 | /* Program bridge control value */ | ||
1279 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
1280 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, | ||
1281 | hpp->latency_timer); | ||
1282 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); | ||
1283 | if (hpp->enable_serr) | ||
1284 | pci_bctl |= PCI_BRIDGE_CTL_SERR; | ||
1285 | if (hpp->enable_perr) | ||
1286 | pci_bctl |= PCI_BRIDGE_CTL_PARITY; | ||
1287 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); | ||
1288 | } | ||
1289 | } | ||
1290 | |||
1291 | static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp) | ||
1292 | { | ||
1293 | if (hpp) | ||
1294 | dev_warn(&dev->dev, "PCI-X settings not supported\n"); | ||
1295 | } | ||
1296 | |||
1297 | static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) | ||
1298 | { | ||
1299 | int pos; | ||
1300 | u32 reg32; | ||
1301 | |||
1302 | if (!hpp) | ||
1303 | return; | ||
1304 | |||
1305 | if (hpp->revision > 1) { | ||
1306 | dev_warn(&dev->dev, "PCIe settings rev %d not supported\n", | ||
1307 | hpp->revision); | ||
1308 | return; | ||
1309 | } | ||
1310 | |||
1311 | /* | ||
1312 | * Don't allow _HPX to change MPS or MRRS settings. We manage | ||
1313 | * those to make sure they're consistent with the rest of the | ||
1314 | * platform. | ||
1315 | */ | ||
1316 | hpp->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD | | ||
1317 | PCI_EXP_DEVCTL_READRQ; | ||
1318 | hpp->pci_exp_devctl_or &= ~(PCI_EXP_DEVCTL_PAYLOAD | | ||
1319 | PCI_EXP_DEVCTL_READRQ); | ||
1320 | |||
1321 | /* Initialize Device Control Register */ | ||
1322 | pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, | ||
1323 | ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or); | ||
1324 | |||
1325 | /* Initialize Link Control Register */ | ||
1326 | if (dev->subordinate) | ||
1327 | pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, | ||
1328 | ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or); | ||
1329 | |||
1330 | /* Find Advanced Error Reporting Enhanced Capability */ | ||
1331 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
1332 | if (!pos) | ||
1333 | return; | ||
1334 | |||
1335 | /* Initialize Uncorrectable Error Mask Register */ | ||
1336 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, ®32); | ||
1337 | reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or; | ||
1338 | pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32); | ||
1339 | |||
1340 | /* Initialize Uncorrectable Error Severity Register */ | ||
1341 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, ®32); | ||
1342 | reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or; | ||
1343 | pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32); | ||
1344 | |||
1345 | /* Initialize Correctable Error Mask Register */ | ||
1346 | pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®32); | ||
1347 | reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or; | ||
1348 | pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32); | ||
1349 | |||
1350 | /* Initialize Advanced Error Capabilities and Control Register */ | ||
1351 | pci_read_config_dword(dev, pos + PCI_ERR_CAP, ®32); | ||
1352 | reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or; | ||
1353 | pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32); | ||
1354 | |||
1355 | /* | ||
1356 | * FIXME: The following two registers are not supported yet. | ||
1357 | * | ||
1358 | * o Secondary Uncorrectable Error Severity Register | ||
1359 | * o Secondary Uncorrectable Error Mask Register | ||
1360 | */ | ||
1361 | } | ||
1362 | |||
1363 | static void pci_configure_device(struct pci_dev *dev) | ||
1364 | { | ||
1365 | struct hotplug_params hpp; | ||
1366 | int ret; | ||
1367 | |||
1368 | memset(&hpp, 0, sizeof(hpp)); | ||
1369 | ret = pci_get_hp_params(dev, &hpp); | ||
1370 | if (ret) | ||
1371 | return; | ||
1372 | |||
1373 | program_hpp_type2(dev, hpp.t2); | ||
1374 | program_hpp_type1(dev, hpp.t1); | ||
1375 | program_hpp_type0(dev, hpp.t0); | ||
1376 | } | ||
1377 | |||
1229 | static void pci_release_capabilities(struct pci_dev *dev) | 1378 | static void pci_release_capabilities(struct pci_dev *dev) |
1230 | { | 1379 | { |
1231 | pci_vpd_release(dev); | 1380 | pci_vpd_release(dev); |
@@ -1282,8 +1431,13 @@ bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l, | |||
1282 | *l == 0x0000ffff || *l == 0xffff0000) | 1431 | *l == 0x0000ffff || *l == 0xffff0000) |
1283 | return false; | 1432 | return false; |
1284 | 1433 | ||
1285 | /* Configuration request Retry Status */ | 1434 | /* |
1286 | while (*l == 0xffff0001) { | 1435 | * Configuration Request Retry Status. Some root ports return the |
1436 | * actual device ID instead of the synthetic ID (0xFFFF) required | ||
1437 | * by the PCIe spec. Ignore the device ID and only check for | ||
1438 | * (vendor id == 1). | ||
1439 | */ | ||
1440 | while ((*l & 0xffff) == 0x0001) { | ||
1287 | if (!crs_timeout) | 1441 | if (!crs_timeout) |
1288 | return false; | 1442 | return false; |
1289 | 1443 | ||
@@ -1363,6 +1517,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) | |||
1363 | { | 1517 | { |
1364 | int ret; | 1518 | int ret; |
1365 | 1519 | ||
1520 | pci_configure_device(dev); | ||
1521 | |||
1366 | device_initialize(&dev->dev); | 1522 | device_initialize(&dev->dev); |
1367 | dev->dev.release = pci_release_dev; | 1523 | dev->dev.release = pci_release_dev; |
1368 | 1524 | ||
@@ -1751,13 +1907,14 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1751 | char bus_addr[64]; | 1907 | char bus_addr[64]; |
1752 | char *fmt; | 1908 | char *fmt; |
1753 | 1909 | ||
1754 | b = pci_alloc_bus(); | 1910 | b = pci_alloc_bus(NULL); |
1755 | if (!b) | 1911 | if (!b) |
1756 | return NULL; | 1912 | return NULL; |
1757 | 1913 | ||
1758 | b->sysdata = sysdata; | 1914 | b->sysdata = sysdata; |
1759 | b->ops = ops; | 1915 | b->ops = ops; |
1760 | b->number = b->busn_res.start = bus; | 1916 | b->number = b->busn_res.start = bus; |
1917 | pci_bus_assign_domain_nr(b, parent); | ||
1761 | b2 = pci_find_bus(pci_domain_nr(b), bus); | 1918 | b2 = pci_find_bus(pci_domain_nr(b), bus); |
1762 | if (b2) { | 1919 | if (b2) { |
1763 | /* If we already got to this bus through a different bridge, ignore it */ | 1920 | /* If we already got to this bus through a different bridge, ignore it */ |