diff options
Diffstat (limited to 'drivers/acpi')
37 files changed, 1891 insertions, 559 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 087a7028ae84..ccf6ea95f68c 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -50,7 +50,6 @@ config ACPI_SLEEP | |||
50 | config ACPI_PROCFS | 50 | config ACPI_PROCFS |
51 | bool "Deprecated /proc/acpi files" | 51 | bool "Deprecated /proc/acpi files" |
52 | depends on PROC_FS | 52 | depends on PROC_FS |
53 | default y | ||
54 | ---help--- | 53 | ---help--- |
55 | For backwards compatibility, this option allows | 54 | For backwards compatibility, this option allows |
56 | deprecated /proc/acpi/ files to exist, even when | 55 | deprecated /proc/acpi/ files to exist, even when |
@@ -61,7 +60,6 @@ config ACPI_PROCFS | |||
61 | /proc/acpi/info (/sys/modules/acpi/parameters/acpica_version) | 60 | /proc/acpi/info (/sys/modules/acpi/parameters/acpica_version) |
62 | /proc/acpi/dsdt (/sys/firmware/acpi/tables/DSDT) | 61 | /proc/acpi/dsdt (/sys/firmware/acpi/tables/DSDT) |
63 | /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) | 62 | /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) |
64 | /proc/acpi/battery (/sys/class/power_supply) | ||
65 | /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) | 63 | /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) |
66 | /proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level) | 64 | /proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level) |
67 | 65 | ||
@@ -69,7 +67,27 @@ config ACPI_PROCFS | |||
69 | and functions which do not yet exist in /sys. | 67 | and functions which do not yet exist in /sys. |
70 | 68 | ||
71 | Say N to delete /proc/acpi/ files that have moved to /sys/ | 69 | Say N to delete /proc/acpi/ files that have moved to /sys/ |
72 | 70 | config ACPI_PROCFS_POWER | |
71 | bool "Deprecated power /proc/acpi folders" | ||
72 | depends on PROC_FS | ||
73 | default y | ||
74 | ---help--- | ||
75 | For backwards compatibility, this option allows | ||
76 | deprecated power /proc/acpi/ folders to exist, even when | ||
77 | they have been replaced by functions in /sys. | ||
78 | The deprecated folders (and their replacements) include: | ||
79 | /proc/acpi/battery/* (/sys/class/power_supply/*) | ||
80 | /proc/acpi/ac_adapter/* (sys/class/power_supply/*) | ||
81 | This option has no effect on /proc/acpi/ folders | ||
82 | and functions, which do not yet exist in /sys | ||
83 | |||
84 | Say N to delete power /proc/acpi/ folders that have moved to /sys/ | ||
85 | config ACPI_SYSFS_POWER | ||
86 | bool "Future power /sys interface" | ||
87 | select POWER_SUPPLY | ||
88 | default y | ||
89 | ---help--- | ||
90 | Say N to disable power /sys interface | ||
73 | config ACPI_PROC_EVENT | 91 | config ACPI_PROC_EVENT |
74 | bool "Deprecated /proc/acpi/event support" | 92 | bool "Deprecated /proc/acpi/event support" |
75 | depends on PROC_FS | 93 | depends on PROC_FS |
@@ -91,7 +109,6 @@ config ACPI_PROC_EVENT | |||
91 | config ACPI_AC | 109 | config ACPI_AC |
92 | tristate "AC Adapter" | 110 | tristate "AC Adapter" |
93 | depends on X86 | 111 | depends on X86 |
94 | select POWER_SUPPLY | ||
95 | default y | 112 | default y |
96 | help | 113 | help |
97 | This driver adds support for the AC Adapter object, which indicates | 114 | This driver adds support for the AC Adapter object, which indicates |
@@ -101,7 +118,6 @@ config ACPI_AC | |||
101 | config ACPI_BATTERY | 118 | config ACPI_BATTERY |
102 | tristate "Battery" | 119 | tristate "Battery" |
103 | depends on X86 | 120 | depends on X86 |
104 | select POWER_SUPPLY | ||
105 | default y | 121 | default y |
106 | help | 122 | help |
107 | This driver adds support for battery information through | 123 | This driver adds support for battery information through |
@@ -356,7 +372,6 @@ config ACPI_HOTPLUG_MEMORY | |||
356 | config ACPI_SBS | 372 | config ACPI_SBS |
357 | tristate "Smart Battery System" | 373 | tristate "Smart Battery System" |
358 | depends on X86 | 374 | depends on X86 |
359 | select POWER_SUPPLY | ||
360 | help | 375 | help |
361 | This driver adds support for the Smart Battery System, another | 376 | This driver adds support for the Smart Battery System, another |
362 | type of access to battery information, found on some laptops. | 377 | type of access to battery information, found on some laptops. |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 54e3ab0e5fc0..456446f90077 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -58,6 +58,6 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o | |||
58 | obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o | 58 | obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o |
59 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o | 59 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o |
60 | obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o | 60 | obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o |
61 | obj-y += cm_sbs.o | 61 | obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o |
62 | obj-$(CONFIG_ACPI_SBS) += sbs.o | 62 | obj-$(CONFIG_ACPI_SBS) += sbs.o |
63 | obj-$(CONFIG_ACPI_SBS) += sbshc.o | 63 | obj-$(CONFIG_ACPI_SBS) += sbshc.o |
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 30238f6ff232..76b9bea98b6d 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
@@ -27,11 +27,13 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | #ifdef CONFIG_ACPI_PROCFS | 30 | #ifdef CONFIG_ACPI_PROCFS_POWER |
31 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
33 | #endif | 33 | #endif |
34 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
34 | #include <linux/power_supply.h> | 35 | #include <linux/power_supply.h> |
36 | #endif | ||
35 | #include <acpi/acpi_bus.h> | 37 | #include <acpi/acpi_bus.h> |
36 | #include <acpi/acpi_drivers.h> | 38 | #include <acpi/acpi_drivers.h> |
37 | 39 | ||
@@ -51,7 +53,7 @@ MODULE_AUTHOR("Paul Diefenbaugh"); | |||
51 | MODULE_DESCRIPTION("ACPI AC Adapter Driver"); | 53 | MODULE_DESCRIPTION("ACPI AC Adapter Driver"); |
52 | MODULE_LICENSE("GPL"); | 54 | MODULE_LICENSE("GPL"); |
53 | 55 | ||
54 | #ifdef CONFIG_ACPI_PROCFS | 56 | #ifdef CONFIG_ACPI_PROCFS_POWER |
55 | extern struct proc_dir_entry *acpi_lock_ac_dir(void); | 57 | extern struct proc_dir_entry *acpi_lock_ac_dir(void); |
56 | extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); | 58 | extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); |
57 | static int acpi_ac_open_fs(struct inode *inode, struct file *file); | 59 | static int acpi_ac_open_fs(struct inode *inode, struct file *file); |
@@ -79,14 +81,16 @@ static struct acpi_driver acpi_ac_driver = { | |||
79 | }; | 81 | }; |
80 | 82 | ||
81 | struct acpi_ac { | 83 | struct acpi_ac { |
84 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
82 | struct power_supply charger; | 85 | struct power_supply charger; |
86 | #endif | ||
83 | struct acpi_device * device; | 87 | struct acpi_device * device; |
84 | unsigned long state; | 88 | unsigned long state; |
85 | }; | 89 | }; |
86 | 90 | ||
87 | #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); | 91 | #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); |
88 | 92 | ||
89 | #ifdef CONFIG_ACPI_PROCFS | 93 | #ifdef CONFIG_ACPI_PROCFS_POWER |
90 | static const struct file_operations acpi_ac_fops = { | 94 | static const struct file_operations acpi_ac_fops = { |
91 | .open = acpi_ac_open_fs, | 95 | .open = acpi_ac_open_fs, |
92 | .read = seq_read, | 96 | .read = seq_read, |
@@ -94,7 +98,7 @@ static const struct file_operations acpi_ac_fops = { | |||
94 | .release = single_release, | 98 | .release = single_release, |
95 | }; | 99 | }; |
96 | #endif | 100 | #endif |
97 | 101 | #ifdef CONFIG_ACPI_SYSFS_POWER | |
98 | static int get_ac_property(struct power_supply *psy, | 102 | static int get_ac_property(struct power_supply *psy, |
99 | enum power_supply_property psp, | 103 | enum power_supply_property psp, |
100 | union power_supply_propval *val) | 104 | union power_supply_propval *val) |
@@ -113,7 +117,7 @@ static int get_ac_property(struct power_supply *psy, | |||
113 | static enum power_supply_property ac_props[] = { | 117 | static enum power_supply_property ac_props[] = { |
114 | POWER_SUPPLY_PROP_ONLINE, | 118 | POWER_SUPPLY_PROP_ONLINE, |
115 | }; | 119 | }; |
116 | 120 | #endif | |
117 | /* -------------------------------------------------------------------------- | 121 | /* -------------------------------------------------------------------------- |
118 | AC Adapter Management | 122 | AC Adapter Management |
119 | -------------------------------------------------------------------------- */ | 123 | -------------------------------------------------------------------------- */ |
@@ -136,7 +140,7 @@ static int acpi_ac_get_state(struct acpi_ac *ac) | |||
136 | return 0; | 140 | return 0; |
137 | } | 141 | } |
138 | 142 | ||
139 | #ifdef CONFIG_ACPI_PROCFS | 143 | #ifdef CONFIG_ACPI_PROCFS_POWER |
140 | /* -------------------------------------------------------------------------- | 144 | /* -------------------------------------------------------------------------- |
141 | FS Interface (/proc) | 145 | FS Interface (/proc) |
142 | -------------------------------------------------------------------------- */ | 146 | -------------------------------------------------------------------------- */ |
@@ -241,7 +245,9 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) | |||
241 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 245 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
242 | device->dev.bus_id, event, | 246 | device->dev.bus_id, event, |
243 | (u32) ac->state); | 247 | (u32) ac->state); |
248 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
244 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); | 249 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); |
250 | #endif | ||
245 | break; | 251 | break; |
246 | default: | 252 | default: |
247 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 253 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
@@ -275,17 +281,19 @@ static int acpi_ac_add(struct acpi_device *device) | |||
275 | if (result) | 281 | if (result) |
276 | goto end; | 282 | goto end; |
277 | 283 | ||
278 | #ifdef CONFIG_ACPI_PROCFS | 284 | #ifdef CONFIG_ACPI_PROCFS_POWER |
279 | result = acpi_ac_add_fs(device); | 285 | result = acpi_ac_add_fs(device); |
280 | #endif | 286 | #endif |
281 | if (result) | 287 | if (result) |
282 | goto end; | 288 | goto end; |
289 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
283 | ac->charger.name = acpi_device_bid(device); | 290 | ac->charger.name = acpi_device_bid(device); |
284 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; | 291 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; |
285 | ac->charger.properties = ac_props; | 292 | ac->charger.properties = ac_props; |
286 | ac->charger.num_properties = ARRAY_SIZE(ac_props); | 293 | ac->charger.num_properties = ARRAY_SIZE(ac_props); |
287 | ac->charger.get_property = get_ac_property; | 294 | ac->charger.get_property = get_ac_property; |
288 | power_supply_register(&ac->device->dev, &ac->charger); | 295 | power_supply_register(&ac->device->dev, &ac->charger); |
296 | #endif | ||
289 | status = acpi_install_notify_handler(device->handle, | 297 | status = acpi_install_notify_handler(device->handle, |
290 | ACPI_ALL_NOTIFY, acpi_ac_notify, | 298 | ACPI_ALL_NOTIFY, acpi_ac_notify, |
291 | ac); | 299 | ac); |
@@ -300,7 +308,7 @@ static int acpi_ac_add(struct acpi_device *device) | |||
300 | 308 | ||
301 | end: | 309 | end: |
302 | if (result) { | 310 | if (result) { |
303 | #ifdef CONFIG_ACPI_PROCFS | 311 | #ifdef CONFIG_ACPI_PROCFS_POWER |
304 | acpi_ac_remove_fs(device); | 312 | acpi_ac_remove_fs(device); |
305 | #endif | 313 | #endif |
306 | kfree(ac); | 314 | kfree(ac); |
@@ -319,8 +327,10 @@ static int acpi_ac_resume(struct acpi_device *device) | |||
319 | old_state = ac->state; | 327 | old_state = ac->state; |
320 | if (acpi_ac_get_state(ac)) | 328 | if (acpi_ac_get_state(ac)) |
321 | return 0; | 329 | return 0; |
330 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
322 | if (old_state != ac->state) | 331 | if (old_state != ac->state) |
323 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); | 332 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); |
333 | #endif | ||
324 | return 0; | 334 | return 0; |
325 | } | 335 | } |
326 | 336 | ||
@@ -337,9 +347,11 @@ static int acpi_ac_remove(struct acpi_device *device, int type) | |||
337 | 347 | ||
338 | status = acpi_remove_notify_handler(device->handle, | 348 | status = acpi_remove_notify_handler(device->handle, |
339 | ACPI_ALL_NOTIFY, acpi_ac_notify); | 349 | ACPI_ALL_NOTIFY, acpi_ac_notify); |
350 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
340 | if (ac->charger.dev) | 351 | if (ac->charger.dev) |
341 | power_supply_unregister(&ac->charger); | 352 | power_supply_unregister(&ac->charger); |
342 | #ifdef CONFIG_ACPI_PROCFS | 353 | #endif |
354 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
343 | acpi_ac_remove_fs(device); | 355 | acpi_ac_remove_fs(device); |
344 | #endif | 356 | #endif |
345 | 357 | ||
@@ -355,7 +367,7 @@ static int __init acpi_ac_init(void) | |||
355 | if (acpi_disabled) | 367 | if (acpi_disabled) |
356 | return -ENODEV; | 368 | return -ENODEV; |
357 | 369 | ||
358 | #ifdef CONFIG_ACPI_PROCFS | 370 | #ifdef CONFIG_ACPI_PROCFS_POWER |
359 | acpi_ac_dir = acpi_lock_ac_dir(); | 371 | acpi_ac_dir = acpi_lock_ac_dir(); |
360 | if (!acpi_ac_dir) | 372 | if (!acpi_ac_dir) |
361 | return -ENODEV; | 373 | return -ENODEV; |
@@ -363,7 +375,7 @@ static int __init acpi_ac_init(void) | |||
363 | 375 | ||
364 | result = acpi_bus_register_driver(&acpi_ac_driver); | 376 | result = acpi_bus_register_driver(&acpi_ac_driver); |
365 | if (result < 0) { | 377 | if (result < 0) { |
366 | #ifdef CONFIG_ACPI_PROCFS | 378 | #ifdef CONFIG_ACPI_PROCFS_POWER |
367 | acpi_unlock_ac_dir(acpi_ac_dir); | 379 | acpi_unlock_ac_dir(acpi_ac_dir); |
368 | #endif | 380 | #endif |
369 | return -ENODEV; | 381 | return -ENODEV; |
@@ -377,7 +389,7 @@ static void __exit acpi_ac_exit(void) | |||
377 | 389 | ||
378 | acpi_bus_unregister_driver(&acpi_ac_driver); | 390 | acpi_bus_unregister_driver(&acpi_ac_driver); |
379 | 391 | ||
380 | #ifdef CONFIG_ACPI_PROCFS | 392 | #ifdef CONFIG_ACPI_PROCFS_POWER |
381 | acpi_unlock_ac_dir(acpi_ac_dir); | 393 | acpi_unlock_ac_dir(acpi_ac_dir); |
382 | #endif | 394 | #endif |
383 | 395 | ||
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index d915fec9bf63..d25ef961415c 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c | |||
@@ -142,6 +142,7 @@ struct asus_hotk { | |||
142 | xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N | 142 | xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N |
143 | A4S, //Z81sp | 143 | A4S, //Z81sp |
144 | //(Centrino) | 144 | //(Centrino) |
145 | F3Sa, | ||
145 | END_MODEL | 146 | END_MODEL |
146 | } model; //Models currently supported | 147 | } model; //Models currently supported |
147 | u16 event_count[128]; //count for each event TODO make this better | 148 | u16 event_count[128]; //count for each event TODO make this better |
@@ -405,7 +406,20 @@ static struct model_data model_conf[END_MODEL] = { | |||
405 | .brightness_get = "GPLV", | 406 | .brightness_get = "GPLV", |
406 | .mt_bt_switch = "BLED", | 407 | .mt_bt_switch = "BLED", |
407 | .mt_wled = "WLED" | 408 | .mt_wled = "WLED" |
408 | } | 409 | }, |
410 | |||
411 | { | ||
412 | .name = "F3Sa", | ||
413 | .mt_bt_switch = "BLED", | ||
414 | .mt_wled = "WLED", | ||
415 | .mt_mled = "MLED", | ||
416 | .brightness_get = "GPLV", | ||
417 | .brightness_set = "SPLV", | ||
418 | .mt_lcd_switch = "\\_SB.PCI0.SBRG.EC0._Q10", | ||
419 | .lcd_status = "\\_SB.PCI0.SBRG.EC0.RPIN", | ||
420 | .display_get = "\\ADVG", | ||
421 | .display_set = "SDSP", | ||
422 | }, | ||
409 | 423 | ||
410 | }; | 424 | }; |
411 | 425 | ||
@@ -710,15 +724,8 @@ static int get_lcd_state(void) | |||
710 | { | 724 | { |
711 | int lcd = 0; | 725 | int lcd = 0; |
712 | 726 | ||
713 | if (hotk->model != L3H) { | 727 | if (hotk->model == L3H) { |
714 | /* We don't have to check anything if we are here */ | 728 | /* L3H and the like have to be handled differently */ |
715 | if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) | ||
716 | printk(KERN_WARNING | ||
717 | "Asus ACPI: Error reading LCD status\n"); | ||
718 | |||
719 | if (hotk->model == L2D) | ||
720 | lcd = ~lcd; | ||
721 | } else { /* L3H and the like have to be handled differently */ | ||
722 | acpi_status status = 0; | 729 | acpi_status status = 0; |
723 | struct acpi_object_list input; | 730 | struct acpi_object_list input; |
724 | union acpi_object mt_params[2]; | 731 | union acpi_object mt_params[2]; |
@@ -745,6 +752,32 @@ static int get_lcd_state(void) | |||
745 | if (out_obj.type == ACPI_TYPE_INTEGER) | 752 | if (out_obj.type == ACPI_TYPE_INTEGER) |
746 | /* That's what the AML code does */ | 753 | /* That's what the AML code does */ |
747 | lcd = out_obj.integer.value >> 8; | 754 | lcd = out_obj.integer.value >> 8; |
755 | } else if (hotk->model == F3Sa) { | ||
756 | unsigned long tmp; | ||
757 | union acpi_object param; | ||
758 | struct acpi_object_list input; | ||
759 | acpi_status status; | ||
760 | |||
761 | /* Read pin 11 */ | ||
762 | param.type = ACPI_TYPE_INTEGER; | ||
763 | param.integer.value = 0x11; | ||
764 | input.count = 1; | ||
765 | input.pointer = ¶m; | ||
766 | |||
767 | status = acpi_evaluate_integer(NULL, hotk->methods->lcd_status, | ||
768 | &input, &tmp); | ||
769 | if (status != AE_OK) | ||
770 | return -1; | ||
771 | |||
772 | lcd = tmp; | ||
773 | } else { | ||
774 | /* We don't have to check anything if we are here */ | ||
775 | if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) | ||
776 | printk(KERN_WARNING | ||
777 | "Asus ACPI: Error reading LCD status\n"); | ||
778 | |||
779 | if (hotk->model == L2D) | ||
780 | lcd = ~lcd; | ||
748 | } | 781 | } |
749 | 782 | ||
750 | return (lcd & 1); | 783 | return (lcd & 1); |
@@ -1134,6 +1167,8 @@ static int asus_model_match(char *model) | |||
1134 | return W5A; | 1167 | return W5A; |
1135 | else if (strncmp(model, "A4S", 3) == 0) | 1168 | else if (strncmp(model, "A4S", 3) == 0) |
1136 | return A4S; | 1169 | return A4S; |
1170 | else if (strncmp(model, "F3Sa", 4) == 0) | ||
1171 | return F3Sa; | ||
1137 | else | 1172 | else |
1138 | return END_MODEL; | 1173 | return END_MODEL; |
1139 | } | 1174 | } |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 192c244f6190..f6215e809808 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
32 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
33 | 33 | ||
34 | #ifdef CONFIG_ACPI_PROCFS | 34 | #ifdef CONFIG_ACPI_PROCFS_POWER |
35 | #include <linux/proc_fs.h> | 35 | #include <linux/proc_fs.h> |
36 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
@@ -40,7 +40,9 @@ | |||
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 | 42 | ||
43 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
43 | #include <linux/power_supply.h> | 44 | #include <linux/power_supply.h> |
45 | #endif | ||
44 | 46 | ||
45 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF | 47 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF |
46 | 48 | ||
@@ -63,7 +65,7 @@ static unsigned int cache_time = 1000; | |||
63 | module_param(cache_time, uint, 0644); | 65 | module_param(cache_time, uint, 0644); |
64 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); | 66 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); |
65 | 67 | ||
66 | #ifdef CONFIG_ACPI_PROCFS | 68 | #ifdef CONFIG_ACPI_PROCFS_POWER |
67 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); | 69 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); |
68 | extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); | 70 | extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); |
69 | 71 | ||
@@ -86,7 +88,9 @@ MODULE_DEVICE_TABLE(acpi, battery_device_ids); | |||
86 | 88 | ||
87 | struct acpi_battery { | 89 | struct acpi_battery { |
88 | struct mutex lock; | 90 | struct mutex lock; |
91 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
89 | struct power_supply bat; | 92 | struct power_supply bat; |
93 | #endif | ||
90 | struct acpi_device *device; | 94 | struct acpi_device *device; |
91 | unsigned long update_time; | 95 | unsigned long update_time; |
92 | int current_now; | 96 | int current_now; |
@@ -117,6 +121,7 @@ inline int acpi_battery_present(struct acpi_battery *battery) | |||
117 | return battery->device->status.battery_present; | 121 | return battery->device->status.battery_present; |
118 | } | 122 | } |
119 | 123 | ||
124 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
120 | static int acpi_battery_technology(struct acpi_battery *battery) | 125 | static int acpi_battery_technology(struct acpi_battery *battery) |
121 | { | 126 | { |
122 | if (!strcasecmp("NiCd", battery->type)) | 127 | if (!strcasecmp("NiCd", battery->type)) |
@@ -125,7 +130,7 @@ static int acpi_battery_technology(struct acpi_battery *battery) | |||
125 | return POWER_SUPPLY_TECHNOLOGY_NiMH; | 130 | return POWER_SUPPLY_TECHNOLOGY_NiMH; |
126 | if (!strcasecmp("LION", battery->type)) | 131 | if (!strcasecmp("LION", battery->type)) |
127 | return POWER_SUPPLY_TECHNOLOGY_LION; | 132 | return POWER_SUPPLY_TECHNOLOGY_LION; |
128 | if (!strcasecmp("LI-ION", battery->type)) | 133 | if (!strncasecmp("LI-ION", battery->type, 6)) |
129 | return POWER_SUPPLY_TECHNOLOGY_LION; | 134 | return POWER_SUPPLY_TECHNOLOGY_LION; |
130 | if (!strcasecmp("LiP", battery->type)) | 135 | if (!strcasecmp("LiP", battery->type)) |
131 | return POWER_SUPPLY_TECHNOLOGY_LIPO; | 136 | return POWER_SUPPLY_TECHNOLOGY_LIPO; |
@@ -153,6 +158,8 @@ static int acpi_battery_get_property(struct power_supply *psy, | |||
153 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | 158 | val->intval = POWER_SUPPLY_STATUS_CHARGING; |
154 | else if (battery->state == 0) | 159 | else if (battery->state == 0) |
155 | val->intval = POWER_SUPPLY_STATUS_FULL; | 160 | val->intval = POWER_SUPPLY_STATUS_FULL; |
161 | else | ||
162 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
156 | break; | 163 | break; |
157 | case POWER_SUPPLY_PROP_PRESENT: | 164 | case POWER_SUPPLY_PROP_PRESENT: |
158 | val->intval = acpi_battery_present(battery); | 165 | val->intval = acpi_battery_present(battery); |
@@ -187,6 +194,9 @@ static int acpi_battery_get_property(struct power_supply *psy, | |||
187 | case POWER_SUPPLY_PROP_MANUFACTURER: | 194 | case POWER_SUPPLY_PROP_MANUFACTURER: |
188 | val->strval = battery->oem_info; | 195 | val->strval = battery->oem_info; |
189 | break; | 196 | break; |
197 | case POWER_SUPPLY_PROP_SERIAL_NUMBER: | ||
198 | val->strval = battery->serial_number; | ||
199 | break; | ||
190 | default: | 200 | default: |
191 | return -EINVAL; | 201 | return -EINVAL; |
192 | } | 202 | } |
@@ -205,6 +215,7 @@ static enum power_supply_property charge_battery_props[] = { | |||
205 | POWER_SUPPLY_PROP_CHARGE_NOW, | 215 | POWER_SUPPLY_PROP_CHARGE_NOW, |
206 | POWER_SUPPLY_PROP_MODEL_NAME, | 216 | POWER_SUPPLY_PROP_MODEL_NAME, |
207 | POWER_SUPPLY_PROP_MANUFACTURER, | 217 | POWER_SUPPLY_PROP_MANUFACTURER, |
218 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | ||
208 | }; | 219 | }; |
209 | 220 | ||
210 | static enum power_supply_property energy_battery_props[] = { | 221 | static enum power_supply_property energy_battery_props[] = { |
@@ -219,9 +230,11 @@ static enum power_supply_property energy_battery_props[] = { | |||
219 | POWER_SUPPLY_PROP_ENERGY_NOW, | 230 | POWER_SUPPLY_PROP_ENERGY_NOW, |
220 | POWER_SUPPLY_PROP_MODEL_NAME, | 231 | POWER_SUPPLY_PROP_MODEL_NAME, |
221 | POWER_SUPPLY_PROP_MANUFACTURER, | 232 | POWER_SUPPLY_PROP_MANUFACTURER, |
233 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | ||
222 | }; | 234 | }; |
235 | #endif | ||
223 | 236 | ||
224 | #ifdef CONFIG_ACPI_PROCFS | 237 | #ifdef CONFIG_ACPI_PROCFS_POWER |
225 | inline char *acpi_battery_units(struct acpi_battery *battery) | 238 | inline char *acpi_battery_units(struct acpi_battery *battery) |
226 | { | 239 | { |
227 | return (battery->power_unit)?"mA":"mW"; | 240 | return (battery->power_unit)?"mA":"mW"; |
@@ -396,6 +409,7 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) | |||
396 | return acpi_battery_set_alarm(battery); | 409 | return acpi_battery_set_alarm(battery); |
397 | } | 410 | } |
398 | 411 | ||
412 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
399 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 413 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
400 | struct device_attribute *attr, | 414 | struct device_attribute *attr, |
401 | char *buf) | 415 | char *buf) |
@@ -427,11 +441,6 @@ static int sysfs_add_battery(struct acpi_battery *battery) | |||
427 | { | 441 | { |
428 | int result; | 442 | int result; |
429 | 443 | ||
430 | battery->update_time = 0; | ||
431 | result = acpi_battery_get_info(battery); | ||
432 | acpi_battery_init_alarm(battery); | ||
433 | if (result) | ||
434 | return result; | ||
435 | if (battery->power_unit) { | 444 | if (battery->power_unit) { |
436 | battery->bat.properties = charge_battery_props; | 445 | battery->bat.properties = charge_battery_props; |
437 | battery->bat.num_properties = | 446 | battery->bat.num_properties = |
@@ -460,18 +469,31 @@ static void sysfs_remove_battery(struct acpi_battery *battery) | |||
460 | power_supply_unregister(&battery->bat); | 469 | power_supply_unregister(&battery->bat); |
461 | battery->bat.dev = NULL; | 470 | battery->bat.dev = NULL; |
462 | } | 471 | } |
472 | #endif | ||
463 | 473 | ||
464 | static int acpi_battery_update(struct acpi_battery *battery) | 474 | static int acpi_battery_update(struct acpi_battery *battery) |
465 | { | 475 | { |
466 | int result = acpi_battery_get_status(battery); | 476 | int result; |
477 | result = acpi_battery_get_status(battery); | ||
467 | if (result) | 478 | if (result) |
468 | return result; | 479 | return result; |
480 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
469 | if (!acpi_battery_present(battery)) { | 481 | if (!acpi_battery_present(battery)) { |
470 | sysfs_remove_battery(battery); | 482 | sysfs_remove_battery(battery); |
483 | battery->update_time = 0; | ||
471 | return 0; | 484 | return 0; |
472 | } | 485 | } |
486 | #endif | ||
487 | if (!battery->update_time) { | ||
488 | result = acpi_battery_get_info(battery); | ||
489 | if (result) | ||
490 | return result; | ||
491 | acpi_battery_init_alarm(battery); | ||
492 | } | ||
493 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
473 | if (!battery->bat.dev) | 494 | if (!battery->bat.dev) |
474 | sysfs_add_battery(battery); | 495 | sysfs_add_battery(battery); |
496 | #endif | ||
475 | return acpi_battery_get_state(battery); | 497 | return acpi_battery_get_state(battery); |
476 | } | 498 | } |
477 | 499 | ||
@@ -479,7 +501,7 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
479 | FS Interface (/proc) | 501 | FS Interface (/proc) |
480 | -------------------------------------------------------------------------- */ | 502 | -------------------------------------------------------------------------- */ |
481 | 503 | ||
482 | #ifdef CONFIG_ACPI_PROCFS | 504 | #ifdef CONFIG_ACPI_PROCFS_POWER |
483 | static struct proc_dir_entry *acpi_battery_dir; | 505 | static struct proc_dir_entry *acpi_battery_dir; |
484 | 506 | ||
485 | static int acpi_battery_print_info(struct seq_file *seq, int result) | 507 | static int acpi_battery_print_info(struct seq_file *seq, int result) |
@@ -765,9 +787,11 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
765 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 787 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
766 | device->dev.bus_id, event, | 788 | device->dev.bus_id, event, |
767 | acpi_battery_present(battery)); | 789 | acpi_battery_present(battery)); |
790 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
768 | /* acpi_batter_update could remove power_supply object */ | 791 | /* acpi_batter_update could remove power_supply object */ |
769 | if (battery->bat.dev) | 792 | if (battery->bat.dev) |
770 | kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); | 793 | kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); |
794 | #endif | ||
771 | } | 795 | } |
772 | 796 | ||
773 | static int acpi_battery_add(struct acpi_device *device) | 797 | static int acpi_battery_add(struct acpi_device *device) |
@@ -786,7 +810,7 @@ static int acpi_battery_add(struct acpi_device *device) | |||
786 | acpi_driver_data(device) = battery; | 810 | acpi_driver_data(device) = battery; |
787 | mutex_init(&battery->lock); | 811 | mutex_init(&battery->lock); |
788 | acpi_battery_update(battery); | 812 | acpi_battery_update(battery); |
789 | #ifdef CONFIG_ACPI_PROCFS | 813 | #ifdef CONFIG_ACPI_PROCFS_POWER |
790 | result = acpi_battery_add_fs(device); | 814 | result = acpi_battery_add_fs(device); |
791 | if (result) | 815 | if (result) |
792 | goto end; | 816 | goto end; |
@@ -804,7 +828,7 @@ static int acpi_battery_add(struct acpi_device *device) | |||
804 | device->status.battery_present ? "present" : "absent"); | 828 | device->status.battery_present ? "present" : "absent"); |
805 | end: | 829 | end: |
806 | if (result) { | 830 | if (result) { |
807 | #ifdef CONFIG_ACPI_PROCFS | 831 | #ifdef CONFIG_ACPI_PROCFS_POWER |
808 | acpi_battery_remove_fs(device); | 832 | acpi_battery_remove_fs(device); |
809 | #endif | 833 | #endif |
810 | kfree(battery); | 834 | kfree(battery); |
@@ -823,10 +847,12 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
823 | status = acpi_remove_notify_handler(device->handle, | 847 | status = acpi_remove_notify_handler(device->handle, |
824 | ACPI_ALL_NOTIFY, | 848 | ACPI_ALL_NOTIFY, |
825 | acpi_battery_notify); | 849 | acpi_battery_notify); |
826 | #ifdef CONFIG_ACPI_PROCFS | 850 | #ifdef CONFIG_ACPI_PROCFS_POWER |
827 | acpi_battery_remove_fs(device); | 851 | acpi_battery_remove_fs(device); |
828 | #endif | 852 | #endif |
853 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
829 | sysfs_remove_battery(battery); | 854 | sysfs_remove_battery(battery); |
855 | #endif | ||
830 | mutex_destroy(&battery->lock); | 856 | mutex_destroy(&battery->lock); |
831 | kfree(battery); | 857 | kfree(battery); |
832 | return 0; | 858 | return 0; |
@@ -859,13 +885,13 @@ static int __init acpi_battery_init(void) | |||
859 | { | 885 | { |
860 | if (acpi_disabled) | 886 | if (acpi_disabled) |
861 | return -ENODEV; | 887 | return -ENODEV; |
862 | #ifdef CONFIG_ACPI_PROCFS | 888 | #ifdef CONFIG_ACPI_PROCFS_POWER |
863 | acpi_battery_dir = acpi_lock_battery_dir(); | 889 | acpi_battery_dir = acpi_lock_battery_dir(); |
864 | if (!acpi_battery_dir) | 890 | if (!acpi_battery_dir) |
865 | return -ENODEV; | 891 | return -ENODEV; |
866 | #endif | 892 | #endif |
867 | if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { | 893 | if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { |
868 | #ifdef CONFIG_ACPI_PROCFS | 894 | #ifdef CONFIG_ACPI_PROCFS_POWER |
869 | acpi_unlock_battery_dir(acpi_battery_dir); | 895 | acpi_unlock_battery_dir(acpi_battery_dir); |
870 | #endif | 896 | #endif |
871 | return -ENODEV; | 897 | return -ENODEV; |
@@ -876,7 +902,7 @@ static int __init acpi_battery_init(void) | |||
876 | static void __exit acpi_battery_exit(void) | 902 | static void __exit acpi_battery_exit(void) |
877 | { | 903 | { |
878 | acpi_bus_unregister_driver(&acpi_battery_driver); | 904 | acpi_bus_unregister_driver(&acpi_battery_driver); |
879 | #ifdef CONFIG_ACPI_PROCFS | 905 | #ifdef CONFIG_ACPI_PROCFS_POWER |
880 | acpi_unlock_battery_dir(acpi_battery_dir); | 906 | acpi_unlock_battery_dir(acpi_battery_dir); |
881 | #endif | 907 | #endif |
882 | } | 908 | } |
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index 6daf6088ac88..477711435b24 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c | |||
@@ -46,6 +46,12 @@ MODULE_LICENSE("GPL"); | |||
46 | printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } | 46 | printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } |
47 | static void bay_notify(acpi_handle handle, u32 event, void *data); | 47 | static void bay_notify(acpi_handle handle, u32 event, void *data); |
48 | 48 | ||
49 | static const struct acpi_device_id bay_device_ids[] = { | ||
50 | {"LNXIOBAY", 0}, | ||
51 | {"", 0}, | ||
52 | }; | ||
53 | MODULE_DEVICE_TABLE(acpi, bay_device_ids); | ||
54 | |||
49 | struct bay { | 55 | struct bay { |
50 | acpi_handle handle; | 56 | acpi_handle handle; |
51 | char *name; | 57 | char *name; |
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 3ec110ce00c8..3ade01680989 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Check to see if the given machine has a known bad ACPI BIOS | 4 | * Check to see if the given machine has a known bad ACPI BIOS |
5 | * or if the BIOS is too old. | 5 | * or if the BIOS is too old. |
6 | * Check given machine against acpi_osi_dmi_table[]. | ||
6 | * | 7 | * |
7 | * Copyright (C) 2004 Len Brown <len.brown@intel.com> | 8 | * Copyright (C) 2004 Len Brown <len.brown@intel.com> |
8 | * Copyright (C) 2002 Andy Grover <andrew.grover@intel.com> | 9 | * Copyright (C) 2002 Andy Grover <andrew.grover@intel.com> |
@@ -50,6 +51,8 @@ struct acpi_blacklist_item { | |||
50 | u32 is_critical_error; | 51 | u32 is_critical_error; |
51 | }; | 52 | }; |
52 | 53 | ||
54 | static struct dmi_system_id acpi_osi_dmi_table[] __initdata; | ||
55 | |||
53 | /* | 56 | /* |
54 | * POLICY: If *anything* doesn't work, put it on the blacklist. | 57 | * POLICY: If *anything* doesn't work, put it on the blacklist. |
55 | * If they are critical errors, mark it critical, and abort driver load. | 58 | * If they are critical errors, mark it critical, and abort driver load. |
@@ -67,8 +70,6 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = { | |||
67 | /* IBM 600E - _ADR should return 7, but it returns 1 */ | 70 | /* IBM 600E - _ADR should return 7, but it returns 1 */ |
68 | {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, | 71 | {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, |
69 | "Incorrect _ADR", 1}, | 72 | "Incorrect _ADR", 1}, |
70 | {"ASUS\0\0", "P2B-S ", 0, ACPI_SIG_DSDT, all_versions, | ||
71 | "Bogus PCI routing", 1}, | ||
72 | 73 | ||
73 | {""} | 74 | {""} |
74 | }; | 75 | }; |
@@ -165,5 +166,383 @@ int __init acpi_blacklisted(void) | |||
165 | 166 | ||
166 | blacklisted += blacklist_by_year(); | 167 | blacklisted += blacklist_by_year(); |
167 | 168 | ||
169 | dmi_check_system(acpi_osi_dmi_table); | ||
170 | |||
168 | return blacklisted; | 171 | return blacklisted; |
169 | } | 172 | } |
173 | #ifdef CONFIG_DMI | ||
174 | static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) | ||
175 | { | ||
176 | acpi_dmi_osi_linux(1, d); /* enable */ | ||
177 | return 0; | ||
178 | } | ||
179 | static int __init dmi_disable_osi_linux(const struct dmi_system_id *d) | ||
180 | { | ||
181 | acpi_dmi_osi_linux(0, d); /* disable */ | ||
182 | return 0; | ||
183 | } | ||
184 | static int __init dmi_unknown_osi_linux(const struct dmi_system_id *d) | ||
185 | { | ||
186 | acpi_dmi_osi_linux(-1, d); /* unknown */ | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Most BIOS that invoke OSI(Linux) do nothing with it. | ||
192 | * But some cause Linux to break. | ||
193 | * Only a couple use it to make Linux run better. | ||
194 | * | ||
195 | * Thus, Linux should continue to disable OSI(Linux) by default, | ||
196 | * should continue to discourage BIOS writers from using it, and | ||
197 | * should whitelist the few existing systems that require it. | ||
198 | * | ||
199 | * If it appears clear a vendor isn't using OSI(Linux) | ||
200 | * for anything constructive, blacklist them by name to disable | ||
201 | * unnecessary dmesg warnings on all of their products. | ||
202 | */ | ||
203 | |||
204 | static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { | ||
205 | /* | ||
206 | * Disable OSI(Linux) warnings on all "Acer, inc." | ||
207 | * | ||
208 | * _OSI(Linux) disables the latest Windows BIOS code: | ||
209 | * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"), | ||
210 | * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"), | ||
211 | * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"), | ||
212 | * _OSI(Linux) effect unknown: | ||
213 | * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"), | ||
214 | */ | ||
215 | { | ||
216 | .callback = dmi_disable_osi_linux, | ||
217 | .ident = "Acer, inc.", | ||
218 | .matches = { | ||
219 | DMI_MATCH(DMI_SYS_VENDOR, "Acer, inc."), | ||
220 | }, | ||
221 | }, | ||
222 | /* | ||
223 | * Disable OSI(Linux) warnings on all "Acer" | ||
224 | * | ||
225 | * _OSI(Linux) effect unknown: | ||
226 | * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), | ||
227 | * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), | ||
228 | * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"), | ||
229 | * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"), | ||
230 | * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"), | ||
231 | * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"), | ||
232 | * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"), | ||
233 | */ | ||
234 | { | ||
235 | .callback = dmi_unknown_osi_linux, | ||
236 | .ident = "Acer", | ||
237 | .matches = { | ||
238 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
239 | }, | ||
240 | }, | ||
241 | /* | ||
242 | * Disable OSI(Linux) warnings on all "Apple Computer, Inc." | ||
243 | * | ||
244 | * _OSI(Linux) confirmed to be a NOP: | ||
245 | * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), | ||
246 | * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"), | ||
247 | * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"), | ||
248 | * _OSI(Linux) effect unknown: | ||
249 | * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"), | ||
250 | * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"), | ||
251 | * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), | ||
252 | */ | ||
253 | { | ||
254 | .callback = dmi_disable_osi_linux, | ||
255 | .ident = "Apple", | ||
256 | .matches = { | ||
257 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), | ||
258 | }, | ||
259 | }, | ||
260 | /* | ||
261 | * Disable OSI(Linux) warnings on all "BenQ" | ||
262 | * | ||
263 | * _OSI(Linux) confirmed to be a NOP: | ||
264 | * DMI_MATCH(DMI_PRODUCT_NAME, "Joybook S31"), | ||
265 | */ | ||
266 | { | ||
267 | .callback = dmi_disable_osi_linux, | ||
268 | .ident = "BenQ", | ||
269 | .matches = { | ||
270 | DMI_MATCH(DMI_SYS_VENDOR, "BenQ"), | ||
271 | }, | ||
272 | }, | ||
273 | /* | ||
274 | * Disable OSI(Linux) warnings on all "Clevo Co." | ||
275 | * | ||
276 | * _OSI(Linux) confirmed to be a NOP: | ||
277 | * DMI_MATCH(DMI_PRODUCT_NAME, "M570RU"), | ||
278 | */ | ||
279 | { | ||
280 | .callback = dmi_disable_osi_linux, | ||
281 | .ident = "Clevo", | ||
282 | .matches = { | ||
283 | DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."), | ||
284 | }, | ||
285 | }, | ||
286 | /* | ||
287 | * Disable OSI(Linux) warnings on all "COMPAL" | ||
288 | * | ||
289 | * _OSI(Linux) confirmed to be a NOP: | ||
290 | * DMI_MATCH(DMI_BOARD_NAME, "HEL8X"), | ||
291 | * _OSI(Linux) unknown effect: | ||
292 | * DMI_MATCH(DMI_BOARD_NAME, "IFL91"), | ||
293 | */ | ||
294 | { | ||
295 | .callback = dmi_unknown_osi_linux, | ||
296 | .ident = "Compal", | ||
297 | .matches = { | ||
298 | DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), | ||
299 | }, | ||
300 | }, | ||
301 | { /* OSI(Linux) touches USB, breaks suspend to disk */ | ||
302 | .callback = dmi_disable_osi_linux, | ||
303 | .ident = "Dell Dimension 5150", | ||
304 | .matches = { | ||
305 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
306 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM051"), | ||
307 | }, | ||
308 | }, | ||
309 | { /* OSI(Linux) is a NOP */ | ||
310 | .callback = dmi_disable_osi_linux, | ||
311 | .ident = "Dell", | ||
312 | .matches = { | ||
313 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
314 | DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"), | ||
315 | }, | ||
316 | }, | ||
317 | { /* OSI(Linux) effect unknown */ | ||
318 | .callback = dmi_unknown_osi_linux, | ||
319 | .ident = "Dell", | ||
320 | .matches = { | ||
321 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
322 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"), | ||
323 | }, | ||
324 | }, | ||
325 | { /* OSI(Linux) effect unknown */ | ||
326 | .callback = dmi_unknown_osi_linux, | ||
327 | .ident = "Dell", | ||
328 | .matches = { | ||
329 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
330 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"), | ||
331 | }, | ||
332 | }, | ||
333 | { /* OSI(Linux) effect unknown */ | ||
334 | .callback = dmi_unknown_osi_linux, | ||
335 | .ident = "Dell", | ||
336 | .matches = { | ||
337 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
338 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"), | ||
339 | }, | ||
340 | }, | ||
341 | { /* OSI(Linux) touches USB */ | ||
342 | .callback = dmi_disable_osi_linux, | ||
343 | .ident = "Dell", | ||
344 | .matches = { | ||
345 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
346 | DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"), | ||
347 | }, | ||
348 | }, | ||
349 | { /* OSI(Linux) is a NOP */ | ||
350 | .callback = dmi_disable_osi_linux, | ||
351 | .ident = "Dell Vostro 1000", | ||
352 | .matches = { | ||
353 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
354 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1000"), | ||
355 | }, | ||
356 | }, | ||
357 | { /* OSI(Linux) effect unknown */ | ||
358 | .callback = dmi_unknown_osi_linux, | ||
359 | .ident = "Dell", | ||
360 | .matches = { | ||
361 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
362 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"), | ||
363 | }, | ||
364 | }, | ||
365 | { /* OSI(Linux) effect unknown */ | ||
366 | .callback = dmi_unknown_osi_linux, | ||
367 | .ident = "Dialogue Flybook V5", | ||
368 | .matches = { | ||
369 | DMI_MATCH(DMI_SYS_VENDOR, "Dialogue Technology Corporation"), | ||
370 | DMI_MATCH(DMI_PRODUCT_NAME, "Flybook V5"), | ||
371 | }, | ||
372 | }, | ||
373 | /* | ||
374 | * Disable OSI(Linux) warnings on all "FUJITSU SIEMENS" | ||
375 | * | ||
376 | * _OSI(Linux) disables latest Windows BIOS code: | ||
377 | * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2510"), | ||
378 | * _OSI(Linux) confirmed to be a NOP: | ||
379 | * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1536"), | ||
380 | * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1556"), | ||
381 | * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 1546"), | ||
382 | * _OSI(Linux) unknown effect: | ||
383 | * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo M1425"), | ||
384 | * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo Si 1520"), | ||
385 | * DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), | ||
386 | */ | ||
387 | { | ||
388 | .callback = dmi_disable_osi_linux, | ||
389 | .ident = "Fujitsu Siemens", | ||
390 | .matches = { | ||
391 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
392 | }, | ||
393 | }, | ||
394 | /* | ||
395 | * Disable OSI(Linux) warnings on all "Hewlett-Packard" | ||
396 | * | ||
397 | * _OSI(Linux) confirmed to be a NOP: | ||
398 | * .ident = "HP Pavilion tx 1000" | ||
399 | * DMI_MATCH(DMI_BOARD_NAME, "30BF"), | ||
400 | * .ident = "HP Pavilion dv2000" | ||
401 | * DMI_MATCH(DMI_BOARD_NAME, "30B5"), | ||
402 | * .ident = "HP Pavilion dv5000", | ||
403 | * DMI_MATCH(DMI_BOARD_NAME, "30A7"), | ||
404 | * .ident = "HP Pavilion dv6300 30BC", | ||
405 | * DMI_MATCH(DMI_BOARD_NAME, "30BC"), | ||
406 | * .ident = "HP Pavilion dv6000", | ||
407 | * DMI_MATCH(DMI_BOARD_NAME, "30B7"), | ||
408 | * DMI_MATCH(DMI_BOARD_NAME, "30B8"), | ||
409 | * .ident = "HP Pavilion dv9000", | ||
410 | * DMI_MATCH(DMI_BOARD_NAME, "30B9"), | ||
411 | * .ident = "HP Pavilion dv9500", | ||
412 | * DMI_MATCH(DMI_BOARD_NAME, "30CB"), | ||
413 | * .ident = "HP/Compaq Presario C500", | ||
414 | * DMI_MATCH(DMI_BOARD_NAME, "30C6"), | ||
415 | * .ident = "HP/Compaq Presario F500", | ||
416 | * DMI_MATCH(DMI_BOARD_NAME, "30D3"), | ||
417 | * _OSI(Linux) unknown effect: | ||
418 | * .ident = "HP Pavilion dv6500", | ||
419 | * DMI_MATCH(DMI_BOARD_NAME, "30D0"), | ||
420 | */ | ||
421 | { | ||
422 | .callback = dmi_disable_osi_linux, | ||
423 | .ident = "Hewlett-Packard", | ||
424 | .matches = { | ||
425 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
426 | }, | ||
427 | }, | ||
428 | /* | ||
429 | * Lenovo has a mix of systems OSI(Linux) situations | ||
430 | * and thus we can not wildcard the vendor. | ||
431 | * | ||
432 | * _OSI(Linux) helps sound | ||
433 | * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"), | ||
434 | * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"), | ||
435 | * _OSI(Linux) is a NOP: | ||
436 | * DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), | ||
437 | */ | ||
438 | { | ||
439 | .callback = dmi_enable_osi_linux, | ||
440 | .ident = "Lenovo ThinkPad R61", | ||
441 | .matches = { | ||
442 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
443 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"), | ||
444 | }, | ||
445 | }, | ||
446 | { | ||
447 | .callback = dmi_enable_osi_linux, | ||
448 | .ident = "Lenovo ThinkPad T61", | ||
449 | .matches = { | ||
450 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
451 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"), | ||
452 | }, | ||
453 | }, | ||
454 | { | ||
455 | .callback = dmi_unknown_osi_linux, | ||
456 | .ident = "Lenovo 3000 V100", | ||
457 | .matches = { | ||
458 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
459 | DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"), | ||
460 | }, | ||
461 | }, | ||
462 | { | ||
463 | .callback = dmi_disable_osi_linux, | ||
464 | .ident = "Lenovo 3000 N100", | ||
465 | .matches = { | ||
466 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
467 | DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), | ||
468 | }, | ||
469 | }, | ||
470 | /* | ||
471 | * Disable OSI(Linux) warnings on all "LG Electronics" | ||
472 | * | ||
473 | * _OSI(Linux) confirmed to be a NOP: | ||
474 | * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"), | ||
475 | */ | ||
476 | { | ||
477 | .callback = dmi_disable_osi_linux, | ||
478 | .ident = "LG", | ||
479 | .matches = { | ||
480 | DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), | ||
481 | }, | ||
482 | }, | ||
483 | /* NEC - OSI(Linux) effect unknown */ | ||
484 | { | ||
485 | .callback = dmi_unknown_osi_linux, | ||
486 | .ident = "NEC VERSA M360", | ||
487 | .matches = { | ||
488 | DMI_MATCH(DMI_SYS_VENDOR, "NEC Computers SAS"), | ||
489 | DMI_MATCH(DMI_PRODUCT_NAME, "NEC VERSA M360"), | ||
490 | }, | ||
491 | }, | ||
492 | /* | ||
493 | * Disable OSI(Linux) warnings on all "Samsung Electronics" | ||
494 | * | ||
495 | * OSI(Linux) disables PNP0C32 and other BIOS code for Windows: | ||
496 | * DMI_MATCH(DMI_PRODUCT_NAME, "R40P/R41P"), | ||
497 | * DMI_MATCH(DMI_PRODUCT_NAME, "R59P/R60P/R61P"), | ||
498 | */ | ||
499 | { | ||
500 | .callback = dmi_disable_osi_linux, | ||
501 | .ident = "Samsung", | ||
502 | .matches = { | ||
503 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | ||
504 | }, | ||
505 | }, | ||
506 | /* | ||
507 | * Disable OSI(Linux) warnings on all "Sony Corporation" | ||
508 | * | ||
509 | * _OSI(Linux) is a NOP: | ||
510 | * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ650N"), | ||
511 | * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ38GP_C"), | ||
512 | * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-TZ21MN_N"), | ||
513 | * _OSI(Linux) unknown effect: | ||
514 | * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"), | ||
515 | */ | ||
516 | { | ||
517 | .callback = dmi_unknown_osi_linux, | ||
518 | .ident = "Sony", | ||
519 | .matches = { | ||
520 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
521 | }, | ||
522 | }, | ||
523 | /* | ||
524 | * Disable OSI(Linux) warnings on all "TOSHIBA" | ||
525 | * | ||
526 | * _OSI(Linux) breaks sound (bugzilla 7787): | ||
527 | * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P100"), | ||
528 | * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P105"), | ||
529 | * _OSI(Linux) is a NOP: | ||
530 | * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A100"), | ||
531 | * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A210"), | ||
532 | * _OSI(Linux) unknown effect: | ||
533 | * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A135"), | ||
534 | * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A200"), | ||
535 | * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P205"), | ||
536 | * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U305"), | ||
537 | */ | ||
538 | { | ||
539 | .callback = dmi_disable_osi_linux, | ||
540 | .ident = "Toshiba", | ||
541 | .matches = { | ||
542 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
543 | }, | ||
544 | }, | ||
545 | {} | ||
546 | }; | ||
547 | |||
548 | #endif /* CONFIG_DMI */ | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 49d432d0a12c..1b4cf984b081 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
32 | #include <linux/pm_legacy.h> | ||
33 | #include <linux/device.h> | 32 | #include <linux/device.h> |
34 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
35 | #ifdef CONFIG_X86 | 34 | #ifdef CONFIG_X86 |
@@ -201,7 +200,7 @@ int acpi_bus_set_power(acpi_handle handle, int state) | |||
201 | * Get device's current power state | 200 | * Get device's current power state |
202 | */ | 201 | */ |
203 | acpi_bus_get_power(device->handle, &device->power.state); | 202 | acpi_bus_get_power(device->handle, &device->power.state); |
204 | if (state == device->power.state) { | 203 | if ((state == device->power.state) && !device->flags.force_power_state) { |
205 | 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", |
206 | state)); | 205 | state)); |
207 | return 0; | 206 | return 0; |
@@ -744,7 +743,7 @@ static int __init acpi_bus_init(void) | |||
744 | return -ENODEV; | 743 | return -ENODEV; |
745 | } | 744 | } |
746 | 745 | ||
747 | decl_subsys(acpi, NULL, NULL); | 746 | struct kobject *acpi_kobj; |
748 | 747 | ||
749 | static int __init acpi_init(void) | 748 | static int __init acpi_init(void) |
750 | { | 749 | { |
@@ -756,24 +755,23 @@ static int __init acpi_init(void) | |||
756 | return -ENODEV; | 755 | return -ENODEV; |
757 | } | 756 | } |
758 | 757 | ||
759 | result = firmware_register(&acpi_subsys); | 758 | acpi_kobj = kobject_create_and_add("acpi", firmware_kobj); |
760 | if (result < 0) | 759 | if (!acpi_kobj) { |
761 | printk(KERN_WARNING "%s: firmware_register error: %d\n", | 760 | printk(KERN_WARNING "%s: kset create error\n", __FUNCTION__); |
762 | __FUNCTION__, result); | 761 | acpi_kobj = NULL; |
762 | } | ||
763 | 763 | ||
764 | result = acpi_bus_init(); | 764 | result = acpi_bus_init(); |
765 | 765 | ||
766 | if (!result) { | 766 | if (!result) { |
767 | #ifdef CONFIG_PM_LEGACY | 767 | if (!(pm_flags & PM_APM)) |
768 | if (!PM_IS_ACTIVE()) | 768 | pm_flags |= PM_ACPI; |
769 | pm_active = 1; | ||
770 | else { | 769 | else { |
771 | printk(KERN_INFO PREFIX | 770 | printk(KERN_INFO PREFIX |
772 | "APM is already active, exiting\n"); | 771 | "APM is already active, exiting\n"); |
773 | disable_acpi(); | 772 | disable_acpi(); |
774 | result = -ENODEV; | 773 | result = -ENODEV; |
775 | } | 774 | } |
776 | #endif | ||
777 | } else | 775 | } else |
778 | disable_acpi(); | 776 | disable_acpi(); |
779 | 777 | ||
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index bf513e07b773..6df564f4ca6e 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c | |||
@@ -130,6 +130,63 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) { | |||
130 | module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); | 130 | module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); |
131 | module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); | 131 | module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); |
132 | 132 | ||
133 | static char trace_method_name[6]; | ||
134 | module_param_string(trace_method_name, trace_method_name, 6, 0644); | ||
135 | static unsigned int trace_debug_layer; | ||
136 | module_param(trace_debug_layer, uint, 0644); | ||
137 | static unsigned int trace_debug_level; | ||
138 | module_param(trace_debug_level, uint, 0644); | ||
139 | |||
140 | static int param_set_trace_state(const char *val, struct kernel_param *kp) | ||
141 | { | ||
142 | int result = 0; | ||
143 | |||
144 | if (!strncmp(val, "enable", strlen("enable") - 1)) { | ||
145 | result = acpi_debug_trace(trace_method_name, trace_debug_level, | ||
146 | trace_debug_layer, 0); | ||
147 | if (result) | ||
148 | result = -EBUSY; | ||
149 | goto exit; | ||
150 | } | ||
151 | |||
152 | if (!strncmp(val, "disable", strlen("disable") - 1)) { | ||
153 | int name = 0; | ||
154 | result = acpi_debug_trace((char *)&name, trace_debug_level, | ||
155 | trace_debug_layer, 0); | ||
156 | if (result) | ||
157 | result = -EBUSY; | ||
158 | goto exit; | ||
159 | } | ||
160 | |||
161 | if (!strncmp(val, "1", 1)) { | ||
162 | result = acpi_debug_trace(trace_method_name, trace_debug_level, | ||
163 | trace_debug_layer, 1); | ||
164 | if (result) | ||
165 | result = -EBUSY; | ||
166 | goto exit; | ||
167 | } | ||
168 | |||
169 | result = -EINVAL; | ||
170 | exit: | ||
171 | return result; | ||
172 | } | ||
173 | |||
174 | static int param_get_trace_state(char *buffer, struct kernel_param *kp) | ||
175 | { | ||
176 | if (!acpi_gbl_trace_method_name) | ||
177 | return sprintf(buffer, "disable"); | ||
178 | else { | ||
179 | if (acpi_gbl_trace_flags & 1) | ||
180 | return sprintf(buffer, "1"); | ||
181 | else | ||
182 | return sprintf(buffer, "enable"); | ||
183 | } | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | module_param_call(trace_state, param_set_trace_state, param_get_trace_state, | ||
188 | NULL, 0644); | ||
189 | |||
133 | /* -------------------------------------------------------------------------- | 190 | /* -------------------------------------------------------------------------- |
134 | FS Interface (/proc) | 191 | FS Interface (/proc) |
135 | -------------------------------------------------------------------------- */ | 192 | -------------------------------------------------------------------------- */ |
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index a474ca2334d5..954ac8ce958a 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c | |||
@@ -137,6 +137,71 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
137 | return_ACPI_STATUS(status); | 137 | return_ACPI_STATUS(status); |
138 | } | 138 | } |
139 | } | 139 | } |
140 | |||
141 | /* Special object resolution for elements of a package */ | ||
142 | |||
143 | if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || | ||
144 | (op->common.parent->common.aml_opcode == | ||
145 | AML_VAR_PACKAGE_OP)) { | ||
146 | /* | ||
147 | * Attempt to resolve the node to a value before we insert it into | ||
148 | * the package. If this is a reference to a common data type, | ||
149 | * resolve it immediately. According to the ACPI spec, package | ||
150 | * elements can only be "data objects" or method references. | ||
151 | * Attempt to resolve to an Integer, Buffer, String or Package. | ||
152 | * If cannot, return the named reference (for things like Devices, | ||
153 | * Methods, etc.) Buffer Fields and Fields will resolve to simple | ||
154 | * objects (int/buf/str/pkg). | ||
155 | * | ||
156 | * NOTE: References to things like Devices, Methods, Mutexes, etc. | ||
157 | * will remain as named references. This behavior is not described | ||
158 | * in the ACPI spec, but it appears to be an oversight. | ||
159 | */ | ||
160 | obj_desc = (union acpi_operand_object *)op->common.node; | ||
161 | |||
162 | status = | ||
163 | acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR | ||
164 | (struct | ||
165 | acpi_namespace_node, | ||
166 | &obj_desc), | ||
167 | walk_state); | ||
168 | if (ACPI_FAILURE(status)) { | ||
169 | return_ACPI_STATUS(status); | ||
170 | } | ||
171 | |||
172 | switch (op->common.node->type) { | ||
173 | /* | ||
174 | * For these types, we need the actual node, not the subobject. | ||
175 | * However, the subobject got an extra reference count above. | ||
176 | */ | ||
177 | case ACPI_TYPE_MUTEX: | ||
178 | case ACPI_TYPE_METHOD: | ||
179 | case ACPI_TYPE_POWER: | ||
180 | case ACPI_TYPE_PROCESSOR: | ||
181 | case ACPI_TYPE_EVENT: | ||
182 | case ACPI_TYPE_REGION: | ||
183 | case ACPI_TYPE_DEVICE: | ||
184 | case ACPI_TYPE_THERMAL: | ||
185 | |||
186 | obj_desc = | ||
187 | (union acpi_operand_object *)op->common. | ||
188 | node; | ||
189 | break; | ||
190 | |||
191 | default: | ||
192 | break; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * If above resolved to an operand object, we are done. Otherwise, | ||
197 | * we have a NS node, we must create the package entry as a named | ||
198 | * reference. | ||
199 | */ | ||
200 | if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != | ||
201 | ACPI_DESC_TYPE_NAMED) { | ||
202 | goto exit; | ||
203 | } | ||
204 | } | ||
140 | } | 205 | } |
141 | 206 | ||
142 | /* Create and init a new internal ACPI object */ | 207 | /* Create and init a new internal ACPI object */ |
@@ -156,6 +221,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
156 | return_ACPI_STATUS(status); | 221 | return_ACPI_STATUS(status); |
157 | } | 222 | } |
158 | 223 | ||
224 | exit: | ||
159 | *obj_desc_ptr = obj_desc; | 225 | *obj_desc_ptr = obj_desc; |
160 | return_ACPI_STATUS(AE_OK); | 226 | return_ACPI_STATUS(AE_OK); |
161 | } | 227 | } |
@@ -356,12 +422,25 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
356 | arg = arg->common.next; | 422 | arg = arg->common.next; |
357 | for (i = 0; arg && (i < element_count); i++) { | 423 | for (i = 0; arg && (i < element_count); i++) { |
358 | if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { | 424 | if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { |
359 | 425 | if (arg->common.node->type == ACPI_TYPE_METHOD) { | |
360 | /* This package element is already built, just get it */ | 426 | /* |
361 | 427 | * A method reference "looks" to the parser to be a method | |
362 | obj_desc->package.elements[i] = | 428 | * invocation, so we special case it here |
363 | ACPI_CAST_PTR(union acpi_operand_object, | 429 | */ |
364 | arg->common.node); | 430 | arg->common.aml_opcode = AML_INT_NAMEPATH_OP; |
431 | status = | ||
432 | acpi_ds_build_internal_object(walk_state, | ||
433 | arg, | ||
434 | &obj_desc-> | ||
435 | package. | ||
436 | elements[i]); | ||
437 | } else { | ||
438 | /* This package element is already built, just get it */ | ||
439 | |||
440 | obj_desc->package.elements[i] = | ||
441 | ACPI_CAST_PTR(union acpi_operand_object, | ||
442 | arg->common.node); | ||
443 | } | ||
365 | } else { | 444 | } else { |
366 | status = acpi_ds_build_internal_object(walk_state, arg, | 445 | status = acpi_ds_build_internal_object(walk_state, arg, |
367 | &obj_desc-> | 446 | &obj_desc-> |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 1dabdf4c07b3..b3dec2101e2e 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -51,6 +51,12 @@ static struct atomic_notifier_head dock_notifier_list; | |||
51 | static struct platform_device *dock_device; | 51 | static struct platform_device *dock_device; |
52 | static char dock_device_name[] = "dock"; | 52 | static char dock_device_name[] = "dock"; |
53 | 53 | ||
54 | static const struct acpi_device_id dock_device_ids[] = { | ||
55 | {"LNXDOCK", 0}, | ||
56 | {"", 0}, | ||
57 | }; | ||
58 | MODULE_DEVICE_TABLE(acpi, dock_device_ids); | ||
59 | |||
54 | struct dock_station { | 60 | struct dock_station { |
55 | acpi_handle handle; | 61 | acpi_handle handle; |
56 | unsigned long last_dock_time; | 62 | unsigned long last_dock_time; |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 06b78e5e33a1..7222a18a0319 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> |
@@ -75,7 +78,11 @@ enum { | |||
75 | EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ | 78 | EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ |
76 | EC_FLAGS_QUERY_PENDING, /* Query is pending */ | 79 | EC_FLAGS_QUERY_PENDING, /* Query is pending */ |
77 | EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ | 80 | EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ |
78 | EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */ | 81 | EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */ |
82 | EC_FLAGS_ADDRESS, /* Address is being written */ | ||
83 | EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ | ||
84 | EC_FLAGS_WDATA, /* Data is being written */ | ||
85 | EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */ | ||
79 | }; | 86 | }; |
80 | 87 | ||
81 | static int acpi_ec_remove(struct acpi_device *device, int type); | 88 | static int acpi_ec_remove(struct acpi_device *device, int type); |
@@ -131,21 +138,27 @@ static struct acpi_ec { | |||
131 | 138 | ||
132 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) | 139 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) |
133 | { | 140 | { |
134 | return inb(ec->command_addr); | 141 | u8 x = inb(ec->command_addr); |
142 | pr_debug(PREFIX "---> status = 0x%2.2x\n", x); | ||
143 | return x; | ||
135 | } | 144 | } |
136 | 145 | ||
137 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) | 146 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) |
138 | { | 147 | { |
148 | u8 x = inb(ec->data_addr); | ||
149 | pr_debug(PREFIX "---> data = 0x%2.2x\n", x); | ||
139 | return inb(ec->data_addr); | 150 | return inb(ec->data_addr); |
140 | } | 151 | } |
141 | 152 | ||
142 | 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) |
143 | { | 154 | { |
155 | pr_debug(PREFIX "<--- command = 0x%2.2x\n", command); | ||
144 | outb(command, ec->command_addr); | 156 | outb(command, ec->command_addr); |
145 | } | 157 | } |
146 | 158 | ||
147 | 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) |
148 | { | 160 | { |
161 | pr_debug(PREFIX "<--- data = 0x%2.2x\n", data); | ||
149 | outb(data, ec->data_addr); | 162 | outb(data, ec->data_addr); |
150 | } | 163 | } |
151 | 164 | ||
@@ -166,38 +179,63 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) | |||
166 | 179 | ||
167 | 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) |
168 | { | 181 | { |
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; | ||
187 | if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && | ||
188 | test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) | ||
189 | force_poll = 1; | ||
190 | if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) && | ||
191 | test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags))) | ||
192 | force_poll = 1; | ||
169 | if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && | 193 | if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && |
170 | likely(!force_poll)) { | 194 | likely(!force_poll)) { |
171 | if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), | 195 | if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), |
172 | msecs_to_jiffies(ACPI_EC_DELAY))) | 196 | msecs_to_jiffies(ACPI_EC_DELAY))) |
173 | return 0; | 197 | goto end; |
174 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 198 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
175 | if (acpi_ec_check_status(ec, event)) { | 199 | if (acpi_ec_check_status(ec, event)) { |
176 | if (event == ACPI_EC_EVENT_OBF_1) { | 200 | if (event == ACPI_EC_EVENT_OBF_1) { |
177 | /* miss OBF = 1 GPE, don't expect it anymore */ | 201 | /* miss OBF_1 GPE, don't expect it */ |
178 | printk(KERN_INFO PREFIX "missing OBF_1 confirmation," | 202 | pr_info(PREFIX "missing OBF confirmation, " |
179 | "switching to degraded mode.\n"); | 203 | "don't expect it any longer.\n"); |
180 | set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags); | 204 | set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags); |
205 | } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { | ||
206 | /* miss address GPE, don't expect it anymore */ | ||
207 | pr_info(PREFIX "missing address confirmation, " | ||
208 | "don't expect it any longer.\n"); | ||
209 | set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags); | ||
210 | } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) { | ||
211 | /* miss write data GPE, don't expect it */ | ||
212 | pr_info(PREFIX "missing write data confirmation, " | ||
213 | "don't expect it any longer.\n"); | ||
214 | set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags); | ||
181 | } else { | 215 | } else { |
182 | /* missing GPEs, switch back to poll mode */ | 216 | /* missing GPEs, switch back to poll mode */ |
183 | printk(KERN_INFO PREFIX "missing IBF_1 confirmations," | 217 | if (printk_ratelimit()) |
184 | "switch off interrupt mode.\n"); | 218 | pr_info(PREFIX "missing confirmations, " |
219 | "switch off interrupt mode.\n"); | ||
185 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 220 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
186 | } | 221 | } |
187 | return 0; | 222 | goto end; |
188 | } | 223 | } |
189 | } else { | 224 | } else { |
190 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 225 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); |
191 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 226 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
192 | while (time_before(jiffies, delay)) { | 227 | while (time_before(jiffies, delay)) { |
193 | if (acpi_ec_check_status(ec, event)) | 228 | if (acpi_ec_check_status(ec, event)) |
194 | return 0; | 229 | goto end; |
195 | } | 230 | } |
196 | } | 231 | } |
197 | printk(KERN_ERR PREFIX "acpi_ec_wait timeout," | 232 | pr_err(PREFIX "acpi_ec_wait timeout," |
198 | " status = %d, expect_event = %d\n", | 233 | " status = %d, expect_event = %d\n", |
199 | acpi_ec_read_status(ec), event); | 234 | acpi_ec_read_status(ec), event); |
200 | return -ETIME; | 235 | ret = -ETIME; |
236 | end: | ||
237 | clear_bit(EC_FLAGS_ADDRESS, &ec->flags); | ||
238 | return ret; | ||
201 | } | 239 | } |
202 | 240 | ||
203 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | 241 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, |
@@ -208,22 +246,26 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
208 | int result = 0; | 246 | int result = 0; |
209 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 247 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
210 | acpi_ec_write_cmd(ec, command); | 248 | acpi_ec_write_cmd(ec, command); |
211 | 249 | pr_debug(PREFIX "transaction start\n"); | |
212 | for (; wdata_len > 0; --wdata_len) { | 250 | for (; wdata_len > 0; --wdata_len) { |
213 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); | 251 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); |
214 | if (result) { | 252 | if (result) { |
215 | printk(KERN_ERR PREFIX | 253 | pr_err(PREFIX |
216 | "write_cmd timeout, command = %d\n", command); | 254 | "write_cmd timeout, command = %d\n", command); |
217 | goto end; | 255 | goto end; |
218 | } | 256 | } |
257 | /* mark the address byte written to EC */ | ||
258 | if (rdata_len + wdata_len > 1) | ||
259 | set_bit(EC_FLAGS_ADDRESS, &ec->flags); | ||
219 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 260 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
220 | acpi_ec_write_data(ec, *(wdata++)); | 261 | acpi_ec_write_data(ec, *(wdata++)); |
221 | } | 262 | } |
222 | 263 | ||
223 | if (!rdata_len) { | 264 | if (!rdata_len) { |
265 | set_bit(EC_FLAGS_WDATA, &ec->flags); | ||
224 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); | 266 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); |
225 | if (result) { | 267 | if (result) { |
226 | printk(KERN_ERR PREFIX | 268 | pr_err(PREFIX |
227 | "finish-write timeout, command = %d\n", command); | 269 | "finish-write timeout, command = %d\n", command); |
228 | goto end; | 270 | goto end; |
229 | } | 271 | } |
@@ -231,12 +273,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
231 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 273 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
232 | 274 | ||
233 | for (; rdata_len > 0; --rdata_len) { | 275 | for (; rdata_len > 0; --rdata_len) { |
234 | if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags)) | ||
235 | force_poll = 1; | ||
236 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); | 276 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); |
237 | if (result) { | 277 | if (result) { |
238 | printk(KERN_ERR PREFIX "read timeout, command = %d\n", | 278 | pr_err(PREFIX "read timeout, command = %d\n", command); |
239 | command); | ||
240 | goto end; | 279 | goto end; |
241 | } | 280 | } |
242 | /* Don't expect GPE after last read */ | 281 | /* Don't expect GPE after last read */ |
@@ -245,6 +284,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
245 | *(rdata++) = acpi_ec_read_data(ec); | 284 | *(rdata++) = acpi_ec_read_data(ec); |
246 | } | 285 | } |
247 | end: | 286 | end: |
287 | pr_debug(PREFIX "transaction end\n"); | ||
248 | return result; | 288 | return result; |
249 | } | 289 | } |
250 | 290 | ||
@@ -273,8 +313,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, | |||
273 | 313 | ||
274 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); | 314 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); |
275 | if (status) { | 315 | if (status) { |
276 | printk(KERN_ERR PREFIX | 316 | pr_err(PREFIX "input buffer is not empty, " |
277 | "input buffer is not empty, aborting transaction\n"); | 317 | "aborting transaction\n"); |
278 | goto end; | 318 | goto end; |
279 | } | 319 | } |
280 | 320 | ||
@@ -488,6 +528,7 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
488 | acpi_status status = AE_OK; | 528 | acpi_status status = AE_OK; |
489 | struct acpi_ec *ec = data; | 529 | struct acpi_ec *ec = data; |
490 | 530 | ||
531 | pr_debug(PREFIX "~~~> interrupt\n"); | ||
491 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 532 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
492 | if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) | 533 | if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) |
493 | wake_up(&ec->wait); | 534 | wake_up(&ec->wait); |
@@ -498,8 +539,9 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
498 | acpi_ec_gpe_query, ec); | 539 | acpi_ec_gpe_query, ec); |
499 | } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { | 540 | } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { |
500 | /* this is non-query, must be confirmation */ | 541 | /* this is non-query, must be confirmation */ |
501 | printk(KERN_INFO PREFIX "non-query interrupt received," | 542 | if (printk_ratelimit()) |
502 | " switching to interrupt mode\n"); | 543 | pr_info(PREFIX "non-query interrupt received," |
544 | " switching to interrupt mode\n"); | ||
503 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 545 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
504 | } | 546 | } |
505 | 547 | ||
@@ -531,7 +573,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, | |||
531 | void *handler_context, void *region_context) | 573 | void *handler_context, void *region_context) |
532 | { | 574 | { |
533 | struct acpi_ec *ec = handler_context; | 575 | struct acpi_ec *ec = handler_context; |
534 | int result = 0, i = 0; | 576 | int result = 0, i; |
535 | u8 temp = 0; | 577 | u8 temp = 0; |
536 | 578 | ||
537 | if ((address > 0xFF) || !value || !handler_context) | 579 | if ((address > 0xFF) || !value || !handler_context) |
@@ -543,7 +585,18 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, | |||
543 | if (bits != 8 && acpi_strict) | 585 | if (bits != 8 && acpi_strict) |
544 | return AE_BAD_PARAMETER; | 586 | return AE_BAD_PARAMETER; |
545 | 587 | ||
546 | while (bits - i > 0) { | 588 | acpi_ec_burst_enable(ec); |
589 | |||
590 | if (function == ACPI_READ) { | ||
591 | result = acpi_ec_read(ec, address, &temp); | ||
592 | *value = temp; | ||
593 | } else { | ||
594 | temp = 0xff & (*value); | ||
595 | result = acpi_ec_write(ec, address, temp); | ||
596 | } | ||
597 | |||
598 | for (i = 8; unlikely(bits - i > 0); i += 8) { | ||
599 | ++address; | ||
547 | if (function == ACPI_READ) { | 600 | if (function == ACPI_READ) { |
548 | result = acpi_ec_read(ec, address, &temp); | 601 | result = acpi_ec_read(ec, address, &temp); |
549 | (*value) |= ((acpi_integer)temp) << i; | 602 | (*value) |= ((acpi_integer)temp) << i; |
@@ -551,10 +604,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, | |||
551 | temp = 0xff & ((*value) >> i); | 604 | temp = 0xff & ((*value) >> i); |
552 | result = acpi_ec_write(ec, address, temp); | 605 | result = acpi_ec_write(ec, address, temp); |
553 | } | 606 | } |
554 | i += 8; | ||
555 | ++address; | ||
556 | } | 607 | } |
557 | 608 | ||
609 | acpi_ec_burst_disable(ec); | ||
610 | |||
558 | switch (result) { | 611 | switch (result) { |
559 | case -EINVAL: | 612 | case -EINVAL: |
560 | return AE_BAD_PARAMETER; | 613 | return AE_BAD_PARAMETER; |
@@ -701,10 +754,10 @@ static void ec_remove_handlers(struct acpi_ec *ec) | |||
701 | { | 754 | { |
702 | if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, | 755 | if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, |
703 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) | 756 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) |
704 | printk(KERN_ERR PREFIX "failed to remove space handler\n"); | 757 | pr_err(PREFIX "failed to remove space handler\n"); |
705 | if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, | 758 | if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, |
706 | &acpi_ec_gpe_handler))) | 759 | &acpi_ec_gpe_handler))) |
707 | printk(KERN_ERR PREFIX "failed to remove gpe handler\n"); | 760 | pr_err(PREFIX "failed to remove gpe handler\n"); |
708 | ec->handlers_installed = 0; | 761 | ec->handlers_installed = 0; |
709 | } | 762 | } |
710 | 763 | ||
@@ -747,9 +800,9 @@ static int acpi_ec_add(struct acpi_device *device) | |||
747 | first_ec = ec; | 800 | first_ec = ec; |
748 | acpi_driver_data(device) = ec; | 801 | acpi_driver_data(device) = ec; |
749 | acpi_ec_add_fs(device); | 802 | acpi_ec_add_fs(device); |
750 | printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", | 803 | pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", |
751 | ec->gpe, ec->command_addr, ec->data_addr); | 804 | ec->gpe, ec->command_addr, ec->data_addr); |
752 | printk(KERN_INFO PREFIX "driver started in %s mode\n", | 805 | pr_info(PREFIX "driver started in %s mode\n", |
753 | (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); | 806 | (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); |
754 | return 0; | 807 | return 0; |
755 | } | 808 | } |
@@ -860,6 +913,17 @@ static int acpi_ec_stop(struct acpi_device *device, int type) | |||
860 | return 0; | 913 | return 0; |
861 | } | 914 | } |
862 | 915 | ||
916 | int __init acpi_boot_ec_enable(void) | ||
917 | { | ||
918 | if (!boot_ec || boot_ec->handlers_installed) | ||
919 | return 0; | ||
920 | if (!ec_install_handlers(boot_ec)) { | ||
921 | first_ec = boot_ec; | ||
922 | return 0; | ||
923 | } | ||
924 | return -EFAULT; | ||
925 | } | ||
926 | |||
863 | int __init acpi_ec_ecdt_probe(void) | 927 | int __init acpi_ec_ecdt_probe(void) |
864 | { | 928 | { |
865 | int ret; | 929 | int ret; |
@@ -875,18 +939,27 @@ int __init acpi_ec_ecdt_probe(void) | |||
875 | status = acpi_get_table(ACPI_SIG_ECDT, 1, | 939 | status = acpi_get_table(ACPI_SIG_ECDT, 1, |
876 | (struct acpi_table_header **)&ecdt_ptr); | 940 | (struct acpi_table_header **)&ecdt_ptr); |
877 | if (ACPI_SUCCESS(status)) { | 941 | if (ACPI_SUCCESS(status)) { |
878 | printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n"); | 942 | pr_info(PREFIX "EC description table is found, configuring boot EC\n"); |
879 | boot_ec->command_addr = ecdt_ptr->control.address; | 943 | boot_ec->command_addr = ecdt_ptr->control.address; |
880 | boot_ec->data_addr = ecdt_ptr->data.address; | 944 | boot_ec->data_addr = ecdt_ptr->data.address; |
881 | boot_ec->gpe = ecdt_ptr->gpe; | 945 | boot_ec->gpe = ecdt_ptr->gpe; |
882 | boot_ec->handle = ACPI_ROOT_OBJECT; | 946 | boot_ec->handle = ACPI_ROOT_OBJECT; |
883 | } else { | 947 | } else { |
948 | /* This workaround is needed only on some broken machines, | ||
949 | * which require early EC, but fail to provide ECDT */ | ||
950 | acpi_handle x; | ||
884 | printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); | 951 | printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); |
885 | status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, | 952 | status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, |
886 | boot_ec, NULL); | 953 | boot_ec, NULL); |
887 | /* Check that acpi_get_devices actually find something */ | 954 | /* Check that acpi_get_devices actually find something */ |
888 | if (ACPI_FAILURE(status) || !boot_ec->handle) | 955 | if (ACPI_FAILURE(status) || !boot_ec->handle) |
889 | goto error; | 956 | goto error; |
957 | /* We really need to limit this workaround, the only ASUS, | ||
958 | * which needs it, has fake EC._INI method, so use it as flag. | ||
959 | * Keep boot_ec struct as it will be needed soon. | ||
960 | */ | ||
961 | if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x))) | ||
962 | return -ENODEV; | ||
890 | } | 963 | } |
891 | 964 | ||
892 | ret = ec_install_handlers(boot_ec); | 965 | ret = ec_install_handlers(boot_ec); |
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index e99f0c435a47..58ad09725dd2 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c | |||
@@ -344,7 +344,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
344 | * setup will potentially execute control methods | 344 | * setup will potentially execute control methods |
345 | * (e.g., _REG method for this region) | 345 | * (e.g., _REG method for this region) |
346 | */ | 346 | */ |
347 | acpi_ex_relinquish_interpreter(); | 347 | acpi_ex_exit_interpreter(); |
348 | 348 | ||
349 | status = region_setup(region_obj, ACPI_REGION_ACTIVATE, | 349 | status = region_setup(region_obj, ACPI_REGION_ACTIVATE, |
350 | handler_desc->address_space.context, | 350 | handler_desc->address_space.context, |
@@ -352,7 +352,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
352 | 352 | ||
353 | /* Re-enter the interpreter */ | 353 | /* Re-enter the interpreter */ |
354 | 354 | ||
355 | acpi_ex_reacquire_interpreter(); | 355 | acpi_ex_enter_interpreter(); |
356 | 356 | ||
357 | /* Check for failure of the Region Setup */ | 357 | /* Check for failure of the Region Setup */ |
358 | 358 | ||
@@ -405,7 +405,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
405 | * exit the interpreter because the handler *might* block -- we don't | 405 | * exit the interpreter because the handler *might* block -- we don't |
406 | * know what it will do, so we can't hold the lock on the intepreter. | 406 | * know what it will do, so we can't hold the lock on the intepreter. |
407 | */ | 407 | */ |
408 | acpi_ex_relinquish_interpreter(); | 408 | acpi_ex_exit_interpreter(); |
409 | } | 409 | } |
410 | 410 | ||
411 | /* Call the handler */ | 411 | /* Call the handler */ |
@@ -426,7 +426,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
426 | * We just returned from a non-default handler, we must re-enter the | 426 | * We just returned from a non-default handler, we must re-enter the |
427 | * interpreter | 427 | * interpreter |
428 | */ | 428 | */ |
429 | acpi_ex_reacquire_interpreter(); | 429 | acpi_ex_enter_interpreter(); |
430 | } | 430 | } |
431 | 431 | ||
432 | return_ACPI_STATUS(status); | 432 | return_ACPI_STATUS(status); |
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/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 81b248429703..fd1c4ba63367 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c | |||
@@ -192,18 +192,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) | |||
192 | arg.type = ACPI_TYPE_INTEGER; | 192 | arg.type = ACPI_TYPE_INTEGER; |
193 | arg.integer.value = sleep_state; | 193 | arg.integer.value = sleep_state; |
194 | 194 | ||
195 | /* Run the _PTS and _GTS methods */ | 195 | /* Run the _PTS method */ |
196 | 196 | ||
197 | status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); | 197 | status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); |
198 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 198 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { |
199 | return_ACPI_STATUS(status); | 199 | return_ACPI_STATUS(status); |
200 | } | 200 | } |
201 | 201 | ||
202 | status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); | ||
203 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
204 | return_ACPI_STATUS(status); | ||
205 | } | ||
206 | |||
207 | /* Setup the argument to _SST */ | 202 | /* Setup the argument to _SST */ |
208 | 203 | ||
209 | switch (sleep_state) { | 204 | switch (sleep_state) { |
@@ -234,10 +229,6 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) | |||
234 | "While executing method _SST")); | 229 | "While executing method _SST")); |
235 | } | 230 | } |
236 | 231 | ||
237 | /* Disable/Clear all GPEs */ | ||
238 | |||
239 | status = acpi_hw_disable_all_gpes(); | ||
240 | |||
241 | return_ACPI_STATUS(status); | 232 | return_ACPI_STATUS(status); |
242 | } | 233 | } |
243 | 234 | ||
@@ -262,6 +253,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | |||
262 | struct acpi_bit_register_info *sleep_type_reg_info; | 253 | struct acpi_bit_register_info *sleep_type_reg_info; |
263 | struct acpi_bit_register_info *sleep_enable_reg_info; | 254 | struct acpi_bit_register_info *sleep_enable_reg_info; |
264 | u32 in_value; | 255 | u32 in_value; |
256 | struct acpi_object_list arg_list; | ||
257 | union acpi_object arg; | ||
265 | acpi_status status; | 258 | acpi_status status; |
266 | 259 | ||
267 | ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); | 260 | ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); |
@@ -307,6 +300,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | |||
307 | return_ACPI_STATUS(status); | 300 | return_ACPI_STATUS(status); |
308 | } | 301 | } |
309 | 302 | ||
303 | /* Execute the _GTS method */ | ||
304 | |||
305 | arg_list.count = 1; | ||
306 | arg_list.pointer = &arg; | ||
307 | arg.type = ACPI_TYPE_INTEGER; | ||
308 | arg.integer.value = sleep_state; | ||
309 | |||
310 | status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); | ||
311 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
312 | return_ACPI_STATUS(status); | ||
313 | } | ||
314 | |||
310 | /* Get current value of PM1A control */ | 315 | /* Get current value of PM1A control */ |
311 | 316 | ||
312 | status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); | 317 | status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); |
@@ -473,17 +478,18 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) | |||
473 | 478 | ||
474 | /******************************************************************************* | 479 | /******************************************************************************* |
475 | * | 480 | * |
476 | * FUNCTION: acpi_leave_sleep_state | 481 | * FUNCTION: acpi_leave_sleep_state_prep |
477 | * | 482 | * |
478 | * PARAMETERS: sleep_state - Which sleep state we just exited | 483 | * PARAMETERS: sleep_state - Which sleep state we are exiting |
479 | * | 484 | * |
480 | * RETURN: Status | 485 | * RETURN: Status |
481 | * | 486 | * |
482 | * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep | 487 | * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a |
483 | * Called with interrupts ENABLED. | 488 | * sleep. |
489 | * Called with interrupts DISABLED. | ||
484 | * | 490 | * |
485 | ******************************************************************************/ | 491 | ******************************************************************************/ |
486 | acpi_status acpi_leave_sleep_state(u8 sleep_state) | 492 | acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) |
487 | { | 493 | { |
488 | struct acpi_object_list arg_list; | 494 | struct acpi_object_list arg_list; |
489 | union acpi_object arg; | 495 | union acpi_object arg; |
@@ -493,7 +499,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) | |||
493 | u32 PM1Acontrol; | 499 | u32 PM1Acontrol; |
494 | u32 PM1Bcontrol; | 500 | u32 PM1Bcontrol; |
495 | 501 | ||
496 | ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); | 502 | ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); |
497 | 503 | ||
498 | /* | 504 | /* |
499 | * Set SLP_TYPE and SLP_EN to state S0. | 505 | * Set SLP_TYPE and SLP_EN to state S0. |
@@ -540,6 +546,41 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) | |||
540 | } | 546 | } |
541 | } | 547 | } |
542 | 548 | ||
549 | /* Execute the _BFS method */ | ||
550 | |||
551 | arg_list.count = 1; | ||
552 | arg_list.pointer = &arg; | ||
553 | arg.type = ACPI_TYPE_INTEGER; | ||
554 | arg.integer.value = sleep_state; | ||
555 | |||
556 | status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); | ||
557 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
558 | ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); | ||
559 | } | ||
560 | |||
561 | return_ACPI_STATUS(status); | ||
562 | } | ||
563 | |||
564 | /******************************************************************************* | ||
565 | * | ||
566 | * FUNCTION: acpi_leave_sleep_state | ||
567 | * | ||
568 | * PARAMETERS: sleep_state - Which sleep state we just exited | ||
569 | * | ||
570 | * RETURN: Status | ||
571 | * | ||
572 | * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep | ||
573 | * Called with interrupts ENABLED. | ||
574 | * | ||
575 | ******************************************************************************/ | ||
576 | acpi_status acpi_leave_sleep_state(u8 sleep_state) | ||
577 | { | ||
578 | struct acpi_object_list arg_list; | ||
579 | union acpi_object arg; | ||
580 | acpi_status status; | ||
581 | |||
582 | ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); | ||
583 | |||
543 | /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ | 584 | /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ |
544 | 585 | ||
545 | acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; | 586 | acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; |
@@ -558,12 +599,6 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) | |||
558 | ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); | 599 | ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); |
559 | } | 600 | } |
560 | 601 | ||
561 | arg.integer.value = sleep_state; | ||
562 | status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); | ||
563 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
564 | ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); | ||
565 | } | ||
566 | |||
567 | /* | 602 | /* |
568 | * GPEs must be enabled before _WAK is called as GPEs | 603 | * GPEs must be enabled before _WAK is called as GPEs |
569 | * might get fired there | 604 | * might get fired there |
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index ab04d848b19d..0822d9fc1cb4 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
@@ -38,9 +38,9 @@ ACPI_MODULE_NAME("numa"); | |||
38 | static nodemask_t nodes_found_map = NODE_MASK_NONE; | 38 | static nodemask_t nodes_found_map = NODE_MASK_NONE; |
39 | 39 | ||
40 | /* maps to convert between proximity domain and logical node ID */ | 40 | /* maps to convert between proximity domain and logical node ID */ |
41 | static int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] | 41 | static int pxm_to_node_map[MAX_PXM_DOMAINS] |
42 | = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; | 42 | = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; |
43 | static int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] | 43 | static int node_to_pxm_map[MAX_NUMNODES] |
44 | = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; | 44 | = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; |
45 | 45 | ||
46 | int pxm_to_node(int pxm) | 46 | int pxm_to_node(int pxm) |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index aabc6ca4a81c..e96f3d933f67 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -77,11 +77,55 @@ static struct workqueue_struct *kacpi_notify_wq; | |||
77 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ | 77 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ |
78 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; | 78 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; |
79 | 79 | ||
80 | static int osi_linux; /* disable _OSI(Linux) by default */ | 80 | /* |
81 | * "Ode to _OSI(Linux)" | ||
82 | * | ||
83 | * osi_linux -- Control response to BIOS _OSI(Linux) query. | ||
84 | * | ||
85 | * As Linux evolves, the features that it supports change. | ||
86 | * So an OSI string such as "Linux" is not specific enough | ||
87 | * to be useful across multiple versions of Linux. It | ||
88 | * doesn't identify any particular feature, interface, | ||
89 | * or even any particular version of Linux... | ||
90 | * | ||
91 | * Unfortunately, Linux-2.6.22 and earlier responded "yes" | ||
92 | * to a BIOS _OSI(Linux) query. When | ||
93 | * a reference mobile BIOS started using it, its use | ||
94 | * started to spread to many vendor platforms. | ||
95 | * As it is not supportable, we need to halt that spread. | ||
96 | * | ||
97 | * Today, most BIOS references to _OSI(Linux) are noise -- | ||
98 | * they have no functional effect and are just dead code | ||
99 | * carried over from the reference BIOS. | ||
100 | * | ||
101 | * The next most common case is that _OSI(Linux) harms Linux, | ||
102 | * usually by causing the BIOS to follow paths that are | ||
103 | * not tested during Windows validation. | ||
104 | * | ||
105 | * Finally, there is a short list of platforms | ||
106 | * where OSI(Linux) benefits Linux. | ||
107 | * | ||
108 | * In Linux-2.6.23, OSI(Linux) is first disabled by default. | ||
109 | * DMI is used to disable the dmesg warning about OSI(Linux) | ||
110 | * on platforms where it is known to have no effect. | ||
111 | * But a dmesg warning remains for systems where | ||
112 | * we do not know if OSI(Linux) is good or bad for the system. | ||
113 | * DMI is also used to enable OSI(Linux) for the machines | ||
114 | * that are known to need it. | ||
115 | * | ||
116 | * BIOS writers should NOT query _OSI(Linux) on future systems. | ||
117 | * It will be ignored by default, and to get Linux to | ||
118 | * not ignore it will require a kernel source update to | ||
119 | * add a DMI entry, or a boot-time "acpi_osi=Linux" invocation. | ||
120 | */ | ||
121 | #define OSI_LINUX_ENABLE 0 | ||
81 | 122 | ||
82 | #ifdef CONFIG_DMI | 123 | struct osi_linux { |
83 | static struct __initdata dmi_system_id acpi_osl_dmi_table[]; | 124 | unsigned int enable:1; |
84 | #endif | 125 | unsigned int dmi:1; |
126 | unsigned int cmdline:1; | ||
127 | unsigned int known:1; | ||
128 | } osi_linux = { OSI_LINUX_ENABLE, 0, 0, 0}; | ||
85 | 129 | ||
86 | static void __init acpi_request_region (struct acpi_generic_address *addr, | 130 | static void __init acpi_request_region (struct acpi_generic_address *addr, |
87 | unsigned int length, char *desc) | 131 | unsigned int length, char *desc) |
@@ -133,7 +177,6 @@ device_initcall(acpi_reserve_resources); | |||
133 | 177 | ||
134 | acpi_status __init acpi_os_initialize(void) | 178 | acpi_status __init acpi_os_initialize(void) |
135 | { | 179 | { |
136 | dmi_check_system(acpi_osl_dmi_table); | ||
137 | return AE_OK; | 180 | return AE_OK; |
138 | } | 181 | } |
139 | 182 | ||
@@ -207,8 +250,12 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) | |||
207 | "System description tables not found\n"); | 250 | "System description tables not found\n"); |
208 | return 0; | 251 | return 0; |
209 | } | 252 | } |
210 | } else | 253 | } else { |
211 | return acpi_find_rsdp(); | 254 | acpi_physical_address pa = 0; |
255 | |||
256 | acpi_find_root_pointer(&pa); | ||
257 | return pa; | ||
258 | } | ||
212 | } | 259 | } |
213 | 260 | ||
214 | void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | 261 | void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) |
@@ -387,17 +434,14 @@ acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width) | |||
387 | if (!value) | 434 | if (!value) |
388 | value = &dummy; | 435 | value = &dummy; |
389 | 436 | ||
390 | switch (width) { | 437 | *value = 0; |
391 | case 8: | 438 | if (width <= 8) { |
392 | *(u8 *) value = inb(port); | 439 | *(u8 *) value = inb(port); |
393 | break; | 440 | } else if (width <= 16) { |
394 | case 16: | ||
395 | *(u16 *) value = inw(port); | 441 | *(u16 *) value = inw(port); |
396 | break; | 442 | } else if (width <= 32) { |
397 | case 32: | ||
398 | *(u32 *) value = inl(port); | 443 | *(u32 *) value = inl(port); |
399 | break; | 444 | } else { |
400 | default: | ||
401 | BUG(); | 445 | BUG(); |
402 | } | 446 | } |
403 | 447 | ||
@@ -408,17 +452,13 @@ EXPORT_SYMBOL(acpi_os_read_port); | |||
408 | 452 | ||
409 | acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width) | 453 | acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width) |
410 | { | 454 | { |
411 | switch (width) { | 455 | if (width <= 8) { |
412 | case 8: | ||
413 | outb(value, port); | 456 | outb(value, port); |
414 | break; | 457 | } else if (width <= 16) { |
415 | case 16: | ||
416 | outw(value, port); | 458 | outw(value, port); |
417 | break; | 459 | } else if (width <= 32) { |
418 | case 32: | ||
419 | outl(value, port); | 460 | outl(value, port); |
420 | break; | 461 | } else { |
421 | default: | ||
422 | BUG(); | 462 | BUG(); |
423 | } | 463 | } |
424 | 464 | ||
@@ -971,13 +1011,37 @@ static int __init acpi_os_name_setup(char *str) | |||
971 | 1011 | ||
972 | __setup("acpi_os_name=", acpi_os_name_setup); | 1012 | __setup("acpi_os_name=", acpi_os_name_setup); |
973 | 1013 | ||
974 | static void enable_osi_linux(int enable) { | 1014 | static void __init set_osi_linux(unsigned int enable) |
1015 | { | ||
1016 | if (osi_linux.enable != enable) { | ||
1017 | osi_linux.enable = enable; | ||
1018 | printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n", | ||
1019 | enable ? "Add": "Delet"); | ||
1020 | } | ||
1021 | return; | ||
1022 | } | ||
1023 | |||
1024 | static void __init acpi_cmdline_osi_linux(unsigned int enable) | ||
1025 | { | ||
1026 | osi_linux.cmdline = 1; /* cmdline set the default */ | ||
1027 | set_osi_linux(enable); | ||
1028 | |||
1029 | return; | ||
1030 | } | ||
1031 | |||
1032 | void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) | ||
1033 | { | ||
1034 | osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */ | ||
975 | 1035 | ||
976 | if (osi_linux != enable) | 1036 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); |
977 | printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n", | 1037 | |
978 | enable ? "En": "Dis"); | 1038 | if (enable == -1) |
1039 | return; | ||
1040 | |||
1041 | osi_linux.known = 1; /* DMI knows which OSI(Linux) default needed */ | ||
1042 | |||
1043 | set_osi_linux(enable); | ||
979 | 1044 | ||
980 | osi_linux = enable; | ||
981 | return; | 1045 | return; |
982 | } | 1046 | } |
983 | 1047 | ||
@@ -994,12 +1058,12 @@ static int __init acpi_osi_setup(char *str) | |||
994 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | 1058 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); |
995 | acpi_gbl_create_osi_method = FALSE; | 1059 | acpi_gbl_create_osi_method = FALSE; |
996 | } else if (!strcmp("!Linux", str)) { | 1060 | } else if (!strcmp("!Linux", str)) { |
997 | enable_osi_linux(0); | 1061 | acpi_cmdline_osi_linux(0); /* !enable */ |
998 | } else if (*str == '!') { | 1062 | } else if (*str == '!') { |
999 | if (acpi_osi_invalidate(++str) == AE_OK) | 1063 | if (acpi_osi_invalidate(++str) == AE_OK) |
1000 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); | 1064 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); |
1001 | } else if (!strcmp("Linux", str)) { | 1065 | } else if (!strcmp("Linux", str)) { |
1002 | enable_osi_linux(1); | 1066 | acpi_cmdline_osi_linux(1); /* enable */ |
1003 | } else if (*osi_additional_string == '\0') { | 1067 | } else if (*osi_additional_string == '\0') { |
1004 | strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); | 1068 | strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); |
1005 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); | 1069 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); |
@@ -1148,6 +1212,34 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) | |||
1148 | return (AE_OK); | 1212 | return (AE_OK); |
1149 | } | 1213 | } |
1150 | 1214 | ||
1215 | /** | ||
1216 | * acpi_dmi_dump - dump DMI slots needed for blacklist entry | ||
1217 | * | ||
1218 | * Returns 0 on success | ||
1219 | */ | ||
1220 | int acpi_dmi_dump(void) | ||
1221 | { | ||
1222 | |||
1223 | if (!dmi_available) | ||
1224 | return -1; | ||
1225 | |||
1226 | printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n", | ||
1227 | dmi_get_slot(DMI_SYS_VENDOR)); | ||
1228 | printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n", | ||
1229 | dmi_get_slot(DMI_PRODUCT_NAME)); | ||
1230 | printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n", | ||
1231 | dmi_get_slot(DMI_PRODUCT_VERSION)); | ||
1232 | printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n", | ||
1233 | dmi_get_slot(DMI_BOARD_NAME)); | ||
1234 | printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n", | ||
1235 | dmi_get_slot(DMI_BIOS_VENDOR)); | ||
1236 | printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n", | ||
1237 | dmi_get_slot(DMI_BIOS_DATE)); | ||
1238 | |||
1239 | return 0; | ||
1240 | } | ||
1241 | |||
1242 | |||
1151 | /****************************************************************************** | 1243 | /****************************************************************************** |
1152 | * | 1244 | * |
1153 | * FUNCTION: acpi_os_validate_interface | 1245 | * FUNCTION: acpi_os_validate_interface |
@@ -1167,13 +1259,29 @@ acpi_os_validate_interface (char *interface) | |||
1167 | if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) | 1259 | if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) |
1168 | return AE_OK; | 1260 | return AE_OK; |
1169 | if (!strcmp("Linux", interface)) { | 1261 | if (!strcmp("Linux", interface)) { |
1170 | printk(KERN_WARNING PREFIX | 1262 | |
1171 | "System BIOS is requesting _OSI(Linux)\n"); | 1263 | printk(KERN_NOTICE PREFIX |
1172 | printk(KERN_WARNING PREFIX | 1264 | "BIOS _OSI(Linux) query %s%s\n", |
1173 | "If \"acpi_osi=Linux\" works better,\n" | 1265 | osi_linux.enable ? "honored" : "ignored", |
1174 | "Please send dmidecode " | 1266 | osi_linux.cmdline ? " via cmdline" : |
1175 | "to linux-acpi@vger.kernel.org\n"); | 1267 | osi_linux.dmi ? " via DMI" : ""); |
1176 | if(osi_linux) | 1268 | |
1269 | if (!osi_linux.dmi) { | ||
1270 | if (acpi_dmi_dump()) | ||
1271 | printk(KERN_NOTICE PREFIX | ||
1272 | "[please extract dmidecode output]\n"); | ||
1273 | printk(KERN_NOTICE PREFIX | ||
1274 | "Please send DMI info above to " | ||
1275 | "linux-acpi@vger.kernel.org\n"); | ||
1276 | } | ||
1277 | if (!osi_linux.known && !osi_linux.cmdline) { | ||
1278 | printk(KERN_NOTICE PREFIX | ||
1279 | "If \"acpi_osi=%sLinux\" works better, " | ||
1280 | "please notify linux-acpi@vger.kernel.org\n", | ||
1281 | osi_linux.enable ? "!" : ""); | ||
1282 | } | ||
1283 | |||
1284 | if (osi_linux.enable) | ||
1177 | return AE_OK; | 1285 | return AE_OK; |
1178 | } | 1286 | } |
1179 | return AE_SUPPORT; | 1287 | return AE_SUPPORT; |
@@ -1205,28 +1313,4 @@ acpi_os_validate_address ( | |||
1205 | return AE_OK; | 1313 | return AE_OK; |
1206 | } | 1314 | } |
1207 | 1315 | ||
1208 | #ifdef CONFIG_DMI | ||
1209 | static int dmi_osi_linux(const struct dmi_system_id *d) | ||
1210 | { | ||
1211 | printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident); | ||
1212 | enable_osi_linux(1); | ||
1213 | return 0; | ||
1214 | } | ||
1215 | |||
1216 | static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { | ||
1217 | /* | ||
1218 | * Boxes that need _OSI(Linux) | ||
1219 | */ | ||
1220 | { | ||
1221 | .callback = dmi_osi_linux, | ||
1222 | .ident = "Intel Napa CRB", | ||
1223 | .matches = { | ||
1224 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), | ||
1225 | DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"), | ||
1226 | }, | ||
1227 | }, | ||
1228 | {} | ||
1229 | }; | ||
1230 | #endif /* CONFIG_DMI */ | ||
1231 | |||
1232 | #endif | 1316 | #endif |
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 028969370bbf..388300de005d 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c | |||
@@ -294,9 +294,6 @@ int acpi_pci_unbind(struct acpi_device *device) | |||
294 | acpi_get_data(device->handle, acpi_pci_data_handler, | 294 | acpi_get_data(device->handle, acpi_pci_data_handler, |
295 | (void **)&data); | 295 | (void **)&data); |
296 | if (ACPI_FAILURE(status)) { | 296 | if (ACPI_FAILURE(status)) { |
297 | ACPI_EXCEPTION((AE_INFO, status, | ||
298 | "Unable to get data from device %s", | ||
299 | acpi_device_bid(device))); | ||
300 | result = -ENODEV; | 297 | result = -ENODEV; |
301 | goto end; | 298 | goto end; |
302 | } | 299 | } |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index dd3186abe07a..62010c2481b3 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -429,6 +429,15 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
429 | &polarity, &link, | 429 | &polarity, &link, |
430 | acpi_pci_allocate_irq); | 430 | acpi_pci_allocate_irq); |
431 | 431 | ||
432 | if (irq < 0) { | ||
433 | /* | ||
434 | * IDE legacy mode controller IRQs are magic. Why do compat | ||
435 | * extensions always make such a nasty mess. | ||
436 | */ | ||
437 | if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && | ||
438 | (dev->class & 0x05) == 0) | ||
439 | return 0; | ||
440 | } | ||
432 | /* | 441 | /* |
433 | * No IRQ known to the ACPI subsystem - maybe the BIOS / | 442 | * No IRQ known to the ACPI subsystem - maybe the BIOS / |
434 | * driver reported one, then use it. Exit in any case. | 443 | * driver reported one, then use it. Exit in any case. |
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index c9f526e55392..5400ea173f6f 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -911,7 +911,7 @@ __setup("acpi_irq_balance", acpi_irq_balance_set); | |||
911 | 911 | ||
912 | /* FIXME: we will remove this interface after all drivers call pci_disable_device */ | 912 | /* FIXME: we will remove this interface after all drivers call pci_disable_device */ |
913 | static struct sysdev_class irqrouter_sysdev_class = { | 913 | static struct sysdev_class irqrouter_sysdev_class = { |
914 | set_kset_name("irqrouter"), | 914 | .name = "irqrouter", |
915 | .resume = irqrouter_resume, | 915 | .resume = irqrouter_resume, |
916 | }; | 916 | }; |
917 | 917 | ||
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 235a51e328c3..c53113e18004 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -494,7 +494,7 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id) | |||
494 | if (apic_id == -1) | 494 | if (apic_id == -1) |
495 | return apic_id; | 495 | return apic_id; |
496 | 496 | ||
497 | for (i = 0; i < NR_CPUS; ++i) { | 497 | for_each_possible_cpu(i) { |
498 | if (cpu_physical_id(i) == apic_id) | 498 | if (cpu_physical_id(i) == apic_id) |
499 | return i; | 499 | return i; |
500 | } | 500 | } |
@@ -612,12 +612,6 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) | |||
612 | request_region(pr->throttling.address, 6, "ACPI CPU throttle"); | 612 | request_region(pr->throttling.address, 6, "ACPI CPU throttle"); |
613 | } | 613 | } |
614 | 614 | ||
615 | #ifdef CONFIG_CPU_FREQ | ||
616 | acpi_processor_ppc_has_changed(pr); | ||
617 | #endif | ||
618 | acpi_processor_get_throttling_info(pr); | ||
619 | acpi_processor_get_limit_info(pr); | ||
620 | |||
621 | return 0; | 615 | return 0; |
622 | } | 616 | } |
623 | 617 | ||
@@ -638,7 +632,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) | |||
638 | return 0; | 632 | return 0; |
639 | } | 633 | } |
640 | 634 | ||
641 | BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0)); | 635 | BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); |
642 | 636 | ||
643 | /* | 637 | /* |
644 | * Buggy BIOS check | 638 | * Buggy BIOS check |
@@ -647,7 +641,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) | |||
647 | */ | 641 | */ |
648 | if (processor_device_array[pr->id] != NULL && | 642 | if (processor_device_array[pr->id] != NULL && |
649 | processor_device_array[pr->id] != device) { | 643 | processor_device_array[pr->id] != device) { |
650 | printk(KERN_WARNING "BIOS reported wrong ACPI id" | 644 | printk(KERN_WARNING "BIOS reported wrong ACPI id " |
651 | "for the processor\n"); | 645 | "for the processor\n"); |
652 | return -ENODEV; | 646 | return -ENODEV; |
653 | } | 647 | } |
@@ -665,6 +659,12 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) | |||
665 | /* _PDC call should be done before doing anything else (if reqd.). */ | 659 | /* _PDC call should be done before doing anything else (if reqd.). */ |
666 | arch_acpi_processor_init_pdc(pr); | 660 | arch_acpi_processor_init_pdc(pr); |
667 | acpi_processor_set_pdc(pr); | 661 | acpi_processor_set_pdc(pr); |
662 | #ifdef CONFIG_CPU_FREQ | ||
663 | acpi_processor_ppc_has_changed(pr); | ||
664 | #endif | ||
665 | acpi_processor_get_throttling_info(pr); | ||
666 | acpi_processor_get_limit_info(pr); | ||
667 | |||
668 | 668 | ||
669 | acpi_processor_power_init(pr, device); | 669 | acpi_processor_power_init(pr, device); |
670 | 670 | ||
@@ -684,7 +684,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) | |||
684 | { | 684 | { |
685 | struct acpi_processor *pr = data; | 685 | struct acpi_processor *pr = data; |
686 | struct acpi_device *device = NULL; | 686 | struct acpi_device *device = NULL; |
687 | 687 | int saved; | |
688 | 688 | ||
689 | if (!pr) | 689 | if (!pr) |
690 | return; | 690 | return; |
@@ -694,7 +694,10 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) | |||
694 | 694 | ||
695 | switch (event) { | 695 | switch (event) { |
696 | case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: | 696 | case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: |
697 | saved = pr->performance_platform_limit; | ||
697 | acpi_processor_ppc_has_changed(pr); | 698 | acpi_processor_ppc_has_changed(pr); |
699 | if (saved == pr->performance_platform_limit) | ||
700 | break; | ||
698 | acpi_bus_generate_proc_event(device, event, | 701 | acpi_bus_generate_proc_event(device, event, |
699 | pr->performance_platform_limit); | 702 | pr->performance_platform_limit); |
700 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 703 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
@@ -771,7 +774,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) | |||
771 | 774 | ||
772 | pr = acpi_driver_data(device); | 775 | pr = acpi_driver_data(device); |
773 | 776 | ||
774 | if (pr->id >= NR_CPUS) { | 777 | if (pr->id >= nr_cpu_ids) { |
775 | kfree(pr); | 778 | kfree(pr); |
776 | return 0; | 779 | return 0; |
777 | } | 780 | } |
@@ -809,11 +812,18 @@ static int is_processor_present(acpi_handle handle) | |||
809 | 812 | ||
810 | 813 | ||
811 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | 814 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
812 | if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) { | 815 | /* |
813 | ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); | 816 | * if a processor object does not have an _STA object, |
814 | return 0; | 817 | * OSPM assumes that the processor is present. |
815 | } | 818 | */ |
816 | return 1; | 819 | if (status == AE_NOT_FOUND) |
820 | return 1; | ||
821 | |||
822 | if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT)) | ||
823 | return 1; | ||
824 | |||
825 | ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); | ||
826 | return 0; | ||
817 | } | 827 | } |
818 | 828 | ||
819 | static | 829 | static |
@@ -842,7 +852,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) | |||
842 | if (!pr) | 852 | if (!pr) |
843 | return -ENODEV; | 853 | return -ENODEV; |
844 | 854 | ||
845 | if ((pr->id >= 0) && (pr->id < NR_CPUS)) { | 855 | if ((pr->id >= 0) && (pr->id < nr_cpu_ids)) { |
846 | kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); | 856 | kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); |
847 | } | 857 | } |
848 | return 0; | 858 | return 0; |
@@ -880,13 +890,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) | |||
880 | break; | 890 | break; |
881 | } | 891 | } |
882 | 892 | ||
883 | if (pr->id >= 0 && (pr->id < NR_CPUS)) { | 893 | if (pr->id >= 0 && (pr->id < nr_cpu_ids)) { |
884 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | 894 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); |
885 | break; | 895 | break; |
886 | } | 896 | } |
887 | 897 | ||
888 | result = acpi_processor_start(device); | 898 | result = acpi_processor_start(device); |
889 | if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) { | 899 | if ((!result) && ((pr->id >= 0) && (pr->id < nr_cpu_ids))) { |
890 | kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); | 900 | kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); |
891 | } else { | 901 | } else { |
892 | printk(KERN_ERR PREFIX "Device [%s] failed to start\n", | 902 | printk(KERN_ERR PREFIX "Device [%s] failed to start\n", |
@@ -909,7 +919,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) | |||
909 | return; | 919 | return; |
910 | } | 920 | } |
911 | 921 | ||
912 | if ((pr->id < NR_CPUS) && (cpu_present(pr->id))) | 922 | if ((pr->id < nr_cpu_ids) && (cpu_present(pr->id))) |
913 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | 923 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); |
914 | break; | 924 | break; |
915 | default: | 925 | default: |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f996d0e37689..199ea2146153 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/dmi.h> | 38 | #include <linux/dmi.h> |
39 | #include <linux/moduleparam.h> | 39 | #include <linux/moduleparam.h> |
40 | #include <linux/sched.h> /* need_resched() */ | 40 | #include <linux/sched.h> /* need_resched() */ |
41 | #include <linux/latency.h> | 41 | #include <linux/pm_qos_params.h> |
42 | #include <linux/clockchips.h> | 42 | #include <linux/clockchips.h> |
43 | #include <linux/cpuidle.h> | 43 | #include <linux/cpuidle.h> |
44 | 44 | ||
@@ -76,7 +76,11 @@ static void (*pm_idle_save) (void) __read_mostly; | |||
76 | #define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000)) | 76 | #define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000)) |
77 | 77 | ||
78 | static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; | 78 | static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; |
79 | #ifdef CONFIG_CPU_IDLE | ||
79 | module_param(max_cstate, uint, 0000); | 80 | module_param(max_cstate, uint, 0000); |
81 | #else | ||
82 | module_param(max_cstate, uint, 0644); | ||
83 | #endif | ||
80 | static unsigned int nocst __read_mostly; | 84 | static unsigned int nocst __read_mostly; |
81 | module_param(nocst, uint, 0000); | 85 | module_param(nocst, uint, 0000); |
82 | 86 | ||
@@ -197,6 +201,19 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) | |||
197 | return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); | 201 | return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); |
198 | } | 202 | } |
199 | 203 | ||
204 | static void acpi_safe_halt(void) | ||
205 | { | ||
206 | current_thread_info()->status &= ~TS_POLLING; | ||
207 | /* | ||
208 | * TS_POLLING-cleared state must be visible before we | ||
209 | * test NEED_RESCHED: | ||
210 | */ | ||
211 | smp_mb(); | ||
212 | if (!need_resched()) | ||
213 | safe_halt(); | ||
214 | current_thread_info()->status |= TS_POLLING; | ||
215 | } | ||
216 | |||
200 | #ifndef CONFIG_CPU_IDLE | 217 | #ifndef CONFIG_CPU_IDLE |
201 | 218 | ||
202 | static void | 219 | static void |
@@ -239,19 +256,6 @@ acpi_processor_power_activate(struct acpi_processor *pr, | |||
239 | return; | 256 | return; |
240 | } | 257 | } |
241 | 258 | ||
242 | static void acpi_safe_halt(void) | ||
243 | { | ||
244 | current_thread_info()->status &= ~TS_POLLING; | ||
245 | /* | ||
246 | * TS_POLLING-cleared state must be visible before we | ||
247 | * test NEED_RESCHED: | ||
248 | */ | ||
249 | smp_mb(); | ||
250 | if (!need_resched()) | ||
251 | safe_halt(); | ||
252 | current_thread_info()->status |= TS_POLLING; | ||
253 | } | ||
254 | |||
255 | static atomic_t c3_cpu_count; | 259 | static atomic_t c3_cpu_count; |
256 | 260 | ||
257 | /* Common C-state entry for C2, C3, .. */ | 261 | /* Common C-state entry for C2, C3, .. */ |
@@ -353,6 +357,26 @@ int acpi_processor_resume(struct acpi_device * device) | |||
353 | return 0; | 357 | return 0; |
354 | } | 358 | } |
355 | 359 | ||
360 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | ||
361 | static int tsc_halts_in_c(int state) | ||
362 | { | ||
363 | switch (boot_cpu_data.x86_vendor) { | ||
364 | case X86_VENDOR_AMD: | ||
365 | /* | ||
366 | * AMD Fam10h TSC will tick in all | ||
367 | * C/P/S0/S1 states when this bit is set. | ||
368 | */ | ||
369 | if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | ||
370 | return 0; | ||
371 | /*FALL THROUGH*/ | ||
372 | case X86_VENDOR_INTEL: | ||
373 | /* Several cases known where TSC halts in C2 too */ | ||
374 | default: | ||
375 | return state > ACPI_STATE_C1; | ||
376 | } | ||
377 | } | ||
378 | #endif | ||
379 | |||
356 | #ifndef CONFIG_CPU_IDLE | 380 | #ifndef CONFIG_CPU_IDLE |
357 | static void acpi_processor_idle(void) | 381 | static void acpi_processor_idle(void) |
358 | { | 382 | { |
@@ -512,7 +536,8 @@ static void acpi_processor_idle(void) | |||
512 | 536 | ||
513 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 537 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
514 | /* TSC halts in C2, so notify users */ | 538 | /* TSC halts in C2, so notify users */ |
515 | mark_tsc_unstable("possible TSC halt in C2"); | 539 | if (tsc_halts_in_c(ACPI_STATE_C2)) |
540 | mark_tsc_unstable("possible TSC halt in C2"); | ||
516 | #endif | 541 | #endif |
517 | /* Compute time (ticks) that we were actually asleep */ | 542 | /* Compute time (ticks) that we were actually asleep */ |
518 | sleep_ticks = ticks_elapsed(t1, t2); | 543 | sleep_ticks = ticks_elapsed(t1, t2); |
@@ -530,6 +555,12 @@ static void acpi_processor_idle(void) | |||
530 | break; | 555 | break; |
531 | 556 | ||
532 | case ACPI_STATE_C3: | 557 | case ACPI_STATE_C3: |
558 | acpi_unlazy_tlb(smp_processor_id()); | ||
559 | /* | ||
560 | * Must be done before busmaster disable as we might | ||
561 | * need to access HPET ! | ||
562 | */ | ||
563 | acpi_state_timer_broadcast(pr, cx, 1); | ||
533 | /* | 564 | /* |
534 | * disable bus master | 565 | * disable bus master |
535 | * bm_check implies we need ARB_DIS | 566 | * bm_check implies we need ARB_DIS |
@@ -557,7 +588,6 @@ static void acpi_processor_idle(void) | |||
557 | /* Get start time (ticks) */ | 588 | /* Get start time (ticks) */ |
558 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 589 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); |
559 | /* Invoke C3 */ | 590 | /* Invoke C3 */ |
560 | acpi_state_timer_broadcast(pr, cx, 1); | ||
561 | /* Tell the scheduler that we are going deep-idle: */ | 591 | /* Tell the scheduler that we are going deep-idle: */ |
562 | sched_clock_idle_sleep_event(); | 592 | sched_clock_idle_sleep_event(); |
563 | acpi_cstate_enter(cx); | 593 | acpi_cstate_enter(cx); |
@@ -571,7 +601,8 @@ static void acpi_processor_idle(void) | |||
571 | 601 | ||
572 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 602 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
573 | /* TSC halts in C3, so notify users */ | 603 | /* TSC halts in C3, so notify users */ |
574 | mark_tsc_unstable("TSC halts in C3"); | 604 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
605 | mark_tsc_unstable("TSC halts in C3"); | ||
575 | #endif | 606 | #endif |
576 | /* Compute time (ticks) that we were actually asleep */ | 607 | /* Compute time (ticks) that we were actually asleep */ |
577 | sleep_ticks = ticks_elapsed(t1, t2); | 608 | sleep_ticks = ticks_elapsed(t1, t2); |
@@ -617,7 +648,8 @@ static void acpi_processor_idle(void) | |||
617 | if (cx->promotion.state && | 648 | if (cx->promotion.state && |
618 | ((cx->promotion.state - pr->power.states) <= max_cstate)) { | 649 | ((cx->promotion.state - pr->power.states) <= max_cstate)) { |
619 | if (sleep_ticks > cx->promotion.threshold.ticks && | 650 | if (sleep_ticks > cx->promotion.threshold.ticks && |
620 | cx->promotion.state->latency <= system_latency_constraint()) { | 651 | cx->promotion.state->latency <= |
652 | pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) { | ||
621 | cx->promotion.count++; | 653 | cx->promotion.count++; |
622 | cx->demotion.count = 0; | 654 | cx->demotion.count = 0; |
623 | if (cx->promotion.count >= | 655 | if (cx->promotion.count >= |
@@ -661,7 +693,8 @@ static void acpi_processor_idle(void) | |||
661 | * or if the latency of the current state is unacceptable | 693 | * or if the latency of the current state is unacceptable |
662 | */ | 694 | */ |
663 | if ((pr->power.state - pr->power.states) > max_cstate || | 695 | if ((pr->power.state - pr->power.states) > max_cstate || |
664 | pr->power.state->latency > system_latency_constraint()) { | 696 | pr->power.state->latency > |
697 | pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) { | ||
665 | if (cx->demotion.state) | 698 | if (cx->demotion.state) |
666 | next_state = cx->demotion.state; | 699 | next_state = cx->demotion.state; |
667 | } | 700 | } |
@@ -1169,7 +1202,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) | |||
1169 | "maximum allowed latency: %d usec\n", | 1202 | "maximum allowed latency: %d usec\n", |
1170 | pr->power.state ? pr->power.state - pr->power.states : 0, | 1203 | pr->power.state ? pr->power.state - pr->power.states : 0, |
1171 | max_cstate, (unsigned)pr->power.bm_activity, | 1204 | max_cstate, (unsigned)pr->power.bm_activity, |
1172 | system_latency_constraint()); | 1205 | pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)); |
1173 | 1206 | ||
1174 | seq_puts(seq, "states:\n"); | 1207 | seq_puts(seq, "states:\n"); |
1175 | 1208 | ||
@@ -1373,15 +1406,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
1373 | if (pr->flags.bm_check) | 1406 | if (pr->flags.bm_check) |
1374 | acpi_idle_update_bm_rld(pr, cx); | 1407 | acpi_idle_update_bm_rld(pr, cx); |
1375 | 1408 | ||
1376 | current_thread_info()->status &= ~TS_POLLING; | 1409 | acpi_safe_halt(); |
1377 | /* | ||
1378 | * TS_POLLING-cleared state must be visible before we test | ||
1379 | * NEED_RESCHED: | ||
1380 | */ | ||
1381 | smp_mb(); | ||
1382 | if (!need_resched()) | ||
1383 | safe_halt(); | ||
1384 | current_thread_info()->status |= TS_POLLING; | ||
1385 | 1410 | ||
1386 | cx->usage++; | 1411 | cx->usage++; |
1387 | 1412 | ||
@@ -1399,6 +1424,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
1399 | struct acpi_processor *pr; | 1424 | struct acpi_processor *pr; |
1400 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 1425 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
1401 | u32 t1, t2; | 1426 | u32 t1, t2; |
1427 | int sleep_ticks = 0; | ||
1428 | |||
1402 | pr = processors[smp_processor_id()]; | 1429 | pr = processors[smp_processor_id()]; |
1403 | 1430 | ||
1404 | if (unlikely(!pr)) | 1431 | if (unlikely(!pr)) |
@@ -1407,9 +1434,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
1407 | if (acpi_idle_suspend) | 1434 | if (acpi_idle_suspend) |
1408 | return(acpi_idle_enter_c1(dev, state)); | 1435 | return(acpi_idle_enter_c1(dev, state)); |
1409 | 1436 | ||
1410 | if (pr->flags.bm_check) | ||
1411 | acpi_idle_update_bm_rld(pr, cx); | ||
1412 | |||
1413 | local_irq_disable(); | 1437 | local_irq_disable(); |
1414 | current_thread_info()->status &= ~TS_POLLING; | 1438 | current_thread_info()->status &= ~TS_POLLING; |
1415 | /* | 1439 | /* |
@@ -1424,18 +1448,34 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
1424 | return 0; | 1448 | return 0; |
1425 | } | 1449 | } |
1426 | 1450 | ||
1451 | acpi_unlazy_tlb(smp_processor_id()); | ||
1452 | /* | ||
1453 | * Must be done before busmaster disable as we might need to | ||
1454 | * access HPET ! | ||
1455 | */ | ||
1456 | acpi_state_timer_broadcast(pr, cx, 1); | ||
1457 | |||
1458 | if (pr->flags.bm_check) | ||
1459 | acpi_idle_update_bm_rld(pr, cx); | ||
1460 | |||
1427 | if (cx->type == ACPI_STATE_C3) | 1461 | if (cx->type == ACPI_STATE_C3) |
1428 | ACPI_FLUSH_CPU_CACHE(); | 1462 | ACPI_FLUSH_CPU_CACHE(); |
1429 | 1463 | ||
1430 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 1464 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); |
1431 | acpi_state_timer_broadcast(pr, cx, 1); | 1465 | /* Tell the scheduler that we are going deep-idle: */ |
1466 | sched_clock_idle_sleep_event(); | ||
1432 | acpi_idle_do_entry(cx); | 1467 | acpi_idle_do_entry(cx); |
1433 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 1468 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); |
1434 | 1469 | ||
1435 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 1470 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
1436 | /* TSC could halt in idle, so notify users */ | 1471 | /* TSC could halt in idle, so notify users */ |
1437 | mark_tsc_unstable("TSC halts in idle");; | 1472 | if (tsc_halts_in_c(cx->type)) |
1473 | mark_tsc_unstable("TSC halts in idle");; | ||
1438 | #endif | 1474 | #endif |
1475 | sleep_ticks = ticks_elapsed(t1, t2); | ||
1476 | |||
1477 | /* Tell the scheduler how much we idled: */ | ||
1478 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); | ||
1439 | 1479 | ||
1440 | local_irq_enable(); | 1480 | local_irq_enable(); |
1441 | current_thread_info()->status |= TS_POLLING; | 1481 | current_thread_info()->status |= TS_POLLING; |
@@ -1443,7 +1483,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
1443 | cx->usage++; | 1483 | cx->usage++; |
1444 | 1484 | ||
1445 | acpi_state_timer_broadcast(pr, cx, 0); | 1485 | acpi_state_timer_broadcast(pr, cx, 0); |
1446 | cx->time += ticks_elapsed(t1, t2); | 1486 | cx->time += sleep_ticks; |
1447 | return ticks_elapsed_in_us(t1, t2); | 1487 | return ticks_elapsed_in_us(t1, t2); |
1448 | } | 1488 | } |
1449 | 1489 | ||
@@ -1463,6 +1503,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1463 | struct acpi_processor *pr; | 1503 | struct acpi_processor *pr; |
1464 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 1504 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
1465 | u32 t1, t2; | 1505 | u32 t1, t2; |
1506 | int sleep_ticks = 0; | ||
1507 | |||
1466 | pr = processors[smp_processor_id()]; | 1508 | pr = processors[smp_processor_id()]; |
1467 | 1509 | ||
1468 | if (unlikely(!pr)) | 1510 | if (unlikely(!pr)) |
@@ -1471,6 +1513,15 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1471 | if (acpi_idle_suspend) | 1513 | if (acpi_idle_suspend) |
1472 | return(acpi_idle_enter_c1(dev, state)); | 1514 | return(acpi_idle_enter_c1(dev, state)); |
1473 | 1515 | ||
1516 | if (acpi_idle_bm_check()) { | ||
1517 | if (dev->safe_state) { | ||
1518 | return dev->safe_state->enter(dev, dev->safe_state); | ||
1519 | } else { | ||
1520 | acpi_safe_halt(); | ||
1521 | return 0; | ||
1522 | } | ||
1523 | } | ||
1524 | |||
1474 | local_irq_disable(); | 1525 | local_irq_disable(); |
1475 | current_thread_info()->status &= ~TS_POLLING; | 1526 | current_thread_info()->status &= ~TS_POLLING; |
1476 | /* | 1527 | /* |
@@ -1485,46 +1536,57 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1485 | return 0; | 1536 | return 0; |
1486 | } | 1537 | } |
1487 | 1538 | ||
1539 | /* Tell the scheduler that we are going deep-idle: */ | ||
1540 | sched_clock_idle_sleep_event(); | ||
1488 | /* | 1541 | /* |
1489 | * Must be done before busmaster disable as we might need to | 1542 | * Must be done before busmaster disable as we might need to |
1490 | * access HPET ! | 1543 | * access HPET ! |
1491 | */ | 1544 | */ |
1492 | acpi_state_timer_broadcast(pr, cx, 1); | 1545 | acpi_state_timer_broadcast(pr, cx, 1); |
1493 | 1546 | ||
1494 | if (acpi_idle_bm_check()) { | 1547 | acpi_idle_update_bm_rld(pr, cx); |
1495 | cx = pr->power.bm_state; | ||
1496 | |||
1497 | acpi_idle_update_bm_rld(pr, cx); | ||
1498 | |||
1499 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | ||
1500 | acpi_idle_do_entry(cx); | ||
1501 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | ||
1502 | } else { | ||
1503 | acpi_idle_update_bm_rld(pr, cx); | ||
1504 | 1548 | ||
1549 | /* | ||
1550 | * disable bus master | ||
1551 | * bm_check implies we need ARB_DIS | ||
1552 | * !bm_check implies we need cache flush | ||
1553 | * bm_control implies whether we can do ARB_DIS | ||
1554 | * | ||
1555 | * That leaves a case where bm_check is set and bm_control is | ||
1556 | * not set. In that case we cannot do much, we enter C3 | ||
1557 | * without doing anything. | ||
1558 | */ | ||
1559 | if (pr->flags.bm_check && pr->flags.bm_control) { | ||
1505 | spin_lock(&c3_lock); | 1560 | spin_lock(&c3_lock); |
1506 | c3_cpu_count++; | 1561 | c3_cpu_count++; |
1507 | /* Disable bus master arbitration when all CPUs are in C3 */ | 1562 | /* Disable bus master arbitration when all CPUs are in C3 */ |
1508 | if (c3_cpu_count == num_online_cpus()) | 1563 | if (c3_cpu_count == num_online_cpus()) |
1509 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); | 1564 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); |
1510 | spin_unlock(&c3_lock); | 1565 | spin_unlock(&c3_lock); |
1566 | } else if (!pr->flags.bm_check) { | ||
1567 | ACPI_FLUSH_CPU_CACHE(); | ||
1568 | } | ||
1511 | 1569 | ||
1512 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 1570 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); |
1513 | acpi_idle_do_entry(cx); | 1571 | acpi_idle_do_entry(cx); |
1514 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 1572 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); |
1515 | 1573 | ||
1574 | /* Re-enable bus master arbitration */ | ||
1575 | if (pr->flags.bm_check && pr->flags.bm_control) { | ||
1516 | spin_lock(&c3_lock); | 1576 | spin_lock(&c3_lock); |
1517 | /* Re-enable bus master arbitration */ | 1577 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); |
1518 | if (c3_cpu_count == num_online_cpus()) | ||
1519 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); | ||
1520 | c3_cpu_count--; | 1578 | c3_cpu_count--; |
1521 | spin_unlock(&c3_lock); | 1579 | spin_unlock(&c3_lock); |
1522 | } | 1580 | } |
1523 | 1581 | ||
1524 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 1582 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
1525 | /* TSC could halt in idle, so notify users */ | 1583 | /* TSC could halt in idle, so notify users */ |
1526 | mark_tsc_unstable("TSC halts in idle"); | 1584 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
1585 | mark_tsc_unstable("TSC halts in idle"); | ||
1527 | #endif | 1586 | #endif |
1587 | sleep_ticks = ticks_elapsed(t1, t2); | ||
1588 | /* Tell the scheduler how much we idled: */ | ||
1589 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); | ||
1528 | 1590 | ||
1529 | local_irq_enable(); | 1591 | local_irq_enable(); |
1530 | current_thread_info()->status |= TS_POLLING; | 1592 | current_thread_info()->status |= TS_POLLING; |
@@ -1532,7 +1594,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1532 | cx->usage++; | 1594 | cx->usage++; |
1533 | 1595 | ||
1534 | acpi_state_timer_broadcast(pr, cx, 0); | 1596 | acpi_state_timer_broadcast(pr, cx, 0); |
1535 | cx->time += ticks_elapsed(t1, t2); | 1597 | cx->time += sleep_ticks; |
1536 | return ticks_elapsed_in_us(t1, t2); | 1598 | return ticks_elapsed_in_us(t1, t2); |
1537 | } | 1599 | } |
1538 | 1600 | ||
@@ -1584,12 +1646,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) | |||
1584 | case ACPI_STATE_C1: | 1646 | case ACPI_STATE_C1: |
1585 | state->flags |= CPUIDLE_FLAG_SHALLOW; | 1647 | state->flags |= CPUIDLE_FLAG_SHALLOW; |
1586 | state->enter = acpi_idle_enter_c1; | 1648 | state->enter = acpi_idle_enter_c1; |
1649 | dev->safe_state = state; | ||
1587 | break; | 1650 | break; |
1588 | 1651 | ||
1589 | case ACPI_STATE_C2: | 1652 | case ACPI_STATE_C2: |
1590 | state->flags |= CPUIDLE_FLAG_BALANCED; | 1653 | state->flags |= CPUIDLE_FLAG_BALANCED; |
1591 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | 1654 | state->flags |= CPUIDLE_FLAG_TIME_VALID; |
1592 | state->enter = acpi_idle_enter_simple; | 1655 | state->enter = acpi_idle_enter_simple; |
1656 | dev->safe_state = state; | ||
1593 | break; | 1657 | break; |
1594 | 1658 | ||
1595 | case ACPI_STATE_C3: | 1659 | case ACPI_STATE_C3: |
@@ -1610,14 +1674,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) | |||
1610 | if (!count) | 1674 | if (!count) |
1611 | return -EINVAL; | 1675 | return -EINVAL; |
1612 | 1676 | ||
1613 | /* find the deepest state that can handle active BM */ | ||
1614 | if (pr->flags.bm_check) { | ||
1615 | for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) | ||
1616 | if (pr->power.states[i].type == ACPI_STATE_C3) | ||
1617 | break; | ||
1618 | pr->power.bm_state = &pr->power.states[i-1]; | ||
1619 | } | ||
1620 | |||
1621 | return 0; | 1677 | return 0; |
1622 | } | 1678 | } |
1623 | 1679 | ||
@@ -1658,13 +1714,15 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1658 | 1714 | ||
1659 | if (!first_run) { | 1715 | if (!first_run) { |
1660 | dmi_check_system(processor_power_dmi_table); | 1716 | dmi_check_system(processor_power_dmi_table); |
1717 | max_cstate = acpi_processor_cstate_check(max_cstate); | ||
1661 | if (max_cstate < ACPI_C_STATES_MAX) | 1718 | if (max_cstate < ACPI_C_STATES_MAX) |
1662 | printk(KERN_NOTICE | 1719 | printk(KERN_NOTICE |
1663 | "ACPI: processor limited to max C-state %d\n", | 1720 | "ACPI: processor limited to max C-state %d\n", |
1664 | max_cstate); | 1721 | max_cstate); |
1665 | first_run++; | 1722 | first_run++; |
1666 | #if !defined (CONFIG_CPU_IDLE) && defined (CONFIG_SMP) | 1723 | #if !defined(CONFIG_CPU_IDLE) && defined(CONFIG_SMP) |
1667 | register_latency_notifier(&acpi_processor_latency_notifier); | 1724 | pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY, |
1725 | &acpi_processor_latency_notifier); | ||
1668 | #endif | 1726 | #endif |
1669 | } | 1727 | } |
1670 | 1728 | ||
@@ -1751,7 +1809,8 @@ int acpi_processor_power_exit(struct acpi_processor *pr, | |||
1751 | */ | 1809 | */ |
1752 | cpu_idle_wait(); | 1810 | cpu_idle_wait(); |
1753 | #ifdef CONFIG_SMP | 1811 | #ifdef CONFIG_SMP |
1754 | unregister_latency_notifier(&acpi_processor_latency_notifier); | 1812 | pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY, |
1813 | &acpi_processor_latency_notifier); | ||
1755 | #endif | 1814 | #endif |
1756 | } | 1815 | } |
1757 | #endif | 1816 | #endif |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 0b8204e7082a..1685b40abda7 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/sched.h> | ||
32 | #include <linux/cpufreq.h> | 33 | #include <linux/cpufreq.h> |
33 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
34 | #include <linux/seq_file.h> | 35 | #include <linux/seq_file.h> |
@@ -70,7 +71,55 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) | |||
70 | 71 | ||
71 | int acpi_processor_tstate_has_changed(struct acpi_processor *pr) | 72 | int acpi_processor_tstate_has_changed(struct acpi_processor *pr) |
72 | { | 73 | { |
73 | return acpi_processor_get_platform_limit(pr); | 74 | int result = 0; |
75 | int throttling_limit; | ||
76 | int current_state; | ||
77 | struct acpi_processor_limit *limit; | ||
78 | int target_state; | ||
79 | |||
80 | result = acpi_processor_get_platform_limit(pr); | ||
81 | if (result) { | ||
82 | /* Throttling Limit is unsupported */ | ||
83 | return result; | ||
84 | } | ||
85 | |||
86 | throttling_limit = pr->throttling_platform_limit; | ||
87 | if (throttling_limit >= pr->throttling.state_count) { | ||
88 | /* Uncorrect Throttling Limit */ | ||
89 | return -EINVAL; | ||
90 | } | ||
91 | |||
92 | current_state = pr->throttling.state; | ||
93 | if (current_state > throttling_limit) { | ||
94 | /* | ||
95 | * The current state can meet the requirement of | ||
96 | * _TPC limit. But it is reasonable that OSPM changes | ||
97 | * t-states from high to low for better performance. | ||
98 | * Of course the limit condition of thermal | ||
99 | * and user should be considered. | ||
100 | */ | ||
101 | limit = &pr->limit; | ||
102 | target_state = throttling_limit; | ||
103 | if (limit->thermal.tx > target_state) | ||
104 | target_state = limit->thermal.tx; | ||
105 | if (limit->user.tx > target_state) | ||
106 | target_state = limit->user.tx; | ||
107 | } else if (current_state == throttling_limit) { | ||
108 | /* | ||
109 | * Unnecessary to change the throttling state | ||
110 | */ | ||
111 | return 0; | ||
112 | } else { | ||
113 | /* | ||
114 | * If the current state is lower than the limit of _TPC, it | ||
115 | * will be forced to switch to the throttling state defined | ||
116 | * by throttling_platfor_limit. | ||
117 | * Because the previous state meets with the limit condition | ||
118 | * of thermal and user, it is unnecessary to check it again. | ||
119 | */ | ||
120 | target_state = throttling_limit; | ||
121 | } | ||
122 | return acpi_processor_set_throttling(pr, target_state); | ||
74 | } | 123 | } |
75 | 124 | ||
76 | /* | 125 | /* |
@@ -83,6 +132,7 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) | |||
83 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 132 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
84 | union acpi_object *ptc = NULL; | 133 | union acpi_object *ptc = NULL; |
85 | union acpi_object obj = { 0 }; | 134 | union acpi_object obj = { 0 }; |
135 | struct acpi_processor_throttling *throttling; | ||
86 | 136 | ||
87 | status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); | 137 | status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); |
88 | if (ACPI_FAILURE(status)) { | 138 | if (ACPI_FAILURE(status)) { |
@@ -134,6 +184,22 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) | |||
134 | memcpy(&pr->throttling.status_register, obj.buffer.pointer, | 184 | memcpy(&pr->throttling.status_register, obj.buffer.pointer, |
135 | sizeof(struct acpi_ptc_register)); | 185 | sizeof(struct acpi_ptc_register)); |
136 | 186 | ||
187 | throttling = &pr->throttling; | ||
188 | |||
189 | if ((throttling->control_register.bit_width + | ||
190 | throttling->control_register.bit_offset) > 32) { | ||
191 | printk(KERN_ERR PREFIX "Invalid _PTC control register\n"); | ||
192 | result = -EFAULT; | ||
193 | goto end; | ||
194 | } | ||
195 | |||
196 | if ((throttling->status_register.bit_width + | ||
197 | throttling->status_register.bit_offset) > 32) { | ||
198 | printk(KERN_ERR PREFIX "Invalid _PTC status register\n"); | ||
199 | result = -EFAULT; | ||
200 | goto end; | ||
201 | } | ||
202 | |||
137 | end: | 203 | end: |
138 | kfree(buffer.pointer); | 204 | kfree(buffer.pointer); |
139 | 205 | ||
@@ -328,44 +394,132 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) | |||
328 | return 0; | 394 | return 0; |
329 | } | 395 | } |
330 | 396 | ||
331 | static int acpi_read_throttling_status(struct acpi_processor_throttling | 397 | #ifdef CONFIG_X86 |
332 | *throttling) | 398 | static int acpi_throttling_rdmsr(struct acpi_processor *pr, |
399 | acpi_integer * value) | ||
400 | { | ||
401 | struct cpuinfo_x86 *c; | ||
402 | u64 msr_high, msr_low; | ||
403 | unsigned int cpu; | ||
404 | u64 msr = 0; | ||
405 | int ret = -1; | ||
406 | |||
407 | cpu = pr->id; | ||
408 | c = &cpu_data(cpu); | ||
409 | |||
410 | if ((c->x86_vendor != X86_VENDOR_INTEL) || | ||
411 | !cpu_has(c, X86_FEATURE_ACPI)) { | ||
412 | printk(KERN_ERR PREFIX | ||
413 | "HARDWARE addr space,NOT supported yet\n"); | ||
414 | } else { | ||
415 | msr_low = 0; | ||
416 | msr_high = 0; | ||
417 | rdmsr_safe(MSR_IA32_THERM_CONTROL, | ||
418 | (u32 *)&msr_low , (u32 *) &msr_high); | ||
419 | msr = (msr_high << 32) | msr_low; | ||
420 | *value = (acpi_integer) msr; | ||
421 | ret = 0; | ||
422 | } | ||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) | ||
333 | { | 427 | { |
334 | int value = -1; | 428 | struct cpuinfo_x86 *c; |
429 | unsigned int cpu; | ||
430 | int ret = -1; | ||
431 | u64 msr; | ||
432 | |||
433 | cpu = pr->id; | ||
434 | c = &cpu_data(cpu); | ||
435 | |||
436 | if ((c->x86_vendor != X86_VENDOR_INTEL) || | ||
437 | !cpu_has(c, X86_FEATURE_ACPI)) { | ||
438 | printk(KERN_ERR PREFIX | ||
439 | "HARDWARE addr space,NOT supported yet\n"); | ||
440 | } else { | ||
441 | msr = value; | ||
442 | wrmsr_safe(MSR_IA32_THERM_CONTROL, | ||
443 | msr & 0xffffffff, msr >> 32); | ||
444 | ret = 0; | ||
445 | } | ||
446 | return ret; | ||
447 | } | ||
448 | #else | ||
449 | static int acpi_throttling_rdmsr(struct acpi_processor *pr, | ||
450 | acpi_integer * value) | ||
451 | { | ||
452 | printk(KERN_ERR PREFIX | ||
453 | "HARDWARE addr space,NOT supported yet\n"); | ||
454 | return -1; | ||
455 | } | ||
456 | |||
457 | static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) | ||
458 | { | ||
459 | printk(KERN_ERR PREFIX | ||
460 | "HARDWARE addr space,NOT supported yet\n"); | ||
461 | return -1; | ||
462 | } | ||
463 | #endif | ||
464 | |||
465 | static int acpi_read_throttling_status(struct acpi_processor *pr, | ||
466 | acpi_integer *value) | ||
467 | { | ||
468 | u32 bit_width, bit_offset; | ||
469 | u64 ptc_value; | ||
470 | u64 ptc_mask; | ||
471 | struct acpi_processor_throttling *throttling; | ||
472 | int ret = -1; | ||
473 | |||
474 | throttling = &pr->throttling; | ||
335 | switch (throttling->status_register.space_id) { | 475 | switch (throttling->status_register.space_id) { |
336 | case ACPI_ADR_SPACE_SYSTEM_IO: | 476 | case ACPI_ADR_SPACE_SYSTEM_IO: |
477 | ptc_value = 0; | ||
478 | bit_width = throttling->status_register.bit_width; | ||
479 | bit_offset = throttling->status_register.bit_offset; | ||
480 | |||
337 | acpi_os_read_port((acpi_io_address) throttling->status_register. | 481 | acpi_os_read_port((acpi_io_address) throttling->status_register. |
338 | address, &value, | 482 | address, (u32 *) &ptc_value, |
339 | (u32) throttling->status_register.bit_width * | 483 | (u32) (bit_width + bit_offset)); |
340 | 8); | 484 | ptc_mask = (1 << bit_width) - 1; |
485 | *value = (acpi_integer) ((ptc_value >> bit_offset) & ptc_mask); | ||
486 | ret = 0; | ||
341 | break; | 487 | break; |
342 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | 488 | case ACPI_ADR_SPACE_FIXED_HARDWARE: |
343 | printk(KERN_ERR PREFIX | 489 | ret = acpi_throttling_rdmsr(pr, value); |
344 | "HARDWARE addr space,NOT supported yet\n"); | ||
345 | break; | 490 | break; |
346 | default: | 491 | default: |
347 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", | 492 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", |
348 | (u32) (throttling->status_register.space_id)); | 493 | (u32) (throttling->status_register.space_id)); |
349 | } | 494 | } |
350 | return value; | 495 | return ret; |
351 | } | 496 | } |
352 | 497 | ||
353 | static int acpi_write_throttling_state(struct acpi_processor_throttling | 498 | static int acpi_write_throttling_state(struct acpi_processor *pr, |
354 | *throttling, int value) | 499 | acpi_integer value) |
355 | { | 500 | { |
501 | u32 bit_width, bit_offset; | ||
502 | u64 ptc_value; | ||
503 | u64 ptc_mask; | ||
504 | struct acpi_processor_throttling *throttling; | ||
356 | int ret = -1; | 505 | int ret = -1; |
357 | 506 | ||
507 | throttling = &pr->throttling; | ||
358 | switch (throttling->control_register.space_id) { | 508 | switch (throttling->control_register.space_id) { |
359 | case ACPI_ADR_SPACE_SYSTEM_IO: | 509 | case ACPI_ADR_SPACE_SYSTEM_IO: |
510 | bit_width = throttling->control_register.bit_width; | ||
511 | bit_offset = throttling->control_register.bit_offset; | ||
512 | ptc_mask = (1 << bit_width) - 1; | ||
513 | ptc_value = value & ptc_mask; | ||
514 | |||
360 | acpi_os_write_port((acpi_io_address) throttling-> | 515 | acpi_os_write_port((acpi_io_address) throttling-> |
361 | control_register.address, value, | 516 | control_register.address, |
362 | (u32) throttling->control_register. | 517 | (u32) (ptc_value << bit_offset), |
363 | bit_width * 8); | 518 | (u32) (bit_width + bit_offset)); |
364 | ret = 0; | 519 | ret = 0; |
365 | break; | 520 | break; |
366 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | 521 | case ACPI_ADR_SPACE_FIXED_HARDWARE: |
367 | printk(KERN_ERR PREFIX | 522 | ret = acpi_throttling_wrmsr(pr, value); |
368 | "HARDWARE addr space,NOT supported yet\n"); | ||
369 | break; | 523 | break; |
370 | default: | 524 | default: |
371 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", | 525 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", |
@@ -374,7 +528,8 @@ static int acpi_write_throttling_state(struct acpi_processor_throttling | |||
374 | return ret; | 528 | return ret; |
375 | } | 529 | } |
376 | 530 | ||
377 | static int acpi_get_throttling_state(struct acpi_processor *pr, int value) | 531 | static int acpi_get_throttling_state(struct acpi_processor *pr, |
532 | acpi_integer value) | ||
378 | { | 533 | { |
379 | int i; | 534 | int i; |
380 | 535 | ||
@@ -390,22 +545,26 @@ static int acpi_get_throttling_state(struct acpi_processor *pr, int value) | |||
390 | return i; | 545 | return i; |
391 | } | 546 | } |
392 | 547 | ||
393 | static int acpi_get_throttling_value(struct acpi_processor *pr, int state) | 548 | static int acpi_get_throttling_value(struct acpi_processor *pr, |
549 | int state, acpi_integer *value) | ||
394 | { | 550 | { |
395 | int value = -1; | 551 | int ret = -1; |
552 | |||
396 | if (state >= 0 && state <= pr->throttling.state_count) { | 553 | if (state >= 0 && state <= pr->throttling.state_count) { |
397 | struct acpi_processor_tx_tss *tx = | 554 | struct acpi_processor_tx_tss *tx = |
398 | (struct acpi_processor_tx_tss *)&(pr->throttling. | 555 | (struct acpi_processor_tx_tss *)&(pr->throttling. |
399 | states_tss[state]); | 556 | states_tss[state]); |
400 | value = tx->control; | 557 | *value = tx->control; |
558 | ret = 0; | ||
401 | } | 559 | } |
402 | return value; | 560 | return ret; |
403 | } | 561 | } |
404 | 562 | ||
405 | static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) | 563 | static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) |
406 | { | 564 | { |
407 | int state = 0; | 565 | int state = 0; |
408 | u32 value = 0; | 566 | int ret; |
567 | acpi_integer value; | ||
409 | 568 | ||
410 | if (!pr) | 569 | if (!pr) |
411 | return -EINVAL; | 570 | return -EINVAL; |
@@ -414,20 +573,66 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) | |||
414 | return -ENODEV; | 573 | return -ENODEV; |
415 | 574 | ||
416 | pr->throttling.state = 0; | 575 | pr->throttling.state = 0; |
417 | local_irq_disable(); | 576 | |
418 | value = acpi_read_throttling_status(&pr->throttling); | 577 | value = 0; |
419 | if (value >= 0) { | 578 | ret = acpi_read_throttling_status(pr, &value); |
579 | if (ret >= 0) { | ||
420 | state = acpi_get_throttling_state(pr, value); | 580 | state = acpi_get_throttling_state(pr, value); |
421 | pr->throttling.state = state; | 581 | pr->throttling.state = state; |
422 | } | 582 | } |
423 | local_irq_enable(); | ||
424 | 583 | ||
425 | return 0; | 584 | return 0; |
426 | } | 585 | } |
427 | 586 | ||
428 | static int acpi_processor_get_throttling(struct acpi_processor *pr) | 587 | static int acpi_processor_get_throttling(struct acpi_processor *pr) |
429 | { | 588 | { |
430 | return pr->throttling.acpi_processor_get_throttling(pr); | 589 | cpumask_t saved_mask; |
590 | int ret; | ||
591 | |||
592 | /* | ||
593 | * Migrate task to the cpu pointed by pr. | ||
594 | */ | ||
595 | saved_mask = current->cpus_allowed; | ||
596 | set_cpus_allowed(current, cpumask_of_cpu(pr->id)); | ||
597 | ret = pr->throttling.acpi_processor_get_throttling(pr); | ||
598 | /* restore the previous state */ | ||
599 | set_cpus_allowed(current, saved_mask); | ||
600 | |||
601 | return ret; | ||
602 | } | ||
603 | |||
604 | static int acpi_processor_get_fadt_info(struct acpi_processor *pr) | ||
605 | { | ||
606 | int i, step; | ||
607 | |||
608 | if (!pr->throttling.address) { | ||
609 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); | ||
610 | return -EINVAL; | ||
611 | } else if (!pr->throttling.duty_width) { | ||
612 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n")); | ||
613 | return -EINVAL; | ||
614 | } | ||
615 | /* TBD: Support duty_cycle values that span bit 4. */ | ||
616 | else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) { | ||
617 | printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n"); | ||
618 | return -EINVAL; | ||
619 | } | ||
620 | |||
621 | pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width; | ||
622 | |||
623 | /* | ||
624 | * Compute state values. Note that throttling displays a linear power | ||
625 | * performance relationship (at 50% performance the CPU will consume | ||
626 | * 50% power). Values are in 1/10th of a percent to preserve accuracy. | ||
627 | */ | ||
628 | |||
629 | step = (1000 / pr->throttling.state_count); | ||
630 | |||
631 | for (i = 0; i < pr->throttling.state_count; i++) { | ||
632 | pr->throttling.states[i].performance = 1000 - step * i; | ||
633 | pr->throttling.states[i].power = 1000 - step * i; | ||
634 | } | ||
635 | return 0; | ||
431 | } | 636 | } |
432 | 637 | ||
433 | static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, | 638 | static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, |
@@ -506,7 +711,8 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, | |||
506 | static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, | 711 | static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, |
507 | int state) | 712 | int state) |
508 | { | 713 | { |
509 | u32 value = 0; | 714 | int ret; |
715 | acpi_integer value; | ||
510 | 716 | ||
511 | if (!pr) | 717 | if (!pr) |
512 | return -EINVAL; | 718 | return -EINVAL; |
@@ -523,28 +729,34 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, | |||
523 | if (state < pr->throttling_platform_limit) | 729 | if (state < pr->throttling_platform_limit) |
524 | return -EPERM; | 730 | return -EPERM; |
525 | 731 | ||
526 | local_irq_disable(); | 732 | value = 0; |
527 | 733 | ret = acpi_get_throttling_value(pr, state, &value); | |
528 | value = acpi_get_throttling_value(pr, state); | 734 | if (ret >= 0) { |
529 | if (value >= 0) { | 735 | acpi_write_throttling_state(pr, value); |
530 | acpi_write_throttling_state(&pr->throttling, value); | ||
531 | pr->throttling.state = state; | 736 | pr->throttling.state = state; |
532 | } | 737 | } |
533 | local_irq_enable(); | ||
534 | 738 | ||
535 | return 0; | 739 | return 0; |
536 | } | 740 | } |
537 | 741 | ||
538 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | 742 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state) |
539 | { | 743 | { |
540 | return pr->throttling.acpi_processor_set_throttling(pr, state); | 744 | cpumask_t saved_mask; |
745 | int ret; | ||
746 | /* | ||
747 | * Migrate task to the cpu pointed by pr. | ||
748 | */ | ||
749 | saved_mask = current->cpus_allowed; | ||
750 | set_cpus_allowed(current, cpumask_of_cpu(pr->id)); | ||
751 | ret = pr->throttling.acpi_processor_set_throttling(pr, state); | ||
752 | /* restore the previous state */ | ||
753 | set_cpus_allowed(current, saved_mask); | ||
754 | return ret; | ||
541 | } | 755 | } |
542 | 756 | ||
543 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) | 757 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) |
544 | { | 758 | { |
545 | int result = 0; | 759 | int result = 0; |
546 | int step = 0; | ||
547 | int i = 0; | ||
548 | 760 | ||
549 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 761 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
550 | "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", | 762 | "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", |
@@ -567,6 +779,8 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
567 | &acpi_processor_get_throttling_fadt; | 779 | &acpi_processor_get_throttling_fadt; |
568 | pr->throttling.acpi_processor_set_throttling = | 780 | pr->throttling.acpi_processor_set_throttling = |
569 | &acpi_processor_set_throttling_fadt; | 781 | &acpi_processor_set_throttling_fadt; |
782 | if (acpi_processor_get_fadt_info(pr)) | ||
783 | return 0; | ||
570 | } else { | 784 | } else { |
571 | pr->throttling.acpi_processor_get_throttling = | 785 | pr->throttling.acpi_processor_get_throttling = |
572 | &acpi_processor_get_throttling_ptc; | 786 | &acpi_processor_get_throttling_ptc; |
@@ -576,19 +790,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
576 | 790 | ||
577 | acpi_processor_get_tsd(pr); | 791 | acpi_processor_get_tsd(pr); |
578 | 792 | ||
579 | if (!pr->throttling.address) { | ||
580 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); | ||
581 | return 0; | ||
582 | } else if (!pr->throttling.duty_width) { | ||
583 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n")); | ||
584 | return 0; | ||
585 | } | ||
586 | /* TBD: Support duty_cycle values that span bit 4. */ | ||
587 | else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) { | ||
588 | printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n"); | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | /* | 793 | /* |
593 | * PIIX4 Errata: We don't support throttling on the original PIIX4. | 794 | * PIIX4 Errata: We don't support throttling on the original PIIX4. |
594 | * This shouldn't be an issue as few (if any) mobile systems ever | 795 | * This shouldn't be an issue as few (if any) mobile systems ever |
@@ -600,21 +801,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
600 | return 0; | 801 | return 0; |
601 | } | 802 | } |
602 | 803 | ||
603 | pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width; | ||
604 | |||
605 | /* | ||
606 | * Compute state values. Note that throttling displays a linear power/ | ||
607 | * performance relationship (at 50% performance the CPU will consume | ||
608 | * 50% power). Values are in 1/10th of a percent to preserve accuracy. | ||
609 | */ | ||
610 | |||
611 | step = (1000 / pr->throttling.state_count); | ||
612 | |||
613 | for (i = 0; i < pr->throttling.state_count; i++) { | ||
614 | pr->throttling.states[i].performance = step * i; | ||
615 | pr->throttling.states[i].power = step * i; | ||
616 | } | ||
617 | |||
618 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", | 804 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", |
619 | pr->throttling.state_count)); | 805 | pr->throttling.state_count)); |
620 | 806 | ||
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 90fd09c65f95..f136c7d3b3c2 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | 31 | ||
32 | #ifdef CONFIG_ACPI_PROCFS | 32 | #ifdef CONFIG_ACPI_PROCFS_POWER |
33 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
34 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
35 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
@@ -40,7 +40,9 @@ | |||
40 | #include <linux/jiffies.h> | 40 | #include <linux/jiffies.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | 42 | ||
43 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
43 | #include <linux/power_supply.h> | 44 | #include <linux/power_supply.h> |
45 | #endif | ||
44 | 46 | ||
45 | #include "sbshc.h" | 47 | #include "sbshc.h" |
46 | 48 | ||
@@ -54,12 +56,6 @@ | |||
54 | #define ACPI_BATTERY_DIR_NAME "BAT%i" | 56 | #define ACPI_BATTERY_DIR_NAME "BAT%i" |
55 | #define ACPI_AC_DIR_NAME "AC0" | 57 | #define ACPI_AC_DIR_NAME "AC0" |
56 | 58 | ||
57 | enum acpi_sbs_device_addr { | ||
58 | ACPI_SBS_CHARGER = 0x9, | ||
59 | ACPI_SBS_MANAGER = 0xa, | ||
60 | ACPI_SBS_BATTERY = 0xb, | ||
61 | }; | ||
62 | |||
63 | #define ACPI_SBS_NOTIFY_STATUS 0x80 | 59 | #define ACPI_SBS_NOTIFY_STATUS 0x80 |
64 | #define ACPI_SBS_NOTIFY_INFO 0x81 | 60 | #define ACPI_SBS_NOTIFY_INFO 0x81 |
65 | 61 | ||
@@ -86,9 +82,11 @@ static const struct acpi_device_id sbs_device_ids[] = { | |||
86 | MODULE_DEVICE_TABLE(acpi, sbs_device_ids); | 82 | MODULE_DEVICE_TABLE(acpi, sbs_device_ids); |
87 | 83 | ||
88 | struct acpi_battery { | 84 | struct acpi_battery { |
85 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
89 | struct power_supply bat; | 86 | struct power_supply bat; |
87 | #endif | ||
90 | struct acpi_sbs *sbs; | 88 | struct acpi_sbs *sbs; |
91 | #ifdef CONFIG_ACPI_PROCFS | 89 | #ifdef CONFIG_ACPI_PROCFS_POWER |
92 | struct proc_dir_entry *proc_entry; | 90 | struct proc_dir_entry *proc_entry; |
93 | #endif | 91 | #endif |
94 | unsigned long update_time; | 92 | unsigned long update_time; |
@@ -113,16 +111,19 @@ struct acpi_battery { | |||
113 | u16 spec; | 111 | u16 spec; |
114 | u8 id; | 112 | u8 id; |
115 | u8 present:1; | 113 | u8 present:1; |
114 | u8 have_sysfs_alarm:1; | ||
116 | }; | 115 | }; |
117 | 116 | ||
118 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); | 117 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); |
119 | 118 | ||
120 | struct acpi_sbs { | 119 | struct acpi_sbs { |
120 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
121 | struct power_supply charger; | 121 | struct power_supply charger; |
122 | #endif | ||
122 | struct acpi_device *device; | 123 | struct acpi_device *device; |
123 | struct acpi_smb_hc *hc; | 124 | struct acpi_smb_hc *hc; |
124 | struct mutex lock; | 125 | struct mutex lock; |
125 | #ifdef CONFIG_ACPI_PROCFS | 126 | #ifdef CONFIG_ACPI_PROCFS_POWER |
126 | struct proc_dir_entry *charger_entry; | 127 | struct proc_dir_entry *charger_entry; |
127 | #endif | 128 | #endif |
128 | struct acpi_battery battery[MAX_SBS_BAT]; | 129 | struct acpi_battery battery[MAX_SBS_BAT]; |
@@ -162,6 +163,7 @@ static inline int acpi_battery_scale(struct acpi_battery *battery) | |||
162 | acpi_battery_ipscale(battery); | 163 | acpi_battery_ipscale(battery); |
163 | } | 164 | } |
164 | 165 | ||
166 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
165 | static int sbs_get_ac_property(struct power_supply *psy, | 167 | static int sbs_get_ac_property(struct power_supply *psy, |
166 | enum power_supply_property psp, | 168 | enum power_supply_property psp, |
167 | union power_supply_propval *val) | 169 | union power_supply_propval *val) |
@@ -299,6 +301,7 @@ static enum power_supply_property sbs_energy_battery_props[] = { | |||
299 | POWER_SUPPLY_PROP_MODEL_NAME, | 301 | POWER_SUPPLY_PROP_MODEL_NAME, |
300 | POWER_SUPPLY_PROP_MANUFACTURER, | 302 | POWER_SUPPLY_PROP_MANUFACTURER, |
301 | }; | 303 | }; |
304 | #endif | ||
302 | 305 | ||
303 | /* -------------------------------------------------------------------------- | 306 | /* -------------------------------------------------------------------------- |
304 | Smart Battery System Management | 307 | Smart Battery System Management |
@@ -434,6 +437,7 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) | |||
434 | return result; | 437 | return result; |
435 | } | 438 | } |
436 | 439 | ||
440 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
437 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 441 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
438 | struct device_attribute *attr, | 442 | struct device_attribute *attr, |
439 | char *buf) | 443 | char *buf) |
@@ -463,12 +467,13 @@ static struct device_attribute alarm_attr = { | |||
463 | .show = acpi_battery_alarm_show, | 467 | .show = acpi_battery_alarm_show, |
464 | .store = acpi_battery_alarm_store, | 468 | .store = acpi_battery_alarm_store, |
465 | }; | 469 | }; |
470 | #endif | ||
466 | 471 | ||
467 | /* -------------------------------------------------------------------------- | 472 | /* -------------------------------------------------------------------------- |
468 | FS Interface (/proc/acpi) | 473 | FS Interface (/proc/acpi) |
469 | -------------------------------------------------------------------------- */ | 474 | -------------------------------------------------------------------------- */ |
470 | 475 | ||
471 | #ifdef CONFIG_ACPI_PROCFS | 476 | #ifdef CONFIG_ACPI_PROCFS_POWER |
472 | /* Generic Routines */ | 477 | /* Generic Routines */ |
473 | static int | 478 | static int |
474 | acpi_sbs_add_fs(struct proc_dir_entry **dir, | 479 | acpi_sbs_add_fs(struct proc_dir_entry **dir, |
@@ -538,7 +543,7 @@ static struct proc_dir_entry *acpi_battery_dir = NULL; | |||
538 | 543 | ||
539 | static inline char *acpi_battery_units(struct acpi_battery *battery) | 544 | static inline char *acpi_battery_units(struct acpi_battery *battery) |
540 | { | 545 | { |
541 | return acpi_battery_mode(battery) ? " mWh" : " mAh"; | 546 | return acpi_battery_mode(battery) ? " mW" : " mA"; |
542 | } | 547 | } |
543 | 548 | ||
544 | 549 | ||
@@ -555,10 +560,10 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) | |||
555 | if (!battery->present) | 560 | if (!battery->present) |
556 | goto end; | 561 | goto end; |
557 | 562 | ||
558 | seq_printf(seq, "design capacity: %i%s\n", | 563 | seq_printf(seq, "design capacity: %i%sh\n", |
559 | battery->design_capacity * acpi_battery_scale(battery), | 564 | battery->design_capacity * acpi_battery_scale(battery), |
560 | acpi_battery_units(battery)); | 565 | acpi_battery_units(battery)); |
561 | seq_printf(seq, "last full capacity: %i%s\n", | 566 | seq_printf(seq, "last full capacity: %i%sh\n", |
562 | battery->full_charge_capacity * acpi_battery_scale(battery), | 567 | battery->full_charge_capacity * acpi_battery_scale(battery), |
563 | acpi_battery_units(battery)); | 568 | acpi_battery_units(battery)); |
564 | seq_printf(seq, "battery technology: rechargeable\n"); | 569 | seq_printf(seq, "battery technology: rechargeable\n"); |
@@ -589,7 +594,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) | |||
589 | { | 594 | { |
590 | struct acpi_battery *battery = seq->private; | 595 | struct acpi_battery *battery = seq->private; |
591 | struct acpi_sbs *sbs = battery->sbs; | 596 | struct acpi_sbs *sbs = battery->sbs; |
592 | int result = 0; | 597 | int rate; |
593 | 598 | ||
594 | mutex_lock(&sbs->lock); | 599 | mutex_lock(&sbs->lock); |
595 | seq_printf(seq, "present: %s\n", | 600 | seq_printf(seq, "present: %s\n", |
@@ -603,9 +608,12 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) | |||
603 | seq_printf(seq, "charging state: %s\n", | 608 | seq_printf(seq, "charging state: %s\n", |
604 | (battery->current_now < 0) ? "discharging" : | 609 | (battery->current_now < 0) ? "discharging" : |
605 | ((battery->current_now > 0) ? "charging" : "charged")); | 610 | ((battery->current_now > 0) ? "charging" : "charged")); |
606 | seq_printf(seq, "present rate: %d mA\n", | 611 | rate = abs(battery->current_now) * acpi_battery_ipscale(battery); |
607 | abs(battery->current_now) * acpi_battery_ipscale(battery)); | 612 | rate *= (acpi_battery_mode(battery))?(battery->voltage_now * |
608 | seq_printf(seq, "remaining capacity: %i%s\n", | 613 | acpi_battery_vscale(battery)/1000):1; |
614 | seq_printf(seq, "present rate: %d%s\n", rate, | ||
615 | acpi_battery_units(battery)); | ||
616 | seq_printf(seq, "remaining capacity: %i%sh\n", | ||
609 | battery->capacity_now * acpi_battery_scale(battery), | 617 | battery->capacity_now * acpi_battery_scale(battery), |
610 | acpi_battery_units(battery)); | 618 | acpi_battery_units(battery)); |
611 | seq_printf(seq, "present voltage: %i mV\n", | 619 | seq_printf(seq, "present voltage: %i mV\n", |
@@ -613,7 +621,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) | |||
613 | 621 | ||
614 | end: | 622 | end: |
615 | mutex_unlock(&sbs->lock); | 623 | mutex_unlock(&sbs->lock); |
616 | return result; | 624 | return 0; |
617 | } | 625 | } |
618 | 626 | ||
619 | static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) | 627 | static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) |
@@ -637,7 +645,7 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) | |||
637 | acpi_battery_get_alarm(battery); | 645 | acpi_battery_get_alarm(battery); |
638 | seq_printf(seq, "alarm: "); | 646 | seq_printf(seq, "alarm: "); |
639 | if (battery->alarm_capacity) | 647 | if (battery->alarm_capacity) |
640 | seq_printf(seq, "%i%s\n", | 648 | seq_printf(seq, "%i%sh\n", |
641 | battery->alarm_capacity * | 649 | battery->alarm_capacity * |
642 | acpi_battery_scale(battery), | 650 | acpi_battery_scale(battery), |
643 | acpi_battery_units(battery)); | 651 | acpi_battery_units(battery)); |
@@ -789,12 +797,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
789 | return result; | 797 | return result; |
790 | 798 | ||
791 | sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); | 799 | sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); |
792 | #ifdef CONFIG_ACPI_PROCFS | 800 | #ifdef CONFIG_ACPI_PROCFS_POWER |
793 | acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, | 801 | acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, |
794 | battery->name, &acpi_battery_info_fops, | 802 | battery->name, &acpi_battery_info_fops, |
795 | &acpi_battery_state_fops, &acpi_battery_alarm_fops, | 803 | &acpi_battery_state_fops, &acpi_battery_alarm_fops, |
796 | battery); | 804 | battery); |
797 | #endif | 805 | #endif |
806 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
798 | battery->bat.name = battery->name; | 807 | battery->bat.name = battery->name; |
799 | battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; | 808 | battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; |
800 | if (!acpi_battery_mode(battery)) { | 809 | if (!acpi_battery_mode(battery)) { |
@@ -808,7 +817,14 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
808 | } | 817 | } |
809 | battery->bat.get_property = acpi_sbs_battery_get_property; | 818 | battery->bat.get_property = acpi_sbs_battery_get_property; |
810 | result = power_supply_register(&sbs->device->dev, &battery->bat); | 819 | result = power_supply_register(&sbs->device->dev, &battery->bat); |
811 | device_create_file(battery->bat.dev, &alarm_attr); | 820 | if (result) |
821 | goto end; | ||
822 | result = device_create_file(battery->bat.dev, &alarm_attr); | ||
823 | if (result) | ||
824 | goto end; | ||
825 | battery->have_sysfs_alarm = 1; | ||
826 | end: | ||
827 | #endif | ||
812 | printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", | 828 | printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", |
813 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), | 829 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
814 | battery->name, sbs->battery->present ? "present" : "absent"); | 830 | battery->name, sbs->battery->present ? "present" : "absent"); |
@@ -817,15 +833,18 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
817 | 833 | ||
818 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) | 834 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) |
819 | { | 835 | { |
820 | if (sbs->battery[id].bat.dev) | 836 | struct acpi_battery *battery = &sbs->battery[id]; |
821 | device_remove_file(sbs->battery[id].bat.dev, &alarm_attr); | 837 | #ifdef CONFIG_ACPI_SYSFS_POWER |
822 | power_supply_unregister(&sbs->battery[id].bat); | 838 | if (battery->bat.dev) { |
823 | #ifdef CONFIG_ACPI_PROCFS | 839 | if (battery->have_sysfs_alarm) |
824 | if (sbs->battery[id].proc_entry) { | 840 | device_remove_file(battery->bat.dev, &alarm_attr); |
825 | acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry), | 841 | power_supply_unregister(&battery->bat); |
826 | acpi_battery_dir); | ||
827 | } | 842 | } |
828 | #endif | 843 | #endif |
844 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
845 | if (battery->proc_entry) | ||
846 | acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); | ||
847 | #endif | ||
829 | } | 848 | } |
830 | 849 | ||
831 | static int acpi_charger_add(struct acpi_sbs *sbs) | 850 | static int acpi_charger_add(struct acpi_sbs *sbs) |
@@ -835,19 +854,21 @@ static int acpi_charger_add(struct acpi_sbs *sbs) | |||
835 | result = acpi_ac_get_present(sbs); | 854 | result = acpi_ac_get_present(sbs); |
836 | if (result) | 855 | if (result) |
837 | goto end; | 856 | goto end; |
838 | #ifdef CONFIG_ACPI_PROCFS | 857 | #ifdef CONFIG_ACPI_PROCFS_POWER |
839 | result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, | 858 | result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, |
840 | ACPI_AC_DIR_NAME, NULL, | 859 | ACPI_AC_DIR_NAME, NULL, |
841 | &acpi_ac_state_fops, NULL, sbs); | 860 | &acpi_ac_state_fops, NULL, sbs); |
842 | if (result) | 861 | if (result) |
843 | goto end; | 862 | goto end; |
844 | #endif | 863 | #endif |
864 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
845 | sbs->charger.name = "sbs-charger"; | 865 | sbs->charger.name = "sbs-charger"; |
846 | sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; | 866 | sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; |
847 | sbs->charger.properties = sbs_ac_props; | 867 | sbs->charger.properties = sbs_ac_props; |
848 | sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); | 868 | sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); |
849 | sbs->charger.get_property = sbs_get_ac_property; | 869 | sbs->charger.get_property = sbs_get_ac_property; |
850 | power_supply_register(&sbs->device->dev, &sbs->charger); | 870 | power_supply_register(&sbs->device->dev, &sbs->charger); |
871 | #endif | ||
851 | printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", | 872 | printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", |
852 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), | 873 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
853 | ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); | 874 | ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); |
@@ -857,9 +878,11 @@ static int acpi_charger_add(struct acpi_sbs *sbs) | |||
857 | 878 | ||
858 | static void acpi_charger_remove(struct acpi_sbs *sbs) | 879 | static void acpi_charger_remove(struct acpi_sbs *sbs) |
859 | { | 880 | { |
881 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
860 | if (sbs->charger.dev) | 882 | if (sbs->charger.dev) |
861 | power_supply_unregister(&sbs->charger); | 883 | power_supply_unregister(&sbs->charger); |
862 | #ifdef CONFIG_ACPI_PROCFS | 884 | #endif |
885 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
863 | if (sbs->charger_entry) | 886 | if (sbs->charger_entry) |
864 | acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); | 887 | acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); |
865 | #endif | 888 | #endif |
@@ -879,7 +902,9 @@ void acpi_sbs_callback(void *context) | |||
879 | ACPI_SBS_NOTIFY_STATUS, | 902 | ACPI_SBS_NOTIFY_STATUS, |
880 | sbs->charger_present); | 903 | sbs->charger_present); |
881 | #endif | 904 | #endif |
905 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
882 | kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); | 906 | kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); |
907 | #endif | ||
883 | } | 908 | } |
884 | if (sbs->manager_present) { | 909 | if (sbs->manager_present) { |
885 | for (id = 0; id < MAX_SBS_BAT; ++id) { | 910 | for (id = 0; id < MAX_SBS_BAT; ++id) { |
@@ -896,7 +921,9 @@ void acpi_sbs_callback(void *context) | |||
896 | ACPI_SBS_NOTIFY_STATUS, | 921 | ACPI_SBS_NOTIFY_STATUS, |
897 | bat->present); | 922 | bat->present); |
898 | #endif | 923 | #endif |
924 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
899 | kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); | 925 | kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); |
926 | #endif | ||
900 | } | 927 | } |
901 | } | 928 | } |
902 | } | 929 | } |
@@ -965,7 +992,7 @@ static int acpi_sbs_remove(struct acpi_device *device, int type) | |||
965 | 992 | ||
966 | static void acpi_sbs_rmdirs(void) | 993 | static void acpi_sbs_rmdirs(void) |
967 | { | 994 | { |
968 | #ifdef CONFIG_ACPI_PROCFS | 995 | #ifdef CONFIG_ACPI_PROCFS_POWER |
969 | if (acpi_ac_dir) { | 996 | if (acpi_ac_dir) { |
970 | acpi_unlock_ac_dir(acpi_ac_dir); | 997 | acpi_unlock_ac_dir(acpi_ac_dir); |
971 | acpi_ac_dir = NULL; | 998 | acpi_ac_dir = NULL; |
@@ -1004,7 +1031,7 @@ static int __init acpi_sbs_init(void) | |||
1004 | 1031 | ||
1005 | if (acpi_disabled) | 1032 | if (acpi_disabled) |
1006 | return -ENODEV; | 1033 | return -ENODEV; |
1007 | #ifdef CONFIG_ACPI_PROCFS | 1034 | #ifdef CONFIG_ACPI_PROCFS_POWER |
1008 | acpi_ac_dir = acpi_lock_ac_dir(); | 1035 | acpi_ac_dir = acpi_lock_ac_dir(); |
1009 | if (!acpi_ac_dir) | 1036 | if (!acpi_ac_dir) |
1010 | return -ENODEV; | 1037 | return -ENODEV; |
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index 046d7c3ed356..fd40b6a1d639 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c | |||
@@ -202,10 +202,9 @@ int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc) | |||
202 | 202 | ||
203 | EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback); | 203 | EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback); |
204 | 204 | ||
205 | static void acpi_smbus_callback(void *context) | 205 | static inline void acpi_smbus_callback(void *context) |
206 | { | 206 | { |
207 | struct acpi_smb_hc *hc = context; | 207 | struct acpi_smb_hc *hc = context; |
208 | |||
209 | if (hc->callback) | 208 | if (hc->callback) |
210 | hc->callback(hc->context); | 209 | hc->callback(hc->context); |
211 | } | 210 | } |
@@ -214,6 +213,7 @@ static int smbus_alarm(void *context) | |||
214 | { | 213 | { |
215 | struct acpi_smb_hc *hc = context; | 214 | struct acpi_smb_hc *hc = context; |
216 | union acpi_smb_status status; | 215 | union acpi_smb_status status; |
216 | u8 address; | ||
217 | if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw)) | 217 | if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw)) |
218 | return 0; | 218 | return 0; |
219 | /* Check if it is only a completion notify */ | 219 | /* Check if it is only a completion notify */ |
@@ -222,9 +222,18 @@ static int smbus_alarm(void *context) | |||
222 | if (!status.fields.alarm) | 222 | if (!status.fields.alarm) |
223 | return 0; | 223 | return 0; |
224 | mutex_lock(&hc->lock); | 224 | mutex_lock(&hc->lock); |
225 | smb_hc_read(hc, ACPI_SMB_ALARM_ADDRESS, &address); | ||
226 | status.fields.alarm = 0; | ||
225 | smb_hc_write(hc, ACPI_SMB_STATUS, status.raw); | 227 | smb_hc_write(hc, ACPI_SMB_STATUS, status.raw); |
226 | if (hc->callback) | 228 | /* We are only interested in events coming from known devices */ |
227 | acpi_os_execute(OSL_GPE_HANDLER, acpi_smbus_callback, hc); | 229 | switch (address >> 1) { |
230 | case ACPI_SBS_CHARGER: | ||
231 | case ACPI_SBS_MANAGER: | ||
232 | case ACPI_SBS_BATTERY: | ||
233 | acpi_os_execute(OSL_GPE_HANDLER, | ||
234 | acpi_smbus_callback, hc); | ||
235 | default:; | ||
236 | } | ||
228 | mutex_unlock(&hc->lock); | 237 | mutex_unlock(&hc->lock); |
229 | return 0; | 238 | return 0; |
230 | } | 239 | } |
diff --git a/drivers/acpi/sbshc.h b/drivers/acpi/sbshc.h index 3bda3491a97b..a57b0762dd7f 100644 --- a/drivers/acpi/sbshc.h +++ b/drivers/acpi/sbshc.h | |||
@@ -16,6 +16,12 @@ enum acpi_smb_protocol { | |||
16 | 16 | ||
17 | static const u8 SMBUS_PEC = 0x80; | 17 | static const u8 SMBUS_PEC = 0x80; |
18 | 18 | ||
19 | enum acpi_sbs_device_addr { | ||
20 | ACPI_SBS_CHARGER = 0x9, | ||
21 | ACPI_SBS_MANAGER = 0xa, | ||
22 | ACPI_SBS_BATTERY = 0xb, | ||
23 | }; | ||
24 | |||
19 | typedef void (*smbus_alarm_callback)(void *context); | 25 | typedef void (*smbus_alarm_callback)(void *context); |
20 | 26 | ||
21 | extern int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address, | 27 | extern int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address, |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5b4d462117cf..c7b0aa52dd23 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -830,7 +830,7 @@ static int acpi_bus_get_flags(struct acpi_device *device) | |||
830 | if (ACPI_SUCCESS(status)) | 830 | if (ACPI_SUCCESS(status)) |
831 | device->flags.wake_capable = 1; | 831 | device->flags.wake_capable = 1; |
832 | 832 | ||
833 | /* TBD: Peformance management */ | 833 | /* TBD: Performance management */ |
834 | 834 | ||
835 | return 0; | 835 | return 0; |
836 | } | 836 | } |
@@ -941,6 +941,15 @@ static int acpi_bay_match(struct acpi_device *device){ | |||
941 | return -ENODEV; | 941 | return -ENODEV; |
942 | } | 942 | } |
943 | 943 | ||
944 | /* | ||
945 | * acpi_dock_match - see if a device has a _DCK method | ||
946 | */ | ||
947 | static int acpi_dock_match(struct acpi_device *device) | ||
948 | { | ||
949 | acpi_handle tmp; | ||
950 | return acpi_get_handle(device->handle, "_DCK", &tmp); | ||
951 | } | ||
952 | |||
944 | static void acpi_device_set_id(struct acpi_device *device, | 953 | static void acpi_device_set_id(struct acpi_device *device, |
945 | struct acpi_device *parent, acpi_handle handle, | 954 | struct acpi_device *parent, acpi_handle handle, |
946 | int type) | 955 | int type) |
@@ -950,6 +959,7 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
950 | char *hid = NULL; | 959 | char *hid = NULL; |
951 | char *uid = NULL; | 960 | char *uid = NULL; |
952 | struct acpi_compatible_id_list *cid_list = NULL; | 961 | struct acpi_compatible_id_list *cid_list = NULL; |
962 | const char *cid_add = NULL; | ||
953 | acpi_status status; | 963 | acpi_status status; |
954 | 964 | ||
955 | switch (type) { | 965 | switch (type) { |
@@ -972,15 +982,18 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
972 | device->flags.bus_address = 1; | 982 | device->flags.bus_address = 1; |
973 | } | 983 | } |
974 | 984 | ||
975 | if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){ | 985 | /* If we have a video/bay/dock device, add our selfdefined |
976 | status = acpi_video_bus_match(device); | 986 | HID to the CID list. Like that the video/bay/dock drivers |
977 | if(ACPI_SUCCESS(status)) | 987 | will get autoloaded and the device might still match |
978 | hid = ACPI_VIDEO_HID; | 988 | against another driver. |
989 | */ | ||
990 | if (ACPI_SUCCESS(acpi_video_bus_match(device))) | ||
991 | cid_add = ACPI_VIDEO_HID; | ||
992 | else if (ACPI_SUCCESS(acpi_bay_match(device))) | ||
993 | cid_add = ACPI_BAY_HID; | ||
994 | else if (ACPI_SUCCESS(acpi_dock_match(device))) | ||
995 | cid_add = ACPI_DOCK_HID; | ||
979 | 996 | ||
980 | status = acpi_bay_match(device); | ||
981 | if (ACPI_SUCCESS(status)) | ||
982 | hid = ACPI_BAY_HID; | ||
983 | } | ||
984 | break; | 997 | break; |
985 | case ACPI_BUS_TYPE_POWER: | 998 | case ACPI_BUS_TYPE_POWER: |
986 | hid = ACPI_POWER_HID; | 999 | hid = ACPI_POWER_HID; |
@@ -1021,11 +1034,44 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
1021 | strcpy(device->pnp.unique_id, uid); | 1034 | strcpy(device->pnp.unique_id, uid); |
1022 | device->flags.unique_id = 1; | 1035 | device->flags.unique_id = 1; |
1023 | } | 1036 | } |
1024 | if (cid_list) { | 1037 | if (cid_list || cid_add) { |
1025 | device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL); | 1038 | struct acpi_compatible_id_list *list; |
1026 | if (device->pnp.cid_list) | 1039 | int size = 0; |
1027 | memcpy(device->pnp.cid_list, cid_list, cid_list->size); | 1040 | int count = 0; |
1028 | else | 1041 | |
1042 | if (cid_list) { | ||
1043 | size = cid_list->size; | ||
1044 | } else if (cid_add) { | ||
1045 | size = sizeof(struct acpi_compatible_id_list); | ||
1046 | cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); | ||
1047 | if (!cid_list) { | ||
1048 | printk(KERN_ERR "Memory allocation error\n"); | ||
1049 | kfree(buffer.pointer); | ||
1050 | return; | ||
1051 | } else { | ||
1052 | cid_list->count = 0; | ||
1053 | cid_list->size = size; | ||
1054 | } | ||
1055 | } | ||
1056 | if (cid_add) | ||
1057 | size += sizeof(struct acpi_compatible_id); | ||
1058 | list = kmalloc(size, GFP_KERNEL); | ||
1059 | |||
1060 | if (list) { | ||
1061 | if (cid_list) { | ||
1062 | memcpy(list, cid_list, cid_list->size); | ||
1063 | count = cid_list->count; | ||
1064 | } | ||
1065 | if (cid_add) { | ||
1066 | strncpy(list->id[count].value, cid_add, | ||
1067 | ACPI_MAX_CID_LENGTH); | ||
1068 | count++; | ||
1069 | device->flags.compatible_ids = 1; | ||
1070 | } | ||
1071 | list->size = size; | ||
1072 | list->count = count; | ||
1073 | device->pnp.cid_list = list; | ||
1074 | } else | ||
1029 | printk(KERN_ERR "Memory allocation error\n"); | 1075 | printk(KERN_ERR "Memory allocation error\n"); |
1030 | } | 1076 | } |
1031 | 1077 | ||
@@ -1081,6 +1127,20 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) | |||
1081 | } | 1127 | } |
1082 | 1128 | ||
1083 | static int | 1129 | static int |
1130 | acpi_is_child_device(struct acpi_device *device, | ||
1131 | int (*matcher)(struct acpi_device *)) | ||
1132 | { | ||
1133 | int result = -ENODEV; | ||
1134 | |||
1135 | do { | ||
1136 | if (ACPI_SUCCESS(matcher(device))) | ||
1137 | return AE_OK; | ||
1138 | } while ((device = device->parent)); | ||
1139 | |||
1140 | return result; | ||
1141 | } | ||
1142 | |||
1143 | static int | ||
1084 | acpi_add_single_object(struct acpi_device **child, | 1144 | acpi_add_single_object(struct acpi_device **child, |
1085 | struct acpi_device *parent, acpi_handle handle, int type, | 1145 | struct acpi_device *parent, acpi_handle handle, int type, |
1086 | struct acpi_bus_ops *ops) | 1146 | struct acpi_bus_ops *ops) |
@@ -1131,10 +1191,20 @@ acpi_add_single_object(struct acpi_device **child, | |||
1131 | case ACPI_BUS_TYPE_PROCESSOR: | 1191 | case ACPI_BUS_TYPE_PROCESSOR: |
1132 | case ACPI_BUS_TYPE_DEVICE: | 1192 | case ACPI_BUS_TYPE_DEVICE: |
1133 | result = acpi_bus_get_status(device); | 1193 | result = acpi_bus_get_status(device); |
1134 | if (ACPI_FAILURE(result) || !device->status.present) { | 1194 | if (ACPI_FAILURE(result)) { |
1135 | result = -ENOENT; | 1195 | result = -ENODEV; |
1136 | goto end; | 1196 | goto end; |
1137 | } | 1197 | } |
1198 | if (!device->status.present) { | ||
1199 | /* Bay and dock should be handled even if absent */ | ||
1200 | if (!ACPI_SUCCESS( | ||
1201 | acpi_is_child_device(device, acpi_bay_match)) && | ||
1202 | !ACPI_SUCCESS( | ||
1203 | acpi_is_child_device(device, acpi_dock_match))) { | ||
1204 | result = -ENODEV; | ||
1205 | goto end; | ||
1206 | } | ||
1207 | } | ||
1138 | break; | 1208 | break; |
1139 | default: | 1209 | default: |
1140 | STRUCT_TO_INT(device->status) = | 1210 | STRUCT_TO_INT(device->status) = |
@@ -1449,6 +1519,8 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) | |||
1449 | return result; | 1519 | return result; |
1450 | } | 1520 | } |
1451 | 1521 | ||
1522 | int __init acpi_boot_ec_enable(void); | ||
1523 | |||
1452 | static int __init acpi_scan_init(void) | 1524 | static int __init acpi_scan_init(void) |
1453 | { | 1525 | { |
1454 | int result; | 1526 | int result; |
@@ -1480,6 +1552,10 @@ static int __init acpi_scan_init(void) | |||
1480 | * Enumerate devices in the ACPI namespace. | 1552 | * Enumerate devices in the ACPI namespace. |
1481 | */ | 1553 | */ |
1482 | result = acpi_bus_scan_fixed(acpi_root); | 1554 | result = acpi_bus_scan_fixed(acpi_root); |
1555 | |||
1556 | /* EC region might be needed at bus_scan, so enable it now */ | ||
1557 | acpi_boot_ec_enable(); | ||
1558 | |||
1483 | if (!result) | 1559 | if (!result) |
1484 | result = acpi_bus_scan(acpi_root, &ops); | 1560 | result = acpi_bus_scan(acpi_root, &ops); |
1485 | 1561 | ||
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 2c0b6630f8ba..7f97e32fc33f 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
@@ -26,9 +26,24 @@ u8 sleep_states[ACPI_S_STATE_COUNT]; | |||
26 | 26 | ||
27 | #ifdef CONFIG_PM_SLEEP | 27 | #ifdef CONFIG_PM_SLEEP |
28 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 28 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
29 | static bool acpi_sleep_finish_wake_up; | ||
30 | |||
31 | /* | ||
32 | * ACPI 2.0 and later want us to execute _PTS after suspending devices, so we | ||
33 | * allow the user to request that behavior by using the 'acpi_new_pts_ordering' | ||
34 | * kernel command line option that causes the following variable to be set. | ||
35 | */ | ||
36 | static bool new_pts_ordering; | ||
37 | |||
38 | static int __init acpi_new_pts_ordering(char *str) | ||
39 | { | ||
40 | new_pts_ordering = true; | ||
41 | return 1; | ||
42 | } | ||
43 | __setup("acpi_new_pts_ordering", acpi_new_pts_ordering); | ||
29 | #endif | 44 | #endif |
30 | 45 | ||
31 | int acpi_sleep_prepare(u32 acpi_state) | 46 | static int acpi_sleep_prepare(u32 acpi_state) |
32 | { | 47 | { |
33 | #ifdef CONFIG_ACPI_SLEEP | 48 | #ifdef CONFIG_ACPI_SLEEP |
34 | /* do we have a wakeup address for S2 and S3? */ | 49 | /* do we have a wakeup address for S2 and S3? */ |
@@ -44,6 +59,8 @@ int acpi_sleep_prepare(u32 acpi_state) | |||
44 | ACPI_FLUSH_CPU_CACHE(); | 59 | ACPI_FLUSH_CPU_CACHE(); |
45 | acpi_enable_wakeup_device_prep(acpi_state); | 60 | acpi_enable_wakeup_device_prep(acpi_state); |
46 | #endif | 61 | #endif |
62 | printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n", | ||
63 | acpi_state); | ||
47 | acpi_enter_sleep_state_prep(acpi_state); | 64 | acpi_enter_sleep_state_prep(acpi_state); |
48 | return 0; | 65 | return 0; |
49 | } | 66 | } |
@@ -63,17 +80,25 @@ static u32 acpi_suspend_states[] = { | |||
63 | static int init_8259A_after_S1; | 80 | static int init_8259A_after_S1; |
64 | 81 | ||
65 | /** | 82 | /** |
66 | * acpi_pm_set_target - Set the target system sleep state to the state | 83 | * acpi_pm_begin - Set the target system sleep state to the state |
67 | * associated with given @pm_state, if supported. | 84 | * associated with given @pm_state, if supported. |
68 | */ | 85 | */ |
69 | 86 | ||
70 | static int acpi_pm_set_target(suspend_state_t pm_state) | 87 | static int acpi_pm_begin(suspend_state_t pm_state) |
71 | { | 88 | { |
72 | u32 acpi_state = acpi_suspend_states[pm_state]; | 89 | u32 acpi_state = acpi_suspend_states[pm_state]; |
73 | int error = 0; | 90 | int error = 0; |
74 | 91 | ||
75 | if (sleep_states[acpi_state]) { | 92 | if (sleep_states[acpi_state]) { |
76 | acpi_target_sleep_state = acpi_state; | 93 | acpi_target_sleep_state = acpi_state; |
94 | if (new_pts_ordering) | ||
95 | return 0; | ||
96 | |||
97 | error = acpi_sleep_prepare(acpi_state); | ||
98 | if (error) | ||
99 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
100 | else | ||
101 | acpi_sleep_finish_wake_up = true; | ||
77 | } else { | 102 | } else { |
78 | printk(KERN_ERR "ACPI does not support this state: %d\n", | 103 | printk(KERN_ERR "ACPI does not support this state: %d\n", |
79 | pm_state); | 104 | pm_state); |
@@ -91,12 +116,17 @@ static int acpi_pm_set_target(suspend_state_t pm_state) | |||
91 | 116 | ||
92 | static int acpi_pm_prepare(void) | 117 | static int acpi_pm_prepare(void) |
93 | { | 118 | { |
94 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | 119 | if (new_pts_ordering) { |
120 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | ||
95 | 121 | ||
96 | if (error) | 122 | if (error) { |
97 | acpi_target_sleep_state = ACPI_STATE_S0; | 123 | acpi_target_sleep_state = ACPI_STATE_S0; |
124 | return error; | ||
125 | } | ||
126 | acpi_sleep_finish_wake_up = true; | ||
127 | } | ||
98 | 128 | ||
99 | return error; | 129 | return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT; |
100 | } | 130 | } |
101 | 131 | ||
102 | /** | 132 | /** |
@@ -120,10 +150,8 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
120 | if (acpi_state == ACPI_STATE_S3) { | 150 | if (acpi_state == ACPI_STATE_S3) { |
121 | int error = acpi_save_state_mem(); | 151 | int error = acpi_save_state_mem(); |
122 | 152 | ||
123 | if (error) { | 153 | if (error) |
124 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
125 | return error; | 154 | return error; |
126 | } | ||
127 | } | 155 | } |
128 | 156 | ||
129 | local_irq_save(flags); | 157 | local_irq_save(flags); |
@@ -139,6 +167,9 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
139 | break; | 167 | break; |
140 | } | 168 | } |
141 | 169 | ||
170 | /* Reprogram control registers and execute _BFS */ | ||
171 | acpi_leave_sleep_state_prep(acpi_state); | ||
172 | |||
142 | /* ACPI 3.0 specs (P62) says that it's the responsabilty | 173 | /* ACPI 3.0 specs (P62) says that it's the responsabilty |
143 | * of the OSPM to clear the status bit [ implying that the | 174 | * of the OSPM to clear the status bit [ implying that the |
144 | * POWER_BUTTON event should not reach userspace ] | 175 | * POWER_BUTTON event should not reach userspace ] |
@@ -146,6 +177,13 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
146 | if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) | 177 | if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) |
147 | acpi_clear_event(ACPI_EVENT_POWER_BUTTON); | 178 | acpi_clear_event(ACPI_EVENT_POWER_BUTTON); |
148 | 179 | ||
180 | /* | ||
181 | * Disable and clear GPE status before interrupt is enabled. Some GPEs | ||
182 | * (like wakeup GPE) haven't handler, this can avoid such GPE misfire. | ||
183 | * acpi_leave_sleep_state will reenable specific GPEs later | ||
184 | */ | ||
185 | acpi_hw_disable_all_gpes(); | ||
186 | |||
149 | local_irq_restore(flags); | 187 | local_irq_restore(flags); |
150 | printk(KERN_DEBUG "Back to C!\n"); | 188 | printk(KERN_DEBUG "Back to C!\n"); |
151 | 189 | ||
@@ -157,7 +195,7 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
157 | } | 195 | } |
158 | 196 | ||
159 | /** | 197 | /** |
160 | * acpi_pm_finish - Finish up suspend sequence. | 198 | * acpi_pm_finish - Instruct the platform to leave a sleep state. |
161 | * | 199 | * |
162 | * This is called after we wake back up (or if entering the sleep state | 200 | * This is called after we wake back up (or if entering the sleep state |
163 | * failed). | 201 | * failed). |
@@ -174,6 +212,7 @@ static void acpi_pm_finish(void) | |||
174 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | 212 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); |
175 | 213 | ||
176 | acpi_target_sleep_state = ACPI_STATE_S0; | 214 | acpi_target_sleep_state = ACPI_STATE_S0; |
215 | acpi_sleep_finish_wake_up = false; | ||
177 | 216 | ||
178 | #ifdef CONFIG_X86 | 217 | #ifdef CONFIG_X86 |
179 | if (init_8259A_after_S1) { | 218 | if (init_8259A_after_S1) { |
@@ -183,6 +222,20 @@ static void acpi_pm_finish(void) | |||
183 | #endif | 222 | #endif |
184 | } | 223 | } |
185 | 224 | ||
225 | /** | ||
226 | * acpi_pm_end - Finish up suspend sequence. | ||
227 | */ | ||
228 | |||
229 | static void acpi_pm_end(void) | ||
230 | { | ||
231 | /* | ||
232 | * This is necessary in case acpi_pm_finish() is not called directly | ||
233 | * during a failing transition to a sleep state. | ||
234 | */ | ||
235 | if (acpi_sleep_finish_wake_up) | ||
236 | acpi_pm_finish(); | ||
237 | } | ||
238 | |||
186 | static int acpi_pm_state_valid(suspend_state_t pm_state) | 239 | static int acpi_pm_state_valid(suspend_state_t pm_state) |
187 | { | 240 | { |
188 | u32 acpi_state; | 241 | u32 acpi_state; |
@@ -201,10 +254,11 @@ static int acpi_pm_state_valid(suspend_state_t pm_state) | |||
201 | 254 | ||
202 | static struct platform_suspend_ops acpi_pm_ops = { | 255 | static struct platform_suspend_ops acpi_pm_ops = { |
203 | .valid = acpi_pm_state_valid, | 256 | .valid = acpi_pm_state_valid, |
204 | .set_target = acpi_pm_set_target, | 257 | .begin = acpi_pm_begin, |
205 | .prepare = acpi_pm_prepare, | 258 | .prepare = acpi_pm_prepare, |
206 | .enter = acpi_pm_enter, | 259 | .enter = acpi_pm_enter, |
207 | .finish = acpi_pm_finish, | 260 | .finish = acpi_pm_finish, |
261 | .end = acpi_pm_end, | ||
208 | }; | 262 | }; |
209 | 263 | ||
210 | /* | 264 | /* |
@@ -229,15 +283,36 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
229 | #endif /* CONFIG_SUSPEND */ | 283 | #endif /* CONFIG_SUSPEND */ |
230 | 284 | ||
231 | #ifdef CONFIG_HIBERNATION | 285 | #ifdef CONFIG_HIBERNATION |
232 | static int acpi_hibernation_start(void) | 286 | static int acpi_hibernation_begin(void) |
233 | { | 287 | { |
288 | int error; | ||
289 | |||
234 | acpi_target_sleep_state = ACPI_STATE_S4; | 290 | acpi_target_sleep_state = ACPI_STATE_S4; |
235 | return 0; | 291 | if (new_pts_ordering) |
292 | return 0; | ||
293 | |||
294 | error = acpi_sleep_prepare(ACPI_STATE_S4); | ||
295 | if (error) | ||
296 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
297 | else | ||
298 | acpi_sleep_finish_wake_up = true; | ||
299 | |||
300 | return error; | ||
236 | } | 301 | } |
237 | 302 | ||
238 | static int acpi_hibernation_prepare(void) | 303 | static int acpi_hibernation_prepare(void) |
239 | { | 304 | { |
240 | return acpi_sleep_prepare(ACPI_STATE_S4); | 305 | if (new_pts_ordering) { |
306 | int error = acpi_sleep_prepare(ACPI_STATE_S4); | ||
307 | |||
308 | if (error) { | ||
309 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
310 | return error; | ||
311 | } | ||
312 | acpi_sleep_finish_wake_up = true; | ||
313 | } | ||
314 | |||
315 | return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT; | ||
241 | } | 316 | } |
242 | 317 | ||
243 | static int acpi_hibernation_enter(void) | 318 | static int acpi_hibernation_enter(void) |
@@ -251,6 +326,8 @@ static int acpi_hibernation_enter(void) | |||
251 | acpi_enable_wakeup_device(ACPI_STATE_S4); | 326 | acpi_enable_wakeup_device(ACPI_STATE_S4); |
252 | /* This shouldn't return. If it returns, we have a problem */ | 327 | /* This shouldn't return. If it returns, we have a problem */ |
253 | status = acpi_enter_sleep_state(ACPI_STATE_S4); | 328 | status = acpi_enter_sleep_state(ACPI_STATE_S4); |
329 | /* Reprogram control registers and execute _BFS */ | ||
330 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); | ||
254 | local_irq_restore(flags); | 331 | local_irq_restore(flags); |
255 | 332 | ||
256 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 333 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
@@ -263,15 +340,12 @@ static void acpi_hibernation_leave(void) | |||
263 | * enable it here. | 340 | * enable it here. |
264 | */ | 341 | */ |
265 | acpi_enable(); | 342 | acpi_enable(); |
343 | /* Reprogram control registers and execute _BFS */ | ||
344 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); | ||
266 | } | 345 | } |
267 | 346 | ||
268 | static void acpi_hibernation_finish(void) | 347 | static void acpi_hibernation_finish(void) |
269 | { | 348 | { |
270 | /* | ||
271 | * If ACPI is not enabled by the BIOS and the boot kernel, we need to | ||
272 | * enable it here. | ||
273 | */ | ||
274 | acpi_enable(); | ||
275 | acpi_disable_wakeup_device(ACPI_STATE_S4); | 349 | acpi_disable_wakeup_device(ACPI_STATE_S4); |
276 | acpi_leave_sleep_state(ACPI_STATE_S4); | 350 | acpi_leave_sleep_state(ACPI_STATE_S4); |
277 | 351 | ||
@@ -279,6 +353,17 @@ static void acpi_hibernation_finish(void) | |||
279 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | 353 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); |
280 | 354 | ||
281 | acpi_target_sleep_state = ACPI_STATE_S0; | 355 | acpi_target_sleep_state = ACPI_STATE_S0; |
356 | acpi_sleep_finish_wake_up = false; | ||
357 | } | ||
358 | |||
359 | static void acpi_hibernation_end(void) | ||
360 | { | ||
361 | /* | ||
362 | * This is necessary in case acpi_hibernation_finish() is not called | ||
363 | * directly during a failing transition to the sleep state. | ||
364 | */ | ||
365 | if (acpi_sleep_finish_wake_up) | ||
366 | acpi_hibernation_finish(); | ||
282 | } | 367 | } |
283 | 368 | ||
284 | static int acpi_hibernation_pre_restore(void) | 369 | static int acpi_hibernation_pre_restore(void) |
@@ -296,7 +381,8 @@ static void acpi_hibernation_restore_cleanup(void) | |||
296 | } | 381 | } |
297 | 382 | ||
298 | static struct platform_hibernation_ops acpi_hibernation_ops = { | 383 | static struct platform_hibernation_ops acpi_hibernation_ops = { |
299 | .start = acpi_hibernation_start, | 384 | .begin = acpi_hibernation_begin, |
385 | .end = acpi_hibernation_end, | ||
300 | .pre_snapshot = acpi_hibernation_prepare, | 386 | .pre_snapshot = acpi_hibernation_prepare, |
301 | .finish = acpi_hibernation_finish, | 387 | .finish = acpi_hibernation_finish, |
302 | .prepare = acpi_hibernation_prepare, | 388 | .prepare = acpi_hibernation_prepare, |
@@ -386,11 +472,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) | |||
386 | if (acpi_target_sleep_state == ACPI_STATE_S0 || | 472 | if (acpi_target_sleep_state == ACPI_STATE_S0 || |
387 | (wake && adev->wakeup.state.enabled && | 473 | (wake && adev->wakeup.state.enabled && |
388 | adev->wakeup.sleep_state <= acpi_target_sleep_state)) { | 474 | adev->wakeup.sleep_state <= acpi_target_sleep_state)) { |
475 | acpi_status status; | ||
476 | |||
389 | acpi_method[3] = 'W'; | 477 | acpi_method[3] = 'W'; |
390 | acpi_evaluate_integer(handle, acpi_method, NULL, &d_max); | 478 | status = acpi_evaluate_integer(handle, acpi_method, NULL, |
391 | /* Sanity check */ | 479 | &d_max); |
392 | if (d_max < d_min) | 480 | if (ACPI_FAILURE(status)) { |
481 | d_max = d_min; | ||
482 | } else if (d_max < d_min) { | ||
483 | /* Warn the user of the broken DSDT */ | ||
484 | printk(KERN_WARNING "ACPI: Wrong value from %s\n", | ||
485 | acpi_method); | ||
486 | /* Sanitize it */ | ||
393 | d_min = d_max; | 487 | d_min = d_max; |
488 | } | ||
394 | } | 489 | } |
395 | 490 | ||
396 | if (d_min_p) | 491 | if (d_min_p) |
@@ -403,6 +498,7 @@ static void acpi_power_off_prepare(void) | |||
403 | { | 498 | { |
404 | /* Prepare to power off the system */ | 499 | /* Prepare to power off the system */ |
405 | acpi_sleep_prepare(ACPI_STATE_S5); | 500 | acpi_sleep_prepare(ACPI_STATE_S5); |
501 | acpi_hw_disable_all_gpes(); | ||
406 | } | 502 | } |
407 | 503 | ||
408 | static void acpi_power_off(void) | 504 | static void acpi_power_off(void) |
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 1538355c266b..f8df5217d477 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c | |||
@@ -178,6 +178,9 @@ static int get_date_field(char **p, u32 * value) | |||
178 | * Try to find delimeter, only to insert null. The end of the | 178 | * Try to find delimeter, only to insert null. The end of the |
179 | * string won't have one, but is still valid. | 179 | * string won't have one, but is still valid. |
180 | */ | 180 | */ |
181 | if (*p == NULL) | ||
182 | return result; | ||
183 | |||
181 | next = strpbrk(*p, "- :"); | 184 | next = strpbrk(*p, "- :"); |
182 | if (next) | 185 | if (next) |
183 | *next++ = '\0'; | 186 | *next++ = '\0'; |
@@ -190,6 +193,8 @@ static int get_date_field(char **p, u32 * value) | |||
190 | 193 | ||
191 | if (next) | 194 | if (next) |
192 | *p = next; | 195 | *p = next; |
196 | else | ||
197 | *p = NULL; | ||
193 | 198 | ||
194 | return result; | 199 | return result; |
195 | } | 200 | } |
@@ -251,27 +256,6 @@ acpi_system_write_alarm(struct file *file, | |||
251 | if ((result = get_date_field(&p, &sec))) | 256 | if ((result = get_date_field(&p, &sec))) |
252 | goto end; | 257 | goto end; |
253 | 258 | ||
254 | if (sec > 59) { | ||
255 | min += 1; | ||
256 | sec -= 60; | ||
257 | } | ||
258 | if (min > 59) { | ||
259 | hr += 1; | ||
260 | min -= 60; | ||
261 | } | ||
262 | if (hr > 23) { | ||
263 | day += 1; | ||
264 | hr -= 24; | ||
265 | } | ||
266 | if (day > 31) { | ||
267 | mo += 1; | ||
268 | day -= 31; | ||
269 | } | ||
270 | if (mo > 12) { | ||
271 | yr += 1; | ||
272 | mo -= 12; | ||
273 | } | ||
274 | |||
275 | spin_lock_irq(&rtc_lock); | 259 | spin_lock_irq(&rtc_lock); |
276 | 260 | ||
277 | rtc_control = CMOS_READ(RTC_CONTROL); | 261 | rtc_control = CMOS_READ(RTC_CONTROL); |
@@ -288,24 +272,24 @@ acpi_system_write_alarm(struct file *file, | |||
288 | spin_unlock_irq(&rtc_lock); | 272 | spin_unlock_irq(&rtc_lock); |
289 | 273 | ||
290 | if (sec > 59) { | 274 | if (sec > 59) { |
291 | min++; | 275 | min += sec/60; |
292 | sec -= 60; | 276 | sec = sec%60; |
293 | } | 277 | } |
294 | if (min > 59) { | 278 | if (min > 59) { |
295 | hr++; | 279 | hr += min/60; |
296 | min -= 60; | 280 | min = min%60; |
297 | } | 281 | } |
298 | if (hr > 23) { | 282 | if (hr > 23) { |
299 | day++; | 283 | day += hr/24; |
300 | hr -= 24; | 284 | hr = hr%24; |
301 | } | 285 | } |
302 | if (day > 31) { | 286 | if (day > 31) { |
303 | mo++; | 287 | mo += day/32; |
304 | day -= 31; | 288 | day = day%32; |
305 | } | 289 | } |
306 | if (mo > 12) { | 290 | if (mo > 12) { |
307 | yr++; | 291 | yr += mo/13; |
308 | mo -= 12; | 292 | mo = mo%13; |
309 | } | 293 | } |
310 | 294 | ||
311 | spin_lock_irq(&rtc_lock); | 295 | spin_lock_irq(&rtc_lock); |
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h index a2ea125ae2d0..cfaf8f5b0a14 100644 --- a/drivers/acpi/sleep/sleep.h +++ b/drivers/acpi/sleep/sleep.h | |||
@@ -5,5 +5,3 @@ extern int acpi_suspend (u32 state); | |||
5 | extern void acpi_enable_wakeup_device_prep(u8 sleep_state); | 5 | extern void acpi_enable_wakeup_device_prep(u8 sleep_state); |
6 | extern void acpi_enable_wakeup_device(u8 sleep_state); | 6 | extern void acpi_enable_wakeup_device(u8 sleep_state); |
7 | extern void acpi_disable_wakeup_device(u8 sleep_state); | 7 | extern void acpi_disable_wakeup_device(u8 sleep_state); |
8 | |||
9 | extern int acpi_sleep_prepare(u32 acpi_state); | ||
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index edee2806e37b..5ffe0ea18967 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
@@ -58,7 +58,7 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); | |||
58 | FS Interface (/sys) | 58 | FS Interface (/sys) |
59 | -------------------------------------------------------------------------- */ | 59 | -------------------------------------------------------------------------- */ |
60 | static LIST_HEAD(acpi_table_attr_list); | 60 | static LIST_HEAD(acpi_table_attr_list); |
61 | static struct kobject tables_kobj; | 61 | static struct kobject *tables_kobj; |
62 | 62 | ||
63 | struct acpi_table_attr { | 63 | struct acpi_table_attr { |
64 | struct bin_attribute attr; | 64 | struct bin_attribute attr; |
@@ -135,11 +135,9 @@ static int acpi_system_sysfs_init(void) | |||
135 | int table_index = 0; | 135 | int table_index = 0; |
136 | int result; | 136 | int result; |
137 | 137 | ||
138 | tables_kobj.parent = &acpi_subsys.kobj; | 138 | tables_kobj = kobject_create_and_add("tables", acpi_kobj); |
139 | kobject_set_name(&tables_kobj, "tables"); | 139 | if (!tables_kobj) |
140 | result = kobject_register(&tables_kobj); | 140 | return -ENOMEM; |
141 | if (result) | ||
142 | return result; | ||
143 | 141 | ||
144 | do { | 142 | do { |
145 | result = acpi_get_table_by_index(table_index, &table_header); | 143 | result = acpi_get_table_by_index(table_index, &table_header); |
@@ -153,7 +151,7 @@ static int acpi_system_sysfs_init(void) | |||
153 | 151 | ||
154 | acpi_table_attr_init(table_attr, table_header); | 152 | acpi_table_attr_init(table_attr, table_header); |
155 | result = | 153 | result = |
156 | sysfs_create_bin_file(&tables_kobj, | 154 | sysfs_create_bin_file(tables_kobj, |
157 | &table_attr->attr); | 155 | &table_attr->attr); |
158 | if (result) { | 156 | if (result) { |
159 | kfree(table_attr); | 157 | kfree(table_attr); |
@@ -163,6 +161,7 @@ static int acpi_system_sysfs_init(void) | |||
163 | &acpi_table_attr_list); | 161 | &acpi_table_attr_list); |
164 | } | 162 | } |
165 | } while (!result); | 163 | } while (!result); |
164 | kobject_uevent(tables_kobj, KOBJ_ADD); | ||
166 | 165 | ||
167 | return 0; | 166 | return 0; |
168 | } | 167 | } |
diff --git a/drivers/acpi/tables/Makefile b/drivers/acpi/tables/Makefile index 0a7d7afac255..7385efa61622 100644 --- a/drivers/acpi/tables/Makefile +++ b/drivers/acpi/tables/Makefile | |||
@@ -2,6 +2,6 @@ | |||
2 | # Makefile for all Linux ACPI interpreter subdirectories | 2 | # Makefile for all Linux ACPI interpreter subdirectories |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o | 5 | obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o |
6 | 6 | ||
7 | EXTRA_CFLAGS += $(ACPI_CFLAGS) | 7 | EXTRA_CFLAGS += $(ACPI_CFLAGS) |
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 5f1d85f2ffe4..010f19652f80 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c | |||
@@ -449,7 +449,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) | |||
449 | /* XSDT has NULL entry, RSDT is used */ | 449 | /* XSDT has NULL entry, RSDT is used */ |
450 | address = rsdt_address; | 450 | address = rsdt_address; |
451 | table_entry_size = sizeof(u32); | 451 | table_entry_size = sizeof(u32); |
452 | ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry," | 452 | ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, " |
453 | "using RSDT")); | 453 | "using RSDT")); |
454 | } | 454 | } |
455 | } | 455 | } |
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index cf8fa514189f..9ecb4b6c1e7d 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c | |||
@@ -100,7 +100,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) | |||
100 | 100 | ||
101 | /******************************************************************************* | 101 | /******************************************************************************* |
102 | * | 102 | * |
103 | * FUNCTION: acpi_tb_find_rsdp | 103 | * FUNCTION: acpi_find_root_pointer |
104 | * | 104 | * |
105 | * PARAMETERS: table_address - Where the table pointer is returned | 105 | * PARAMETERS: table_address - Where the table pointer is returned |
106 | * | 106 | * |
@@ -219,8 +219,6 @@ acpi_status acpi_find_root_pointer(acpi_native_uint * table_address) | |||
219 | return_ACPI_STATUS(AE_NOT_FOUND); | 219 | return_ACPI_STATUS(AE_NOT_FOUND); |
220 | } | 220 | } |
221 | 221 | ||
222 | ACPI_EXPORT_SYMBOL(acpi_find_root_pointer) | ||
223 | |||
224 | /******************************************************************************* | 222 | /******************************************************************************* |
225 | * | 223 | * |
226 | * FUNCTION: acpi_tb_scan_memory_for_rsdp | 224 | * FUNCTION: acpi_tb_scan_memory_for_rsdp |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 5f79b4451212..3a0af9a8cd27 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -492,7 +492,7 @@ static int acpi_thermal_get_devices(struct acpi_thermal *tz) | |||
492 | 492 | ||
493 | static int acpi_thermal_critical(struct acpi_thermal *tz) | 493 | static int acpi_thermal_critical(struct acpi_thermal *tz) |
494 | { | 494 | { |
495 | if (!tz || !tz->trips.critical.flags.valid || nocrt) | 495 | if (!tz || !tz->trips.critical.flags.valid) |
496 | return -EINVAL; | 496 | return -EINVAL; |
497 | 497 | ||
498 | if (tz->temperature >= tz->trips.critical.temperature) { | 498 | if (tz->temperature >= tz->trips.critical.temperature) { |
@@ -501,9 +501,6 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) | |||
501 | } else if (tz->trips.critical.flags.enabled) | 501 | } else if (tz->trips.critical.flags.enabled) |
502 | tz->trips.critical.flags.enabled = 0; | 502 | tz->trips.critical.flags.enabled = 0; |
503 | 503 | ||
504 | printk(KERN_EMERG | ||
505 | "Critical temperature reached (%ld C), shutting down.\n", | ||
506 | KELVIN_TO_CELSIUS(tz->temperature)); | ||
507 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, | 504 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, |
508 | tz->trips.critical.flags.enabled); | 505 | tz->trips.critical.flags.enabled); |
509 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, | 506 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, |
@@ -511,14 +508,20 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) | |||
511 | ACPI_THERMAL_NOTIFY_CRITICAL, | 508 | ACPI_THERMAL_NOTIFY_CRITICAL, |
512 | tz->trips.critical.flags.enabled); | 509 | tz->trips.critical.flags.enabled); |
513 | 510 | ||
514 | orderly_poweroff(true); | 511 | /* take no action if nocrt is set */ |
512 | if(!nocrt) { | ||
513 | printk(KERN_EMERG | ||
514 | "Critical temperature reached (%ld C), shutting down.\n", | ||
515 | KELVIN_TO_CELSIUS(tz->temperature)); | ||
516 | orderly_poweroff(true); | ||
517 | } | ||
515 | 518 | ||
516 | return 0; | 519 | return 0; |
517 | } | 520 | } |
518 | 521 | ||
519 | static int acpi_thermal_hot(struct acpi_thermal *tz) | 522 | static int acpi_thermal_hot(struct acpi_thermal *tz) |
520 | { | 523 | { |
521 | if (!tz || !tz->trips.hot.flags.valid || nocrt) | 524 | if (!tz || !tz->trips.hot.flags.valid) |
522 | return -EINVAL; | 525 | return -EINVAL; |
523 | 526 | ||
524 | if (tz->temperature >= tz->trips.hot.temperature) { | 527 | if (tz->temperature >= tz->trips.hot.temperature) { |
@@ -534,7 +537,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz) | |||
534 | ACPI_THERMAL_NOTIFY_HOT, | 537 | ACPI_THERMAL_NOTIFY_HOT, |
535 | tz->trips.hot.flags.enabled); | 538 | tz->trips.hot.flags.enabled); |
536 | 539 | ||
537 | /* TBD: Call user-mode "sleep(S4)" function */ | 540 | /* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */ |
538 | 541 | ||
539 | return 0; | 542 | return 0; |
540 | } | 543 | } |
diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c index cbbd3315a1e2..b630ee137ee1 100644 --- a/drivers/acpi/utilities/utresrc.c +++ b/drivers/acpi/utilities/utresrc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | * | 2 | * |
3 | * Module Name: utresrc - Resource managment utilities | 3 | * Module Name: utresrc - Resource management utilities |
4 | * | 4 | * |
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bac956b30c57..a54ff6bce8fa 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
32 | #include <linux/mutex.h> | ||
32 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
33 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
34 | #include <linux/input.h> | 35 | #include <linux/input.h> |
@@ -135,8 +136,8 @@ struct acpi_video_bus { | |||
135 | u8 attached_count; | 136 | u8 attached_count; |
136 | struct acpi_video_bus_cap cap; | 137 | struct acpi_video_bus_cap cap; |
137 | struct acpi_video_bus_flags flags; | 138 | struct acpi_video_bus_flags flags; |
138 | struct semaphore sem; | ||
139 | struct list_head video_device_list; | 139 | struct list_head video_device_list; |
140 | struct mutex device_list_lock; /* protects video_device_list */ | ||
140 | struct proc_dir_entry *dir; | 141 | struct proc_dir_entry *dir; |
141 | struct input_dev *input; | 142 | struct input_dev *input; |
142 | char phys[32]; /* for input device */ | 143 | char phys[32]; /* for input device */ |
@@ -291,18 +292,26 @@ static int acpi_video_device_set_state(struct acpi_video_device *device, int sta | |||
291 | static int acpi_video_get_brightness(struct backlight_device *bd) | 292 | static int acpi_video_get_brightness(struct backlight_device *bd) |
292 | { | 293 | { |
293 | unsigned long cur_level; | 294 | unsigned long cur_level; |
295 | int i; | ||
294 | struct acpi_video_device *vd = | 296 | struct acpi_video_device *vd = |
295 | (struct acpi_video_device *)bl_get_data(bd); | 297 | (struct acpi_video_device *)bl_get_data(bd); |
296 | acpi_video_device_lcd_get_level_current(vd, &cur_level); | 298 | acpi_video_device_lcd_get_level_current(vd, &cur_level); |
297 | return (int) cur_level; | 299 | for (i = 2; i < vd->brightness->count; i++) { |
300 | if (vd->brightness->levels[i] == cur_level) | ||
301 | /* The first two entries are special - see page 575 | ||
302 | of the ACPI spec 3.0 */ | ||
303 | return i-2; | ||
304 | } | ||
305 | return 0; | ||
298 | } | 306 | } |
299 | 307 | ||
300 | static int acpi_video_set_brightness(struct backlight_device *bd) | 308 | static int acpi_video_set_brightness(struct backlight_device *bd) |
301 | { | 309 | { |
302 | int request_level = bd->props.brightness; | 310 | int request_level = bd->props.brightness+2; |
303 | struct acpi_video_device *vd = | 311 | struct acpi_video_device *vd = |
304 | (struct acpi_video_device *)bl_get_data(bd); | 312 | (struct acpi_video_device *)bl_get_data(bd); |
305 | acpi_video_device_lcd_set_level(vd, request_level); | 313 | acpi_video_device_lcd_set_level(vd, |
314 | vd->brightness->levels[request_level]); | ||
306 | return 0; | 315 | return 0; |
307 | } | 316 | } |
308 | 317 | ||
@@ -576,7 +585,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
576 | struct acpi_video_device_brightness *br = NULL; | 585 | struct acpi_video_device_brightness *br = NULL; |
577 | 586 | ||
578 | 587 | ||
579 | memset(&device->cap, 0, 4); | 588 | memset(&device->cap, 0, sizeof(device->cap)); |
580 | 589 | ||
581 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { | 590 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { |
582 | device->cap._ADR = 1; | 591 | device->cap._ADR = 1; |
@@ -651,7 +660,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
651 | kfree(obj); | 660 | kfree(obj); |
652 | 661 | ||
653 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ | 662 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ |
654 | unsigned long tmp; | ||
655 | static int count = 0; | 663 | static int count = 0; |
656 | char *name; | 664 | char *name; |
657 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 665 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); |
@@ -659,11 +667,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
659 | return; | 667 | return; |
660 | 668 | ||
661 | sprintf(name, "acpi_video%d", count++); | 669 | sprintf(name, "acpi_video%d", count++); |
662 | acpi_video_device_lcd_get_level_current(device, &tmp); | ||
663 | device->backlight = backlight_device_register(name, | 670 | device->backlight = backlight_device_register(name, |
664 | NULL, device, &acpi_backlight_ops); | 671 | NULL, device, &acpi_backlight_ops); |
665 | device->backlight->props.max_brightness = max_level; | 672 | device->backlight->props.max_brightness = device->brightness->count-3; |
666 | device->backlight->props.brightness = (int)tmp; | 673 | device->backlight->props.brightness = acpi_video_get_brightness(device->backlight); |
667 | backlight_update_status(device->backlight); | 674 | backlight_update_status(device->backlight); |
668 | 675 | ||
669 | kfree(name); | 676 | kfree(name); |
@@ -696,7 +703,7 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) | |||
696 | { | 703 | { |
697 | acpi_handle h_dummy1; | 704 | acpi_handle h_dummy1; |
698 | 705 | ||
699 | memset(&video->cap, 0, 4); | 706 | memset(&video->cap, 0, sizeof(video->cap)); |
700 | if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { | 707 | if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { |
701 | video->cap._DOS = 1; | 708 | video->cap._DOS = 1; |
702 | } | 709 | } |
@@ -896,7 +903,7 @@ acpi_video_device_write_brightness(struct file *file, | |||
896 | { | 903 | { |
897 | struct seq_file *m = file->private_data; | 904 | struct seq_file *m = file->private_data; |
898 | struct acpi_video_device *dev = m->private; | 905 | struct acpi_video_device *dev = m->private; |
899 | char str[4] = { 0 }; | 906 | char str[5] = { 0 }; |
900 | unsigned int level = 0; | 907 | unsigned int level = 0; |
901 | int i; | 908 | int i; |
902 | 909 | ||
@@ -1255,8 +1262,37 @@ acpi_video_bus_write_DOS(struct file *file, | |||
1255 | 1262 | ||
1256 | static int acpi_video_bus_add_fs(struct acpi_device *device) | 1263 | static int acpi_video_bus_add_fs(struct acpi_device *device) |
1257 | { | 1264 | { |
1265 | long device_id; | ||
1266 | int status; | ||
1258 | struct proc_dir_entry *entry = NULL; | 1267 | struct proc_dir_entry *entry = NULL; |
1259 | struct acpi_video_bus *video; | 1268 | struct acpi_video_bus *video; |
1269 | struct device *dev; | ||
1270 | |||
1271 | status = | ||
1272 | acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); | ||
1273 | |||
1274 | if (!ACPI_SUCCESS(status)) | ||
1275 | return -ENODEV; | ||
1276 | |||
1277 | /* We need to attempt to determine whether the _ADR refers to a | ||
1278 | PCI device or not. There's no terribly good way to do this, | ||
1279 | so the best we can hope for is to assume that there'll never | ||
1280 | be a video device in the host bridge */ | ||
1281 | if (device_id >= 0x10000) { | ||
1282 | /* It looks like a PCI device. Does it exist? */ | ||
1283 | dev = acpi_get_physical_device(device->handle); | ||
1284 | } else { | ||
1285 | /* It doesn't look like a PCI device. Does its parent | ||
1286 | exist? */ | ||
1287 | acpi_handle phandle; | ||
1288 | if (acpi_get_parent(device->handle, &phandle)) | ||
1289 | return -ENODEV; | ||
1290 | dev = acpi_get_physical_device(phandle); | ||
1291 | } | ||
1292 | if (!dev) | ||
1293 | return -ENODEV; | ||
1294 | put_device(dev); | ||
1295 | |||
1260 | 1296 | ||
1261 | 1297 | ||
1262 | video = acpi_driver_data(device); | 1298 | video = acpi_driver_data(device); |
@@ -1436,9 +1472,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1436 | return -ENODEV; | 1472 | return -ENODEV; |
1437 | } | 1473 | } |
1438 | 1474 | ||
1439 | down(&video->sem); | 1475 | mutex_lock(&video->device_list_lock); |
1440 | list_add_tail(&data->entry, &video->video_device_list); | 1476 | list_add_tail(&data->entry, &video->video_device_list); |
1441 | up(&video->sem); | 1477 | mutex_unlock(&video->device_list_lock); |
1442 | 1478 | ||
1443 | acpi_video_device_add_fs(device); | 1479 | acpi_video_device_add_fs(device); |
1444 | 1480 | ||
@@ -1462,12 +1498,14 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1462 | 1498 | ||
1463 | static void acpi_video_device_rebind(struct acpi_video_bus *video) | 1499 | static void acpi_video_device_rebind(struct acpi_video_bus *video) |
1464 | { | 1500 | { |
1465 | struct list_head *node, *next; | 1501 | struct acpi_video_device *dev; |
1466 | list_for_each_safe(node, next, &video->video_device_list) { | 1502 | |
1467 | struct acpi_video_device *dev = | 1503 | mutex_lock(&video->device_list_lock); |
1468 | container_of(node, struct acpi_video_device, entry); | 1504 | |
1505 | list_for_each_entry(dev, &video->video_device_list, entry) | ||
1469 | acpi_video_device_bind(video, dev); | 1506 | acpi_video_device_bind(video, dev); |
1470 | } | 1507 | |
1508 | mutex_unlock(&video->device_list_lock); | ||
1471 | } | 1509 | } |
1472 | 1510 | ||
1473 | /* | 1511 | /* |
@@ -1592,30 +1630,33 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1592 | 1630 | ||
1593 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event) | 1631 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event) |
1594 | { | 1632 | { |
1595 | struct list_head *node, *next; | 1633 | struct list_head *node; |
1596 | struct acpi_video_device *dev = NULL; | 1634 | struct acpi_video_device *dev = NULL; |
1597 | struct acpi_video_device *dev_next = NULL; | 1635 | struct acpi_video_device *dev_next = NULL; |
1598 | struct acpi_video_device *dev_prev = NULL; | 1636 | struct acpi_video_device *dev_prev = NULL; |
1599 | unsigned long state; | 1637 | unsigned long state; |
1600 | int status = 0; | 1638 | int status = 0; |
1601 | 1639 | ||
1640 | mutex_lock(&video->device_list_lock); | ||
1602 | 1641 | ||
1603 | list_for_each_safe(node, next, &video->video_device_list) { | 1642 | list_for_each(node, &video->video_device_list) { |
1604 | dev = container_of(node, struct acpi_video_device, entry); | 1643 | dev = container_of(node, struct acpi_video_device, entry); |
1605 | status = acpi_video_device_get_state(dev, &state); | 1644 | status = acpi_video_device_get_state(dev, &state); |
1606 | if (state & 0x2) { | 1645 | if (state & 0x2) { |
1607 | dev_next = | 1646 | dev_next = container_of(node->next, |
1608 | container_of(node->next, struct acpi_video_device, | 1647 | struct acpi_video_device, entry); |
1609 | entry); | 1648 | dev_prev = container_of(node->prev, |
1610 | dev_prev = | 1649 | struct acpi_video_device, entry); |
1611 | container_of(node->prev, struct acpi_video_device, | ||
1612 | entry); | ||
1613 | goto out; | 1650 | goto out; |
1614 | } | 1651 | } |
1615 | } | 1652 | } |
1653 | |||
1616 | dev_next = container_of(node->next, struct acpi_video_device, entry); | 1654 | dev_next = container_of(node->next, struct acpi_video_device, entry); |
1617 | dev_prev = container_of(node->prev, struct acpi_video_device, entry); | 1655 | dev_prev = container_of(node->prev, struct acpi_video_device, entry); |
1618 | out: | 1656 | |
1657 | out: | ||
1658 | mutex_unlock(&video->device_list_lock); | ||
1659 | |||
1619 | switch (event) { | 1660 | switch (event) { |
1620 | case ACPI_VIDEO_NOTIFY_CYCLE: | 1661 | case ACPI_VIDEO_NOTIFY_CYCLE: |
1621 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: | 1662 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: |
@@ -1691,24 +1732,17 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, | |||
1691 | struct acpi_device *device) | 1732 | struct acpi_device *device) |
1692 | { | 1733 | { |
1693 | int status = 0; | 1734 | int status = 0; |
1694 | struct list_head *node, *next; | 1735 | struct acpi_device *dev; |
1695 | |||
1696 | 1736 | ||
1697 | acpi_video_device_enumerate(video); | 1737 | acpi_video_device_enumerate(video); |
1698 | 1738 | ||
1699 | list_for_each_safe(node, next, &device->children) { | 1739 | list_for_each_entry(dev, &device->children, node) { |
1700 | struct acpi_device *dev = | ||
1701 | list_entry(node, struct acpi_device, node); | ||
1702 | |||
1703 | if (!dev) | ||
1704 | continue; | ||
1705 | 1740 | ||
1706 | status = acpi_video_bus_get_one_device(dev, video); | 1741 | status = acpi_video_bus_get_one_device(dev, video); |
1707 | if (ACPI_FAILURE(status)) { | 1742 | if (ACPI_FAILURE(status)) { |
1708 | ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); | 1743 | ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); |
1709 | continue; | 1744 | continue; |
1710 | } | 1745 | } |
1711 | |||
1712 | } | 1746 | } |
1713 | return status; | 1747 | return status; |
1714 | } | 1748 | } |
@@ -1724,9 +1758,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
1724 | 1758 | ||
1725 | video = device->video; | 1759 | video = device->video; |
1726 | 1760 | ||
1727 | down(&video->sem); | ||
1728 | list_del(&device->entry); | ||
1729 | up(&video->sem); | ||
1730 | acpi_video_device_remove_fs(device->dev); | 1761 | acpi_video_device_remove_fs(device->dev); |
1731 | 1762 | ||
1732 | status = acpi_remove_notify_handler(device->dev->handle, | 1763 | status = acpi_remove_notify_handler(device->dev->handle, |
@@ -1734,32 +1765,34 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
1734 | acpi_video_device_notify); | 1765 | acpi_video_device_notify); |
1735 | backlight_device_unregister(device->backlight); | 1766 | backlight_device_unregister(device->backlight); |
1736 | video_output_unregister(device->output_dev); | 1767 | video_output_unregister(device->output_dev); |
1768 | |||
1737 | return 0; | 1769 | return 0; |
1738 | } | 1770 | } |
1739 | 1771 | ||
1740 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) | 1772 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) |
1741 | { | 1773 | { |
1742 | int status; | 1774 | int status; |
1743 | struct list_head *node, *next; | 1775 | struct acpi_video_device *dev, *next; |
1744 | 1776 | ||
1777 | mutex_lock(&video->device_list_lock); | ||
1745 | 1778 | ||
1746 | list_for_each_safe(node, next, &video->video_device_list) { | 1779 | list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { |
1747 | struct acpi_video_device *data = | ||
1748 | list_entry(node, struct acpi_video_device, entry); | ||
1749 | if (!data) | ||
1750 | continue; | ||
1751 | 1780 | ||
1752 | status = acpi_video_bus_put_one_device(data); | 1781 | status = acpi_video_bus_put_one_device(dev); |
1753 | if (ACPI_FAILURE(status)) | 1782 | if (ACPI_FAILURE(status)) |
1754 | printk(KERN_WARNING PREFIX | 1783 | printk(KERN_WARNING PREFIX |
1755 | "hhuuhhuu bug in acpi video driver.\n"); | 1784 | "hhuuhhuu bug in acpi video driver.\n"); |
1756 | 1785 | ||
1757 | if (data->brightness) | 1786 | if (dev->brightness) { |
1758 | kfree(data->brightness->levels); | 1787 | kfree(dev->brightness->levels); |
1759 | kfree(data->brightness); | 1788 | kfree(dev->brightness); |
1760 | kfree(data); | 1789 | } |
1790 | list_del(&dev->entry); | ||
1791 | kfree(dev); | ||
1761 | } | 1792 | } |
1762 | 1793 | ||
1794 | mutex_unlock(&video->device_list_lock); | ||
1795 | |||
1763 | return 0; | 1796 | return 0; |
1764 | } | 1797 | } |
1765 | 1798 | ||
@@ -1782,9 +1815,6 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1782 | struct input_dev *input; | 1815 | struct input_dev *input; |
1783 | int keycode; | 1816 | int keycode; |
1784 | 1817 | ||
1785 | |||
1786 | printk("video bus notify\n"); | ||
1787 | |||
1788 | if (!video) | 1818 | if (!video) |
1789 | return; | 1819 | return; |
1790 | 1820 | ||
@@ -1897,14 +1927,10 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
1897 | static int instance; | 1927 | static int instance; |
1898 | static int acpi_video_bus_add(struct acpi_device *device) | 1928 | static int acpi_video_bus_add(struct acpi_device *device) |
1899 | { | 1929 | { |
1900 | int result = 0; | 1930 | acpi_status status; |
1901 | acpi_status status = 0; | 1931 | struct acpi_video_bus *video; |
1902 | struct acpi_video_bus *video = NULL; | ||
1903 | struct input_dev *input; | 1932 | struct input_dev *input; |
1904 | 1933 | int error; | |
1905 | |||
1906 | if (!device) | ||
1907 | return -EINVAL; | ||
1908 | 1934 | ||
1909 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); | 1935 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); |
1910 | if (!video) | 1936 | if (!video) |
@@ -1923,15 +1949,15 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1923 | acpi_driver_data(device) = video; | 1949 | acpi_driver_data(device) = video; |
1924 | 1950 | ||
1925 | acpi_video_bus_find_cap(video); | 1951 | acpi_video_bus_find_cap(video); |
1926 | result = acpi_video_bus_check(video); | 1952 | error = acpi_video_bus_check(video); |
1927 | if (result) | 1953 | if (error) |
1928 | goto end; | 1954 | goto err_free_video; |
1929 | 1955 | ||
1930 | result = acpi_video_bus_add_fs(device); | 1956 | error = acpi_video_bus_add_fs(device); |
1931 | if (result) | 1957 | if (error) |
1932 | goto end; | 1958 | goto err_free_video; |
1933 | 1959 | ||
1934 | init_MUTEX(&video->sem); | 1960 | mutex_init(&video->device_list_lock); |
1935 | INIT_LIST_HEAD(&video->video_device_list); | 1961 | INIT_LIST_HEAD(&video->video_device_list); |
1936 | 1962 | ||
1937 | acpi_video_bus_get_devices(video, device); | 1963 | acpi_video_bus_get_devices(video, device); |
@@ -1943,16 +1969,15 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1943 | if (ACPI_FAILURE(status)) { | 1969 | if (ACPI_FAILURE(status)) { |
1944 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1970 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
1945 | "Error installing notify handler\n")); | 1971 | "Error installing notify handler\n")); |
1946 | acpi_video_bus_stop_devices(video); | 1972 | error = -ENODEV; |
1947 | acpi_video_bus_put_devices(video); | 1973 | goto err_stop_video; |
1948 | kfree(video->attached_array); | ||
1949 | acpi_video_bus_remove_fs(device); | ||
1950 | result = -ENODEV; | ||
1951 | goto end; | ||
1952 | } | 1974 | } |
1953 | 1975 | ||
1954 | |||
1955 | video->input = input = input_allocate_device(); | 1976 | video->input = input = input_allocate_device(); |
1977 | if (!input) { | ||
1978 | error = -ENOMEM; | ||
1979 | goto err_uninstall_notify; | ||
1980 | } | ||
1956 | 1981 | ||
1957 | snprintf(video->phys, sizeof(video->phys), | 1982 | snprintf(video->phys, sizeof(video->phys), |
1958 | "%s/video/input0", acpi_device_hid(video->device)); | 1983 | "%s/video/input0", acpi_device_hid(video->device)); |
@@ -1961,6 +1986,7 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1961 | input->phys = video->phys; | 1986 | input->phys = video->phys; |
1962 | input->id.bustype = BUS_HOST; | 1987 | input->id.bustype = BUS_HOST; |
1963 | input->id.product = 0x06; | 1988 | input->id.product = 0x06; |
1989 | input->dev.parent = &device->dev; | ||
1964 | input->evbit[0] = BIT(EV_KEY); | 1990 | input->evbit[0] = BIT(EV_KEY); |
1965 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); | 1991 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); |
1966 | set_bit(KEY_VIDEO_NEXT, input->keybit); | 1992 | set_bit(KEY_VIDEO_NEXT, input->keybit); |
@@ -1971,18 +1997,10 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1971 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); | 1997 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); |
1972 | set_bit(KEY_DISPLAY_OFF, input->keybit); | 1998 | set_bit(KEY_DISPLAY_OFF, input->keybit); |
1973 | set_bit(KEY_UNKNOWN, input->keybit); | 1999 | set_bit(KEY_UNKNOWN, input->keybit); |
1974 | result = input_register_device(input); | ||
1975 | if (result) { | ||
1976 | acpi_remove_notify_handler(video->device->handle, | ||
1977 | ACPI_DEVICE_NOTIFY, | ||
1978 | acpi_video_bus_notify); | ||
1979 | acpi_video_bus_stop_devices(video); | ||
1980 | acpi_video_bus_put_devices(video); | ||
1981 | kfree(video->attached_array); | ||
1982 | acpi_video_bus_remove_fs(device); | ||
1983 | goto end; | ||
1984 | } | ||
1985 | 2000 | ||
2001 | error = input_register_device(input); | ||
2002 | if (error) | ||
2003 | goto err_free_input_dev; | ||
1986 | 2004 | ||
1987 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", | 2005 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", |
1988 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 2006 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
@@ -1990,11 +2008,23 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1990 | video->flags.rom ? "yes" : "no", | 2008 | video->flags.rom ? "yes" : "no", |
1991 | video->flags.post ? "yes" : "no"); | 2009 | video->flags.post ? "yes" : "no"); |
1992 | 2010 | ||
1993 | end: | 2011 | return 0; |
1994 | if (result) | 2012 | |
1995 | kfree(video); | 2013 | err_free_input_dev: |
2014 | input_free_device(input); | ||
2015 | err_uninstall_notify: | ||
2016 | acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, | ||
2017 | acpi_video_bus_notify); | ||
2018 | err_stop_video: | ||
2019 | acpi_video_bus_stop_devices(video); | ||
2020 | acpi_video_bus_put_devices(video); | ||
2021 | kfree(video->attached_array); | ||
2022 | acpi_video_bus_remove_fs(device); | ||
2023 | err_free_video: | ||
2024 | kfree(video); | ||
2025 | acpi_driver_data(device) = NULL; | ||
1996 | 2026 | ||
1997 | return result; | 2027 | return error; |
1998 | } | 2028 | } |
1999 | 2029 | ||
2000 | static int acpi_video_bus_remove(struct acpi_device *device, int type) | 2030 | static int acpi_video_bus_remove(struct acpi_device *device, int type) |