From patchwork Mon Sep 7 23:29:47 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Wysocki X-Patchwork-Id: 46168 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n87NSvp5010190 for ; Mon, 7 Sep 2009 23:28:57 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752564AbZIGX2x (ORCPT ); Mon, 7 Sep 2009 19:28:53 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752737AbZIGX2x (ORCPT ); Mon, 7 Sep 2009 19:28:53 -0400 Received: from ogre.sisk.pl ([217.79.144.158]:53659 "EHLO ogre.sisk.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752564AbZIGX2x (ORCPT ); Mon, 7 Sep 2009 19:28:53 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by ogre.sisk.pl (Postfix) with ESMTP id 826C1156B2B; Mon, 7 Sep 2009 22:26:06 +0200 (CEST) Received: from ogre.sisk.pl ([127.0.0.1]) by localhost (ogre.sisk.pl [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 11290-02; Mon, 7 Sep 2009 22:25:48 +0200 (CEST) Received: from tosh.localnet (220-bem-13.acn.waw.pl [82.210.184.220]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ogre.sisk.pl (Postfix) with ESMTP id A74DF1567C0; Mon, 7 Sep 2009 22:25:48 +0200 (CEST) From: "Rafael J. Wysocki" To: linux-pm@lists.linux-foundation.org Subject: [RFC][PATCH 1/3 update] PCI: Clear saved_state after the state has been restored Date: Tue, 8 Sep 2009 01:29:47 +0200 User-Agent: KMail/1.12.1 (Linux/2.6.31-rc9-rjw; KDE/4.3.1; x86_64; ; ) Cc: "linux-pci" , Jesse Barnes References: <200909070102.21056.rjw@sisk.pl> <200909070103.20731.rjw@sisk.pl> In-Reply-To: <200909070103.20731.rjw@sisk.pl> MIME-Version: 1.0 Message-Id: <200909080129.47665.rjw@sisk.pl> X-Virus-Scanned: amavisd-new at ogre.sisk.pl using MkS_Vir for Linux Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Rafael J. Wysocki Subject: PCI: Clear saved_state after the state has been restored 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 to so that the values saved during the "freeze" phase of hibernation are not used later by mistake. Signed-off-by: Rafael J. Wysocki --- Of course, the state_saved flag has to be cleared in pci_pm_thaw() in case the driver doesn't restore the state saved in ->freeze() (it doesn't need to do that). Thanks, Rafael --- drivers/pci/pci-driver.c | 11 ++--------- drivers/pci/pci.c | 3 +++ drivers/pci/probe.c | 3 +++ 3 files changed, 8 insertions(+), 9 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: linux-2.6/drivers/pci/pci-driver.c =================================================================== --- linux-2.6.orig/drivers/pci/pci-driver.c +++ linux-2.6/drivers/pci/pci-driver.c @@ -417,8 +417,6 @@ static int pci_legacy_suspend(struct dev 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; @@ -514,7 +512,6 @@ static int pci_restore_standard_config(s 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); } @@ -580,8 +577,6 @@ static int pci_pm_suspend(struct device 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; @@ -716,8 +711,6 @@ static int pci_pm_freeze(struct device * 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; @@ -793,6 +786,8 @@ static int pci_pm_thaw(struct device *de pci_pm_reenable_device(pci_dev); } + pci_dev->state_saved = false; + return error; } @@ -804,8 +799,6 @@ static int pci_pm_poweroff(struct device 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; Index: linux-2.6/drivers/pci/pci.c =================================================================== --- linux-2.6.orig/drivers/pci/pci.c +++ linux-2.6/drivers/pci/pci.c @@ -852,6 +852,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); @@ -873,6 +874,8 @@ pci_restore_state(struct pci_dev *dev) pci_restore_msi_state(dev); pci_restore_iov_state(dev); + dev->state_saved = false; + return 0; } Index: linux-2.6/drivers/pci/probe.c =================================================================== --- linux-2.6.orig/drivers/pci/probe.c +++ linux-2.6/drivers/pci/probe.c @@ -1009,6 +1009,9 @@ void pci_device_add(struct pci_dev *dev, /* 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);