diff options
| -rw-r--r-- | drivers/acpi/bus.c | 11 | ||||
| -rw-r--r-- | drivers/acpi/glue.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/sleep/main.c | 25 | ||||
| -rw-r--r-- | drivers/acpi/sleep/wakeup.c | 11 | ||||
| -rw-r--r-- | drivers/base/power/sysfs.c | 3 | ||||
| -rw-r--r-- | drivers/pci/pci-acpi.c | 20 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 169 | ||||
| -rw-r--r-- | drivers/pci/pci.h | 8 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 47 | ||||
| -rw-r--r-- | include/acpi/acpi_bus.h | 2 | ||||
| -rw-r--r-- | include/linux/pm_wakeup.h | 26 |
11 files changed, 208 insertions, 116 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b9b69d9629b5..fc1110d6a078 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -306,6 +306,17 @@ bool acpi_bus_power_manageable(acpi_handle handle) | |||
| 306 | 306 | ||
| 307 | EXPORT_SYMBOL(acpi_bus_power_manageable); | 307 | EXPORT_SYMBOL(acpi_bus_power_manageable); |
| 308 | 308 | ||
| 309 | bool acpi_bus_can_wakeup(acpi_handle handle) | ||
| 310 | { | ||
| 311 | struct acpi_device *device; | ||
| 312 | int result; | ||
| 313 | |||
| 314 | result = acpi_bus_get_device(handle, &device); | ||
| 315 | return result ? false : device->wakeup.flags.valid; | ||
| 316 | } | ||
| 317 | |||
| 318 | EXPORT_SYMBOL(acpi_bus_can_wakeup); | ||
| 319 | |||
| 309 | /* -------------------------------------------------------------------------- | 320 | /* -------------------------------------------------------------------------- |
| 310 | Event Management | 321 | Event Management |
| 311 | -------------------------------------------------------------------------- */ | 322 | -------------------------------------------------------------------------- */ |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 06f8634fe58b..87c5d456e180 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -166,6 +166,8 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
| 166 | "firmware_node"); | 166 | "firmware_node"); |
| 167 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, | 167 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, |
| 168 | "physical_node"); | 168 | "physical_node"); |
| 169 | if (acpi_dev->wakeup.flags.valid) | ||
| 170 | device_set_wakeup_capable(dev, true); | ||
| 169 | } | 171 | } |
| 170 | 172 | ||
| 171 | return 0; | 173 | return 0; |
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 4addf8ad50ae..af7f4663deaa 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
| @@ -468,6 +468,31 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
| 468 | *d_min_p = d_min; | 468 | *d_min_p = d_min; |
| 469 | return d_max; | 469 | return d_max; |
| 470 | } | 470 | } |
| 471 | |||
| 472 | /** | ||
| 473 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up | ||
| 474 | * capability of given device | ||
| 475 | * @dev: device to handle | ||
| 476 | * @enable: 'true' - enable, 'false' - disable the wake-up capability | ||
| 477 | */ | ||
| 478 | int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | ||
| 479 | { | ||
| 480 | acpi_handle handle; | ||
| 481 | struct acpi_device *adev; | ||
| 482 | |||
| 483 | if (!device_may_wakeup(dev)) | ||
| 484 | return -EINVAL; | ||
| 485 | |||
| 486 | handle = DEVICE_ACPI_HANDLE(dev); | ||
| 487 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { | ||
| 488 | printk(KERN_DEBUG "ACPI handle has no context!\n"); | ||
| 489 | return -ENODEV; | ||
| 490 | } | ||
| 491 | |||
| 492 | return enable ? | ||
| 493 | acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : | ||
| 494 | acpi_disable_wakeup_device_power(adev); | ||
| 495 | } | ||
| 471 | #endif | 496 | #endif |
| 472 | 497 | ||
| 473 | static void acpi_power_off_prepare(void) | 498 | static void acpi_power_off_prepare(void) |
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 7422a2213944..38655eb132dc 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c | |||
| @@ -66,13 +66,15 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
| 66 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | 66 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
| 67 | struct acpi_device *dev = | 67 | struct acpi_device *dev = |
| 68 | container_of(node, struct acpi_device, wakeup_list); | 68 | container_of(node, struct acpi_device, wakeup_list); |
| 69 | |||
| 69 | if (!dev->wakeup.flags.valid) | 70 | if (!dev->wakeup.flags.valid) |
| 70 | continue; | 71 | continue; |
| 72 | |||
| 71 | /* If users want to disable run-wake GPE, | 73 | /* If users want to disable run-wake GPE, |
| 72 | * we only disable it for wake and leave it for runtime | 74 | * we only disable it for wake and leave it for runtime |
| 73 | */ | 75 | */ |
| 74 | if (!dev->wakeup.state.enabled || | 76 | if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) |
| 75 | sleep_state > (u32) dev->wakeup.sleep_state) { | 77 | || sleep_state > (u32) dev->wakeup.sleep_state) { |
| 76 | if (dev->wakeup.flags.run_wake) { | 78 | if (dev->wakeup.flags.run_wake) { |
| 77 | spin_unlock(&acpi_device_lock); | 79 | spin_unlock(&acpi_device_lock); |
| 78 | /* set_gpe_type will disable GPE, leave it like that */ | 80 | /* set_gpe_type will disable GPE, leave it like that */ |
| @@ -110,8 +112,9 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
| 110 | 112 | ||
| 111 | if (!dev->wakeup.flags.valid) | 113 | if (!dev->wakeup.flags.valid) |
| 112 | continue; | 114 | continue; |
| 113 | if (!dev->wakeup.state.enabled || | 115 | |
| 114 | sleep_state > (u32) dev->wakeup.sleep_state) { | 116 | if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) |
| 117 | || sleep_state > (u32) dev->wakeup.sleep_state) { | ||
| 115 | if (dev->wakeup.flags.run_wake) { | 118 | if (dev->wakeup.flags.run_wake) { |
| 116 | spin_unlock(&acpi_device_lock); | 119 | spin_unlock(&acpi_device_lock); |
| 117 | acpi_set_gpe_type(dev->wakeup.gpe_device, | 120 | acpi_set_gpe_type(dev->wakeup.gpe_device, |
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index d11f74b038db..596aeecfdffe 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
| @@ -6,9 +6,6 @@ | |||
| 6 | #include <linux/string.h> | 6 | #include <linux/string.h> |
| 7 | #include "power.h" | 7 | #include "power.h" |
| 8 | 8 | ||
| 9 | int (*platform_enable_wakeup)(struct device *dev, int is_on); | ||
| 10 | |||
| 11 | |||
| 12 | /* | 9 | /* |
| 13 | * wakeup - Report/change current wakeup option for device | 10 | * wakeup - Report/change current wakeup option for device |
| 14 | * | 11 | * |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 6bc0d8c870af..7764768b6a0e 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
| @@ -299,10 +299,30 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
| 299 | return error; | 299 | return error; |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | static bool acpi_pci_can_wakeup(struct pci_dev *dev) | ||
| 303 | { | ||
| 304 | acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); | ||
| 305 | |||
| 306 | return handle ? acpi_bus_can_wakeup(handle) : false; | ||
| 307 | } | ||
| 308 | |||
| 309 | static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) | ||
| 310 | { | ||
| 311 | int error = acpi_pm_device_sleep_wake(&dev->dev, enable); | ||
| 312 | |||
| 313 | if (!error) | ||
| 314 | dev_printk(KERN_INFO, &dev->dev, | ||
| 315 | "wake-up capability %s by ACPI\n", | ||
| 316 | enable ? "enabled" : "disabled"); | ||
| 317 | return error; | ||
| 318 | } | ||
| 319 | |||
| 302 | static struct pci_platform_pm_ops acpi_pci_platform_pm = { | 320 | static struct pci_platform_pm_ops acpi_pci_platform_pm = { |
| 303 | .is_manageable = acpi_pci_power_manageable, | 321 | .is_manageable = acpi_pci_power_manageable, |
| 304 | .set_state = acpi_pci_set_power_state, | 322 | .set_state = acpi_pci_set_power_state, |
| 305 | .choose_state = acpi_pci_choose_state, | 323 | .choose_state = acpi_pci_choose_state, |
| 324 | .can_wakeup = acpi_pci_can_wakeup, | ||
| 325 | .sleep_wake = acpi_pci_sleep_wake, | ||
| 306 | }; | 326 | }; |
| 307 | 327 | ||
| 308 | /* ACPI bus type */ | 328 | /* ACPI bus type */ |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 20e28077b96d..a6b1b6f96abc 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -380,7 +380,8 @@ static struct pci_platform_pm_ops *pci_platform_pm; | |||
| 380 | 380 | ||
| 381 | int pci_set_platform_pm(struct pci_platform_pm_ops *ops) | 381 | int pci_set_platform_pm(struct pci_platform_pm_ops *ops) |
| 382 | { | 382 | { |
| 383 | if (!ops->is_manageable || !ops->set_state || !ops->choose_state) | 383 | if (!ops->is_manageable || !ops->set_state || !ops->choose_state |
| 384 | || !ops->sleep_wake || !ops->can_wakeup) | ||
| 384 | return -EINVAL; | 385 | return -EINVAL; |
| 385 | pci_platform_pm = ops; | 386 | pci_platform_pm = ops; |
| 386 | return 0; | 387 | return 0; |
| @@ -403,6 +404,17 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev) | |||
| 403 | pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR; | 404 | pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR; |
| 404 | } | 405 | } |
| 405 | 406 | ||
| 407 | static inline bool platform_pci_can_wakeup(struct pci_dev *dev) | ||
| 408 | { | ||
| 409 | return pci_platform_pm ? pci_platform_pm->can_wakeup(dev) : false; | ||
| 410 | } | ||
| 411 | |||
| 412 | static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | ||
| 413 | { | ||
| 414 | return pci_platform_pm ? | ||
| 415 | pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; | ||
| 416 | } | ||
| 417 | |||
| 406 | /** | 418 | /** |
| 407 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of | 419 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of |
| 408 | * given PCI device | 420 | * given PCI device |
| @@ -1036,6 +1048,56 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) | |||
| 1036 | } | 1048 | } |
| 1037 | 1049 | ||
| 1038 | /** | 1050 | /** |
| 1051 | * pci_pme_capable - check the capability of PCI device to generate PME# | ||
| 1052 | * @dev: PCI device to handle. | ||
| 1053 | * @pm: PCI PM capability offset of the device. | ||
| 1054 | * @state: PCI state from which device will issue PME#. | ||
| 1055 | */ | ||
| 1056 | static bool pci_pme_capable(struct pci_dev *dev, int pm, pci_power_t state) | ||
| 1057 | { | ||
| 1058 | u16 pmc; | ||
| 1059 | |||
| 1060 | if (!pm) | ||
| 1061 | return false; | ||
| 1062 | |||
| 1063 | /* Check device's ability to generate PME# from given state */ | ||
| 1064 | pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc); | ||
| 1065 | |||
| 1066 | pmc &= PCI_PM_CAP_PME_MASK; | ||
| 1067 | pmc >>= ffs(PCI_PM_CAP_PME_MASK) - 1; /* First bit of mask */ | ||
| 1068 | |||
| 1069 | return !!(pmc & (1 << state)); | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | /** | ||
| 1073 | * pci_pme_active - enable or disable PCI device's PME# function | ||
| 1074 | * @dev: PCI device to handle. | ||
| 1075 | * @pm: PCI PM capability offset of the device. | ||
| 1076 | * @enable: 'true' to enable PME# generation; 'false' to disable it. | ||
| 1077 | * | ||
| 1078 | * The caller must verify that the device is capable of generating PME# before | ||
| 1079 | * calling this function with @enable equal to 'true'. | ||
| 1080 | */ | ||
| 1081 | static void pci_pme_active(struct pci_dev *dev, int pm, bool enable) | ||
| 1082 | { | ||
| 1083 | u16 pmcsr; | ||
| 1084 | |||
| 1085 | if (!pm) | ||
| 1086 | return; | ||
| 1087 | |||
| 1088 | pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); | ||
| 1089 | /* Clear PME_Status by writing 1 to it and enable PME# */ | ||
| 1090 | pmcsr |= PCI_PM_CTRL_PME_STATUS | PCI_PM_CTRL_PME_ENABLE; | ||
| 1091 | if (!enable) | ||
| 1092 | pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; | ||
| 1093 | |||
| 1094 | pci_write_config_word(dev, pm + PCI_PM_CTRL, pmcsr); | ||
| 1095 | |||
| 1096 | dev_printk(KERN_INFO, &dev->dev, "PME# %s\n", | ||
| 1097 | enable ? "enabled" : "disabled"); | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | /** | ||
| 1039 | * pci_enable_wake - enable PCI device as wakeup event source | 1101 | * pci_enable_wake - enable PCI device as wakeup event source |
| 1040 | * @dev: PCI device affected | 1102 | * @dev: PCI device affected |
| 1041 | * @state: PCI state from which device will issue wakeup events | 1103 | * @state: PCI state from which device will issue wakeup events |
| @@ -1046,66 +1108,83 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) | |||
| 1046 | * called automatically by this routine. | 1108 | * called automatically by this routine. |
| 1047 | * | 1109 | * |
| 1048 | * Devices with legacy power management (no standard PCI PM capabilities) | 1110 | * Devices with legacy power management (no standard PCI PM capabilities) |
| 1049 | * always require such platform hooks. Depending on the platform, devices | 1111 | * always require such platform hooks. |
| 1050 | * supporting the standard PCI PME# signal may require such platform hooks; | ||
| 1051 | * they always update bits in config space to allow PME# generation. | ||
| 1052 | * | 1112 | * |
| 1053 | * -EIO is returned if the device can't ever be a wakeup event source. | 1113 | * RETURN VALUE: |
| 1054 | * -EINVAL is returned if the device can't generate wakeup events from | 1114 | * 0 is returned on success |
| 1055 | * the specified PCI state. Returns zero if the operation is successful. | 1115 | * -EINVAL is returned if device is not supposed to wake up the system |
| 1116 | * Error code depending on the platform is returned if both the platform and | ||
| 1117 | * the native mechanism fail to enable the generation of wake-up events | ||
| 1056 | */ | 1118 | */ |
| 1057 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) | 1119 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) |
| 1058 | { | 1120 | { |
| 1059 | int pm; | 1121 | int pm; |
| 1060 | int status; | 1122 | int error = 0; |
| 1061 | u16 value; | 1123 | bool pme_done = false; |
| 1062 | |||
| 1063 | /* Note that drivers should verify device_may_wakeup(&dev->dev) | ||
| 1064 | * before calling this function. Platform code should report | ||
| 1065 | * errors when drivers try to enable wakeup on devices that | ||
| 1066 | * can't issue wakeups, or on which wakeups were disabled by | ||
| 1067 | * userspace updating the /sys/devices.../power/wakeup file. | ||
| 1068 | */ | ||
| 1069 | 1124 | ||
| 1070 | status = call_platform_enable_wakeup(&dev->dev, enable); | 1125 | if (!device_may_wakeup(&dev->dev)) |
| 1071 | 1126 | return -EINVAL; | |
| 1072 | /* find PCI PM capability in list */ | ||
| 1073 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); | ||
| 1074 | 1127 | ||
| 1075 | /* If device doesn't support PM Capabilities, but caller wants to | 1128 | /* |
| 1076 | * disable wake events, it's a NOP. Otherwise fail unless the | 1129 | * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don |
| 1077 | * platform hooks handled this legacy device already. | 1130 | * Anderson we should be doing PME# wake enable followed by ACPI wake |
| 1131 | * enable. To disable wake-up we call the platform first, for symmetry. | ||
| 1078 | */ | 1132 | */ |
| 1079 | if (!pm) | ||
| 1080 | return enable ? status : 0; | ||
| 1081 | 1133 | ||
| 1082 | /* Check device's ability to generate PME# */ | 1134 | if (!enable && platform_pci_can_wakeup(dev)) |
| 1083 | pci_read_config_word(dev,pm+PCI_PM_PMC,&value); | 1135 | error = platform_pci_sleep_wake(dev, false); |
| 1084 | 1136 | ||
| 1085 | value &= PCI_PM_CAP_PME_MASK; | 1137 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); |
| 1086 | value >>= ffs(PCI_PM_CAP_PME_MASK) - 1; /* First bit of mask */ | 1138 | if (!enable || pci_pme_capable(dev, pm, state)) { |
| 1087 | 1139 | pci_pme_active(dev, pm, enable); | |
| 1088 | /* Check if it can generate PME# from requested state. */ | 1140 | pme_done = true; |
| 1089 | if (!value || !(value & (1 << state))) { | ||
| 1090 | /* if it can't, revert what the platform hook changed, | ||
| 1091 | * always reporting the base "EINVAL, can't PME#" error | ||
| 1092 | */ | ||
| 1093 | if (enable) | ||
| 1094 | call_platform_enable_wakeup(&dev->dev, 0); | ||
| 1095 | return enable ? -EINVAL : 0; | ||
| 1096 | } | 1141 | } |
| 1097 | 1142 | ||
| 1098 | pci_read_config_word(dev, pm + PCI_PM_CTRL, &value); | 1143 | if (enable && platform_pci_can_wakeup(dev)) |
| 1144 | error = platform_pci_sleep_wake(dev, true); | ||
| 1099 | 1145 | ||
| 1100 | /* Clear PME_Status by writing 1 to it and enable PME# */ | 1146 | return pme_done ? 0 : error; |
| 1101 | value |= PCI_PM_CTRL_PME_STATUS | PCI_PM_CTRL_PME_ENABLE; | 1147 | } |
| 1102 | 1148 | ||
| 1103 | if (!enable) | 1149 | /** |
| 1104 | value &= ~PCI_PM_CTRL_PME_ENABLE; | 1150 | * pci_pm_init - Initialize PM functions of given PCI device |
| 1151 | * @dev: PCI device to handle. | ||
| 1152 | */ | ||
| 1153 | void pci_pm_init(struct pci_dev *dev) | ||
| 1154 | { | ||
| 1155 | int pm; | ||
| 1156 | u16 pmc; | ||
| 1105 | 1157 | ||
| 1106 | pci_write_config_word(dev, pm + PCI_PM_CTRL, value); | 1158 | /* find PCI PM capability in list */ |
| 1159 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); | ||
| 1160 | if (!pm) | ||
| 1161 | return; | ||
| 1162 | /* Check device's ability to generate PME# */ | ||
| 1163 | pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc); | ||
| 1107 | 1164 | ||
| 1108 | return 0; | 1165 | if ((pmc & PCI_PM_CAP_VER_MASK) > 3) { |
| 1166 | dev_err(&dev->dev, "unsupported PM cap regs version (%u)\n", | ||
| 1167 | pmc & PCI_PM_CAP_VER_MASK); | ||
| 1168 | return; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | if (pmc & PCI_PM_CAP_PME_MASK) { | ||
| 1172 | dev_printk(KERN_INFO, &dev->dev, | ||
| 1173 | "PME# supported from%s%s%s%s%s\n", | ||
| 1174 | (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "", | ||
| 1175 | (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "", | ||
| 1176 | (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "", | ||
| 1177 | (pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "", | ||
| 1178 | (pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : ""); | ||
| 1179 | /* | ||
| 1180 | * Make device's PM flags reflect the wake-up capability, but | ||
| 1181 | * let the user space enable it to wake up the system as needed. | ||
| 1182 | */ | ||
| 1183 | device_set_wakeup_capable(&dev->dev, true); | ||
| 1184 | device_set_wakeup_enable(&dev->dev, false); | ||
| 1185 | /* Disable the PME# generation functionality */ | ||
| 1186 | pci_pme_active(dev, pm, false); | ||
| 1187 | } | ||
| 1109 | } | 1188 | } |
| 1110 | 1189 | ||
| 1111 | int | 1190 | int |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 0cd2e719933b..b08dfc9746af 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -17,6 +17,11 @@ extern void pci_cleanup_rom(struct pci_dev *dev); | |||
| 17 | * platform; to be used during system-wide transitions from a | 17 | * platform; to be used during system-wide transitions from a |
| 18 | * sleeping state to the working state and vice versa | 18 | * sleeping state to the working state and vice versa |
| 19 | * | 19 | * |
| 20 | * @can_wakeup - returns 'true' if given device is capable of waking up the | ||
| 21 | * system from a sleeping state | ||
| 22 | * | ||
| 23 | * @sleep_wake - enables/disables the system wake up capability of given device | ||
| 24 | * | ||
| 20 | * If given platform is generally capable of power managing PCI devices, all of | 25 | * If given platform is generally capable of power managing PCI devices, all of |
| 21 | * these callbacks are mandatory. | 26 | * these callbacks are mandatory. |
| 22 | */ | 27 | */ |
| @@ -24,9 +29,12 @@ struct pci_platform_pm_ops { | |||
| 24 | bool (*is_manageable)(struct pci_dev *dev); | 29 | bool (*is_manageable)(struct pci_dev *dev); |
| 25 | int (*set_state)(struct pci_dev *dev, pci_power_t state); | 30 | int (*set_state)(struct pci_dev *dev, pci_power_t state); |
| 26 | pci_power_t (*choose_state)(struct pci_dev *dev); | 31 | pci_power_t (*choose_state)(struct pci_dev *dev); |
| 32 | bool (*can_wakeup)(struct pci_dev *dev); | ||
| 33 | int (*sleep_wake)(struct pci_dev *dev, bool enable); | ||
| 27 | }; | 34 | }; |
| 28 | 35 | ||
| 29 | extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); | 36 | extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); |
| 37 | extern void pci_pm_init(struct pci_dev *dev); | ||
| 30 | 38 | ||
| 31 | extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); | 39 | extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); |
| 32 | extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val); | 40 | extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2f0ae70710d6..b1724cf31b66 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -860,49 +860,6 @@ int pci_cfg_space_size_ext(struct pci_dev *dev) | |||
| 860 | return PCI_CFG_SPACE_SIZE; | 860 | return PCI_CFG_SPACE_SIZE; |
| 861 | } | 861 | } |
| 862 | 862 | ||
| 863 | /** | ||
| 864 | * pci_disable_pme - Disable the PME function of PCI device | ||
| 865 | * @dev: PCI device affected | ||
| 866 | * -EINVAL is returned if PCI device doesn't support PME. | ||
| 867 | * Zero is returned if the PME is supported and can be disabled. | ||
| 868 | */ | ||
| 869 | static int pci_disable_pme(struct pci_dev *dev) | ||
| 870 | { | ||
| 871 | int pm; | ||
| 872 | u16 value; | ||
| 873 | |||
| 874 | /* find PCI PM capability in list */ | ||
| 875 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); | ||
| 876 | |||
| 877 | /* If device doesn't support PM Capabilities, it means that PME is | ||
| 878 | * not supported. | ||
| 879 | */ | ||
| 880 | if (!pm) | ||
| 881 | return -EINVAL; | ||
| 882 | /* Check device's ability to generate PME# */ | ||
| 883 | pci_read_config_word(dev, pm + PCI_PM_PMC, &value); | ||
| 884 | |||
| 885 | value &= PCI_PM_CAP_PME_MASK; | ||
| 886 | /* Check if it can generate PME# */ | ||
| 887 | if (!value) { | ||
| 888 | /* | ||
| 889 | * If it is zero, it means that PME is still unsupported | ||
| 890 | * although there exists the PM capability. | ||
| 891 | */ | ||
| 892 | return -EINVAL; | ||
| 893 | } | ||
| 894 | |||
| 895 | pci_read_config_word(dev, pm + PCI_PM_CTRL, &value); | ||
| 896 | |||
| 897 | /* Clear PME_Status by writing 1 to it */ | ||
| 898 | value |= PCI_PM_CTRL_PME_STATUS ; | ||
| 899 | /* Disable PME enable bit */ | ||
| 900 | value &= ~PCI_PM_CTRL_PME_ENABLE; | ||
| 901 | pci_write_config_word(dev, pm + PCI_PM_CTRL, value); | ||
| 902 | |||
| 903 | return 0; | ||
| 904 | } | ||
| 905 | |||
| 906 | int pci_cfg_space_size(struct pci_dev *dev) | 863 | int pci_cfg_space_size(struct pci_dev *dev) |
| 907 | { | 864 | { |
| 908 | int pos; | 865 | int pos; |
| @@ -1010,7 +967,6 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) | |||
| 1010 | } | 967 | } |
| 1011 | 968 | ||
| 1012 | pci_vpd_pci22_init(dev); | 969 | pci_vpd_pci22_init(dev); |
| 1013 | pci_disable_pme(dev); | ||
| 1014 | 970 | ||
| 1015 | return dev; | 971 | return dev; |
| 1016 | } | 972 | } |
| @@ -1031,6 +987,9 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) | |||
| 1031 | /* Fix up broken headers */ | 987 | /* Fix up broken headers */ |
| 1032 | pci_fixup_device(pci_fixup_header, dev); | 988 | pci_fixup_device(pci_fixup_header, dev); |
| 1033 | 989 | ||
| 990 | /* Initialize power management of the device */ | ||
| 991 | pci_pm_init(dev); | ||
| 992 | |||
| 1034 | /* | 993 | /* |
| 1035 | * Add the device to our list of discovered devices | 994 | * Add the device to our list of discovered devices |
| 1036 | * and the bus list for fixup functions, etc. | 995 | * and the bus list for fixup functions, etc. |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 071daf8db600..7ab5a611e43f 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -337,6 +337,7 @@ int acpi_bus_get_status(struct acpi_device *device); | |||
| 337 | int acpi_bus_get_power(acpi_handle handle, int *state); | 337 | int acpi_bus_get_power(acpi_handle handle, int *state); |
| 338 | int acpi_bus_set_power(acpi_handle handle, int state); | 338 | int acpi_bus_set_power(acpi_handle handle, int state); |
| 339 | bool acpi_bus_power_manageable(acpi_handle handle); | 339 | bool acpi_bus_power_manageable(acpi_handle handle); |
| 340 | bool acpi_bus_can_wakeup(acpi_handle handle); | ||
| 340 | #ifdef CONFIG_ACPI_PROC_EVENT | 341 | #ifdef CONFIG_ACPI_PROC_EVENT |
| 341 | int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); | 342 | int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); |
| 342 | int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data); | 343 | int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data); |
| @@ -379,6 +380,7 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); | |||
| 379 | 380 | ||
| 380 | #ifdef CONFIG_PM_SLEEP | 381 | #ifdef CONFIG_PM_SLEEP |
| 381 | int acpi_pm_device_sleep_state(struct device *, int *); | 382 | int acpi_pm_device_sleep_state(struct device *, int *); |
| 383 | int acpi_pm_device_sleep_wake(struct device *, bool); | ||
| 382 | #else /* !CONFIG_PM_SLEEP */ | 384 | #else /* !CONFIG_PM_SLEEP */ |
| 383 | static inline int acpi_pm_device_sleep_state(struct device *d, int *p) | 385 | static inline int acpi_pm_device_sleep_state(struct device *d, int *p) |
| 384 | { | 386 | { |
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index f0d0b2cb8d20..3af0c8d05cdc 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h | |||
| @@ -35,6 +35,11 @@ static inline void device_init_wakeup(struct device *dev, int val) | |||
| 35 | dev->power.can_wakeup = dev->power.should_wakeup = !!val; | 35 | dev->power.can_wakeup = dev->power.should_wakeup = !!val; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | static inline void device_set_wakeup_capable(struct device *dev, int val) | ||
| 39 | { | ||
| 40 | dev->power.can_wakeup = !!val; | ||
| 41 | } | ||
| 42 | |||
| 38 | static inline int device_can_wakeup(struct device *dev) | 43 | static inline int device_can_wakeup(struct device *dev) |
| 39 | { | 44 | { |
| 40 | return dev->power.can_wakeup; | 45 | return dev->power.can_wakeup; |
| @@ -47,21 +52,7 @@ static inline void device_set_wakeup_enable(struct device *dev, int val) | |||
| 47 | 52 | ||
| 48 | static inline int device_may_wakeup(struct device *dev) | 53 | static inline int device_may_wakeup(struct device *dev) |
| 49 | { | 54 | { |
| 50 | return dev->power.can_wakeup & dev->power.should_wakeup; | 55 | return dev->power.can_wakeup && dev->power.should_wakeup; |
| 51 | } | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Platform hook to activate device wakeup capability, if that's not already | ||
| 55 | * handled by enable_irq_wake() etc. | ||
| 56 | * Returns zero on success, else negative errno | ||
| 57 | */ | ||
| 58 | extern int (*platform_enable_wakeup)(struct device *dev, int is_on); | ||
| 59 | |||
| 60 | static inline int call_platform_enable_wakeup(struct device *dev, int is_on) | ||
| 61 | { | ||
| 62 | if (platform_enable_wakeup) | ||
| 63 | return (*platform_enable_wakeup)(dev, is_on); | ||
| 64 | return 0; | ||
| 65 | } | 56 | } |
| 66 | 57 | ||
| 67 | #else /* !CONFIG_PM */ | 58 | #else /* !CONFIG_PM */ |
| @@ -80,11 +71,6 @@ static inline int device_can_wakeup(struct device *dev) | |||
| 80 | #define device_set_wakeup_enable(dev, val) do {} while (0) | 71 | #define device_set_wakeup_enable(dev, val) do {} while (0) |
| 81 | #define device_may_wakeup(dev) 0 | 72 | #define device_may_wakeup(dev) 0 |
| 82 | 73 | ||
| 83 | static inline int call_platform_enable_wakeup(struct device *dev, int is_on) | ||
| 84 | { | ||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | #endif /* !CONFIG_PM */ | 74 | #endif /* !CONFIG_PM */ |
| 89 | 75 | ||
| 90 | #endif /* _LINUX_PM_WAKEUP_H */ | 76 | #endif /* _LINUX_PM_WAKEUP_H */ |
