aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/bus.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/acpi/bus.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/acpi/bus.c')
-rw-r--r--drivers/acpi/bus.c183
1 files changed, 93 insertions, 90 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 310e3b9749cb..d1e06c182cdb 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -40,6 +40,7 @@
40#include <acpi/acpi_bus.h> 40#include <acpi/acpi_bus.h>
41#include <acpi/acpi_drivers.h> 41#include <acpi/acpi_drivers.h>
42#include <linux/dmi.h> 42#include <linux/dmi.h>
43#include <linux/suspend.h>
43 44
44#include "internal.h" 45#include "internal.h"
45 46
@@ -52,22 +53,6 @@ EXPORT_SYMBOL(acpi_root_dir);
52 53
53#define STRUCT_TO_INT(s) (*((int*)&s)) 54#define STRUCT_TO_INT(s) (*((int*)&s))
54 55
55static int set_power_nocheck(const struct dmi_system_id *id)
56{
57 printk(KERN_NOTICE PREFIX "%s detected - "
58 "disable power check in power transition\n", id->ident);
59 acpi_power_nocheck = 1;
60 return 0;
61}
62static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = {
63 {
64 set_power_nocheck, "HP Pavilion 05", {
65 DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
66 DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"),
67 DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL},
68 {},
69};
70
71 56
72#ifdef CONFIG_X86 57#ifdef CONFIG_X86
73static int set_copy_dsdt(const struct dmi_system_id *id) 58static int set_copy_dsdt(const struct dmi_system_id *id)
@@ -196,33 +181,24 @@ EXPORT_SYMBOL(acpi_bus_get_private_data);
196 Power Management 181 Power Management
197 -------------------------------------------------------------------------- */ 182 -------------------------------------------------------------------------- */
198 183
199int acpi_bus_get_power(acpi_handle handle, int *state) 184static int __acpi_bus_get_power(struct acpi_device *device, int *state)
200{ 185{
201 int result = 0; 186 int result = 0;
202 acpi_status status = 0; 187 acpi_status status = 0;
203 struct acpi_device *device = NULL;
204 unsigned long long psc = 0; 188 unsigned long long psc = 0;
205 189
206 190 if (!device || !state)
207 result = acpi_bus_get_device(handle, &device); 191 return -EINVAL;
208 if (result)
209 return result;
210 192
211 *state = ACPI_STATE_UNKNOWN; 193 *state = ACPI_STATE_UNKNOWN;
212 194
213 if (!device->flags.power_manageable) { 195 if (device->flags.power_manageable) {
214 /* TBD: Non-recursive algorithm for walking up hierarchy */
215 if (device->parent)
216 *state = device->parent->power.state;
217 else
218 *state = ACPI_STATE_D0;
219 } else {
220 /* 196 /*
221 * Get the device's power state either directly (via _PSC) or 197 * Get the device's power state either directly (via _PSC) or
222 * indirectly (via power resources). 198 * indirectly (via power resources).
223 */ 199 */
224 if (device->power.flags.power_resources) { 200 if (device->power.flags.power_resources) {
225 result = acpi_power_get_inferred_state(device); 201 result = acpi_power_get_inferred_state(device, state);
226 if (result) 202 if (result)
227 return result; 203 return result;
228 } else if (device->power.flags.explicit_get) { 204 } else if (device->power.flags.explicit_get) {
@@ -230,59 +206,33 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
230 NULL, &psc); 206 NULL, &psc);
231 if (ACPI_FAILURE(status)) 207 if (ACPI_FAILURE(status))
232 return -ENODEV; 208 return -ENODEV;
233 device->power.state = (int)psc; 209 *state = (int)psc;
234 } 210 }
235 211 } else {
236 *state = device->power.state; 212 /* TBD: Non-recursive algorithm for walking up hierarchy. */
213 *state = device->parent ?
214 device->parent->power.state : ACPI_STATE_D0;
237 } 215 }
238 216
239 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", 217 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n",
240 device->pnp.bus_id, device->power.state)); 218 device->pnp.bus_id, *state));
241 219
242 return 0; 220 return 0;
243} 221}
244 222
245EXPORT_SYMBOL(acpi_bus_get_power);
246 223
247int acpi_bus_set_power(acpi_handle handle, int state) 224static int __acpi_bus_set_power(struct acpi_device *device, int state)
248{ 225{
249 int result = 0; 226 int result = 0;
250 acpi_status status = AE_OK; 227 acpi_status status = AE_OK;
251 struct acpi_device *device = NULL;
252 char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; 228 char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' };
253 229
254 230 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
255 result = acpi_bus_get_device(handle, &device);
256 if (result)
257 return result;
258
259 if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
260 return -EINVAL; 231 return -EINVAL;
261 232
262 /* Make sure this is a valid target state */ 233 /* Make sure this is a valid target state */
263 234
264 if (!device->flags.power_manageable) { 235 if (state == device->power.state) {
265 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
266 kobject_name(&device->dev.kobj)));
267 return -ENODEV;
268 }
269 /*
270 * Get device's current power state
271 */
272 if (!acpi_power_nocheck) {
273 /*
274 * Maybe the incorrect power state is returned on the bogus
275 * bios, which is different with the real power state.
276 * For example: the bios returns D0 state and the real power
277 * state is D3. OS expects to set the device to D0 state. In
278 * such case if OS uses the power state returned by the BIOS,
279 * the device can't be transisted to the correct power state.
280 * So if the acpi_power_nocheck is set, it is unnecessary to
281 * get the power state by calling acpi_bus_get_power.
282 */
283 acpi_bus_get_power(device->handle, &device->power.state);
284 }
285 if ((state == device->power.state) && !device->flags.force_power_state) {
286 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", 236 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
287 state)); 237 state));
288 return 0; 238 return 0;
@@ -351,8 +301,75 @@ int acpi_bus_set_power(acpi_handle handle, int state)
351 return result; 301 return result;
352} 302}
353 303
304
305int acpi_bus_set_power(acpi_handle handle, int state)
306{
307 struct acpi_device *device;
308 int result;
309
310 result = acpi_bus_get_device(handle, &device);
311 if (result)
312 return result;
313
314 if (!device->flags.power_manageable) {
315 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
316 "Device [%s] is not power manageable\n",
317 dev_name(&device->dev)));
318 return -ENODEV;
319 }
320
321 return __acpi_bus_set_power(device, state);
322}
354EXPORT_SYMBOL(acpi_bus_set_power); 323EXPORT_SYMBOL(acpi_bus_set_power);
355 324
325
326int acpi_bus_init_power(struct acpi_device *device)
327{
328 int state;
329 int result;
330
331 if (!device)
332 return -EINVAL;
333
334 device->power.state = ACPI_STATE_UNKNOWN;
335
336 result = __acpi_bus_get_power(device, &state);
337 if (result)
338 return result;
339
340 if (device->power.flags.power_resources)
341 result = acpi_power_on_resources(device, state);
342
343 if (!result)
344 device->power.state = state;
345
346 return result;
347}
348
349
350int acpi_bus_update_power(acpi_handle handle, int *state_p)
351{
352 struct acpi_device *device;
353 int state;
354 int result;
355
356 result = acpi_bus_get_device(handle, &device);
357 if (result)
358 return result;
359
360 result = __acpi_bus_get_power(device, &state);
361 if (result)
362 return result;
363
364 result = __acpi_bus_set_power(device, state);
365 if (!result && state_p)
366 *state_p = state;
367
368 return result;
369}
370EXPORT_SYMBOL_GPL(acpi_bus_update_power);
371
372
356bool acpi_bus_power_manageable(acpi_handle handle) 373bool acpi_bus_power_manageable(acpi_handle handle)
357{ 374{
358 struct acpi_device *device; 375 struct acpi_device *device;
@@ -935,6 +952,12 @@ static int __init acpi_bus_init(void)
935 goto error1; 952 goto error1;
936 } 953 }
937 954
955 /*
956 * _PDC control method may load dynamic SSDT tables,
957 * and we need to install the table handler before that.
958 */
959 acpi_sysfs_init();
960
938 acpi_early_processor_set_pdc(); 961 acpi_early_processor_set_pdc();
939 962
940 /* 963 /*
@@ -984,8 +1007,7 @@ struct kobject *acpi_kobj;
984 1007
985static int __init acpi_init(void) 1008static int __init acpi_init(void)
986{ 1009{
987 int result = 0; 1010 int result;
988
989 1011
990 if (acpi_disabled) { 1012 if (acpi_disabled) {
991 printk(KERN_INFO PREFIX "Interpreter disabled.\n"); 1013 printk(KERN_INFO PREFIX "Interpreter disabled.\n");
@@ -1000,37 +1022,18 @@ static int __init acpi_init(void)
1000 1022
1001 init_acpi_device_notify(); 1023 init_acpi_device_notify();
1002 result = acpi_bus_init(); 1024 result = acpi_bus_init();
1003 1025 if (result) {
1004 if (!result) {
1005 pci_mmcfg_late_init();
1006 if (!(pm_flags & PM_APM))
1007 pm_flags |= PM_ACPI;
1008 else {
1009 printk(KERN_INFO PREFIX
1010 "APM is already active, exiting\n");
1011 disable_acpi();
1012 result = -ENODEV;
1013 }
1014 } else
1015 disable_acpi(); 1026 disable_acpi();
1016
1017 if (acpi_disabled)
1018 return result; 1027 return result;
1028 }
1019 1029
1020 /* 1030 pci_mmcfg_late_init();
1021 * If the laptop falls into the DMI check table, the power state check
1022 * will be disabled in the course of device power transition.
1023 */
1024 dmi_check_system(power_nocheck_dmi_table);
1025
1026 acpi_scan_init(); 1031 acpi_scan_init();
1027 acpi_ec_init(); 1032 acpi_ec_init();
1028 acpi_power_init();
1029 acpi_sysfs_init();
1030 acpi_debugfs_init(); 1033 acpi_debugfs_init();
1031 acpi_sleep_proc_init(); 1034 acpi_sleep_proc_init();
1032 acpi_wakeup_device_init(); 1035 acpi_wakeup_device_init();
1033 return result; 1036 return 0;
1034} 1037}
1035 1038
1036subsys_initcall(acpi_init); 1039subsys_initcall(acpi_init);