Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 4718
b: refs/heads/master
c: 0f64474
h: refs/heads/master
v: v3
  • Loading branch information
David Shaohua Li authored and Len Brown committed Jul 12, 2005
1 parent 0f68b3b commit 638d05d
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 84df749f364209c9623304b7a94ddb954dc343bb
refs/heads/master: 0f64474b8f7f1f7f3af5b24ef997baa35f923509
47 changes: 46 additions & 1 deletion trunk/drivers/pci/pci-acpi.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* File: pci-acpi.c
* Purpose: Provide PCI support in ACPI
* Purpose: Provde PCI support in ACPI
*
* Copyright (C) 2005 David Shaohua Li <shaohua.li@intel.com>
* Copyright (C) 2004 Tom Long Nguyen <tom.l.nguyen@intel.com>
Expand All @@ -17,6 +17,7 @@
#include <acpi/acpi_bus.h>

#include <linux/pci-acpi.h>
#include "pci.h"

static u32 ctrlset_buf[3] = {0, 0, 0};
static u32 global_ctrlsets = 0;
Expand Down Expand Up @@ -209,6 +210,49 @@ acpi_status pci_osc_control_set(u32 flags)
}
EXPORT_SYMBOL(pci_osc_control_set);

/*
* _SxD returns the D-state with the highest power
* (lowest D-state number) supported in the S-state "x".
*
* If the devices does not have a _PRW
* (Power Resources for Wake) supporting system wakeup from "x"
* then the OS is free to choose a lower power (higher number
* D-state) than the return value from _SxD.
*
* But if _PRW is enabled at S-state "x", the OS
* must not choose a power lower than _SxD --
* unless the device has an _SxW method specifying
* the lowest power (highest D-state number) the device
* may enter while still able to wake the system.
*
* ie. depending on global OS policy:
*
* if (_PRW at S-state x)
* choose from highest power _SxD to lowest power _SxW
* else // no _PRW at S-state x
* choose highest power _SxD or any lower power
*
* currently we simply return _SxD, if present.
*/

static int acpi_pci_choose_state(struct pci_dev *pdev, pm_message_t state)
{
char dstate_str[] = "_S0D";
acpi_status status;
unsigned long val;
struct device *dev = &pdev->dev;

/* Fixme: the check is wrong after pm_message_t is a struct */
if ((state >= PM_SUSPEND_MAX) || !DEVICE_ACPI_HANDLE(dev))
return -EINVAL;
dstate_str[2] += state; /* _S1D, _S2D, _S3D, _S4D */
status = acpi_evaluate_integer(DEVICE_ACPI_HANDLE(dev), dstate_str,
NULL, &val);
if (ACPI_SUCCESS(status))
return val;
return -ENODEV;
}

/* ACPI bus type */
static int pci_acpi_find_device(struct device *dev, acpi_handle *handle)
{
Expand Down Expand Up @@ -255,6 +299,7 @@ static int __init pci_acpi_init(void)
ret = register_acpi_bus_type(&pci_acpi_bus);
if (ret)
return 0;
platform_pci_choose_state = acpi_pci_choose_state;
return 0;
}
arch_initcall(pci_acpi_init);
11 changes: 10 additions & 1 deletion trunk/drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
return 0;
}

int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state) = NULL;

/**
* pci_choose_state - Choose the power state of a PCI device
* @dev: PCI device to be suspended
Expand All @@ -316,10 +318,17 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)

pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
{
int ret;

if (!pci_find_capability(dev, PCI_CAP_ID_PM))
return PCI_D0;

switch (state) {
if (platform_pci_choose_state) {
ret = platform_pci_choose_state(dev, state);
if (ret >= 0)
state = ret;
}
switch (state) {
case 0: return PCI_D0;
case 3: return PCI_D3hot;
default:
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
void (*alignf)(void *, struct resource *,
unsigned long, unsigned long),
void *alignf_data);
/* Firmware callbacks */
extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);

/* PCI /proc functions */
#ifdef CONFIG_PROC_FS
extern int pci_proc_attach_device(struct pci_dev *dev);
Expand Down

0 comments on commit 638d05d

Please sign in to comment.