Skip to content

Commit

Permalink
PCI: Clear saved_state after the state has been restored
Browse files Browse the repository at this point in the history
Some PCI devices fail if their standard configuration registers are
restored twice in a row.  Prevent this from happening by making
pci_restore_state() clear the saved_state flag of the device right
after the device's standard configuration registers have been
populated with the previously saved values.

Simplify PCI PM callbacks by removing the direct clearing of
state_saved from them, as it shouldn't be necessary any more (except
in pci_pm_thaw(), where it has to be cleared, so that the values saved
during the "freeze" phase of hibernation are not used later by mistake).

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
  • Loading branch information
Rafael J. Wysocki authored and Jesse Barnes committed Sep 14, 2009
1 parent 999cce4 commit 4b77b0a
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 9 deletions.
11 changes: 2 additions & 9 deletions drivers/pci/pci-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,6 @@ 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;

pci_dev->state_saved = false;

if (drv && drv->suspend) {
pci_power_t prev = pci_dev->current_state;
int error;
Expand Down Expand Up @@ -542,7 +540,6 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev)
static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
{
pci_restore_standard_config(pci_dev);
pci_dev->state_saved = false;
pci_fixup_device(pci_fixup_resume_early, pci_dev);
}

Expand Down Expand Up @@ -608,8 +605,6 @@ static int pci_pm_suspend(struct device *dev)
if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_suspend(dev, PMSG_SUSPEND);

pci_dev->state_saved = false;

if (!pm) {
pci_pm_default_suspend(pci_dev);
goto Fixup;
Expand Down Expand Up @@ -744,8 +739,6 @@ static int pci_pm_freeze(struct device *dev)
if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_suspend(dev, PMSG_FREEZE);

pci_dev->state_saved = false;

if (!pm) {
pci_pm_default_suspend(pci_dev);
return 0;
Expand Down Expand Up @@ -821,6 +814,8 @@ static int pci_pm_thaw(struct device *dev)
pci_pm_reenable_device(pci_dev);
}

pci_dev->state_saved = false;

return error;
}

Expand All @@ -832,8 +827,6 @@ static int pci_pm_poweroff(struct device *dev)
if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_suspend(dev, PMSG_HIBERNATE);

pci_dev->state_saved = false;

if (!pm) {
pci_pm_default_suspend(pci_dev);
goto Fixup;
Expand Down
3 changes: 3 additions & 0 deletions drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@ pci_restore_state(struct pci_dev *dev)

if (!dev->state_saved)
return 0;

/* PCI Express register must be restored first */
pci_restore_pcie_state(dev);

Expand All @@ -875,6 +876,8 @@ pci_restore_state(struct pci_dev *dev)
pci_restore_msi_state(dev);
pci_restore_iov_state(dev);

dev->state_saved = false;

return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions drivers/pci/probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,9 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
/* Fix up broken headers */
pci_fixup_device(pci_fixup_header, dev);

/* Clear the state_saved flag. */
dev->state_saved = false;

/* Initialize various capabilities */
pci_init_capabilities(dev);

Expand Down

0 comments on commit 4b77b0a

Please sign in to comment.