Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 139007
b: refs/heads/master
c: 46939f8
h: refs/heads/master
i:
  139005: b7136bb
  139003: 36b6b84
  138999: eae1bed
  138991: 6fb7562
  138975: 22c4a30
  138943: 8c7be62
  138879: d703c10
  138751: 9aeeda1
v: v3
  • Loading branch information
Rafael J. Wysocki committed Mar 30, 2009
1 parent aec5843 commit 588d1b5
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 54 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: 0128a89cf75124500b5b69f0c3c7b7c5aa60676f
refs/heads/master: 46939f8b15e44f065d052e89ea4f2adc81fdc740
134 changes: 81 additions & 53 deletions trunk/drivers/pci/pci-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,53 +352,60 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
{
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
int error = 0;

pci_dev->state_saved = false;

if (drv && drv->suspend) {
pci_power_t prev = pci_dev->current_state;

pci_dev->state_saved = false;
int error;

error = drv->suspend(pci_dev, state);
suspend_report_result(drv->suspend, error);
if (error)
return error;

if (pci_dev->state_saved)
goto Fixup;

if (pci_dev->current_state != PCI_D0
if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
&& pci_dev->current_state != PCI_UNKNOWN) {
WARN_ONCE(pci_dev->current_state != prev,
"PCI PM: Device state not saved by %pF\n",
drv->suspend);
goto Fixup;
}
}

pci_save_state(pci_dev);
/*
* This is for compatibility with existing code with legacy PM support.
*/
pci_pm_set_unknown_state(pci_dev);

Fixup:
pci_fixup_device(pci_fixup_suspend, pci_dev);

return error;
return 0;
}

static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
{
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
int error = 0;

if (drv && drv->suspend_late) {
pci_power_t prev = pci_dev->current_state;
int error;

error = drv->suspend_late(pci_dev, state);
suspend_report_result(drv->suspend_late, error);
if (error)
return error;

if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
&& pci_dev->current_state != PCI_UNKNOWN) {
WARN_ONCE(pci_dev->current_state != prev,
"PCI PM: Device state not saved by %pF\n",
drv->suspend_late);
return 0;
}
}
return error;

if (!pci_dev->state_saved)
pci_save_state(pci_dev);

pci_pm_set_unknown_state(pci_dev);

return 0;
}

static int pci_legacy_resume_early(struct device *dev)
Expand Down Expand Up @@ -460,7 +467,6 @@ static void pci_pm_default_suspend(struct pci_dev *pci_dev)
/* Disable non-bridge devices without PM support */
if (!pci_is_bridge(pci_dev))
pci_disable_enabled_device(pci_dev);
pci_save_state(pci_dev);
}

static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
Expand Down Expand Up @@ -526,24 +532,14 @@ static int pci_pm_suspend(struct device *dev)
if (error)
return error;

if (pci_dev->state_saved)
goto Fixup;

if (pci_dev->current_state != PCI_D0
if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
&& pci_dev->current_state != PCI_UNKNOWN) {
WARN_ONCE(pci_dev->current_state != prev,
"PCI PM: State of device not saved by %pF\n",
pm->suspend);
goto Fixup;
}
}

if (!pci_dev->state_saved) {
pci_save_state(pci_dev);
if (!pci_is_bridge(pci_dev))
pci_prepare_to_sleep(pci_dev);
}

Fixup:
pci_fixup_device(pci_fixup_suspend, pci_dev);

Expand All @@ -553,21 +549,41 @@ static int pci_pm_suspend(struct device *dev)
static int pci_pm_suspend_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;
struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;

if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_suspend_late(dev, PMSG_SUSPEND);

if (drv && drv->pm && drv->pm->suspend_noirq) {
error = drv->pm->suspend_noirq(dev);
suspend_report_result(drv->pm->suspend_noirq, error);
if (!pm)
return 0;

if (pm->suspend_noirq) {
pci_power_t prev = pci_dev->current_state;
int error;

error = pm->suspend_noirq(dev);
suspend_report_result(pm->suspend_noirq, error);
if (error)
return error;

if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
&& pci_dev->current_state != PCI_UNKNOWN) {
WARN_ONCE(pci_dev->current_state != prev,
"PCI PM: State of device not saved by %pF\n",
pm->suspend_noirq);
return 0;
}
}

if (!error)
pci_pm_set_unknown_state(pci_dev);
if (!pci_dev->state_saved) {
pci_save_state(pci_dev);
if (!pci_is_bridge(pci_dev))
pci_prepare_to_sleep(pci_dev);
}

return error;
pci_pm_set_unknown_state(pci_dev);

return 0;
}

static int pci_pm_resume_noirq(struct device *dev)
Expand Down Expand Up @@ -650,30 +666,32 @@ static int pci_pm_freeze(struct device *dev)
return error;
}

if (!pci_dev->state_saved)
pci_save_state(pci_dev);

return 0;
}

static int pci_pm_freeze_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;

if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_suspend_late(dev, PMSG_FREEZE);

if (drv && drv->pm && drv->pm->freeze_noirq) {
int error;

error = drv->pm->freeze_noirq(dev);
suspend_report_result(drv->pm->freeze_noirq, error);
if (error)
return error;
}

if (!error)
pci_pm_set_unknown_state(pci_dev);
if (!pci_dev->state_saved)
pci_save_state(pci_dev);

return error;
pci_pm_set_unknown_state(pci_dev);

return 0;
}

static int pci_pm_thaw_noirq(struct device *dev)
Expand Down Expand Up @@ -716,7 +734,6 @@ static int pci_pm_poweroff(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int error = 0;

if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_suspend(dev, PMSG_HIBERNATE);
Expand All @@ -729,33 +746,44 @@ static int pci_pm_poweroff(struct device *dev)
pci_dev->state_saved = false;

if (pm->poweroff) {
int error;

error = pm->poweroff(dev);
suspend_report_result(pm->poweroff, error);
if (error)
return error;
}

if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
pci_prepare_to_sleep(pci_dev);

Fixup:
pci_fixup_device(pci_fixup_suspend, pci_dev);

return error;
return 0;
}

static int pci_pm_poweroff_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;

if (pci_has_legacy_pm_support(to_pci_dev(dev)))
return pci_legacy_suspend_late(dev, PMSG_HIBERNATE);

if (drv && drv->pm && drv->pm->poweroff_noirq) {
if (!drv || !drv->pm)
return 0;

if (drv->pm->poweroff_noirq) {
int error;

error = drv->pm->poweroff_noirq(dev);
suspend_report_result(drv->pm->poweroff_noirq, error);
if (error)
return error;
}

return error;
if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
pci_prepare_to_sleep(pci_dev);

return 0;
}

static int pci_pm_restore_noirq(struct device *dev)
Expand Down

0 comments on commit 588d1b5

Please sign in to comment.