aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index f94c86fbc669..8eb599708de8 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * File: pci-acpi.c 2 * File: pci-acpi.c
3 * Purpose: Provide PCI support in ACPI 3 * Purpose: Provde PCI support in ACPI
4 * 4 *
5 * Copyright (C) 2005 David Shaohua Li <shaohua.li@intel.com> 5 * Copyright (C) 2005 David Shaohua Li <shaohua.li@intel.com>
6 * Copyright (C) 2004 Tom Long Nguyen <tom.l.nguyen@intel.com> 6 * Copyright (C) 2004 Tom Long Nguyen <tom.l.nguyen@intel.com>
@@ -17,6 +17,7 @@
17#include <acpi/acpi_bus.h> 17#include <acpi/acpi_bus.h>
18 18
19#include <linux/pci-acpi.h> 19#include <linux/pci-acpi.h>
20#include "pci.h"
20 21
21static u32 ctrlset_buf[3] = {0, 0, 0}; 22static u32 ctrlset_buf[3] = {0, 0, 0};
22static u32 global_ctrlsets = 0; 23static u32 global_ctrlsets = 0;
@@ -209,6 +210,49 @@ acpi_status pci_osc_control_set(u32 flags)
209} 210}
210EXPORT_SYMBOL(pci_osc_control_set); 211EXPORT_SYMBOL(pci_osc_control_set);
211 212
213/*
214 * _SxD returns the D-state with the highest power
215 * (lowest D-state number) supported in the S-state "x".
216 *
217 * If the devices does not have a _PRW
218 * (Power Resources for Wake) supporting system wakeup from "x"
219 * then the OS is free to choose a lower power (higher number
220 * D-state) than the return value from _SxD.
221 *
222 * But if _PRW is enabled at S-state "x", the OS
223 * must not choose a power lower than _SxD --
224 * unless the device has an _SxW method specifying
225 * the lowest power (highest D-state number) the device
226 * may enter while still able to wake the system.
227 *
228 * ie. depending on global OS policy:
229 *
230 * if (_PRW at S-state x)
231 * choose from highest power _SxD to lowest power _SxW
232 * else // no _PRW at S-state x
233 * choose highest power _SxD or any lower power
234 *
235 * currently we simply return _SxD, if present.
236 */
237
238static int acpi_pci_choose_state(struct pci_dev *pdev, pm_message_t state)
239{
240 char dstate_str[] = "_S0D";
241 acpi_status status;
242 unsigned long val;
243 struct device *dev = &pdev->dev;
244
245 /* Fixme: the check is wrong after pm_message_t is a struct */
246 if ((state >= PM_SUSPEND_MAX) || !DEVICE_ACPI_HANDLE(dev))
247 return -EINVAL;
248 dstate_str[2] += state; /* _S1D, _S2D, _S3D, _S4D */
249 status = acpi_evaluate_integer(DEVICE_ACPI_HANDLE(dev), dstate_str,
250 NULL, &val);
251 if (ACPI_SUCCESS(status))
252 return val;
253 return -ENODEV;
254}
255
212/* ACPI bus type */ 256/* ACPI bus type */
213static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) 257static int pci_acpi_find_device(struct device *dev, acpi_handle *handle)
214{ 258{
@@ -255,6 +299,7 @@ static int __init pci_acpi_init(void)
255 ret = register_acpi_bus_type(&pci_acpi_bus); 299 ret = register_acpi_bus_type(&pci_acpi_bus);
256 if (ret) 300 if (ret)
257 return 0; 301 return 0;
302 platform_pci_choose_state = acpi_pci_choose_state;
258 return 0; 303 return 0;
259} 304}
260arch_initcall(pci_acpi_init); 305arch_initcall(pci_acpi_init);