diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e9651f0a8817..7cd417e94058 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1407,13 +1407,16 @@ bool pci_check_pme_status(struct pci_dev *dev) | |||
1407 | /** | 1407 | /** |
1408 | * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. | 1408 | * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. |
1409 | * @dev: Device to handle. | 1409 | * @dev: Device to handle. |
1410 | * @ign: Ignored. | 1410 | * @pme_poll_reset: Whether or not to reset the device's pme_poll flag. |
1411 | * | 1411 | * |
1412 | * Check if @dev has generated PME and queue a resume request for it in that | 1412 | * Check if @dev has generated PME and queue a resume request for it in that |
1413 | * case. | 1413 | * case. |
1414 | */ | 1414 | */ |
1415 | static int pci_pme_wakeup(struct pci_dev *dev, void *ign) | 1415 | static int pci_pme_wakeup(struct pci_dev *dev, void *pme_poll_reset) |
1416 | { | 1416 | { |
1417 | if (pme_poll_reset && dev->pme_poll) | ||
1418 | dev->pme_poll = false; | ||
1419 | |||
1417 | if (pci_check_pme_status(dev)) { | 1420 | if (pci_check_pme_status(dev)) { |
1418 | pci_wakeup_event(dev); | 1421 | pci_wakeup_event(dev); |
1419 | pm_request_resume(&dev->dev); | 1422 | pm_request_resume(&dev->dev); |
@@ -1428,7 +1431,7 @@ static int pci_pme_wakeup(struct pci_dev *dev, void *ign) | |||
1428 | void pci_pme_wakeup_bus(struct pci_bus *bus) | 1431 | void pci_pme_wakeup_bus(struct pci_bus *bus) |
1429 | { | 1432 | { |
1430 | if (bus) | 1433 | if (bus) |
1431 | pci_walk_bus(bus, pci_pme_wakeup, NULL); | 1434 | pci_walk_bus(bus, pci_pme_wakeup, (void *)true); |
1432 | } | 1435 | } |
1433 | 1436 | ||
1434 | /** | 1437 | /** |
@@ -1446,31 +1449,26 @@ bool pci_pme_capable(struct pci_dev *dev, pci_power_t state) | |||
1446 | 1449 | ||
1447 | static void pci_pme_list_scan(struct work_struct *work) | 1450 | static void pci_pme_list_scan(struct work_struct *work) |
1448 | { | 1451 | { |
1449 | struct pci_pme_device *pme_dev; | 1452 | struct pci_pme_device *pme_dev, *n; |
1450 | 1453 | ||
1451 | mutex_lock(&pci_pme_list_mutex); | 1454 | mutex_lock(&pci_pme_list_mutex); |
1452 | if (!list_empty(&pci_pme_list)) { | 1455 | if (!list_empty(&pci_pme_list)) { |
1453 | list_for_each_entry(pme_dev, &pci_pme_list, list) | 1456 | list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) { |
1454 | pci_pme_wakeup(pme_dev->dev, NULL); | 1457 | if (pme_dev->dev->pme_poll) { |
1455 | schedule_delayed_work(&pci_pme_work, msecs_to_jiffies(PME_TIMEOUT)); | 1458 | pci_pme_wakeup(pme_dev->dev, NULL); |
1459 | } else { | ||
1460 | list_del(&pme_dev->list); | ||
1461 | kfree(pme_dev); | ||
1462 | } | ||
1463 | } | ||
1464 | if (!list_empty(&pci_pme_list)) | ||
1465 | schedule_delayed_work(&pci_pme_work, | ||
1466 | msecs_to_jiffies(PME_TIMEOUT)); | ||
1456 | } | 1467 | } |
1457 | mutex_unlock(&pci_pme_list_mutex); | 1468 | mutex_unlock(&pci_pme_list_mutex); |
1458 | } | 1469 | } |
1459 | 1470 | ||
1460 | /** | 1471 | /** |
1461 | * pci_external_pme - is a device an external PCI PME source? | ||
1462 | * @dev: PCI device to check | ||
1463 | * | ||
1464 | */ | ||
1465 | |||
1466 | static bool pci_external_pme(struct pci_dev *dev) | ||
1467 | { | ||
1468 | if (pci_is_pcie(dev) || dev->bus->number == 0) | ||
1469 | return false; | ||
1470 | return true; | ||
1471 | } | ||
1472 | |||
1473 | /** | ||
1474 | * pci_pme_active - enable or disable PCI device's PME# function | 1472 | * pci_pme_active - enable or disable PCI device's PME# function |
1475 | * @dev: PCI device to handle. | 1473 | * @dev: PCI device to handle. |
1476 | * @enable: 'true' to enable PME# generation; 'false' to disable it. | 1474 | * @enable: 'true' to enable PME# generation; 'false' to disable it. |
@@ -1503,7 +1501,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable) | |||
1503 | hit, and the power savings from the devices will still be a | 1501 | hit, and the power savings from the devices will still be a |
1504 | win. */ | 1502 | win. */ |
1505 | 1503 | ||
1506 | if (pci_external_pme(dev)) { | 1504 | if (dev->pme_poll) { |
1507 | struct pci_pme_device *pme_dev; | 1505 | struct pci_pme_device *pme_dev; |
1508 | if (enable) { | 1506 | if (enable) { |
1509 | pme_dev = kmalloc(sizeof(struct pci_pme_device), | 1507 | pme_dev = kmalloc(sizeof(struct pci_pme_device), |
@@ -1821,6 +1819,7 @@ void pci_pm_init(struct pci_dev *dev) | |||
1821 | (pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "", | 1819 | (pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "", |
1822 | (pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : ""); | 1820 | (pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : ""); |
1823 | dev->pme_support = pmc >> PCI_PM_CAP_PME_SHIFT; | 1821 | dev->pme_support = pmc >> PCI_PM_CAP_PME_SHIFT; |
1822 | dev->pme_poll = true; | ||
1824 | /* | 1823 | /* |
1825 | * Make device's PM flags reflect the wake-up capability, but | 1824 | * Make device's PM flags reflect the wake-up capability, but |
1826 | * let the user space enable it to wake up the system as needed. | 1825 | * let the user space enable it to wake up the system as needed. |