diff options
Diffstat (limited to 'drivers/acpi')
30 files changed, 1208 insertions, 236 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b9f923ef173d..ccf6ea95f68c 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -82,6 +82,12 @@ config ACPI_PROCFS_POWER | |||
82 | and functions, which do not yet exist in /sys | 82 | and functions, which do not yet exist in /sys |
83 | 83 | ||
84 | Say N to delete power /proc/acpi/ folders that have moved to /sys/ | 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 | ||
85 | config ACPI_PROC_EVENT | 91 | config ACPI_PROC_EVENT |
86 | bool "Deprecated /proc/acpi/event support" | 92 | bool "Deprecated /proc/acpi/event support" |
87 | depends on PROC_FS | 93 | depends on PROC_FS |
@@ -103,7 +109,6 @@ config ACPI_PROC_EVENT | |||
103 | config ACPI_AC | 109 | config ACPI_AC |
104 | tristate "AC Adapter" | 110 | tristate "AC Adapter" |
105 | depends on X86 | 111 | depends on X86 |
106 | select POWER_SUPPLY | ||
107 | default y | 112 | default y |
108 | help | 113 | help |
109 | This driver adds support for the AC Adapter object, which indicates | 114 | This driver adds support for the AC Adapter object, which indicates |
@@ -113,7 +118,6 @@ config ACPI_AC | |||
113 | config ACPI_BATTERY | 118 | config ACPI_BATTERY |
114 | tristate "Battery" | 119 | tristate "Battery" |
115 | depends on X86 | 120 | depends on X86 |
116 | select POWER_SUPPLY | ||
117 | default y | 121 | default y |
118 | help | 122 | help |
119 | This driver adds support for battery information through | 123 | This driver adds support for battery information through |
@@ -368,7 +372,6 @@ config ACPI_HOTPLUG_MEMORY | |||
368 | config ACPI_SBS | 372 | config ACPI_SBS |
369 | tristate "Smart Battery System" | 373 | tristate "Smart Battery System" |
370 | depends on X86 | 374 | depends on X86 |
371 | select POWER_SUPPLY | ||
372 | help | 375 | help |
373 | This driver adds support for the Smart Battery System, another | 376 | This driver adds support for the Smart Battery System, another |
374 | 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/ac.c b/drivers/acpi/ac.c index 76ed4f52bebd..76b9bea98b6d 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
@@ -31,7 +31,9 @@ | |||
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 | ||
@@ -79,7 +81,9 @@ 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 | }; |
@@ -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 | -------------------------------------------------------------------------- */ |
@@ -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, |
@@ -280,12 +286,14 @@ static int acpi_ac_add(struct acpi_device *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); |
@@ -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,8 +347,10 @@ 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); |
353 | #endif | ||
342 | #ifdef CONFIG_ACPI_PROCFS_POWER | 354 | #ifdef CONFIG_ACPI_PROCFS_POWER |
343 | acpi_ac_remove_fs(device); | 355 | acpi_ac_remove_fs(device); |
344 | #endif | 356 | #endif |
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 8f7505d304b5..f6215e809808 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -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 | ||
@@ -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)) |
@@ -189,6 +194,9 @@ static int acpi_battery_get_property(struct power_supply *psy, | |||
189 | case POWER_SUPPLY_PROP_MANUFACTURER: | 194 | case POWER_SUPPLY_PROP_MANUFACTURER: |
190 | val->strval = battery->oem_info; | 195 | val->strval = battery->oem_info; |
191 | break; | 196 | break; |
197 | case POWER_SUPPLY_PROP_SERIAL_NUMBER: | ||
198 | val->strval = battery->serial_number; | ||
199 | break; | ||
192 | default: | 200 | default: |
193 | return -EINVAL; | 201 | return -EINVAL; |
194 | } | 202 | } |
@@ -207,6 +215,7 @@ static enum power_supply_property charge_battery_props[] = { | |||
207 | POWER_SUPPLY_PROP_CHARGE_NOW, | 215 | POWER_SUPPLY_PROP_CHARGE_NOW, |
208 | POWER_SUPPLY_PROP_MODEL_NAME, | 216 | POWER_SUPPLY_PROP_MODEL_NAME, |
209 | POWER_SUPPLY_PROP_MANUFACTURER, | 217 | POWER_SUPPLY_PROP_MANUFACTURER, |
218 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | ||
210 | }; | 219 | }; |
211 | 220 | ||
212 | static enum power_supply_property energy_battery_props[] = { | 221 | static enum power_supply_property energy_battery_props[] = { |
@@ -221,7 +230,9 @@ static enum power_supply_property energy_battery_props[] = { | |||
221 | POWER_SUPPLY_PROP_ENERGY_NOW, | 230 | POWER_SUPPLY_PROP_ENERGY_NOW, |
222 | POWER_SUPPLY_PROP_MODEL_NAME, | 231 | POWER_SUPPLY_PROP_MODEL_NAME, |
223 | POWER_SUPPLY_PROP_MANUFACTURER, | 232 | POWER_SUPPLY_PROP_MANUFACTURER, |
233 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | ||
224 | }; | 234 | }; |
235 | #endif | ||
225 | 236 | ||
226 | #ifdef CONFIG_ACPI_PROCFS_POWER | 237 | #ifdef CONFIG_ACPI_PROCFS_POWER |
227 | inline char *acpi_battery_units(struct acpi_battery *battery) | 238 | inline char *acpi_battery_units(struct acpi_battery *battery) |
@@ -398,6 +409,7 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) | |||
398 | return acpi_battery_set_alarm(battery); | 409 | return acpi_battery_set_alarm(battery); |
399 | } | 410 | } |
400 | 411 | ||
412 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
401 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 413 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
402 | struct device_attribute *attr, | 414 | struct device_attribute *attr, |
403 | char *buf) | 415 | char *buf) |
@@ -429,11 +441,6 @@ static int sysfs_add_battery(struct acpi_battery *battery) | |||
429 | { | 441 | { |
430 | int result; | 442 | int result; |
431 | 443 | ||
432 | battery->update_time = 0; | ||
433 | result = acpi_battery_get_info(battery); | ||
434 | acpi_battery_init_alarm(battery); | ||
435 | if (result) | ||
436 | return result; | ||
437 | if (battery->power_unit) { | 444 | if (battery->power_unit) { |
438 | battery->bat.properties = charge_battery_props; | 445 | battery->bat.properties = charge_battery_props; |
439 | battery->bat.num_properties = | 446 | battery->bat.num_properties = |
@@ -462,18 +469,31 @@ static void sysfs_remove_battery(struct acpi_battery *battery) | |||
462 | power_supply_unregister(&battery->bat); | 469 | power_supply_unregister(&battery->bat); |
463 | battery->bat.dev = NULL; | 470 | battery->bat.dev = NULL; |
464 | } | 471 | } |
472 | #endif | ||
465 | 473 | ||
466 | static int acpi_battery_update(struct acpi_battery *battery) | 474 | static int acpi_battery_update(struct acpi_battery *battery) |
467 | { | 475 | { |
468 | int result = acpi_battery_get_status(battery); | 476 | int result; |
477 | result = acpi_battery_get_status(battery); | ||
469 | if (result) | 478 | if (result) |
470 | return result; | 479 | return result; |
480 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
471 | if (!acpi_battery_present(battery)) { | 481 | if (!acpi_battery_present(battery)) { |
472 | sysfs_remove_battery(battery); | 482 | sysfs_remove_battery(battery); |
483 | battery->update_time = 0; | ||
473 | return 0; | 484 | return 0; |
474 | } | 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 | ||
475 | if (!battery->bat.dev) | 494 | if (!battery->bat.dev) |
476 | sysfs_add_battery(battery); | 495 | sysfs_add_battery(battery); |
496 | #endif | ||
477 | return acpi_battery_get_state(battery); | 497 | return acpi_battery_get_state(battery); |
478 | } | 498 | } |
479 | 499 | ||
@@ -767,9 +787,11 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
767 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 787 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
768 | device->dev.bus_id, event, | 788 | device->dev.bus_id, event, |
769 | acpi_battery_present(battery)); | 789 | acpi_battery_present(battery)); |
790 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
770 | /* acpi_batter_update could remove power_supply object */ | 791 | /* acpi_batter_update could remove power_supply object */ |
771 | if (battery->bat.dev) | 792 | if (battery->bat.dev) |
772 | kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); | 793 | kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); |
794 | #endif | ||
773 | } | 795 | } |
774 | 796 | ||
775 | static int acpi_battery_add(struct acpi_device *device) | 797 | static int acpi_battery_add(struct acpi_device *device) |
@@ -828,7 +850,9 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
828 | #ifdef CONFIG_ACPI_PROCFS_POWER | 850 | #ifdef CONFIG_ACPI_PROCFS_POWER |
829 | acpi_battery_remove_fs(device); | 851 | acpi_battery_remove_fs(device); |
830 | #endif | 852 | #endif |
853 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
831 | sysfs_remove_battery(battery); | 854 | sysfs_remove_battery(battery); |
855 | #endif | ||
832 | mutex_destroy(&battery->lock); | 856 | mutex_destroy(&battery->lock); |
833 | kfree(battery); | 857 | kfree(battery); |
834 | return 0; | 858 | return 0; |
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/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 d411017f8c06..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> |
@@ -47,9 +50,6 @@ | |||
47 | #undef PREFIX | 50 | #undef PREFIX |
48 | #define PREFIX "ACPI: EC: " | 51 | #define PREFIX "ACPI: EC: " |
49 | 52 | ||
50 | /* Uncomment next line to get verbose print outs*/ | ||
51 | /* #define DEBUG */ | ||
52 | |||
53 | /* EC status register */ | 53 | /* EC status register */ |
54 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ | 54 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ |
55 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ | 55 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ |
@@ -82,6 +82,7 @@ enum { | |||
82 | EC_FLAGS_ADDRESS, /* Address is being written */ | 82 | EC_FLAGS_ADDRESS, /* Address is being written */ |
83 | EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ | 83 | EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ |
84 | EC_FLAGS_WDATA, /* Data is being written */ | 84 | EC_FLAGS_WDATA, /* Data is being written */ |
85 | EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */ | ||
85 | }; | 86 | }; |
86 | 87 | ||
87 | static int acpi_ec_remove(struct acpi_device *device, int type); | 88 | static int acpi_ec_remove(struct acpi_device *device, int type); |
@@ -138,26 +139,26 @@ static struct acpi_ec { | |||
138 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) | 139 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) |
139 | { | 140 | { |
140 | u8 x = inb(ec->command_addr); | 141 | u8 x = inb(ec->command_addr); |
141 | pr_debug(PREFIX "---> status = 0x%2x\n", x); | 142 | pr_debug(PREFIX "---> status = 0x%2.2x\n", x); |
142 | return x; | 143 | return x; |
143 | } | 144 | } |
144 | 145 | ||
145 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) | 146 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) |
146 | { | 147 | { |
147 | u8 x = inb(ec->data_addr); | 148 | u8 x = inb(ec->data_addr); |
148 | pr_debug(PREFIX "---> data = 0x%2x\n", x); | 149 | pr_debug(PREFIX "---> data = 0x%2.2x\n", x); |
149 | return inb(ec->data_addr); | 150 | return inb(ec->data_addr); |
150 | } | 151 | } |
151 | 152 | ||
152 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) | 153 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) |
153 | { | 154 | { |
154 | pr_debug(PREFIX "<--- command = 0x%2x\n", command); | 155 | pr_debug(PREFIX "<--- command = 0x%2.2x\n", command); |
155 | outb(command, ec->command_addr); | 156 | outb(command, ec->command_addr); |
156 | } | 157 | } |
157 | 158 | ||
158 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) | 159 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) |
159 | { | 160 | { |
160 | pr_debug(PREFIX "<--- data = 0x%2x\n", data); | 161 | pr_debug(PREFIX "<--- data = 0x%2.2x\n", data); |
161 | outb(data, ec->data_addr); | 162 | outb(data, ec->data_addr); |
162 | } | 163 | } |
163 | 164 | ||
@@ -179,6 +180,10 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) | |||
179 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | 180 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) |
180 | { | 181 | { |
181 | int ret = 0; | 182 | int ret = 0; |
183 | |||
184 | if (unlikely(event == ACPI_EC_EVENT_OBF_1 && | ||
185 | test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) | ||
186 | force_poll = 1; | ||
182 | if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && | 187 | if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && |
183 | test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) | 188 | test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) |
184 | force_poll = 1; | 189 | force_poll = 1; |
@@ -192,7 +197,12 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | |||
192 | goto end; | 197 | goto end; |
193 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 198 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
194 | if (acpi_ec_check_status(ec, event)) { | 199 | if (acpi_ec_check_status(ec, event)) { |
195 | if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { | 200 | if (event == ACPI_EC_EVENT_OBF_1) { |
201 | /* miss OBF_1 GPE, don't expect it */ | ||
202 | pr_info(PREFIX "missing OBF confirmation, " | ||
203 | "don't expect it any longer.\n"); | ||
204 | set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags); | ||
205 | } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { | ||
196 | /* miss address GPE, don't expect it anymore */ | 206 | /* miss address GPE, don't expect it anymore */ |
197 | pr_info(PREFIX "missing address confirmation, " | 207 | pr_info(PREFIX "missing address confirmation, " |
198 | "don't expect it any longer.\n"); | 208 | "don't expect it any longer.\n"); |
@@ -563,7 +573,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, | |||
563 | void *handler_context, void *region_context) | 573 | void *handler_context, void *region_context) |
564 | { | 574 | { |
565 | struct acpi_ec *ec = handler_context; | 575 | struct acpi_ec *ec = handler_context; |
566 | int result = 0, i = 0; | 576 | int result = 0, i; |
567 | u8 temp = 0; | 577 | u8 temp = 0; |
568 | 578 | ||
569 | if ((address > 0xFF) || !value || !handler_context) | 579 | if ((address > 0xFF) || !value || !handler_context) |
@@ -575,7 +585,18 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, | |||
575 | if (bits != 8 && acpi_strict) | 585 | if (bits != 8 && acpi_strict) |
576 | return AE_BAD_PARAMETER; | 586 | return AE_BAD_PARAMETER; |
577 | 587 | ||
578 | 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; | ||
579 | if (function == ACPI_READ) { | 600 | if (function == ACPI_READ) { |
580 | result = acpi_ec_read(ec, address, &temp); | 601 | result = acpi_ec_read(ec, address, &temp); |
581 | (*value) |= ((acpi_integer)temp) << i; | 602 | (*value) |= ((acpi_integer)temp) << i; |
@@ -583,10 +604,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, | |||
583 | temp = 0xff & ((*value) >> i); | 604 | temp = 0xff & ((*value) >> i); |
584 | result = acpi_ec_write(ec, address, temp); | 605 | result = acpi_ec_write(ec, address, temp); |
585 | } | 606 | } |
586 | i += 8; | ||
587 | ++address; | ||
588 | } | 607 | } |
589 | 608 | ||
609 | acpi_ec_burst_disable(ec); | ||
610 | |||
590 | switch (result) { | 611 | switch (result) { |
591 | case -EINVAL: | 612 | case -EINVAL: |
592 | return AE_BAD_PARAMETER; | 613 | return AE_BAD_PARAMETER; |
@@ -892,6 +913,17 @@ static int acpi_ec_stop(struct acpi_device *device, int type) | |||
892 | return 0; | 913 | return 0; |
893 | } | 914 | } |
894 | 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 | |||
895 | int __init acpi_ec_ecdt_probe(void) | 927 | int __init acpi_ec_ecdt_probe(void) |
896 | { | 928 | { |
897 | int ret; | 929 | int ret; |
@@ -924,9 +956,10 @@ int __init acpi_ec_ecdt_probe(void) | |||
924 | goto error; | 956 | goto error; |
925 | /* We really need to limit this workaround, the only ASUS, | 957 | /* We really need to limit this workaround, the only ASUS, |
926 | * which needs it, has fake EC._INI method, so use it as flag. | 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. | ||
927 | */ | 960 | */ |
928 | if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x))) | 961 | if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x))) |
929 | goto error; | 962 | return -ENODEV; |
930 | } | 963 | } |
931 | 964 | ||
932 | ret = ec_install_handlers(boot_ec); | 965 | ret = ec_install_handlers(boot_ec); |
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index e22f4a973c0f..056b78844829 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c | |||
@@ -270,18 +270,18 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
270 | case ACPI_GPE_TYPE_WAKE_RUN: | 270 | case ACPI_GPE_TYPE_WAKE_RUN: |
271 | ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); | 271 | ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); |
272 | 272 | ||
273 | /*lint -fallthrough */ | 273 | /* fallthrough */ |
274 | 274 | ||
275 | case ACPI_GPE_TYPE_RUNTIME: | 275 | case ACPI_GPE_TYPE_RUNTIME: |
276 | 276 | ||
277 | /* Disable the requested runtime GPE */ | 277 | /* Disable the requested runtime GPE */ |
278 | 278 | ||
279 | ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); | 279 | ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); |
280 | status = acpi_hw_write_gpe_enable_reg(gpe_event_info); | 280 | |
281 | break; | 281 | /* fallthrough */ |
282 | 282 | ||
283 | default: | 283 | default: |
284 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 284 | acpi_hw_write_gpe_enable_reg(gpe_event_info); |
285 | } | 285 | } |
286 | 286 | ||
287 | return_ACPI_STATUS(AE_OK); | 287 | return_ACPI_STATUS(AE_OK); |
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/osl.c b/drivers/acpi/osl.c index e3a673a00845..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) |
@@ -964,13 +1011,37 @@ static int __init acpi_os_name_setup(char *str) | |||
964 | 1011 | ||
965 | __setup("acpi_os_name=", acpi_os_name_setup); | 1012 | __setup("acpi_os_name=", acpi_os_name_setup); |
966 | 1013 | ||
967 | 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) */ | ||
1035 | |||
1036 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); | ||
1037 | |||
1038 | if (enable == -1) | ||
1039 | return; | ||
1040 | |||
1041 | osi_linux.known = 1; /* DMI knows which OSI(Linux) default needed */ | ||
968 | 1042 | ||
969 | if (osi_linux != enable) | 1043 | set_osi_linux(enable); |
970 | printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n", | ||
971 | enable ? "En": "Dis"); | ||
972 | 1044 | ||
973 | osi_linux = enable; | ||
974 | return; | 1045 | return; |
975 | } | 1046 | } |
976 | 1047 | ||
@@ -987,12 +1058,12 @@ static int __init acpi_osi_setup(char *str) | |||
987 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | 1058 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); |
988 | acpi_gbl_create_osi_method = FALSE; | 1059 | acpi_gbl_create_osi_method = FALSE; |
989 | } else if (!strcmp("!Linux", str)) { | 1060 | } else if (!strcmp("!Linux", str)) { |
990 | enable_osi_linux(0); | 1061 | acpi_cmdline_osi_linux(0); /* !enable */ |
991 | } else if (*str == '!') { | 1062 | } else if (*str == '!') { |
992 | if (acpi_osi_invalidate(++str) == AE_OK) | 1063 | if (acpi_osi_invalidate(++str) == AE_OK) |
993 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); | 1064 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); |
994 | } else if (!strcmp("Linux", str)) { | 1065 | } else if (!strcmp("Linux", str)) { |
995 | enable_osi_linux(1); | 1066 | acpi_cmdline_osi_linux(1); /* enable */ |
996 | } else if (*osi_additional_string == '\0') { | 1067 | } else if (*osi_additional_string == '\0') { |
997 | strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); | 1068 | strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); |
998 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); | 1069 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); |
@@ -1141,6 +1212,34 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) | |||
1141 | return (AE_OK); | 1212 | return (AE_OK); |
1142 | } | 1213 | } |
1143 | 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 | |||
1144 | /****************************************************************************** | 1243 | /****************************************************************************** |
1145 | * | 1244 | * |
1146 | * FUNCTION: acpi_os_validate_interface | 1245 | * FUNCTION: acpi_os_validate_interface |
@@ -1160,13 +1259,29 @@ acpi_os_validate_interface (char *interface) | |||
1160 | if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) | 1259 | if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) |
1161 | return AE_OK; | 1260 | return AE_OK; |
1162 | if (!strcmp("Linux", interface)) { | 1261 | if (!strcmp("Linux", interface)) { |
1163 | printk(KERN_WARNING PREFIX | 1262 | |
1164 | "System BIOS is requesting _OSI(Linux)\n"); | 1263 | printk(KERN_NOTICE PREFIX |
1165 | printk(KERN_WARNING PREFIX | 1264 | "BIOS _OSI(Linux) query %s%s\n", |
1166 | "If \"acpi_osi=Linux\" works better,\n" | 1265 | osi_linux.enable ? "honored" : "ignored", |
1167 | "Please send dmidecode " | 1266 | osi_linux.cmdline ? " via cmdline" : |
1168 | "to linux-acpi@vger.kernel.org\n"); | 1267 | osi_linux.dmi ? " via DMI" : ""); |
1169 | 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) | ||
1170 | return AE_OK; | 1285 | return AE_OK; |
1171 | } | 1286 | } |
1172 | return AE_SUPPORT; | 1287 | return AE_SUPPORT; |
@@ -1198,28 +1313,4 @@ acpi_os_validate_address ( | |||
1198 | return AE_OK; | 1313 | return AE_OK; |
1199 | } | 1314 | } |
1200 | 1315 | ||
1201 | #ifdef CONFIG_DMI | ||
1202 | static int dmi_osi_linux(const struct dmi_system_id *d) | ||
1203 | { | ||
1204 | printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident); | ||
1205 | enable_osi_linux(1); | ||
1206 | return 0; | ||
1207 | } | ||
1208 | |||
1209 | static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { | ||
1210 | /* | ||
1211 | * Boxes that need _OSI(Linux) | ||
1212 | */ | ||
1213 | { | ||
1214 | .callback = dmi_osi_linux, | ||
1215 | .ident = "Intel Napa CRB", | ||
1216 | .matches = { | ||
1217 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), | ||
1218 | DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"), | ||
1219 | }, | ||
1220 | }, | ||
1221 | {} | ||
1222 | }; | ||
1223 | #endif /* CONFIG_DMI */ | ||
1224 | |||
1225 | #endif | 1316 | #endif |
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_idle.c b/drivers/acpi/processor_idle.c index 2fe34cc73c13..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 | ||
@@ -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,7 @@ 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()); | ||
533 | /* | 559 | /* |
534 | * Must be done before busmaster disable as we might | 560 | * Must be done before busmaster disable as we might |
535 | * need to access HPET ! | 561 | * need to access HPET ! |
@@ -575,7 +601,8 @@ static void acpi_processor_idle(void) | |||
575 | 601 | ||
576 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 602 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
577 | /* TSC halts in C3, so notify users */ | 603 | /* TSC halts in C3, so notify users */ |
578 | mark_tsc_unstable("TSC halts in C3"); | 604 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
605 | mark_tsc_unstable("TSC halts in C3"); | ||
579 | #endif | 606 | #endif |
580 | /* Compute time (ticks) that we were actually asleep */ | 607 | /* Compute time (ticks) that we were actually asleep */ |
581 | sleep_ticks = ticks_elapsed(t1, t2); | 608 | sleep_ticks = ticks_elapsed(t1, t2); |
@@ -621,7 +648,8 @@ static void acpi_processor_idle(void) | |||
621 | if (cx->promotion.state && | 648 | if (cx->promotion.state && |
622 | ((cx->promotion.state - pr->power.states) <= max_cstate)) { | 649 | ((cx->promotion.state - pr->power.states) <= max_cstate)) { |
623 | if (sleep_ticks > cx->promotion.threshold.ticks && | 650 | if (sleep_ticks > cx->promotion.threshold.ticks && |
624 | cx->promotion.state->latency <= system_latency_constraint()) { | 651 | cx->promotion.state->latency <= |
652 | pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) { | ||
625 | cx->promotion.count++; | 653 | cx->promotion.count++; |
626 | cx->demotion.count = 0; | 654 | cx->demotion.count = 0; |
627 | if (cx->promotion.count >= | 655 | if (cx->promotion.count >= |
@@ -665,7 +693,8 @@ static void acpi_processor_idle(void) | |||
665 | * or if the latency of the current state is unacceptable | 693 | * or if the latency of the current state is unacceptable |
666 | */ | 694 | */ |
667 | if ((pr->power.state - pr->power.states) > max_cstate || | 695 | if ((pr->power.state - pr->power.states) > max_cstate || |
668 | pr->power.state->latency > system_latency_constraint()) { | 696 | pr->power.state->latency > |
697 | pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) { | ||
669 | if (cx->demotion.state) | 698 | if (cx->demotion.state) |
670 | next_state = cx->demotion.state; | 699 | next_state = cx->demotion.state; |
671 | } | 700 | } |
@@ -1173,7 +1202,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) | |||
1173 | "maximum allowed latency: %d usec\n", | 1202 | "maximum allowed latency: %d usec\n", |
1174 | pr->power.state ? pr->power.state - pr->power.states : 0, | 1203 | pr->power.state ? pr->power.state - pr->power.states : 0, |
1175 | max_cstate, (unsigned)pr->power.bm_activity, | 1204 | max_cstate, (unsigned)pr->power.bm_activity, |
1176 | system_latency_constraint()); | 1205 | pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)); |
1177 | 1206 | ||
1178 | seq_puts(seq, "states:\n"); | 1207 | seq_puts(seq, "states:\n"); |
1179 | 1208 | ||
@@ -1419,6 +1448,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
1419 | return 0; | 1448 | return 0; |
1420 | } | 1449 | } |
1421 | 1450 | ||
1451 | acpi_unlazy_tlb(smp_processor_id()); | ||
1422 | /* | 1452 | /* |
1423 | * Must be done before busmaster disable as we might need to | 1453 | * Must be done before busmaster disable as we might need to |
1424 | * access HPET ! | 1454 | * access HPET ! |
@@ -1439,7 +1469,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
1439 | 1469 | ||
1440 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 1470 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
1441 | /* TSC could halt in idle, so notify users */ | 1471 | /* TSC could halt in idle, so notify users */ |
1442 | mark_tsc_unstable("TSC halts in idle");; | 1472 | if (tsc_halts_in_c(cx->type)) |
1473 | mark_tsc_unstable("TSC halts in idle");; | ||
1443 | #endif | 1474 | #endif |
1444 | sleep_ticks = ticks_elapsed(t1, t2); | 1475 | sleep_ticks = ticks_elapsed(t1, t2); |
1445 | 1476 | ||
@@ -1550,7 +1581,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1550 | 1581 | ||
1551 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 1582 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
1552 | /* TSC could halt in idle, so notify users */ | 1583 | /* TSC could halt in idle, so notify users */ |
1553 | mark_tsc_unstable("TSC halts in idle"); | 1584 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
1585 | mark_tsc_unstable("TSC halts in idle"); | ||
1554 | #endif | 1586 | #endif |
1555 | sleep_ticks = ticks_elapsed(t1, t2); | 1587 | sleep_ticks = ticks_elapsed(t1, t2); |
1556 | /* Tell the scheduler how much we idled: */ | 1588 | /* Tell the scheduler how much we idled: */ |
@@ -1688,8 +1720,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1688 | "ACPI: processor limited to max C-state %d\n", | 1720 | "ACPI: processor limited to max C-state %d\n", |
1689 | max_cstate); | 1721 | max_cstate); |
1690 | first_run++; | 1722 | first_run++; |
1691 | #if !defined (CONFIG_CPU_IDLE) && defined (CONFIG_SMP) | 1723 | #if !defined(CONFIG_CPU_IDLE) && defined(CONFIG_SMP) |
1692 | register_latency_notifier(&acpi_processor_latency_notifier); | 1724 | pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY, |
1725 | &acpi_processor_latency_notifier); | ||
1693 | #endif | 1726 | #endif |
1694 | } | 1727 | } |
1695 | 1728 | ||
@@ -1776,7 +1809,8 @@ int acpi_processor_power_exit(struct acpi_processor *pr, | |||
1776 | */ | 1809 | */ |
1777 | cpu_idle_wait(); | 1810 | cpu_idle_wait(); |
1778 | #ifdef CONFIG_SMP | 1811 | #ifdef CONFIG_SMP |
1779 | unregister_latency_notifier(&acpi_processor_latency_notifier); | 1812 | pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY, |
1813 | &acpi_processor_latency_notifier); | ||
1780 | #endif | 1814 | #endif |
1781 | } | 1815 | } |
1782 | #endif | 1816 | #endif |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 6742d7bc4777..1685b40abda7 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
@@ -775,12 +775,12 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
775 | acpi_processor_get_throttling_states(pr) || | 775 | acpi_processor_get_throttling_states(pr) || |
776 | acpi_processor_get_platform_limit(pr)) | 776 | acpi_processor_get_platform_limit(pr)) |
777 | { | 777 | { |
778 | if (acpi_processor_get_fadt_info(pr)) | ||
779 | return 0; | ||
780 | pr->throttling.acpi_processor_get_throttling = | 778 | pr->throttling.acpi_processor_get_throttling = |
781 | &acpi_processor_get_throttling_fadt; | 779 | &acpi_processor_get_throttling_fadt; |
782 | pr->throttling.acpi_processor_set_throttling = | 780 | pr->throttling.acpi_processor_set_throttling = |
783 | &acpi_processor_set_throttling_fadt; | 781 | &acpi_processor_set_throttling_fadt; |
782 | if (acpi_processor_get_fadt_info(pr)) | ||
783 | return 0; | ||
784 | } else { | 784 | } else { |
785 | pr->throttling.acpi_processor_get_throttling = | 785 | pr->throttling.acpi_processor_get_throttling = |
786 | &acpi_processor_get_throttling_ptc; | 786 | &acpi_processor_get_throttling_ptc; |
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 22cb95b349e4..f136c7d3b3c2 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
@@ -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 | ||
@@ -80,7 +82,9 @@ static const struct acpi_device_id sbs_device_ids[] = { | |||
80 | MODULE_DEVICE_TABLE(acpi, sbs_device_ids); | 82 | MODULE_DEVICE_TABLE(acpi, sbs_device_ids); |
81 | 83 | ||
82 | struct acpi_battery { | 84 | struct acpi_battery { |
85 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
83 | struct power_supply bat; | 86 | struct power_supply bat; |
87 | #endif | ||
84 | struct acpi_sbs *sbs; | 88 | struct acpi_sbs *sbs; |
85 | #ifdef CONFIG_ACPI_PROCFS_POWER | 89 | #ifdef CONFIG_ACPI_PROCFS_POWER |
86 | struct proc_dir_entry *proc_entry; | 90 | struct proc_dir_entry *proc_entry; |
@@ -113,7 +117,9 @@ struct acpi_battery { | |||
113 | #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); |
114 | 118 | ||
115 | struct acpi_sbs { | 119 | struct acpi_sbs { |
120 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
116 | struct power_supply charger; | 121 | struct power_supply charger; |
122 | #endif | ||
117 | struct acpi_device *device; | 123 | struct acpi_device *device; |
118 | struct acpi_smb_hc *hc; | 124 | struct acpi_smb_hc *hc; |
119 | struct mutex lock; | 125 | struct mutex lock; |
@@ -157,6 +163,7 @@ static inline int acpi_battery_scale(struct acpi_battery *battery) | |||
157 | acpi_battery_ipscale(battery); | 163 | acpi_battery_ipscale(battery); |
158 | } | 164 | } |
159 | 165 | ||
166 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
160 | static int sbs_get_ac_property(struct power_supply *psy, | 167 | static int sbs_get_ac_property(struct power_supply *psy, |
161 | enum power_supply_property psp, | 168 | enum power_supply_property psp, |
162 | union power_supply_propval *val) | 169 | union power_supply_propval *val) |
@@ -294,6 +301,7 @@ static enum power_supply_property sbs_energy_battery_props[] = { | |||
294 | POWER_SUPPLY_PROP_MODEL_NAME, | 301 | POWER_SUPPLY_PROP_MODEL_NAME, |
295 | POWER_SUPPLY_PROP_MANUFACTURER, | 302 | POWER_SUPPLY_PROP_MANUFACTURER, |
296 | }; | 303 | }; |
304 | #endif | ||
297 | 305 | ||
298 | /* -------------------------------------------------------------------------- | 306 | /* -------------------------------------------------------------------------- |
299 | Smart Battery System Management | 307 | Smart Battery System Management |
@@ -429,6 +437,7 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) | |||
429 | return result; | 437 | return result; |
430 | } | 438 | } |
431 | 439 | ||
440 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
432 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 441 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
433 | struct device_attribute *attr, | 442 | struct device_attribute *attr, |
434 | char *buf) | 443 | char *buf) |
@@ -458,6 +467,7 @@ static struct device_attribute alarm_attr = { | |||
458 | .show = acpi_battery_alarm_show, | 467 | .show = acpi_battery_alarm_show, |
459 | .store = acpi_battery_alarm_store, | 468 | .store = acpi_battery_alarm_store, |
460 | }; | 469 | }; |
470 | #endif | ||
461 | 471 | ||
462 | /* -------------------------------------------------------------------------- | 472 | /* -------------------------------------------------------------------------- |
463 | FS Interface (/proc/acpi) | 473 | FS Interface (/proc/acpi) |
@@ -793,6 +803,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
793 | &acpi_battery_state_fops, &acpi_battery_alarm_fops, | 803 | &acpi_battery_state_fops, &acpi_battery_alarm_fops, |
794 | battery); | 804 | battery); |
795 | #endif | 805 | #endif |
806 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
796 | battery->bat.name = battery->name; | 807 | battery->bat.name = battery->name; |
797 | battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; | 808 | battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; |
798 | if (!acpi_battery_mode(battery)) { | 809 | if (!acpi_battery_mode(battery)) { |
@@ -813,6 +824,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
813 | goto end; | 824 | goto end; |
814 | battery->have_sysfs_alarm = 1; | 825 | battery->have_sysfs_alarm = 1; |
815 | end: | 826 | end: |
827 | #endif | ||
816 | 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", |
817 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), | 829 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
818 | battery->name, sbs->battery->present ? "present" : "absent"); | 830 | battery->name, sbs->battery->present ? "present" : "absent"); |
@@ -822,12 +834,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
822 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) | 834 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) |
823 | { | 835 | { |
824 | struct acpi_battery *battery = &sbs->battery[id]; | 836 | struct acpi_battery *battery = &sbs->battery[id]; |
825 | 837 | #ifdef CONFIG_ACPI_SYSFS_POWER | |
826 | if (battery->bat.dev) { | 838 | if (battery->bat.dev) { |
827 | if (battery->have_sysfs_alarm) | 839 | if (battery->have_sysfs_alarm) |
828 | device_remove_file(battery->bat.dev, &alarm_attr); | 840 | device_remove_file(battery->bat.dev, &alarm_attr); |
829 | power_supply_unregister(&battery->bat); | 841 | power_supply_unregister(&battery->bat); |
830 | } | 842 | } |
843 | #endif | ||
831 | #ifdef CONFIG_ACPI_PROCFS_POWER | 844 | #ifdef CONFIG_ACPI_PROCFS_POWER |
832 | if (battery->proc_entry) | 845 | if (battery->proc_entry) |
833 | acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); | 846 | acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); |
@@ -848,12 +861,14 @@ static int acpi_charger_add(struct acpi_sbs *sbs) | |||
848 | if (result) | 861 | if (result) |
849 | goto end; | 862 | goto end; |
850 | #endif | 863 | #endif |
864 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
851 | sbs->charger.name = "sbs-charger"; | 865 | sbs->charger.name = "sbs-charger"; |
852 | sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; | 866 | sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; |
853 | sbs->charger.properties = sbs_ac_props; | 867 | sbs->charger.properties = sbs_ac_props; |
854 | sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); | 868 | sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); |
855 | sbs->charger.get_property = sbs_get_ac_property; | 869 | sbs->charger.get_property = sbs_get_ac_property; |
856 | power_supply_register(&sbs->device->dev, &sbs->charger); | 870 | power_supply_register(&sbs->device->dev, &sbs->charger); |
871 | #endif | ||
857 | printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", | 872 | printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", |
858 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), | 873 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
859 | ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); | 874 | ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); |
@@ -863,8 +878,10 @@ static int acpi_charger_add(struct acpi_sbs *sbs) | |||
863 | 878 | ||
864 | static void acpi_charger_remove(struct acpi_sbs *sbs) | 879 | static void acpi_charger_remove(struct acpi_sbs *sbs) |
865 | { | 880 | { |
881 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
866 | if (sbs->charger.dev) | 882 | if (sbs->charger.dev) |
867 | power_supply_unregister(&sbs->charger); | 883 | power_supply_unregister(&sbs->charger); |
884 | #endif | ||
868 | #ifdef CONFIG_ACPI_PROCFS_POWER | 885 | #ifdef CONFIG_ACPI_PROCFS_POWER |
869 | if (sbs->charger_entry) | 886 | if (sbs->charger_entry) |
870 | acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); | 887 | acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); |
@@ -885,7 +902,9 @@ void acpi_sbs_callback(void *context) | |||
885 | ACPI_SBS_NOTIFY_STATUS, | 902 | ACPI_SBS_NOTIFY_STATUS, |
886 | sbs->charger_present); | 903 | sbs->charger_present); |
887 | #endif | 904 | #endif |
905 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
888 | kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); | 906 | kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); |
907 | #endif | ||
889 | } | 908 | } |
890 | if (sbs->manager_present) { | 909 | if (sbs->manager_present) { |
891 | for (id = 0; id < MAX_SBS_BAT; ++id) { | 910 | for (id = 0; id < MAX_SBS_BAT; ++id) { |
@@ -902,7 +921,9 @@ void acpi_sbs_callback(void *context) | |||
902 | ACPI_SBS_NOTIFY_STATUS, | 921 | ACPI_SBS_NOTIFY_STATUS, |
903 | bat->present); | 922 | bat->present); |
904 | #endif | 923 | #endif |
924 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
905 | kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); | 925 | kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); |
926 | #endif | ||
906 | } | 927 | } |
907 | } | 928 | } |
908 | } | 929 | } |
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/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 bd77e81e81c1..a54ff6bce8fa 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -292,18 +292,26 @@ static int acpi_video_device_set_state(struct acpi_video_device *device, int sta | |||
292 | static int acpi_video_get_brightness(struct backlight_device *bd) | 292 | static int acpi_video_get_brightness(struct backlight_device *bd) |
293 | { | 293 | { |
294 | unsigned long cur_level; | 294 | unsigned long cur_level; |
295 | int i; | ||
295 | struct acpi_video_device *vd = | 296 | struct acpi_video_device *vd = |
296 | (struct acpi_video_device *)bl_get_data(bd); | 297 | (struct acpi_video_device *)bl_get_data(bd); |
297 | acpi_video_device_lcd_get_level_current(vd, &cur_level); | 298 | acpi_video_device_lcd_get_level_current(vd, &cur_level); |
298 | 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; | ||
299 | } | 306 | } |
300 | 307 | ||
301 | static int acpi_video_set_brightness(struct backlight_device *bd) | 308 | static int acpi_video_set_brightness(struct backlight_device *bd) |
302 | { | 309 | { |
303 | int request_level = bd->props.brightness; | 310 | int request_level = bd->props.brightness+2; |
304 | struct acpi_video_device *vd = | 311 | struct acpi_video_device *vd = |
305 | (struct acpi_video_device *)bl_get_data(bd); | 312 | (struct acpi_video_device *)bl_get_data(bd); |
306 | acpi_video_device_lcd_set_level(vd, request_level); | 313 | acpi_video_device_lcd_set_level(vd, |
314 | vd->brightness->levels[request_level]); | ||
307 | return 0; | 315 | return 0; |
308 | } | 316 | } |
309 | 317 | ||
@@ -652,7 +660,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
652 | kfree(obj); | 660 | kfree(obj); |
653 | 661 | ||
654 | 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){ |
655 | unsigned long tmp; | ||
656 | static int count = 0; | 663 | static int count = 0; |
657 | char *name; | 664 | char *name; |
658 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 665 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); |
@@ -660,11 +667,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
660 | return; | 667 | return; |
661 | 668 | ||
662 | sprintf(name, "acpi_video%d", count++); | 669 | sprintf(name, "acpi_video%d", count++); |
663 | acpi_video_device_lcd_get_level_current(device, &tmp); | ||
664 | device->backlight = backlight_device_register(name, | 670 | device->backlight = backlight_device_register(name, |
665 | NULL, device, &acpi_backlight_ops); | 671 | NULL, device, &acpi_backlight_ops); |
666 | device->backlight->props.max_brightness = max_level; | 672 | device->backlight->props.max_brightness = device->brightness->count-3; |
667 | device->backlight->props.brightness = (int)tmp; | 673 | device->backlight->props.brightness = acpi_video_get_brightness(device->backlight); |
668 | backlight_update_status(device->backlight); | 674 | backlight_update_status(device->backlight); |
669 | 675 | ||
670 | kfree(name); | 676 | kfree(name); |
@@ -1256,8 +1262,37 @@ acpi_video_bus_write_DOS(struct file *file, | |||
1256 | 1262 | ||
1257 | static int acpi_video_bus_add_fs(struct acpi_device *device) | 1263 | static int acpi_video_bus_add_fs(struct acpi_device *device) |
1258 | { | 1264 | { |
1265 | long device_id; | ||
1266 | int status; | ||
1259 | struct proc_dir_entry *entry = NULL; | 1267 | struct proc_dir_entry *entry = NULL; |
1260 | 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 | |||
1261 | 1296 | ||
1262 | 1297 | ||
1263 | video = acpi_driver_data(device); | 1298 | video = acpi_driver_data(device); |