Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 270316
b: refs/heads/master
c: 379021d
h: refs/heads/master
v: v3
  • Loading branch information
Rafael J. Wysocki authored and Jesse Barnes committed Oct 14, 2011
1 parent 7a42e0f commit cbf3fe2
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 22 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3e309cdf07c930f29a4e0f233e47d399bea34c68
refs/heads/master: 379021d5c0899fcf9410cae4ca7a59a5a94ca769
3 changes: 3 additions & 0 deletions trunk/drivers/pci/pci-acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
struct pci_dev *pci_dev = context;

if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) {
if (pci_dev->pme_poll)
pci_dev->pme_poll = false;

pci_wakeup_event(pci_dev);
pci_check_pme_status(pci_dev);
pm_runtime_resume(&pci_dev->dev);
Expand Down
41 changes: 20 additions & 21 deletions trunk/drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1407,13 +1407,16 @@ bool pci_check_pme_status(struct pci_dev *dev)
/**
* pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set.
* @dev: Device to handle.
* @ign: Ignored.
* @pme_poll_reset: Whether or not to reset the device's pme_poll flag.
*
* Check if @dev has generated PME and queue a resume request for it in that
* case.
*/
static int pci_pme_wakeup(struct pci_dev *dev, void *ign)
static int pci_pme_wakeup(struct pci_dev *dev, void *pme_poll_reset)
{
if (pme_poll_reset && dev->pme_poll)
dev->pme_poll = false;

if (pci_check_pme_status(dev)) {
pci_wakeup_event(dev);
pm_request_resume(&dev->dev);
Expand All @@ -1428,7 +1431,7 @@ static int pci_pme_wakeup(struct pci_dev *dev, void *ign)
void pci_pme_wakeup_bus(struct pci_bus *bus)
{
if (bus)
pci_walk_bus(bus, pci_pme_wakeup, NULL);
pci_walk_bus(bus, pci_pme_wakeup, (void *)true);
}

/**
Expand All @@ -1446,30 +1449,25 @@ bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)

static void pci_pme_list_scan(struct work_struct *work)
{
struct pci_pme_device *pme_dev;
struct pci_pme_device *pme_dev, *n;

mutex_lock(&pci_pme_list_mutex);
if (!list_empty(&pci_pme_list)) {
list_for_each_entry(pme_dev, &pci_pme_list, list)
pci_pme_wakeup(pme_dev->dev, NULL);
schedule_delayed_work(&pci_pme_work, msecs_to_jiffies(PME_TIMEOUT));
list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
if (pme_dev->dev->pme_poll) {
pci_pme_wakeup(pme_dev->dev, NULL);
} else {
list_del(&pme_dev->list);
kfree(pme_dev);
}
}
if (!list_empty(&pci_pme_list))
schedule_delayed_work(&pci_pme_work,
msecs_to_jiffies(PME_TIMEOUT));
}
mutex_unlock(&pci_pme_list_mutex);
}

/**
* pci_external_pme - is a device an external PCI PME source?
* @dev: PCI device to check
*
*/

static bool pci_external_pme(struct pci_dev *dev)
{
if (pci_is_pcie(dev) || dev->bus->number == 0)
return false;
return true;
}

/**
* pci_pme_active - enable or disable PCI device's PME# function
* @dev: PCI device to handle.
Expand Down Expand Up @@ -1503,7 +1501,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
hit, and the power savings from the devices will still be a
win. */

if (pci_external_pme(dev)) {
if (dev->pme_poll) {
struct pci_pme_device *pme_dev;
if (enable) {
pme_dev = kmalloc(sizeof(struct pci_pme_device),
Expand Down Expand Up @@ -1821,6 +1819,7 @@ void pci_pm_init(struct pci_dev *dev)
(pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "",
(pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : "");
dev->pme_support = pmc >> PCI_PM_CAP_PME_SHIFT;
dev->pme_poll = true;
/*
* Make device's PM flags reflect the wake-up capability, but
* let the user space enable it to wake up the system as needed.
Expand Down
9 changes: 9 additions & 0 deletions trunk/drivers/pci/pcie/pme.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ static bool pcie_pme_walk_bus(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) {
/* Skip PCIe devices in case we started from a root port. */
if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) {
if (dev->pme_poll)
dev->pme_poll = false;

pci_wakeup_event(dev);
pm_request_resume(&dev->dev);
ret = true;
Expand Down Expand Up @@ -142,6 +145,9 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)

/* First, check if the PME is from the root port itself. */
if (port->devfn == devfn && port->bus->number == busnr) {
if (port->pme_poll)
port->pme_poll = false;

if (pci_check_pme_status(port)) {
pm_request_resume(&port->dev);
found = true;
Expand Down Expand Up @@ -187,6 +193,9 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
/* The device is there, but we have to check its PME status. */
found = pci_check_pme_status(dev);
if (found) {
if (dev->pme_poll)
dev->pme_poll = false;

pci_wakeup_event(dev);
pm_request_resume(&dev->dev);
}
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ struct pci_dev {
unsigned int pme_support:5; /* Bitmask of states from which PME#
can be generated */
unsigned int pme_interrupt:1;
unsigned int pme_poll:1; /* Poll device's PME status bit */
unsigned int d1_support:1; /* Low power state D1 is supported */
unsigned int d2_support:1; /* Low power state D2 is supported */
unsigned int no_d1d2:1; /* Only allow D0 and D3 */
Expand Down

0 comments on commit cbf3fe2

Please sign in to comment.