From patchwork Fri Sep 28 21:56:52 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Wysocki X-Patchwork-Id: 1527011 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id A38E6DF283 for ; Fri, 28 Sep 2012 21:51:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965220Ab2I1VvA (ORCPT ); Fri, 28 Sep 2012 17:51:00 -0400 Received: from ogre.sisk.pl ([193.178.161.156]:50882 "EHLO ogre.sisk.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965203Ab2I1Vu5 (ORCPT ); Fri, 28 Sep 2012 17:50:57 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by ogre.sisk.pl (Postfix) with ESMTP id DA9611DC64F; Fri, 28 Sep 2012 23:47:17 +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 28333-03; Fri, 28 Sep 2012 23:46:56 +0200 (CEST) Received: from ferrari.rjw.lan (89-67-90-11.dynamic.chello.pl [89.67.90.11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ogre.sisk.pl (Postfix) with ESMTP id 786BA1DC837; Fri, 28 Sep 2012 23:46:37 +0200 (CEST) From: "Rafael J. Wysocki" To: Linux PM list Subject: [RFD][PATCH 7/7] PM / ACPI: Take device PM QoS flags into account Date: Fri, 28 Sep 2012 23:56:52 +0200 User-Agent: KMail/1.13.6 (Linux/3.6.0-rc6+; KDE/4.6.0; x86_64; ; ) Cc: ACPI Devel Mailing List , Alan Stern , Huang Ying , Sarah Sharp , Lan Tianyu , Aaron Lu , Jean Pihet , linux-pci@vger.kernel.org, "Greg Kroah-Hartman" , mark gross References: <201209282351.10663.rjw@sisk.pl> In-Reply-To: <201209282351.10663.rjw@sisk.pl> MIME-Version: 1.0 Message-Id: <201209282356.52558.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 Make ACPI power management routines and PCI power management routines depending on ACPI take device PM QoS flags into account when deciding what power state to put the device into. In particular, after this change acpi_pm_device_sleep_state() will not return ACPI_STATE_D3_COLD as the deepest available low-power state if PM_QOS_FLAG_NO_POWER_OFF is requested for the device and it will not require remote wakeup to work for the device in the returned low-power state if there is at least one PM QoS flags request for the device, but PM_QOS_FLAG_REMOTE_WAKEUP is not requested for it. Accordingly, acpi_pci_set_power_state() will refuse to put the device into D3cold if PM_QOS_FLAG_NO_POWER_OFF is requested for it. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 16 ++++++++++++---- drivers/pci/pci-acpi.c | 8 +++++++- 2 files changed, 19 insertions(+), 5 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/drivers/pci/pci-acpi.c =================================================================== --- linux.orig/drivers/pci/pci-acpi.c +++ linux/drivers/pci/pci-acpi.c @@ -17,6 +17,7 @@ #include #include +#include #include "pci.h" static DEFINE_MUTEX(pci_acpi_pm_notify_mtx); @@ -257,11 +258,16 @@ static int acpi_pci_set_power_state(stru return -ENODEV; switch (state) { + case PCI_D3cold: + if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) == + PM_QOS_FLAGS_ALL) { + error = -EBUSY; + break; + } case PCI_D0: case PCI_D1: case PCI_D2: case PCI_D3hot: - case PCI_D3cold: error = acpi_bus_set_power(handle, state_conv[state]); } Index: linux/drivers/acpi/sleep.c =================================================================== --- linux.orig/drivers/acpi/sleep.c +++ linux/drivers/acpi/sleep.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -711,6 +712,7 @@ int acpi_pm_device_sleep_state(struct de struct acpi_device *adev; char acpi_method[] = "_SxD"; unsigned long long d_min, d_max; + bool wakeup = false; if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3) return -EINVAL; @@ -718,6 +720,8 @@ int acpi_pm_device_sleep_state(struct de printk(KERN_DEBUG "ACPI handle has no context!\n"); return -ENODEV; } + if (dev_pm_qos_flags(dev, PM_QOS_FLAG_NO_POWER_OFF) == PM_QOS_FLAGS_ALL) + d_max_in = ACPI_STATE_D3_HOT; acpi_method[2] = '0' + acpi_target_sleep_state; /* @@ -737,8 +741,14 @@ int acpi_pm_device_sleep_state(struct de * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer * provided -- that's our fault recovery, we ignore retval. */ - if (acpi_target_sleep_state > ACPI_STATE_S0) + if (acpi_target_sleep_state > ACPI_STATE_S0) { acpi_evaluate_integer(handle, acpi_method, NULL, &d_min); + wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid + && adev->wakeup.sleep_state >= acpi_target_sleep_state; + } else if (dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) != + PM_QOS_FLAGS_NONE) { + wakeup = adev->wakeup.flags.valid; + } /* * If _PRW says we can wake up the system from the target sleep state, @@ -747,9 +757,7 @@ int acpi_pm_device_sleep_state(struct de * (ACPI 3.x), it should return the maximum (lowest power) D-state that * can wake the system. _S0W may be valid, too. */ - if (acpi_target_sleep_state == ACPI_STATE_S0 || - (device_may_wakeup(dev) && adev->wakeup.flags.valid && - adev->wakeup.sleep_state >= acpi_target_sleep_state)) { + if (wakeup) { acpi_status status; acpi_method[3] = 'W';