Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pci-v6.8-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci

Pull pci fixes from Bjorn Helgaas:

- Fix a potential deadlock that was reintroduced by an ASPM revert
merged for v6.8 (Johan Hovold)

- Add Manivannan Sadhasivam as PCI Endpoint maintainer (Lorenzo
Pieralisi)

* tag 'pci-v6.8-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci:
MAINTAINERS: Add Manivannan Sadhasivam as PCI Endpoint maintainer
PCI/ASPM: Fix deadlock when enabling ASPM

+102 -52
+1 -2
MAINTAINERS
··· 16862 16862 F: drivers/pci/controller/pcie-xilinx-cpm.c 16863 16863 16864 16864 PCI ENDPOINT SUBSYSTEM 16865 - M: Lorenzo Pieralisi <lpieralisi@kernel.org> 16865 + M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 16866 16866 M: Krzysztof Wilczyński <kw@linux.com> 16867 - R: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 16868 16867 R: Kishon Vijay Abraham I <kishon@kernel.org> 16869 16868 L: linux-pci@vger.kernel.org 16870 16869 S: Supported
+32 -17
drivers/pci/bus.c
··· 386 386 } 387 387 EXPORT_SYMBOL(pci_bus_add_devices); 388 388 389 - /** pci_walk_bus - walk devices on/under bus, calling callback. 390 - * @top bus whose devices should be walked 391 - * @cb callback to be called for each device found 392 - * @userdata arbitrary pointer to be passed to callback. 393 - * 394 - * Walk the given bus, including any bridged devices 395 - * on buses under this bus. Call the provided callback 396 - * on each device found. 397 - * 398 - * We check the return of @cb each time. If it returns anything 399 - * other than 0, we break out. 400 - * 401 - */ 402 - void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), 403 - void *userdata) 389 + static void __pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), 390 + void *userdata, bool locked) 404 391 { 405 392 struct pci_dev *dev; 406 393 struct pci_bus *bus; ··· 395 408 int retval; 396 409 397 410 bus = top; 398 - down_read(&pci_bus_sem); 411 + if (!locked) 412 + down_read(&pci_bus_sem); 399 413 next = top->devices.next; 400 414 for (;;) { 401 415 if (next == &bus->devices) { ··· 419 431 if (retval) 420 432 break; 421 433 } 422 - up_read(&pci_bus_sem); 434 + if (!locked) 435 + up_read(&pci_bus_sem); 436 + } 437 + 438 + /** 439 + * pci_walk_bus - walk devices on/under bus, calling callback. 440 + * @top: bus whose devices should be walked 441 + * @cb: callback to be called for each device found 442 + * @userdata: arbitrary pointer to be passed to callback 443 + * 444 + * Walk the given bus, including any bridged devices 445 + * on buses under this bus. Call the provided callback 446 + * on each device found. 447 + * 448 + * We check the return of @cb each time. If it returns anything 449 + * other than 0, we break out. 450 + */ 451 + void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata) 452 + { 453 + __pci_walk_bus(top, cb, userdata, false); 423 454 } 424 455 EXPORT_SYMBOL_GPL(pci_walk_bus); 456 + 457 + void pci_walk_bus_locked(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata) 458 + { 459 + lockdep_assert_held(&pci_bus_sem); 460 + 461 + __pci_walk_bus(top, cb, userdata, true); 462 + } 463 + EXPORT_SYMBOL_GPL(pci_walk_bus_locked); 425 464 426 465 struct pci_bus *pci_bus_get(struct pci_bus *bus) 427 466 {
+1 -1
drivers/pci/controller/dwc/pcie-qcom.c
··· 972 972 * Downstream devices need to be in D0 state before enabling PCI PM 973 973 * substates. 974 974 */ 975 - pci_set_power_state(pdev, PCI_D0); 975 + pci_set_power_state_locked(pdev, PCI_D0); 976 976 pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); 977 977 978 978 return 0;
+52 -26
drivers/pci/pci.c
··· 1354 1354 /** 1355 1355 * pci_set_full_power_state - Put a PCI device into D0 and update its state 1356 1356 * @dev: PCI device to power up 1357 + * @locked: whether pci_bus_sem is held 1357 1358 * 1358 1359 * Call pci_power_up() to put @dev into D0, read from its PCI_PM_CTRL register 1359 1360 * to confirm the state change, restore its BARs if they might be lost and ··· 1364 1363 * to D0, it is more efficient to use pci_power_up() directly instead of this 1365 1364 * function. 1366 1365 */ 1367 - static int pci_set_full_power_state(struct pci_dev *dev) 1366 + static int pci_set_full_power_state(struct pci_dev *dev, bool locked) 1368 1367 { 1369 1368 u16 pmcsr; 1370 1369 int ret; ··· 1400 1399 } 1401 1400 1402 1401 if (dev->bus->self) 1403 - pcie_aspm_pm_state_change(dev->bus->self); 1402 + pcie_aspm_pm_state_change(dev->bus->self, locked); 1404 1403 1405 1404 return 0; 1406 1405 } ··· 1429 1428 pci_walk_bus(bus, __pci_dev_set_current_state, &state); 1430 1429 } 1431 1430 1431 + static void __pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state, bool locked) 1432 + { 1433 + if (!bus) 1434 + return; 1435 + 1436 + if (locked) 1437 + pci_walk_bus_locked(bus, __pci_dev_set_current_state, &state); 1438 + else 1439 + pci_walk_bus(bus, __pci_dev_set_current_state, &state); 1440 + } 1441 + 1432 1442 /** 1433 1443 * pci_set_low_power_state - Put a PCI device into a low-power state. 1434 1444 * @dev: PCI device to handle. 1435 1445 * @state: PCI power state (D1, D2, D3hot) to put the device into. 1446 + * @locked: whether pci_bus_sem is held 1436 1447 * 1437 1448 * Use the device's PCI_PM_CTRL register to put it into a low-power state. 1438 1449 * ··· 1455 1442 * 0 if device already is in the requested state. 1456 1443 * 0 if device's power state has been successfully changed. 1457 1444 */ 1458 - static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) 1445 + static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state, bool locked) 1459 1446 { 1460 1447 u16 pmcsr; 1461 1448 ··· 1509 1496 pci_power_name(state)); 1510 1497 1511 1498 if (dev->bus->self) 1512 - pcie_aspm_pm_state_change(dev->bus->self); 1499 + pcie_aspm_pm_state_change(dev->bus->self, locked); 1513 1500 1514 1501 return 0; 1515 1502 } 1516 1503 1517 - /** 1518 - * pci_set_power_state - Set the power state of a PCI device 1519 - * @dev: PCI device to handle. 1520 - * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. 1521 - * 1522 - * Transition a device to a new power state, using the platform firmware and/or 1523 - * the device's PCI PM registers. 1524 - * 1525 - * RETURN VALUE: 1526 - * -EINVAL if the requested state is invalid. 1527 - * -EIO if device does not support PCI PM or its PM capabilities register has a 1528 - * wrong version, or device doesn't support the requested state. 1529 - * 0 if the transition is to D1 or D2 but D1 and D2 are not supported. 1530 - * 0 if device already is in the requested state. 1531 - * 0 if the transition is to D3 but D3 is not supported. 1532 - * 0 if device's power state has been successfully changed. 1533 - */ 1534 - int pci_set_power_state(struct pci_dev *dev, pci_power_t state) 1504 + static int __pci_set_power_state(struct pci_dev *dev, pci_power_t state, bool locked) 1535 1505 { 1536 1506 int error; 1537 1507 ··· 1538 1542 return 0; 1539 1543 1540 1544 if (state == PCI_D0) 1541 - return pci_set_full_power_state(dev); 1545 + return pci_set_full_power_state(dev, locked); 1542 1546 1543 1547 /* 1544 1548 * This device is quirked not to be put into D3, so don't put it in ··· 1552 1556 * To put the device in D3cold, put it into D3hot in the native 1553 1557 * way, then put it into D3cold using platform ops. 1554 1558 */ 1555 - error = pci_set_low_power_state(dev, PCI_D3hot); 1559 + error = pci_set_low_power_state(dev, PCI_D3hot, locked); 1556 1560 1557 1561 if (pci_platform_power_transition(dev, PCI_D3cold)) 1558 1562 return error; 1559 1563 1560 1564 /* Powering off a bridge may power off the whole hierarchy */ 1561 1565 if (dev->current_state == PCI_D3cold) 1562 - pci_bus_set_current_state(dev->subordinate, PCI_D3cold); 1566 + __pci_bus_set_current_state(dev->subordinate, PCI_D3cold, locked); 1563 1567 } else { 1564 - error = pci_set_low_power_state(dev, state); 1568 + error = pci_set_low_power_state(dev, state, locked); 1565 1569 1566 1570 if (pci_platform_power_transition(dev, state)) 1567 1571 return error; ··· 1569 1573 1570 1574 return 0; 1571 1575 } 1576 + 1577 + /** 1578 + * pci_set_power_state - Set the power state of a PCI device 1579 + * @dev: PCI device to handle. 1580 + * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. 1581 + * 1582 + * Transition a device to a new power state, using the platform firmware and/or 1583 + * the device's PCI PM registers. 1584 + * 1585 + * RETURN VALUE: 1586 + * -EINVAL if the requested state is invalid. 1587 + * -EIO if device does not support PCI PM or its PM capabilities register has a 1588 + * wrong version, or device doesn't support the requested state. 1589 + * 0 if the transition is to D1 or D2 but D1 and D2 are not supported. 1590 + * 0 if device already is in the requested state. 1591 + * 0 if the transition is to D3 but D3 is not supported. 1592 + * 0 if device's power state has been successfully changed. 1593 + */ 1594 + int pci_set_power_state(struct pci_dev *dev, pci_power_t state) 1595 + { 1596 + return __pci_set_power_state(dev, state, false); 1597 + } 1572 1598 EXPORT_SYMBOL(pci_set_power_state); 1599 + 1600 + int pci_set_power_state_locked(struct pci_dev *dev, pci_power_t state) 1601 + { 1602 + lockdep_assert_held(&pci_bus_sem); 1603 + 1604 + return __pci_set_power_state(dev, state, true); 1605 + } 1606 + EXPORT_SYMBOL(pci_set_power_state_locked); 1573 1607 1574 1608 #define PCI_EXP_SAVE_REGS 7 1575 1609
+2 -2
drivers/pci/pci.h
··· 571 571 #ifdef CONFIG_PCIEASPM 572 572 void pcie_aspm_init_link_state(struct pci_dev *pdev); 573 573 void pcie_aspm_exit_link_state(struct pci_dev *pdev); 574 - void pcie_aspm_pm_state_change(struct pci_dev *pdev); 574 + void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked); 575 575 void pcie_aspm_powersave_config_link(struct pci_dev *pdev); 576 576 #else 577 577 static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) { } 578 578 static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) { } 579 - static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) { } 579 + static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked) { } 580 580 static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) { } 581 581 #endif 582 582
+9 -4
drivers/pci/pcie/aspm.c
··· 1003 1003 up_read(&pci_bus_sem); 1004 1004 } 1005 1005 1006 - /* @pdev: the root port or switch downstream port */ 1007 - void pcie_aspm_pm_state_change(struct pci_dev *pdev) 1006 + /* 1007 + * @pdev: the root port or switch downstream port 1008 + * @locked: whether pci_bus_sem is held 1009 + */ 1010 + void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked) 1008 1011 { 1009 1012 struct pcie_link_state *link = pdev->link_state; 1010 1013 ··· 1017 1014 * Devices changed PM state, we should recheck if latency 1018 1015 * meets all functions' requirement 1019 1016 */ 1020 - down_read(&pci_bus_sem); 1017 + if (!locked) 1018 + down_read(&pci_bus_sem); 1021 1019 mutex_lock(&aspm_lock); 1022 1020 pcie_update_aspm_capable(link->root); 1023 1021 pcie_config_aspm_path(link); 1024 1022 mutex_unlock(&aspm_lock); 1025 - up_read(&pci_bus_sem); 1023 + if (!locked) 1024 + up_read(&pci_bus_sem); 1026 1025 } 1027 1026 1028 1027 void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
+5
include/linux/pci.h
··· 1422 1422 struct pci_saved_state **state); 1423 1423 int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state); 1424 1424 int pci_set_power_state(struct pci_dev *dev, pci_power_t state); 1425 + int pci_set_power_state_locked(struct pci_dev *dev, pci_power_t state); 1425 1426 pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); 1426 1427 bool pci_pme_capable(struct pci_dev *dev, pci_power_t state); 1427 1428 void pci_pme_active(struct pci_dev *dev, bool enable); ··· 1626 1625 1627 1626 void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), 1628 1627 void *userdata); 1628 + void pci_walk_bus_locked(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), 1629 + void *userdata); 1629 1630 int pci_cfg_space_size(struct pci_dev *dev); 1630 1631 unsigned char pci_bus_max_busnr(struct pci_bus *bus); 1631 1632 void pci_setup_bridge(struct pci_bus *bus); ··· 2027 2024 static inline int pci_save_state(struct pci_dev *dev) { return 0; } 2028 2025 static inline void pci_restore_state(struct pci_dev *dev) { } 2029 2026 static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) 2027 + { return 0; } 2028 + static inline int pci_set_power_state_locked(struct pci_dev *dev, pci_power_t state) 2030 2029 { return 0; } 2031 2030 static inline int pci_wake_from_d3(struct pci_dev *dev, bool enable) 2032 2031 { return 0; }