From patchwork Fri Mar 20 23:03:54 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Wysocki X-Patchwork-Id: 13404 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 n2KN4Awx012062 for ; Fri, 20 Mar 2009 23:04:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754926AbZCTXEG (ORCPT ); Fri, 20 Mar 2009 19:04:06 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754554AbZCTXEG (ORCPT ); Fri, 20 Mar 2009 19:04:06 -0400 Received: from ogre.sisk.pl ([217.79.144.158]:49784 "EHLO ogre.sisk.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752475AbZCTXEC (ORCPT ); Fri, 20 Mar 2009 19:04:02 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by ogre.sisk.pl (Postfix) with ESMTP id 6634F12DB91; Fri, 20 Mar 2009 21:25:02 +0100 (CET) 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 04431-05; Fri, 20 Mar 2009 21:24:55 +0100 (CET) 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 A1BF712DB46; Fri, 20 Mar 2009 21:24:55 +0100 (CET) From: "Rafael J. Wysocki" To: Jesse Barnes Subject: [RFC][PATCH] PCI PM: Be extra careful when changing power states of devices Date: Sat, 21 Mar 2009 00:03:54 +0100 User-Agent: KMail/1.11.1 (Linux/2.6.29-rc8-tst; KDE/4.2.1; x86_64; ; ) Cc: Benjamin Herrenschmidt , Linux PCI , pm list , LKML , Linus Torvalds , Andrew Morton MIME-Version: 1.0 Content-Disposition: inline Message-Id: <200903210003.55161.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 The story in http://bugzilla.kernel.org/show_bug.cgi?id=12846 shows that setting the power state of a PCI device by pci_raw_set_power_state() may sometimes fail. For this reason, pci_raw_set_power_state() should not assume that the power state of the device has actually changed after writing into its PMCSR. Instead, it should read the value from there and use it to update dev->current_state. It also is useful to print a warning if the device's power state hasn't changed as expected. Signed-off-by: Rafael J. Wysocki --- drivers/pci/pci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 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.c =================================================================== --- linux-2.6.orig/drivers/pci/pci.c +++ linux-2.6/drivers/pci/pci.c @@ -436,7 +436,7 @@ static inline int platform_pci_sleep_wak */ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) { - u16 pmcsr; + u16 pmcsr, new_pmcsr; bool need_restore = false; /* Check if we're already there */ @@ -498,7 +498,15 @@ static int pci_raw_set_power_state(struc else if (state == PCI_D2 || dev->current_state == PCI_D2) udelay(PCI_PM_D2_DELAY); - dev->current_state = state; + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &new_pmcsr); + if (new_pmcsr == pmcsr) { + dev->current_state = state; + } else { + dev->current_state = (new_pmcsr & PCI_PM_CTRL_STATE_MASK); + dev_warn(&dev->dev, + "failed to set power state to D%d, is D%d\n", state, + dev->current_state); + } /* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning