# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/19 00:16:18-05:00 len.brown@intel.com # [ACPI] pci_set_power_state() now calls # platform_pci_set_power_state() # and ACPI can answer # # http://bugzilla.kernel.org/show_bug.cgi?id=4277 # # Signed-off-by: David Shaohua Li # Signed-off-by: Len Brown # # drivers/pci/pci.h # 2005/03/03 04:20:56-05:00 len.brown@intel.com +1 -0 # pci_set_power_state() now calls platform_pci_set_power_state() # # drivers/pci/pci.c # 2005/03/03 04:20:56-05:00 len.brown@intel.com +9 -2 # pci_set_power_state() now calls platform_pci_set_power_state() # # drivers/pci/pci-acpi.c # 2005/03/03 04:28:23-05:00 len.brown@intel.com +19 -0 # pci_set_power_state() now calls platform_pci_set_power_state() # # drivers/acpi/bus.c # 2005/03/03 04:20:56-05:00 len.brown@intel.com +7 -1 # pci_set_power_state() now calls platform_pci_set_power_state() # Index: linux-2.6.12/drivers/acpi/bus.c =================================================================== --- linux-2.6.12.orig/drivers/acpi/bus.c 2005-07-09 23:35:08.000000000 -0400 +++ linux-2.6.12/drivers/acpi/bus.c 2005-07-10 00:11:52.000000000 -0400 @@ -212,6 +212,12 @@ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device is not power manageable\n")); return_VALUE(-ENODEV); } + /* + * Get device's current power state if it's unknown + * This means device power state isn't initialized or previous setting failed + */ + if (device->power.state == ACPI_STATE_UNKNOWN) + acpi_bus_get_power(device->handle, &device->power.state); if (state == device->power.state) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); return_VALUE(0); @@ -231,7 +237,7 @@ * On transitions to a high-powered state we first apply power (via * power resources) then evalute _PSx. Conversly for transitions to * a lower-powered state. - */ + */ if (state < device->power.state) { if (device->power.flags.power_resources) { result = acpi_power_transition(device, state); Index: linux-2.6.12/drivers/pci/pci-acpi.c =================================================================== --- linux-2.6.12.orig/drivers/pci/pci-acpi.c 2005-07-10 00:08:23.000000000 -0400 +++ linux-2.6.12/drivers/pci/pci-acpi.c 2005-07-10 00:11:52.000000000 -0400 @@ -253,6 +253,24 @@ return -ENODEV; } +static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); + static int state_conv[] = { + [0] = 0, + [1] = 1, + [2] = 2, + [3] = 3, + [4] = 3 + }; + int acpi_state = state_conv[(int __force) state]; + + if (!handle) + return -ENODEV; + return acpi_bus_set_power(handle, acpi_state); +} + + /* ACPI bus type */ static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) { @@ -300,6 +318,7 @@ if (ret) return 0; platform_pci_choose_state = acpi_pci_choose_state; + platform_pci_set_power_state = acpi_pci_set_power_state; return 0; } arch_initcall(pci_acpi_init); Index: linux-2.6.12/drivers/pci/pci.c =================================================================== --- linux-2.6.12.orig/drivers/pci/pci.c 2005-07-10 00:11:00.000000000 -0400 +++ linux-2.6.12/drivers/pci/pci.c 2005-07-10 00:11:52.000000000 -0400 @@ -235,7 +235,7 @@ * -EIO if device does not support PCI PM. * 0 if we can successfully change the power state. */ - +int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t) = NULL; int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { @@ -299,8 +299,15 @@ msleep(10); else if (state == PCI_D2 || dev->current_state == PCI_D2) udelay(200); - dev->current_state = state; + /* + * Give firmware a chance to be called, such as ACPI _PRx, _PSx + * Firmware method after natice method ? + */ + if (platform_pci_set_power_state) + platform_pci_set_power_state(dev, state); + + dev->current_state = state; return 0; } Index: linux-2.6.12/drivers/pci/pci.h =================================================================== --- linux-2.6.12.orig/drivers/pci/pci.h 2005-07-10 00:08:23.000000000 -0400 +++ linux-2.6.12/drivers/pci/pci.h 2005-07-10 00:11:52.000000000 -0400 @@ -13,6 +13,7 @@ void *alignf_data); /* Firmware callbacks */ extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); +extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state); /* PCI /proc functions */ #ifdef CONFIG_PROC_FS