diff options
| -rw-r--r-- | drivers/acpi/bus.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/ec.c | 26 | ||||
| -rw-r--r-- | drivers/acpi/fan.c | 40 | ||||
| -rw-r--r-- | drivers/acpi/processor_throttling.c | 4 | ||||
| -rw-r--r-- | include/acpi/acpi_bus.h | 3 |
5 files changed, 63 insertions, 12 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d7a115c362d1..f4487c38d9f2 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -200,7 +200,7 @@ int acpi_bus_set_power(acpi_handle handle, int state) | |||
| 200 | * Get device's current power state | 200 | * Get device's current power state |
| 201 | */ | 201 | */ |
| 202 | acpi_bus_get_power(device->handle, &device->power.state); | 202 | acpi_bus_get_power(device->handle, &device->power.state); |
| 203 | if (state == device->power.state) { | 203 | if ((state == device->power.state) && !device->flags.force_power_state) { |
| 204 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", | 204 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", |
| 205 | state)); | 205 | state)); |
| 206 | return 0; | 206 | return 0; |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 97dc16155a55..987b967c7467 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -26,6 +26,9 @@ | |||
| 26 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 26 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 27 | */ | 27 | */ |
| 28 | 28 | ||
| 29 | /* Uncomment next line to get verbose print outs*/ | ||
| 30 | /* #define DEBUG */ | ||
| 31 | |||
| 29 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
| 30 | #include <linux/module.h> | 33 | #include <linux/module.h> |
| 31 | #include <linux/init.h> | 34 | #include <linux/init.h> |
| @@ -47,9 +50,6 @@ | |||
| 47 | #undef PREFIX | 50 | #undef PREFIX |
| 48 | #define PREFIX "ACPI: EC: " | 51 | #define PREFIX "ACPI: EC: " |
| 49 | 52 | ||
| 50 | /* Uncomment next line to get verbose print outs*/ | ||
| 51 | /* #define DEBUG */ | ||
| 52 | |||
| 53 | /* EC status register */ | 53 | /* EC status register */ |
| 54 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ | 54 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ |
| 55 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ | 55 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ |
| @@ -82,6 +82,7 @@ enum { | |||
| 82 | EC_FLAGS_ADDRESS, /* Address is being written */ | 82 | EC_FLAGS_ADDRESS, /* Address is being written */ |
| 83 | EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ | 83 | EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ |
| 84 | EC_FLAGS_WDATA, /* Data is being written */ | 84 | EC_FLAGS_WDATA, /* Data is being written */ |
| 85 | EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */ | ||
| 85 | }; | 86 | }; |
| 86 | 87 | ||
| 87 | static int acpi_ec_remove(struct acpi_device *device, int type); | 88 | static int acpi_ec_remove(struct acpi_device *device, int type); |
| @@ -138,26 +139,26 @@ static struct acpi_ec { | |||
| 138 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) | 139 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) |
| 139 | { | 140 | { |
| 140 | u8 x = inb(ec->command_addr); | 141 | u8 x = inb(ec->command_addr); |
| 141 | pr_debug(PREFIX "---> status = 0x%2x\n", x); | 142 | pr_debug(PREFIX "---> status = 0x%2.2x\n", x); |
| 142 | return x; | 143 | return x; |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) | 146 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) |
| 146 | { | 147 | { |
| 147 | u8 x = inb(ec->data_addr); | 148 | u8 x = inb(ec->data_addr); |
| 148 | pr_debug(PREFIX "---> data = 0x%2x\n", x); | 149 | pr_debug(PREFIX "---> data = 0x%2.2x\n", x); |
| 149 | return inb(ec->data_addr); | 150 | return inb(ec->data_addr); |
| 150 | } | 151 | } |
| 151 | 152 | ||
| 152 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) | 153 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) |
| 153 | { | 154 | { |
| 154 | pr_debug(PREFIX "<--- command = 0x%2x\n", command); | 155 | pr_debug(PREFIX "<--- command = 0x%2.2x\n", command); |
| 155 | outb(command, ec->command_addr); | 156 | outb(command, ec->command_addr); |
| 156 | } | 157 | } |
| 157 | 158 | ||
| 158 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) | 159 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) |
| 159 | { | 160 | { |
| 160 | pr_debug(PREFIX "<--- data = 0x%2x\n", data); | 161 | pr_debug(PREFIX "<--- data = 0x%2.2x\n", data); |
| 161 | outb(data, ec->data_addr); | 162 | outb(data, ec->data_addr); |
| 162 | } | 163 | } |
| 163 | 164 | ||
| @@ -179,6 +180,10 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) | |||
| 179 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | 180 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) |
| 180 | { | 181 | { |
| 181 | int ret = 0; | 182 | int ret = 0; |
| 183 | |||
| 184 | if (unlikely(event == ACPI_EC_EVENT_OBF_1 && | ||
| 185 | test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) | ||
| 186 | force_poll = 1; | ||
| 182 | if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && | 187 | if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && |
| 183 | test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) | 188 | test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) |
| 184 | force_poll = 1; | 189 | force_poll = 1; |
| @@ -192,7 +197,12 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | |||
| 192 | goto end; | 197 | goto end; |
| 193 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 198 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
| 194 | if (acpi_ec_check_status(ec, event)) { | 199 | if (acpi_ec_check_status(ec, event)) { |
| 195 | if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { | 200 | if (event == ACPI_EC_EVENT_OBF_1) { |
| 201 | /* miss OBF_1 GPE, don't expect it */ | ||
| 202 | pr_info(PREFIX "missing OBF confirmation, " | ||
| 203 | "don't expect it any longer.\n"); | ||
| 204 | set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags); | ||
| 205 | } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { | ||
| 196 | /* miss address GPE, don't expect it anymore */ | 206 | /* miss address GPE, don't expect it anymore */ |
| 197 | pr_info(PREFIX "missing address confirmation, " | 207 | pr_info(PREFIX "missing address confirmation, " |
| 198 | "don't expect it any longer.\n"); | 208 | "don't expect it any longer.\n"); |
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index a5a5532db268..a6e149d692cb 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
| @@ -47,6 +47,8 @@ MODULE_LICENSE("GPL"); | |||
| 47 | 47 | ||
| 48 | static int acpi_fan_add(struct acpi_device *device); | 48 | static int acpi_fan_add(struct acpi_device *device); |
| 49 | static int acpi_fan_remove(struct acpi_device *device, int type); | 49 | static int acpi_fan_remove(struct acpi_device *device, int type); |
| 50 | static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state); | ||
| 51 | static int acpi_fan_resume(struct acpi_device *device); | ||
| 50 | 52 | ||
| 51 | static const struct acpi_device_id fan_device_ids[] = { | 53 | static const struct acpi_device_id fan_device_ids[] = { |
| 52 | {"PNP0C0B", 0}, | 54 | {"PNP0C0B", 0}, |
| @@ -61,6 +63,8 @@ static struct acpi_driver acpi_fan_driver = { | |||
| 61 | .ops = { | 63 | .ops = { |
| 62 | .add = acpi_fan_add, | 64 | .add = acpi_fan_add, |
| 63 | .remove = acpi_fan_remove, | 65 | .remove = acpi_fan_remove, |
| 66 | .suspend = acpi_fan_suspend, | ||
| 67 | .resume = acpi_fan_resume, | ||
| 64 | }, | 68 | }, |
| 65 | }; | 69 | }; |
| 66 | 70 | ||
| @@ -191,6 +195,10 @@ static int acpi_fan_add(struct acpi_device *device) | |||
| 191 | goto end; | 195 | goto end; |
| 192 | } | 196 | } |
| 193 | 197 | ||
| 198 | device->flags.force_power_state = 1; | ||
| 199 | acpi_bus_set_power(device->handle, state); | ||
| 200 | device->flags.force_power_state = 0; | ||
| 201 | |||
| 194 | result = acpi_fan_add_fs(device); | 202 | result = acpi_fan_add_fs(device); |
| 195 | if (result) | 203 | if (result) |
| 196 | goto end; | 204 | goto end; |
| @@ -216,6 +224,38 @@ static int acpi_fan_remove(struct acpi_device *device, int type) | |||
| 216 | return 0; | 224 | return 0; |
| 217 | } | 225 | } |
| 218 | 226 | ||
| 227 | static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) | ||
| 228 | { | ||
| 229 | if (!device) | ||
| 230 | return -EINVAL; | ||
| 231 | |||
| 232 | acpi_bus_set_power(device->handle, ACPI_STATE_D0); | ||
| 233 | |||
| 234 | return AE_OK; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int acpi_fan_resume(struct acpi_device *device) | ||
| 238 | { | ||
| 239 | int result = 0; | ||
| 240 | int power_state = 0; | ||
| 241 | |||
| 242 | if (!device) | ||
| 243 | return -EINVAL; | ||
| 244 | |||
| 245 | result = acpi_bus_get_power(device->handle, &power_state); | ||
| 246 | if (result) { | ||
| 247 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
| 248 | "Error reading fan power state\n")); | ||
| 249 | return result; | ||
| 250 | } | ||
| 251 | |||
| 252 | device->flags.force_power_state = 1; | ||
| 253 | acpi_bus_set_power(device->handle, power_state); | ||
| 254 | device->flags.force_power_state = 0; | ||
| 255 | |||
| 256 | return result; | ||
| 257 | } | ||
| 258 | |||
| 219 | static int __init acpi_fan_init(void) | 259 | static int __init acpi_fan_init(void) |
| 220 | { | 260 | { |
| 221 | int result = 0; | 261 | int result = 0; |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 6742d7bc4777..1685b40abda7 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
| @@ -775,12 +775,12 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
| 775 | acpi_processor_get_throttling_states(pr) || | 775 | acpi_processor_get_throttling_states(pr) || |
| 776 | acpi_processor_get_platform_limit(pr)) | 776 | acpi_processor_get_platform_limit(pr)) |
| 777 | { | 777 | { |
| 778 | if (acpi_processor_get_fadt_info(pr)) | ||
| 779 | return 0; | ||
| 780 | pr->throttling.acpi_processor_get_throttling = | 778 | pr->throttling.acpi_processor_get_throttling = |
| 781 | &acpi_processor_get_throttling_fadt; | 779 | &acpi_processor_get_throttling_fadt; |
| 782 | pr->throttling.acpi_processor_set_throttling = | 780 | pr->throttling.acpi_processor_set_throttling = |
| 783 | &acpi_processor_set_throttling_fadt; | 781 | &acpi_processor_set_throttling_fadt; |
| 782 | if (acpi_processor_get_fadt_info(pr)) | ||
| 783 | return 0; | ||
| 784 | } else { | 784 | } else { |
| 785 | pr->throttling.acpi_processor_get_throttling = | 785 | pr->throttling.acpi_processor_get_throttling = |
| 786 | &acpi_processor_get_throttling_ptc; | 786 | &acpi_processor_get_throttling_ptc; |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 19c3ead2a90b..7b74b60a68a4 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -168,7 +168,8 @@ struct acpi_device_flags { | |||
| 168 | u32 power_manageable:1; | 168 | u32 power_manageable:1; |
| 169 | u32 performance_manageable:1; | 169 | u32 performance_manageable:1; |
| 170 | u32 wake_capable:1; /* Wakeup(_PRW) supported? */ | 170 | u32 wake_capable:1; /* Wakeup(_PRW) supported? */ |
| 171 | u32 reserved:20; | 171 | u32 force_power_state:1; |
| 172 | u32 reserved:19; | ||
| 172 | }; | 173 | }; |
| 173 | 174 | ||
| 174 | /* File System */ | 175 | /* File System */ |
