aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig11
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/asus_acpi.c55
-rw-r--r--drivers/acpi/battery.c5
-rw-r--r--drivers/acpi/bay.c6
-rw-r--r--drivers/acpi/blacklist.c58
-rw-r--r--drivers/acpi/bus.c25
-rw-r--r--drivers/acpi/debug.c57
-rw-r--r--drivers/acpi/dock.c6
-rw-r--r--drivers/acpi/ec.c19
-rw-r--r--drivers/acpi/event.c28
-rw-r--r--drivers/acpi/events/evevent.c2
-rw-r--r--drivers/acpi/events/evgpe.c27
-rw-r--r--drivers/acpi/fan.c92
-rw-r--r--drivers/acpi/hardware/hwsleep.c2
-rw-r--r--drivers/acpi/namespace/nsxfeval.c10
-rw-r--r--drivers/acpi/osl.c81
-rw-r--r--drivers/acpi/pci_irq.c5
-rw-r--r--drivers/acpi/power.c6
-rw-r--r--drivers/acpi/processor_core.c42
-rw-r--r--drivers/acpi/processor_idle.c47
-rw-r--r--drivers/acpi/processor_perflib.c16
-rw-r--r--drivers/acpi/processor_thermal.c134
-rw-r--r--drivers/acpi/processor_throttling.c346
-rw-r--r--drivers/acpi/scan.c100
-rw-r--r--drivers/acpi/sleep/main.c17
-rw-r--r--drivers/acpi/sleep/proc.c46
-rw-r--r--drivers/acpi/system.c208
-rw-r--r--drivers/acpi/tables/Makefile2
-rw-r--r--drivers/acpi/tables/tbxfroot.c4
-rw-r--r--drivers/acpi/thermal.c663
-rw-r--r--drivers/acpi/utilities/utglobal.c2
-rw-r--r--drivers/acpi/video.c262
-rw-r--r--drivers/acpi/wmi.c710
34 files changed, 2662 insertions, 433 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ccf6ea95f68c..0065f3794576 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -186,6 +186,7 @@ config ACPI_HOTPLUG_CPU
186config ACPI_THERMAL 186config ACPI_THERMAL
187 tristate "Thermal Zone" 187 tristate "Thermal Zone"
188 depends on ACPI_PROCESSOR 188 depends on ACPI_PROCESSOR
189 select THERMAL
189 default y 190 default y
190 help 191 help
191 This driver adds support for ACPI thermal zones. Most mobile and 192 This driver adds support for ACPI thermal zones. Most mobile and
@@ -199,6 +200,16 @@ config ACPI_NUMA
199 depends on (X86 || IA64) 200 depends on (X86 || IA64)
200 default y if IA64_GENERIC || IA64_SGI_SN2 201 default y if IA64_GENERIC || IA64_SGI_SN2
201 202
203config ACPI_WMI
204 tristate "WMI (EXPERIMENTAL)"
205 depends on EXPERIMENTAL
206 help
207 This driver adds support for the ACPI-WMI mapper device (PNP0C14)
208 found on some systems.
209
210 NOTE: You will need another driver or userspace application on top of
211 this to actually use anything defined in the ACPI-WMI mapper.
212
202config ACPI_ASUS 213config ACPI_ASUS
203 tristate "ASUS/Medion Laptop Extras" 214 tristate "ASUS/Medion Laptop Extras"
204 depends on X86 215 depends on X86
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 456446f90077..f29812a86533 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_ACPI_THERMAL) += thermal.o
55obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o 55obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
56obj-$(CONFIG_ACPI_DEBUG) += debug.o 56obj-$(CONFIG_ACPI_DEBUG) += debug.o
57obj-$(CONFIG_ACPI_NUMA) += numa.o 57obj-$(CONFIG_ACPI_NUMA) += numa.o
58obj-$(CONFIG_ACPI_WMI) += wmi.o
58obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o 59obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
59obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 60obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
60obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o 61obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
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 = &param;
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 c4a769d1ba85..f6215e809808 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -194,6 +194,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
194 case POWER_SUPPLY_PROP_MANUFACTURER: 194 case POWER_SUPPLY_PROP_MANUFACTURER:
195 val->strval = battery->oem_info; 195 val->strval = battery->oem_info;
196 break; 196 break;
197 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
198 val->strval = battery->serial_number;
199 break;
197 default: 200 default:
198 return -EINVAL; 201 return -EINVAL;
199 } 202 }
@@ -212,6 +215,7 @@ static enum power_supply_property charge_battery_props[] = {
212 POWER_SUPPLY_PROP_CHARGE_NOW, 215 POWER_SUPPLY_PROP_CHARGE_NOW,
213 POWER_SUPPLY_PROP_MODEL_NAME, 216 POWER_SUPPLY_PROP_MODEL_NAME,
214 POWER_SUPPLY_PROP_MANUFACTURER, 217 POWER_SUPPLY_PROP_MANUFACTURER,
218 POWER_SUPPLY_PROP_SERIAL_NUMBER,
215}; 219};
216 220
217static enum power_supply_property energy_battery_props[] = { 221static enum power_supply_property energy_battery_props[] = {
@@ -226,6 +230,7 @@ static enum power_supply_property energy_battery_props[] = {
226 POWER_SUPPLY_PROP_ENERGY_NOW, 230 POWER_SUPPLY_PROP_ENERGY_NOW,
227 POWER_SUPPLY_PROP_MODEL_NAME, 231 POWER_SUPPLY_PROP_MODEL_NAME,
228 POWER_SUPPLY_PROP_MANUFACTURER, 232 POWER_SUPPLY_PROP_MANUFACTURER,
233 POWER_SUPPLY_PROP_SERIAL_NUMBER,
229}; 234};
230#endif 235#endif
231 236
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); }
47static void bay_notify(acpi_handle handle, u32 event, void *data); 47static void bay_notify(acpi_handle handle, u32 event, void *data);
48 48
49static const struct acpi_device_id bay_device_ids[] = {
50 {"LNXIOBAY", 0},
51 {"", 0},
52};
53MODULE_DEVICE_TABLE(acpi, bay_device_ids);
54
49struct bay { 55struct 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 8809654d6cc9..6dbaa2d15fe0 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -70,8 +70,6 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
70 /* IBM 600E - _ADR should return 7, but it returns 1 */ 70 /* IBM 600E - _ADR should return 7, but it returns 1 */
71 {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, 71 {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal,
72 "Incorrect _ADR", 1}, 72 "Incorrect _ADR", 1},
73 {"ASUS\0\0", "P2B-S ", 0, ACPI_SIG_DSDT, all_versions,
74 "Bogus PCI routing", 1},
75 73
76 {""} 74 {""}
77}; 75};
@@ -208,33 +206,35 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
208 * Disable OSI(Linux) warnings on all "Acer, inc." 206 * Disable OSI(Linux) warnings on all "Acer, inc."
209 * 207 *
210 * _OSI(Linux) disables the latest Windows BIOS code: 208 * _OSI(Linux) disables the latest Windows BIOS code:
209 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),
211 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"), 210 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"),
211 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
212 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"), 212 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"),
213 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"), 213 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"),
214 * _OSI(Linux) effect unknown: 214 * _OSI(Linux) effect unknown:
215 * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"), 215 * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"),
216 */ 216 */
217 { 217 /*
218 .callback = dmi_disable_osi_linux, 218 * note that dmi_check_system() uses strstr()
219 .ident = "Acer, inc.", 219 * to match sub-strings rather than !strcmp(),
220 .matches = { 220 * so "Acer" below matches "Acer, inc." above.
221 DMI_MATCH(DMI_SYS_VENDOR, "Acer, inc."), 221 */
222 },
223 },
224 /* 222 /*
225 * Disable OSI(Linux) warnings on all "Acer" 223 * Disable OSI(Linux) warnings on all "Acer"
226 * 224 *
227 * _OSI(Linux) effect unknown: 225 * _OSI(Linux) effect unknown:
228 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
229 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), 226 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
230 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"), 227 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"),
231 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"), 228 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"),
232 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"), 229 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"),
233 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"), 230 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"),
234 * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"), 231 * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"),
232 *
233 * _OSI(Linux) is a NOP:
234 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
235 */ 235 */
236 { 236 {
237 .callback = dmi_unknown_osi_linux, 237 .callback = dmi_disable_osi_linux,
238 .ident = "Acer", 238 .ident = "Acer",
239 .matches = { 239 .matches = {
240 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 240 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -242,21 +242,22 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
242 }, 242 },
243 /* 243 /*
244 * Disable OSI(Linux) warnings on all "Apple Computer, Inc." 244 * Disable OSI(Linux) warnings on all "Apple Computer, Inc."
245 * Disable OSI(Linux) warnings on all "Apple Inc."
245 * 246 *
246 * _OSI(Linux) confirmed to be a NOP: 247 * _OSI(Linux) confirmed to be a NOP:
247 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), 248 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
248 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"), 249 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
249 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"), 250 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
251 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
250 * _OSI(Linux) effect unknown: 252 * _OSI(Linux) effect unknown:
251 * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"), 253 * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"),
252 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"), 254 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
253 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
254 */ 255 */
255 { 256 {
256 .callback = dmi_disable_osi_linux, 257 .callback = dmi_disable_osi_linux,
257 .ident = "Apple", 258 .ident = "Apple",
258 .matches = { 259 .matches = {
259 DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), 260 DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
260 }, 261 },
261 }, 262 },
262 /* 263 /*
@@ -294,13 +295,13 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
294 * DMI_MATCH(DMI_BOARD_NAME, "IFL91"), 295 * DMI_MATCH(DMI_BOARD_NAME, "IFL91"),
295 */ 296 */
296 { 297 {
297 .callback = dmi_unknown_osi_linux, 298 .callback = dmi_disable_osi_linux,
298 .ident = "Compal", 299 .ident = "Compal",
299 .matches = { 300 .matches = {
300 DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), 301 DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
301 }, 302 },
302 }, 303 },
303 { /* OSI(Linux) touches USB, breaks suspend to disk */ 304 { /* OSI(Linux) touches USB, unknown side-effect */
304 .callback = dmi_disable_osi_linux, 305 .callback = dmi_disable_osi_linux,
305 .ident = "Dell Dimension 5150", 306 .ident = "Dell Dimension 5150",
306 .matches = { 307 .matches = {
@@ -310,7 +311,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
310 }, 311 },
311 { /* OSI(Linux) is a NOP */ 312 { /* OSI(Linux) is a NOP */
312 .callback = dmi_disable_osi_linux, 313 .callback = dmi_disable_osi_linux,
313 .ident = "Dell", 314 .ident = "Dell i1501",
314 .matches = { 315 .matches = {
315 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 316 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
316 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"), 317 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"),
@@ -318,7 +319,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
318 }, 319 },
319 { /* OSI(Linux) effect unknown */ 320 { /* OSI(Linux) effect unknown */
320 .callback = dmi_unknown_osi_linux, 321 .callback = dmi_unknown_osi_linux,
321 .ident = "Dell", 322 .ident = "Dell Latitude D830",
322 .matches = { 323 .matches = {
323 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 324 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
324 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"), 325 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"),
@@ -326,7 +327,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
326 }, 327 },
327 { /* OSI(Linux) effect unknown */ 328 { /* OSI(Linux) effect unknown */
328 .callback = dmi_unknown_osi_linux, 329 .callback = dmi_unknown_osi_linux,
329 .ident = "Dell", 330 .ident = "Dell OP GX620",
330 .matches = { 331 .matches = {
331 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 332 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
332 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"), 333 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"),
@@ -334,15 +335,23 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
334 }, 335 },
335 { /* OSI(Linux) effect unknown */ 336 { /* OSI(Linux) effect unknown */
336 .callback = dmi_unknown_osi_linux, 337 .callback = dmi_unknown_osi_linux,
337 .ident = "Dell", 338 .ident = "Dell PE 1900",
338 .matches = { 339 .matches = {
339 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 340 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
340 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"), 341 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"),
341 }, 342 },
342 }, 343 },
344 { /* OSI(Linux) is a NOP */
345 .callback = dmi_disable_osi_linux,
346 .ident = "Dell PE R200",
347 .matches = {
348 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
349 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R200"),
350 },
351 },
343 { /* OSI(Linux) touches USB */ 352 { /* OSI(Linux) touches USB */
344 .callback = dmi_disable_osi_linux, 353 .callback = dmi_disable_osi_linux,
345 .ident = "Dell", 354 .ident = "Dell PR 390",
346 .matches = { 355 .matches = {
347 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 356 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
348 DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"), 357 DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"),
@@ -358,7 +367,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
358 }, 367 },
359 { /* OSI(Linux) effect unknown */ 368 { /* OSI(Linux) effect unknown */
360 .callback = dmi_unknown_osi_linux, 369 .callback = dmi_unknown_osi_linux,
361 .ident = "Dell", 370 .ident = "Dell PE SC440",
362 .matches = { 371 .matches = {
363 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 372 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
364 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"), 373 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"),
@@ -474,6 +483,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
474 * 483 *
475 * _OSI(Linux) confirmed to be a NOP: 484 * _OSI(Linux) confirmed to be a NOP:
476 * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"), 485 * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"),
486 * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
487 *
488 * unknown:
489 * DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"),
490 * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
477 */ 491 */
478 { 492 {
479 .callback = dmi_disable_osi_linux, 493 .callback = dmi_disable_osi_linux,
@@ -516,7 +530,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
516 * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"), 530 * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"),
517 */ 531 */
518 { 532 {
519 .callback = dmi_unknown_osi_linux, 533 .callback = dmi_disable_osi_linux,
520 .ident = "Sony", 534 .ident = "Sony",
521 .matches = { 535 .matches = {
522 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 536 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 1b4cf984b081..8df325dafe0f 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -122,6 +122,31 @@ int acpi_bus_get_status(struct acpi_device *device)
122 122
123EXPORT_SYMBOL(acpi_bus_get_status); 123EXPORT_SYMBOL(acpi_bus_get_status);
124 124
125void acpi_bus_private_data_handler(acpi_handle handle,
126 u32 function, void *context)
127{
128 return;
129}
130EXPORT_SYMBOL(acpi_bus_private_data_handler);
131
132int acpi_bus_get_private_data(acpi_handle handle, void **data)
133{
134 acpi_status status = AE_OK;
135
136 if (!*data)
137 return -EINVAL;
138
139 status = acpi_get_data(handle, acpi_bus_private_data_handler, data);
140 if (ACPI_FAILURE(status) || !*data) {
141 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
142 handle));
143 return -ENODEV;
144 }
145
146 return 0;
147}
148EXPORT_SYMBOL(acpi_bus_get_private_data);
149
125/* -------------------------------------------------------------------------- 150/* --------------------------------------------------------------------------
126 Power Management 151 Power Management
127 -------------------------------------------------------------------------- */ 152 -------------------------------------------------------------------------- */
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) {
130module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); 130module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644);
131module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); 131module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644);
132 132
133static char trace_method_name[6];
134module_param_string(trace_method_name, trace_method_name, 6, 0644);
135static unsigned int trace_debug_layer;
136module_param(trace_debug_layer, uint, 0644);
137static unsigned int trace_debug_level;
138module_param(trace_debug_level, uint, 0644);
139
140static 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;
170exit:
171 return result;
172}
173
174static 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
187module_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;
51static struct platform_device *dock_device; 51static struct platform_device *dock_device;
52static char dock_device_name[] = "dock"; 52static char dock_device_name[] = "dock";
53 53
54static const struct acpi_device_id dock_device_ids[] = {
55 {"LNXDOCK", 0},
56 {"", 0},
57};
58MODULE_DEVICE_TABLE(acpi, dock_device_ids);
59
54struct dock_station { 60struct 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 987b967c7467..7222a18a0319 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -573,7 +573,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
573 void *handler_context, void *region_context) 573 void *handler_context, void *region_context)
574{ 574{
575 struct acpi_ec *ec = handler_context; 575 struct acpi_ec *ec = handler_context;
576 int result = 0, i = 0; 576 int result = 0, i;
577 u8 temp = 0; 577 u8 temp = 0;
578 578
579 if ((address > 0xFF) || !value || !handler_context) 579 if ((address > 0xFF) || !value || !handler_context)
@@ -585,7 +585,18 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
585 if (bits != 8 && acpi_strict) 585 if (bits != 8 && acpi_strict)
586 return AE_BAD_PARAMETER; 586 return AE_BAD_PARAMETER;
587 587
588 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;
589 if (function == ACPI_READ) { 600 if (function == ACPI_READ) {
590 result = acpi_ec_read(ec, address, &temp); 601 result = acpi_ec_read(ec, address, &temp);
591 (*value) |= ((acpi_integer)temp) << i; 602 (*value) |= ((acpi_integer)temp) << i;
@@ -593,10 +604,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
593 temp = 0xff & ((*value) >> i); 604 temp = 0xff & ((*value) >> i);
594 result = acpi_ec_write(ec, address, temp); 605 result = acpi_ec_write(ec, address, temp);
595 } 606 }
596 i += 8;
597 ++address;
598 } 607 }
599 608
609 acpi_ec_burst_disable(ec);
610
600 switch (result) { 611 switch (result) {
601 case -EINVAL: 612 case -EINVAL:
602 return AE_BAD_PARAMETER; 613 return AE_BAD_PARAMETER;
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index 5c95863f8fa9..5479dc0eeeec 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -109,6 +109,34 @@ static const struct file_operations acpi_system_event_ops = {
109}; 109};
110#endif /* CONFIG_ACPI_PROC_EVENT */ 110#endif /* CONFIG_ACPI_PROC_EVENT */
111 111
112/* ACPI notifier chain */
113BLOCKING_NOTIFIER_HEAD(acpi_chain_head);
114
115int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)
116{
117 struct acpi_bus_event event;
118
119 strcpy(event.device_class, dev->pnp.device_class);
120 strcpy(event.bus_id, dev->pnp.bus_id);
121 event.type = type;
122 event.data = data;
123 return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event)
124 == NOTIFY_BAD) ? -EINVAL : 0;
125}
126EXPORT_SYMBOL(acpi_notifier_call_chain);
127
128int register_acpi_notifier(struct notifier_block *nb)
129{
130 return blocking_notifier_chain_register(&acpi_chain_head, nb);
131}
132EXPORT_SYMBOL(register_acpi_notifier);
133
134int unregister_acpi_notifier(struct notifier_block *nb)
135{
136 return blocking_notifier_chain_unregister(&acpi_chain_head, nb);
137}
138EXPORT_SYMBOL(unregister_acpi_notifier);
139
112#ifdef CONFIG_NET 140#ifdef CONFIG_NET
113static unsigned int acpi_event_seqnum; 141static unsigned int acpi_event_seqnum;
114struct acpi_genl_event { 142struct acpi_genl_event {
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index e41287815ea1..3048801a37b5 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -259,7 +259,7 @@ u32 acpi_ev_fixed_event_detect(void)
259 enable_bit_mask)) { 259 enable_bit_mask)) {
260 260
261 /* Found an active (signalled) event */ 261 /* Found an active (signalled) event */
262 262 acpi_os_fixed_event_count(i);
263 int_status |= acpi_ev_fixed_event_dispatch((u32) i); 263 int_status |= acpi_ev_fixed_event_dispatch((u32) i);
264 } 264 }
265 } 265 }
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index e22f4a973c0f..0dadd2adc800 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);
@@ -501,6 +501,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
501 * an interrupt handler. 501 * an interrupt handler.
502 * 502 *
503 ******************************************************************************/ 503 ******************************************************************************/
504static void acpi_ev_asynch_enable_gpe(void *context);
504 505
505static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) 506static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
506{ 507{
@@ -576,22 +577,30 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
576 method_node))); 577 method_node)));
577 } 578 }
578 } 579 }
580 /* Defer enabling of GPE until all notify handlers are done */
581 acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe,
582 gpe_event_info);
583 return_VOID;
584}
579 585
580 if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == 586static void acpi_ev_asynch_enable_gpe(void *context)
587{
588 struct acpi_gpe_event_info *gpe_event_info = context;
589 acpi_status status;
590 if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
581 ACPI_GPE_LEVEL_TRIGGERED) { 591 ACPI_GPE_LEVEL_TRIGGERED) {
582 /* 592 /*
583 * GPE is level-triggered, we clear the GPE status bit after 593 * GPE is level-triggered, we clear the GPE status bit after
584 * handling the event. 594 * handling the event.
585 */ 595 */
586 status = acpi_hw_clear_gpe(&local_gpe_event_info); 596 status = acpi_hw_clear_gpe(gpe_event_info);
587 if (ACPI_FAILURE(status)) { 597 if (ACPI_FAILURE(status)) {
588 return_VOID; 598 return_VOID;
589 } 599 }
590 } 600 }
591 601
592 /* Enable this GPE */ 602 /* Enable this GPE */
593 603 (void)acpi_hw_write_gpe_enable_reg(gpe_event_info);
594 (void)acpi_hw_write_gpe_enable_reg(&local_gpe_event_info);
595 return_VOID; 604 return_VOID;
596} 605}
597 606
@@ -618,7 +627,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
618 627
619 ACPI_FUNCTION_TRACE(ev_gpe_dispatch); 628 ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
620 629
621 acpi_gpe_count++; 630 acpi_os_gpe_count(gpe_number);
622 631
623 /* 632 /*
624 * If edge-triggered, clear the GPE status bit now. Note that 633 * If edge-triggered, clear the GPE status bit now. Note that
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index a6e149d692cb..48cb705b274a 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -30,7 +30,7 @@
30#include <linux/proc_fs.h> 30#include <linux/proc_fs.h>
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <asm/uaccess.h> 32#include <asm/uaccess.h>
33 33#include <linux/thermal.h>
34#include <acpi/acpi_bus.h> 34#include <acpi/acpi_bus.h>
35#include <acpi/acpi_drivers.h> 35#include <acpi/acpi_drivers.h>
36 36
@@ -68,9 +68,55 @@ static struct acpi_driver acpi_fan_driver = {
68 }, 68 },
69}; 69};
70 70
71/* thermal cooling device callbacks */
72static int fan_get_max_state(struct thermal_cooling_device *cdev, char *buf)
73{
74 /* ACPI fan device only support two states: ON/OFF */
75 return sprintf(buf, "1\n");
76}
77
78static int fan_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
79{
80 struct acpi_device *device = cdev->devdata;
81 int state;
82 int result;
83
84 if (!device)
85 return -EINVAL;
86
87 result = acpi_bus_get_power(device->handle, &state);
88 if (result)
89 return result;
90
91 return sprintf(buf, "%s\n", state == ACPI_STATE_D3 ? "0" :
92 (state == ACPI_STATE_D0 ? "1" : "unknown"));
93}
94
95static int
96fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
97{
98 struct acpi_device *device = cdev->devdata;
99 int result;
100
101 if (!device || (state != 0 && state != 1))
102 return -EINVAL;
103
104 result = acpi_bus_set_power(device->handle,
105 state ? ACPI_STATE_D0 : ACPI_STATE_D3);
106
107 return result;
108}
109
110static struct thermal_cooling_device_ops fan_cooling_ops = {
111 .get_max_state = fan_get_max_state,
112 .get_cur_state = fan_get_cur_state,
113 .set_cur_state = fan_set_cur_state,
114};
115
71/* -------------------------------------------------------------------------- 116/* --------------------------------------------------------------------------
72 FS Interface (/proc) 117 FS Interface (/proc)
73 -------------------------------------------------------------------------- */ 118 -------------------------------------------------------------------------- */
119#ifdef CONFIG_ACPI_PROCFS
74 120
75static struct proc_dir_entry *acpi_fan_dir; 121static struct proc_dir_entry *acpi_fan_dir;
76 122
@@ -171,7 +217,17 @@ static int acpi_fan_remove_fs(struct acpi_device *device)
171 217
172 return 0; 218 return 0;
173} 219}
220#else
221static int acpi_fan_add_fs(struct acpi_device *device)
222{
223 return 0;
224}
174 225
226static int acpi_fan_remove_fs(struct acpi_device *device)
227{
228 return 0;
229}
230#endif
175/* -------------------------------------------------------------------------- 231/* --------------------------------------------------------------------------
176 Driver Interface 232 Driver Interface
177 -------------------------------------------------------------------------- */ 233 -------------------------------------------------------------------------- */
@@ -179,9 +235,8 @@ static int acpi_fan_remove_fs(struct acpi_device *device)
179static int acpi_fan_add(struct acpi_device *device) 235static int acpi_fan_add(struct acpi_device *device)
180{ 236{
181 int result = 0; 237 int result = 0;
182 struct acpi_fan *fan = NULL;
183 int state = 0; 238 int state = 0;
184 239 struct thermal_cooling_device *cdev;
185 240
186 if (!device) 241 if (!device)
187 return -EINVAL; 242 return -EINVAL;
@@ -199,6 +254,25 @@ static int acpi_fan_add(struct acpi_device *device)
199 acpi_bus_set_power(device->handle, state); 254 acpi_bus_set_power(device->handle, state);
200 device->flags.force_power_state = 0; 255 device->flags.force_power_state = 0;
201 256
257 cdev = thermal_cooling_device_register("Fan", device,
258 &fan_cooling_ops);
259 if (cdev)
260 printk(KERN_INFO PREFIX
261 "%s is registered as cooling_device%d\n",
262 device->dev.bus_id, cdev->id);
263 else
264 goto end;
265 acpi_driver_data(device) = cdev;
266 result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj,
267 "thermal_cooling");
268 if (result)
269 return result;
270
271 result = sysfs_create_link(&cdev->device.kobj, &device->dev.kobj,
272 "device");
273 if (result)
274 return result;
275
202 result = acpi_fan_add_fs(device); 276 result = acpi_fan_add_fs(device);
203 if (result) 277 if (result)
204 goto end; 278 goto end;
@@ -208,18 +282,20 @@ static int acpi_fan_add(struct acpi_device *device)
208 !device->power.state ? "on" : "off"); 282 !device->power.state ? "on" : "off");
209 283
210 end: 284 end:
211 if (result)
212 kfree(fan);
213
214 return result; 285 return result;
215} 286}
216 287
217static int acpi_fan_remove(struct acpi_device *device, int type) 288static int acpi_fan_remove(struct acpi_device *device, int type)
218{ 289{
219 if (!device || !acpi_driver_data(device)) 290 struct thermal_cooling_device *cdev = acpi_driver_data(device);
291
292 if (!device || !cdev)
220 return -EINVAL; 293 return -EINVAL;
221 294
222 acpi_fan_remove_fs(device); 295 acpi_fan_remove_fs(device);
296 sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
297 sysfs_remove_link(&cdev->device.kobj, "device");
298 thermal_cooling_device_unregister(cdev);
223 299
224 return 0; 300 return 0;
225} 301}
@@ -261,10 +337,12 @@ static int __init acpi_fan_init(void)
261 int result = 0; 337 int result = 0;
262 338
263 339
340#ifdef CONFIG_ACPI_PROCFS
264 acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); 341 acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
265 if (!acpi_fan_dir) 342 if (!acpi_fan_dir)
266 return -ENODEV; 343 return -ENODEV;
267 acpi_fan_dir->owner = THIS_MODULE; 344 acpi_fan_dir->owner = THIS_MODULE;
345#endif
268 346
269 result = acpi_bus_register_driver(&acpi_fan_driver); 347 result = acpi_bus_register_driver(&acpi_fan_driver);
270 if (result < 0) { 348 if (result < 0) {
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index fd1c4ba63367..058d0be5cbe2 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -286,13 +286,13 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
286 } 286 }
287 287
288 /* 288 /*
289 * 1) Disable/Clear all GPEs
289 * 2) Enable all wakeup GPEs 290 * 2) Enable all wakeup GPEs
290 */ 291 */
291 status = acpi_hw_disable_all_gpes(); 292 status = acpi_hw_disable_all_gpes();
292 if (ACPI_FAILURE(status)) { 293 if (ACPI_FAILURE(status)) {
293 return_ACPI_STATUS(status); 294 return_ACPI_STATUS(status);
294 } 295 }
295
296 acpi_gbl_system_awake_and_running = FALSE; 296 acpi_gbl_system_awake_and_running = FALSE;
297 297
298 status = acpi_hw_enable_all_wakeup_gpes(); 298 status = acpi_hw_enable_all_wakeup_gpes();
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index f39fbc6b9237..b92133faf5b7 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -443,6 +443,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
443 struct acpica_device_id hid; 443 struct acpica_device_id hid;
444 struct acpi_compatible_id_list *cid; 444 struct acpi_compatible_id_list *cid;
445 acpi_native_uint i; 445 acpi_native_uint i;
446 int found;
446 447
447 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 448 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
448 if (ACPI_FAILURE(status)) { 449 if (ACPI_FAILURE(status)) {
@@ -496,16 +497,19 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
496 497
497 /* Walk the CID list */ 498 /* Walk the CID list */
498 499
500 found = 0;
499 for (i = 0; i < cid->count; i++) { 501 for (i = 0; i < cid->count; i++) {
500 if (ACPI_STRNCMP(cid->id[i].value, info->hid, 502 if (ACPI_STRNCMP(cid->id[i].value, info->hid,
501 sizeof(struct 503 sizeof(struct
502 acpi_compatible_id)) != 504 acpi_compatible_id)) ==
503 0) { 505 0) {
504 ACPI_FREE(cid); 506 found = 1;
505 return (AE_OK); 507 break;
506 } 508 }
507 } 509 }
508 ACPI_FREE(cid); 510 ACPI_FREE(cid);
511 if (!found)
512 return (AE_OK);
509 } 513 }
510 } 514 }
511 515
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index bc1604bfa4db..6f49f6437289 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -134,7 +134,7 @@ static char osi_additional_string[OSI_STRING_LENGTH_MAX];
134 */ 134 */
135#define OSI_LINUX_ENABLE 0 135#define OSI_LINUX_ENABLE 0
136 136
137struct osi_linux { 137static struct osi_linux {
138 unsigned int enable:1; 138 unsigned int enable:1;
139 unsigned int dmi:1; 139 unsigned int dmi:1;
140 unsigned int cmdline:1; 140 unsigned int cmdline:1;
@@ -264,11 +264,16 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
264 "System description tables not found\n"); 264 "System description tables not found\n");
265 return 0; 265 return 0;
266 } 266 }
267 } else 267 } else {
268 return acpi_find_rsdp(); 268 acpi_physical_address pa = 0;
269
270 acpi_find_root_pointer(&pa);
271 return pa;
272 }
269} 273}
270 274
271void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) 275void __iomem *__init_refok
276acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
272{ 277{
273 if (phys > ULONG_MAX) { 278 if (phys > ULONG_MAX) {
274 printk(KERN_ERR PREFIX "Cannot map memory that high\n"); 279 printk(KERN_ERR PREFIX "Cannot map memory that high\n");
@@ -346,7 +351,15 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
346 351
347static irqreturn_t acpi_irq(int irq, void *dev_id) 352static irqreturn_t acpi_irq(int irq, void *dev_id)
348{ 353{
349 return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; 354 u32 handled;
355
356 handled = (*acpi_irq_handler) (acpi_irq_context);
357
358 if (handled) {
359 acpi_irq_handled++;
360 return IRQ_HANDLED;
361 } else
362 return IRQ_NONE;
350} 363}
351 364
352acpi_status 365acpi_status
@@ -355,6 +368,8 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
355{ 368{
356 unsigned int irq; 369 unsigned int irq;
357 370
371 acpi_irq_stats_init();
372
358 /* 373 /*
359 * Ignore the GSI from the core, and use the value in our copy of the 374 * Ignore the GSI from the core, and use the value in our copy of the
360 * FADT. It may not be the same if an interrupt source override exists 375 * FADT. It may not be the same if an interrupt source override exists
@@ -675,25 +690,6 @@ static void acpi_os_execute_deferred(struct work_struct *work)
675 dpc->function(dpc->context); 690 dpc->function(dpc->context);
676 kfree(dpc); 691 kfree(dpc);
677 692
678 /* Yield cpu to notify thread */
679 cond_resched();
680
681 return;
682}
683
684static void acpi_os_execute_notify(struct work_struct *work)
685{
686 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
687
688 if (!dpc) {
689 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
690 return;
691 }
692
693 dpc->function(dpc->context);
694
695 kfree(dpc);
696
697 return; 693 return;
698} 694}
699 695
@@ -717,7 +713,7 @@ acpi_status acpi_os_execute(acpi_execute_type type,
717{ 713{
718 acpi_status status = AE_OK; 714 acpi_status status = AE_OK;
719 struct acpi_os_dpc *dpc; 715 struct acpi_os_dpc *dpc;
720 716 struct workqueue_struct *queue;
721 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 717 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
722 "Scheduling function [%p(%p)] for deferred execution.\n", 718 "Scheduling function [%p(%p)] for deferred execution.\n",
723 function, context)); 719 function, context));
@@ -741,20 +737,13 @@ acpi_status acpi_os_execute(acpi_execute_type type,
741 dpc->function = function; 737 dpc->function = function;
742 dpc->context = context; 738 dpc->context = context;
743 739
744 if (type == OSL_NOTIFY_HANDLER) { 740 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
745 INIT_WORK(&dpc->work, acpi_os_execute_notify); 741 queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq;
746 if (!queue_work(kacpi_notify_wq, &dpc->work)) { 742 if (!queue_work(queue, &dpc->work)) {
747 status = AE_ERROR; 743 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
748 kfree(dpc); 744 "Call to queue_work() failed.\n"));
749 } 745 status = AE_ERROR;
750 } else { 746 kfree(dpc);
751 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
752 if (!queue_work(kacpid_wq, &dpc->work)) {
753 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
754 "Call to queue_work() failed.\n"));
755 status = AE_ERROR;
756 kfree(dpc);
757 }
758 } 747 }
759 return_ACPI_STATUS(status); 748 return_ACPI_STATUS(status);
760} 749}
@@ -1349,24 +1338,24 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
1349 * 1338 *
1350 * Returns 0 on success 1339 * Returns 0 on success
1351 */ 1340 */
1352int acpi_dmi_dump(void) 1341static int acpi_dmi_dump(void)
1353{ 1342{
1354 1343
1355 if (!dmi_available) 1344 if (!dmi_available)
1356 return -1; 1345 return -1;
1357 1346
1358 printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n", 1347 printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
1359 dmi_get_slot(DMI_SYS_VENDOR)); 1348 dmi_get_system_info(DMI_SYS_VENDOR));
1360 printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n", 1349 printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
1361 dmi_get_slot(DMI_PRODUCT_NAME)); 1350 dmi_get_system_info(DMI_PRODUCT_NAME));
1362 printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n", 1351 printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
1363 dmi_get_slot(DMI_PRODUCT_VERSION)); 1352 dmi_get_system_info(DMI_PRODUCT_VERSION));
1364 printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n", 1353 printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
1365 dmi_get_slot(DMI_BOARD_NAME)); 1354 dmi_get_system_info(DMI_BOARD_NAME));
1366 printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n", 1355 printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
1367 dmi_get_slot(DMI_BIOS_VENDOR)); 1356 dmi_get_system_info(DMI_BIOS_VENDOR));
1368 printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n", 1357 printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
1369 dmi_get_slot(DMI_BIOS_DATE)); 1358 dmi_get_system_info(DMI_BIOS_DATE));
1370 1359
1371 return 0; 1360 return 0;
1372} 1361}
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 62010c2481b3..76d9c669d2d8 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -51,10 +51,8 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
51 int bus, 51 int bus,
52 int device, int pin) 52 int device, int pin)
53{ 53{
54 struct list_head *node = NULL;
55 struct acpi_prt_entry *entry = NULL; 54 struct acpi_prt_entry *entry = NULL;
56 55
57
58 if (!acpi_prt.count) 56 if (!acpi_prt.count)
59 return NULL; 57 return NULL;
60 58
@@ -64,8 +62,7 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
64 * 62 *
65 */ 63 */
66 spin_lock(&acpi_prt_lock); 64 spin_lock(&acpi_prt_lock);
67 list_for_each(node, &acpi_prt.entries) { 65 list_for_each_entry(entry, &acpi_prt.entries, node) {
68 entry = list_entry(node, struct acpi_prt_entry, node);
69 if ((segment == entry->id.segment) 66 if ((segment == entry->id.segment)
70 && (bus == entry->id.bus) 67 && (bus == entry->id.bus)
71 && (device == entry->id.device) 68 && (device == entry->id.device)
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index af1769a20c7a..76bf6d90c700 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -458,11 +458,9 @@ int acpi_power_transition(struct acpi_device *device, int state)
458 } 458 }
459 459
460 end: 460 end:
461 if (result) { 461 if (result)
462 device->power.state = ACPI_STATE_UNKNOWN; 462 device->power.state = ACPI_STATE_UNKNOWN;
463 printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n", 463 else {
464 device->pnp.bus_id, state);
465 } else {
466 /* We shouldn't change the state till all above operations succeed */ 464 /* We shouldn't change the state till all above operations succeed */
467 device->power.state = state; 465 device->power.state = state;
468 } 466 }
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index e48ee4f8749f..75ccf5d18bf4 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -668,6 +668,24 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
668 668
669 acpi_processor_power_init(pr, device); 669 acpi_processor_power_init(pr, device);
670 670
671 pr->cdev = thermal_cooling_device_register("Processor", device,
672 &processor_cooling_ops);
673 if (pr->cdev)
674 printk(KERN_INFO PREFIX
675 "%s is registered as cooling_device%d\n",
676 device->dev.bus_id, pr->cdev->id);
677 else
678 goto end;
679
680 result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj,
681 "thermal_cooling");
682 if (result)
683 return result;
684 result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj,
685 "device");
686 if (result)
687 return result;
688
671 if (pr->flags.throttling) { 689 if (pr->flags.throttling) {
672 printk(KERN_INFO PREFIX "%s [%s] (supports", 690 printk(KERN_INFO PREFIX "%s [%s] (supports",
673 acpi_device_name(device), acpi_device_bid(device)); 691 acpi_device_name(device), acpi_device_bid(device));
@@ -791,6 +809,11 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
791 809
792 acpi_processor_remove_fs(device); 810 acpi_processor_remove_fs(device);
793 811
812 sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
813 sysfs_remove_link(&pr->cdev->device.kobj, "device");
814 thermal_cooling_device_unregister(pr->cdev);
815 pr->cdev = NULL;
816
794 processors[pr->id] = NULL; 817 processors[pr->id] = NULL;
795 818
796 kfree(pr); 819 kfree(pr);
@@ -812,11 +835,18 @@ static int is_processor_present(acpi_handle handle)
812 835
813 836
814 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); 837 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
815 if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) { 838 /*
816 ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); 839 * if a processor object does not have an _STA object,
817 return 0; 840 * OSPM assumes that the processor is present.
818 } 841 */
819 return 1; 842 if (status == AE_NOT_FOUND)
843 return 1;
844
845 if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
846 return 1;
847
848 ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
849 return 0;
820} 850}
821 851
822static 852static
@@ -1061,6 +1091,8 @@ static int __init acpi_processor_init(void)
1061 1091
1062 acpi_processor_ppc_init(); 1092 acpi_processor_ppc_init();
1063 1093
1094 acpi_processor_throttling_init();
1095
1064 return 0; 1096 return 0;
1065 1097
1066out_cpuidle: 1098out_cpuidle:
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 199ea2146153..32003fdc91e8 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -98,6 +98,9 @@ module_param(bm_history, uint, 0644);
98 98
99static int acpi_processor_set_power_policy(struct acpi_processor *pr); 99static int acpi_processor_set_power_policy(struct acpi_processor *pr);
100 100
101#else /* CONFIG_CPU_IDLE */
102static unsigned int latency_factor __read_mostly = 2;
103module_param(latency_factor, uint, 0644);
101#endif 104#endif
102 105
103/* 106/*
@@ -201,6 +204,10 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2)
201 return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); 204 return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
202} 205}
203 206
207/*
208 * Callers should disable interrupts before the call and enable
209 * interrupts after return.
210 */
204static void acpi_safe_halt(void) 211static void acpi_safe_halt(void)
205{ 212{
206 current_thread_info()->status &= ~TS_POLLING; 213 current_thread_info()->status &= ~TS_POLLING;
@@ -261,7 +268,7 @@ static atomic_t c3_cpu_count;
261/* Common C-state entry for C2, C3, .. */ 268/* Common C-state entry for C2, C3, .. */
262static void acpi_cstate_enter(struct acpi_processor_cx *cstate) 269static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
263{ 270{
264 if (cstate->space_id == ACPI_CSTATE_FFH) { 271 if (cstate->entry_method == ACPI_CSTATE_FFH) {
265 /* Call into architectural FFH based C-state */ 272 /* Call into architectural FFH based C-state */
266 acpi_processor_ffh_cstate_enter(cstate); 273 acpi_processor_ffh_cstate_enter(cstate);
267 } else { 274 } else {
@@ -413,6 +420,8 @@ static void acpi_processor_idle(void)
413 pm_idle_save(); 420 pm_idle_save();
414 else 421 else
415 acpi_safe_halt(); 422 acpi_safe_halt();
423
424 local_irq_enable();
416 return; 425 return;
417 } 426 }
418 427
@@ -521,6 +530,7 @@ static void acpi_processor_idle(void)
521 * skew otherwise. 530 * skew otherwise.
522 */ 531 */
523 sleep_ticks = 0xFFFFFFFF; 532 sleep_ticks = 0xFFFFFFFF;
533 local_irq_enable();
524 break; 534 break;
525 535
526 case ACPI_STATE_C2: 536 case ACPI_STATE_C2:
@@ -922,20 +932,20 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
922 cx.address = reg->address; 932 cx.address = reg->address;
923 cx.index = current_count + 1; 933 cx.index = current_count + 1;
924 934
925 cx.space_id = ACPI_CSTATE_SYSTEMIO; 935 cx.entry_method = ACPI_CSTATE_SYSTEMIO;
926 if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { 936 if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
927 if (acpi_processor_ffh_cstate_probe 937 if (acpi_processor_ffh_cstate_probe
928 (pr->id, &cx, reg) == 0) { 938 (pr->id, &cx, reg) == 0) {
929 cx.space_id = ACPI_CSTATE_FFH; 939 cx.entry_method = ACPI_CSTATE_FFH;
930 } else if (cx.type != ACPI_STATE_C1) { 940 } else if (cx.type == ACPI_STATE_C1) {
931 /* 941 /*
932 * C1 is a special case where FIXED_HARDWARE 942 * C1 is a special case where FIXED_HARDWARE
933 * can be handled in non-MWAIT way as well. 943 * can be handled in non-MWAIT way as well.
934 * In that case, save this _CST entry info. 944 * In that case, save this _CST entry info.
935 * That is, we retain space_id of SYSTEM_IO for
936 * halt based C1.
937 * Otherwise, ignore this info and continue. 945 * Otherwise, ignore this info and continue.
938 */ 946 */
947 cx.entry_method = ACPI_CSTATE_HALT;
948 } else {
939 continue; 949 continue;
940 } 950 }
941 } 951 }
@@ -1369,12 +1379,16 @@ static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr,
1369/** 1379/**
1370 * acpi_idle_do_entry - a helper function that does C2 and C3 type entry 1380 * acpi_idle_do_entry - a helper function that does C2 and C3 type entry
1371 * @cx: cstate data 1381 * @cx: cstate data
1382 *
1383 * Caller disables interrupt before call and enables interrupt after return.
1372 */ 1384 */
1373static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) 1385static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
1374{ 1386{
1375 if (cx->space_id == ACPI_CSTATE_FFH) { 1387 if (cx->entry_method == ACPI_CSTATE_FFH) {
1376 /* Call into architectural FFH based C-state */ 1388 /* Call into architectural FFH based C-state */
1377 acpi_processor_ffh_cstate_enter(cx); 1389 acpi_processor_ffh_cstate_enter(cx);
1390 } else if (cx->entry_method == ACPI_CSTATE_HALT) {
1391 acpi_safe_halt();
1378 } else { 1392 } else {
1379 int unused; 1393 int unused;
1380 /* IO port based C-state */ 1394 /* IO port based C-state */
@@ -1396,21 +1410,27 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
1396static int acpi_idle_enter_c1(struct cpuidle_device *dev, 1410static int acpi_idle_enter_c1(struct cpuidle_device *dev,
1397 struct cpuidle_state *state) 1411 struct cpuidle_state *state)
1398{ 1412{
1413 u32 t1, t2;
1399 struct acpi_processor *pr; 1414 struct acpi_processor *pr;
1400 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 1415 struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
1416
1401 pr = processors[smp_processor_id()]; 1417 pr = processors[smp_processor_id()];
1402 1418
1403 if (unlikely(!pr)) 1419 if (unlikely(!pr))
1404 return 0; 1420 return 0;
1405 1421
1422 local_irq_disable();
1406 if (pr->flags.bm_check) 1423 if (pr->flags.bm_check)
1407 acpi_idle_update_bm_rld(pr, cx); 1424 acpi_idle_update_bm_rld(pr, cx);
1408 1425
1409 acpi_safe_halt(); 1426 t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
1427 acpi_idle_do_entry(cx);
1428 t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
1410 1429
1430 local_irq_enable();
1411 cx->usage++; 1431 cx->usage++;
1412 1432
1413 return 0; 1433 return ticks_elapsed_in_us(t1, t2);
1414} 1434}
1415 1435
1416/** 1436/**
@@ -1517,7 +1537,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
1517 if (dev->safe_state) { 1537 if (dev->safe_state) {
1518 return dev->safe_state->enter(dev, dev->safe_state); 1538 return dev->safe_state->enter(dev, dev->safe_state);
1519 } else { 1539 } else {
1540 local_irq_disable();
1520 acpi_safe_halt(); 1541 acpi_safe_halt();
1542 local_irq_enable();
1521 return 0; 1543 return 0;
1522 } 1544 }
1523 } 1545 }
@@ -1609,7 +1631,7 @@ struct cpuidle_driver acpi_idle_driver = {
1609 */ 1631 */
1610static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) 1632static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
1611{ 1633{
1612 int i, count = 0; 1634 int i, count = CPUIDLE_DRIVER_STATE_START;
1613 struct acpi_processor_cx *cx; 1635 struct acpi_processor_cx *cx;
1614 struct cpuidle_state *state; 1636 struct cpuidle_state *state;
1615 struct cpuidle_device *dev = &pr->power.dev; 1637 struct cpuidle_device *dev = &pr->power.dev;
@@ -1638,13 +1660,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
1638 1660
1639 snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); 1661 snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
1640 state->exit_latency = cx->latency; 1662 state->exit_latency = cx->latency;
1641 state->target_residency = cx->latency * 6; 1663 state->target_residency = cx->latency * latency_factor;
1642 state->power_usage = cx->power; 1664 state->power_usage = cx->power;
1643 1665
1644 state->flags = 0; 1666 state->flags = 0;
1645 switch (cx->type) { 1667 switch (cx->type) {
1646 case ACPI_STATE_C1: 1668 case ACPI_STATE_C1:
1647 state->flags |= CPUIDLE_FLAG_SHALLOW; 1669 state->flags |= CPUIDLE_FLAG_SHALLOW;
1670 state->flags |= CPUIDLE_FLAG_TIME_VALID;
1648 state->enter = acpi_idle_enter_c1; 1671 state->enter = acpi_idle_enter_c1;
1649 dev->safe_state = state; 1672 dev->safe_state = state;
1650 break; 1673 break;
@@ -1667,6 +1690,8 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
1667 } 1690 }
1668 1691
1669 count++; 1692 count++;
1693 if (count == CPUIDLE_STATE_MAX)
1694 break;
1670 } 1695 }
1671 1696
1672 dev->state_count = count; 1697 dev->state_count = count;
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 463b0247cbc5..f32010bee4d5 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -60,6 +60,11 @@ static DEFINE_MUTEX(performance_mutex);
60 * policy is adjusted accordingly. 60 * policy is adjusted accordingly.
61 */ 61 */
62 62
63static unsigned int ignore_ppc = 0;
64module_param(ignore_ppc, uint, 0644);
65MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
66 "limited by BIOS, this should help");
67
63#define PPC_REGISTERED 1 68#define PPC_REGISTERED 1
64#define PPC_IN_USE 2 69#define PPC_IN_USE 2
65 70
@@ -72,6 +77,9 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
72 struct acpi_processor *pr; 77 struct acpi_processor *pr;
73 unsigned int ppc = 0; 78 unsigned int ppc = 0;
74 79
80 if (ignore_ppc)
81 return 0;
82
75 mutex_lock(&performance_mutex); 83 mutex_lock(&performance_mutex);
76 84
77 if (event != CPUFREQ_INCOMPATIBLE) 85 if (event != CPUFREQ_INCOMPATIBLE)
@@ -130,7 +138,13 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
130 138
131int acpi_processor_ppc_has_changed(struct acpi_processor *pr) 139int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
132{ 140{
133 int ret = acpi_processor_get_platform_limit(pr); 141 int ret;
142
143 if (ignore_ppc)
144 return 0;
145
146 ret = acpi_processor_get_platform_limit(pr);
147
134 if (ret < 0) 148 if (ret < 0)
135 return (ret); 149 return (ret);
136 else 150 else
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 06e6f3fb8825..9cb43f52f7b6 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -32,6 +32,7 @@
32#include <linux/cpufreq.h> 32#include <linux/cpufreq.h>
33#include <linux/proc_fs.h> 33#include <linux/proc_fs.h>
34#include <linux/seq_file.h> 34#include <linux/seq_file.h>
35#include <linux/sysdev.h>
35 36
36#include <asm/uaccess.h> 37#include <asm/uaccess.h>
37 38
@@ -93,6 +94,9 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr)
93 * _any_ cpufreq driver and not only the acpi-cpufreq driver. 94 * _any_ cpufreq driver and not only the acpi-cpufreq driver.
94 */ 95 */
95 96
97#define CPUFREQ_THERMAL_MIN_STEP 0
98#define CPUFREQ_THERMAL_MAX_STEP 3
99
96static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS]; 100static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS];
97static unsigned int acpi_thermal_cpufreq_is_init = 0; 101static unsigned int acpi_thermal_cpufreq_is_init = 0;
98 102
@@ -109,8 +113,9 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu)
109 if (!cpu_has_cpufreq(cpu)) 113 if (!cpu_has_cpufreq(cpu))
110 return -ENODEV; 114 return -ENODEV;
111 115
112 if (cpufreq_thermal_reduction_pctg[cpu] < 60) { 116 if (cpufreq_thermal_reduction_pctg[cpu] <
113 cpufreq_thermal_reduction_pctg[cpu] += 20; 117 CPUFREQ_THERMAL_MAX_STEP) {
118 cpufreq_thermal_reduction_pctg[cpu]++;
114 cpufreq_update_policy(cpu); 119 cpufreq_update_policy(cpu);
115 return 0; 120 return 0;
116 } 121 }
@@ -123,8 +128,9 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
123 if (!cpu_has_cpufreq(cpu)) 128 if (!cpu_has_cpufreq(cpu))
124 return -ENODEV; 129 return -ENODEV;
125 130
126 if (cpufreq_thermal_reduction_pctg[cpu] > 20) 131 if (cpufreq_thermal_reduction_pctg[cpu] >
127 cpufreq_thermal_reduction_pctg[cpu] -= 20; 132 (CPUFREQ_THERMAL_MIN_STEP + 1))
133 cpufreq_thermal_reduction_pctg[cpu]--;
128 else 134 else
129 cpufreq_thermal_reduction_pctg[cpu] = 0; 135 cpufreq_thermal_reduction_pctg[cpu] = 0;
130 cpufreq_update_policy(cpu); 136 cpufreq_update_policy(cpu);
@@ -143,7 +149,7 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
143 149
144 max_freq = 150 max_freq =
145 (policy->cpuinfo.max_freq * 151 (policy->cpuinfo.max_freq *
146 (100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100; 152 (100 - cpufreq_thermal_reduction_pctg[policy->cpu] * 20)) / 100;
147 153
148 cpufreq_verify_within_limits(policy, 0, max_freq); 154 cpufreq_verify_within_limits(policy, 0, max_freq);
149 155
@@ -155,6 +161,32 @@ static struct notifier_block acpi_thermal_cpufreq_notifier_block = {
155 .notifier_call = acpi_thermal_cpufreq_notifier, 161 .notifier_call = acpi_thermal_cpufreq_notifier,
156}; 162};
157 163
164static int cpufreq_get_max_state(unsigned int cpu)
165{
166 if (!cpu_has_cpufreq(cpu))
167 return 0;
168
169 return CPUFREQ_THERMAL_MAX_STEP;
170}
171
172static int cpufreq_get_cur_state(unsigned int cpu)
173{
174 if (!cpu_has_cpufreq(cpu))
175 return 0;
176
177 return cpufreq_thermal_reduction_pctg[cpu];
178}
179
180static int cpufreq_set_cur_state(unsigned int cpu, int state)
181{
182 if (!cpu_has_cpufreq(cpu))
183 return 0;
184
185 cpufreq_thermal_reduction_pctg[cpu] = state;
186 cpufreq_update_policy(cpu);
187 return 0;
188}
189
158void acpi_thermal_cpufreq_init(void) 190void acpi_thermal_cpufreq_init(void)
159{ 191{
160 int i; 192 int i;
@@ -179,6 +211,20 @@ void acpi_thermal_cpufreq_exit(void)
179} 211}
180 212
181#else /* ! CONFIG_CPU_FREQ */ 213#else /* ! CONFIG_CPU_FREQ */
214static int cpufreq_get_max_state(unsigned int cpu)
215{
216 return 0;
217}
218
219static int cpufreq_get_cur_state(unsigned int cpu)
220{
221 return 0;
222}
223
224static int cpufreq_set_cur_state(unsigned int cpu, int state)
225{
226 return 0;
227}
182 228
183static int acpi_thermal_cpufreq_increase(unsigned int cpu) 229static int acpi_thermal_cpufreq_increase(unsigned int cpu)
184{ 230{
@@ -310,6 +356,84 @@ int acpi_processor_get_limit_info(struct acpi_processor *pr)
310 return 0; 356 return 0;
311} 357}
312 358
359/* thermal coolign device callbacks */
360static int acpi_processor_max_state(struct acpi_processor *pr)
361{
362 int max_state = 0;
363
364 /*
365 * There exists four states according to
366 * cpufreq_thermal_reduction_ptg. 0, 1, 2, 3
367 */
368 max_state += cpufreq_get_max_state(pr->id);
369 if (pr->flags.throttling)
370 max_state += (pr->throttling.state_count -1);
371
372 return max_state;
373}
374static int
375processor_get_max_state(struct thermal_cooling_device *cdev, char *buf)
376{
377 struct acpi_device *device = cdev->devdata;
378 struct acpi_processor *pr = acpi_driver_data(device);
379
380 if (!device || !pr)
381 return -EINVAL;
382
383 return sprintf(buf, "%d\n", acpi_processor_max_state(pr));
384}
385
386static int
387processor_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
388{
389 struct acpi_device *device = cdev->devdata;
390 struct acpi_processor *pr = acpi_driver_data(device);
391 int cur_state;
392
393 if (!device || !pr)
394 return -EINVAL;
395
396 cur_state = cpufreq_get_cur_state(pr->id);
397 if (pr->flags.throttling)
398 cur_state += pr->throttling.state;
399
400 return sprintf(buf, "%d\n", cur_state);
401}
402
403static int
404processor_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
405{
406 struct acpi_device *device = cdev->devdata;
407 struct acpi_processor *pr = acpi_driver_data(device);
408 int result = 0;
409 int max_pstate;
410
411 if (!device || !pr)
412 return -EINVAL;
413
414 max_pstate = cpufreq_get_max_state(pr->id);
415
416 if (state > acpi_processor_max_state(pr))
417 return -EINVAL;
418
419 if (state <= max_pstate) {
420 if (pr->flags.throttling && pr->throttling.state)
421 result = acpi_processor_set_throttling(pr, 0);
422 cpufreq_set_cur_state(pr->id, state);
423 } else {
424 cpufreq_set_cur_state(pr->id, max_pstate);
425 result = acpi_processor_set_throttling(pr,
426 state - max_pstate);
427 }
428 return result;
429}
430
431struct thermal_cooling_device_ops processor_cooling_ops = {
432 .get_max_state = processor_get_max_state,
433 .get_cur_state = processor_get_cur_state,
434 .set_cur_state = processor_set_cur_state,
435};
436
313/* /proc interface */ 437/* /proc interface */
314 438
315static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) 439static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 1685b40abda7..1b8e592a8241 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -45,9 +45,229 @@
45#define _COMPONENT ACPI_PROCESSOR_COMPONENT 45#define _COMPONENT ACPI_PROCESSOR_COMPONENT
46ACPI_MODULE_NAME("processor_throttling"); 46ACPI_MODULE_NAME("processor_throttling");
47 47
48struct throttling_tstate {
49 unsigned int cpu; /* cpu nr */
50 int target_state; /* target T-state */
51};
52
53#define THROTTLING_PRECHANGE (1)
54#define THROTTLING_POSTCHANGE (2)
55
48static int acpi_processor_get_throttling(struct acpi_processor *pr); 56static int acpi_processor_get_throttling(struct acpi_processor *pr);
49int acpi_processor_set_throttling(struct acpi_processor *pr, int state); 57int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
50 58
59static int acpi_processor_update_tsd_coord(void)
60{
61 int count, count_target;
62 int retval = 0;
63 unsigned int i, j;
64 cpumask_t covered_cpus;
65 struct acpi_processor *pr, *match_pr;
66 struct acpi_tsd_package *pdomain, *match_pdomain;
67 struct acpi_processor_throttling *pthrottling, *match_pthrottling;
68
69 /*
70 * Now that we have _TSD data from all CPUs, lets setup T-state
71 * coordination between all CPUs.
72 */
73 for_each_possible_cpu(i) {
74 pr = processors[i];
75 if (!pr)
76 continue;
77
78 /* Basic validity check for domain info */
79 pthrottling = &(pr->throttling);
80
81 /*
82 * If tsd package for one cpu is invalid, the coordination
83 * among all CPUs is thought as invalid.
84 * Maybe it is ugly.
85 */
86 if (!pthrottling->tsd_valid_flag) {
87 retval = -EINVAL;
88 break;
89 }
90 }
91 if (retval)
92 goto err_ret;
93
94 cpus_clear(covered_cpus);
95 for_each_possible_cpu(i) {
96 pr = processors[i];
97 if (!pr)
98 continue;
99
100 if (cpu_isset(i, covered_cpus))
101 continue;
102 pthrottling = &pr->throttling;
103
104 pdomain = &(pthrottling->domain_info);
105 cpu_set(i, pthrottling->shared_cpu_map);
106 cpu_set(i, covered_cpus);
107 /*
108 * If the number of processor in the TSD domain is 1, it is
109 * unnecessary to parse the coordination for this CPU.
110 */
111 if (pdomain->num_processors <= 1)
112 continue;
113
114 /* Validate the Domain info */
115 count_target = pdomain->num_processors;
116 count = 1;
117
118 for_each_possible_cpu(j) {
119 if (i == j)
120 continue;
121
122 match_pr = processors[j];
123 if (!match_pr)
124 continue;
125
126 match_pthrottling = &(match_pr->throttling);
127 match_pdomain = &(match_pthrottling->domain_info);
128 if (match_pdomain->domain != pdomain->domain)
129 continue;
130
131 /* Here i and j are in the same domain.
132 * If two TSD packages have the same domain, they
133 * should have the same num_porcessors and
134 * coordination type. Otherwise it will be regarded
135 * as illegal.
136 */
137 if (match_pdomain->num_processors != count_target) {
138 retval = -EINVAL;
139 goto err_ret;
140 }
141
142 if (pdomain->coord_type != match_pdomain->coord_type) {
143 retval = -EINVAL;
144 goto err_ret;
145 }
146
147 cpu_set(j, covered_cpus);
148 cpu_set(j, pthrottling->shared_cpu_map);
149 count++;
150 }
151 for_each_possible_cpu(j) {
152 if (i == j)
153 continue;
154
155 match_pr = processors[j];
156 if (!match_pr)
157 continue;
158
159 match_pthrottling = &(match_pr->throttling);
160 match_pdomain = &(match_pthrottling->domain_info);
161 if (match_pdomain->domain != pdomain->domain)
162 continue;
163
164 /*
165 * If some CPUS have the same domain, they
166 * will have the same shared_cpu_map.
167 */
168 match_pthrottling->shared_cpu_map =
169 pthrottling->shared_cpu_map;
170 }
171 }
172
173err_ret:
174 for_each_possible_cpu(i) {
175 pr = processors[i];
176 if (!pr)
177 continue;
178
179 /*
180 * Assume no coordination on any error parsing domain info.
181 * The coordination type will be forced as SW_ALL.
182 */
183 if (retval) {
184 pthrottling = &(pr->throttling);
185 cpus_clear(pthrottling->shared_cpu_map);
186 cpu_set(i, pthrottling->shared_cpu_map);
187 pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
188 }
189 }
190
191 return retval;
192}
193
194/*
195 * Update the T-state coordination after the _TSD
196 * data for all cpus is obtained.
197 */
198void acpi_processor_throttling_init(void)
199{
200 if (acpi_processor_update_tsd_coord())
201 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
202 "Assume no T-state coordination\n"));
203
204 return;
205}
206
207static int acpi_processor_throttling_notifier(unsigned long event, void *data)
208{
209 struct throttling_tstate *p_tstate = data;
210 struct acpi_processor *pr;
211 unsigned int cpu ;
212 int target_state;
213 struct acpi_processor_limit *p_limit;
214 struct acpi_processor_throttling *p_throttling;
215
216 cpu = p_tstate->cpu;
217 pr = processors[cpu];
218 if (!pr) {
219 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n"));
220 return 0;
221 }
222 if (!pr->flags.throttling) {
223 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling control is "
224 "unsupported on CPU %d\n", cpu));
225 return 0;
226 }
227 target_state = p_tstate->target_state;
228 p_throttling = &(pr->throttling);
229 switch (event) {
230 case THROTTLING_PRECHANGE:
231 /*
232 * Prechange event is used to choose one proper t-state,
233 * which meets the limits of thermal, user and _TPC.
234 */
235 p_limit = &pr->limit;
236 if (p_limit->thermal.tx > target_state)
237 target_state = p_limit->thermal.tx;
238 if (p_limit->user.tx > target_state)
239 target_state = p_limit->user.tx;
240 if (pr->throttling_platform_limit > target_state)
241 target_state = pr->throttling_platform_limit;
242 if (target_state >= p_throttling->state_count) {
243 printk(KERN_WARNING
244 "Exceed the limit of T-state \n");
245 target_state = p_throttling->state_count - 1;
246 }
247 p_tstate->target_state = target_state;
248 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PreChange Event:"
249 "target T-state of CPU %d is T%d\n",
250 cpu, target_state));
251 break;
252 case THROTTLING_POSTCHANGE:
253 /*
254 * Postchange event is only used to update the
255 * T-state flag of acpi_processor_throttling.
256 */
257 p_throttling->state = target_state;
258 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PostChange Event:"
259 "CPU %d is switched to T%d\n",
260 cpu, target_state));
261 break;
262 default:
263 printk(KERN_WARNING
264 "Unsupported Throttling notifier event\n");
265 break;
266 }
267
268 return 0;
269}
270
51/* 271/*
52 * _TPC - Throttling Present Capabilities 272 * _TPC - Throttling Present Capabilities
53 */ 273 */
@@ -293,6 +513,10 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
293 struct acpi_buffer state = { 0, NULL }; 513 struct acpi_buffer state = { 0, NULL };
294 union acpi_object *tsd = NULL; 514 union acpi_object *tsd = NULL;
295 struct acpi_tsd_package *pdomain; 515 struct acpi_tsd_package *pdomain;
516 struct acpi_processor_throttling *pthrottling;
517
518 pthrottling = &pr->throttling;
519 pthrottling->tsd_valid_flag = 0;
296 520
297 status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer); 521 status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer);
298 if (ACPI_FAILURE(status)) { 522 if (ACPI_FAILURE(status)) {
@@ -340,6 +564,22 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
340 goto end; 564 goto end;
341 } 565 }
342 566
567 pthrottling = &pr->throttling;
568 pthrottling->tsd_valid_flag = 1;
569 pthrottling->shared_type = pdomain->coord_type;
570 cpu_set(pr->id, pthrottling->shared_cpu_map);
571 /*
572 * If the coordination type is not defined in ACPI spec,
573 * the tsd_valid_flag will be clear and coordination type
574 * will be forecd as DOMAIN_COORD_TYPE_SW_ALL.
575 */
576 if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
577 pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
578 pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
579 pthrottling->tsd_valid_flag = 0;
580 pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
581 }
582
343 end: 583 end:
344 kfree(buffer.pointer); 584 kfree(buffer.pointer);
345 return result; 585 return result;
@@ -589,6 +829,11 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
589 cpumask_t saved_mask; 829 cpumask_t saved_mask;
590 int ret; 830 int ret;
591 831
832 if (!pr)
833 return -EINVAL;
834
835 if (!pr->flags.throttling)
836 return -ENODEV;
592 /* 837 /*
593 * Migrate task to the cpu pointed by pr. 838 * Migrate task to the cpu pointed by pr.
594 */ 839 */
@@ -742,13 +987,92 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
742int acpi_processor_set_throttling(struct acpi_processor *pr, int state) 987int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
743{ 988{
744 cpumask_t saved_mask; 989 cpumask_t saved_mask;
745 int ret; 990 int ret = 0;
991 unsigned int i;
992 struct acpi_processor *match_pr;
993 struct acpi_processor_throttling *p_throttling;
994 struct throttling_tstate t_state;
995 cpumask_t online_throttling_cpus;
996
997 if (!pr)
998 return -EINVAL;
999
1000 if (!pr->flags.throttling)
1001 return -ENODEV;
1002
1003 if ((state < 0) || (state > (pr->throttling.state_count - 1)))
1004 return -EINVAL;
1005
1006 saved_mask = current->cpus_allowed;
1007 t_state.target_state = state;
1008 p_throttling = &(pr->throttling);
1009 cpus_and(online_throttling_cpus, cpu_online_map,
1010 p_throttling->shared_cpu_map);
746 /* 1011 /*
747 * Migrate task to the cpu pointed by pr. 1012 * The throttling notifier will be called for every
1013 * affected cpu in order to get one proper T-state.
1014 * The notifier event is THROTTLING_PRECHANGE.
748 */ 1015 */
749 saved_mask = current->cpus_allowed; 1016 for_each_cpu_mask(i, online_throttling_cpus) {
750 set_cpus_allowed(current, cpumask_of_cpu(pr->id)); 1017 t_state.cpu = i;
751 ret = pr->throttling.acpi_processor_set_throttling(pr, state); 1018 acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
1019 &t_state);
1020 }
1021 /*
1022 * The function of acpi_processor_set_throttling will be called
1023 * to switch T-state. If the coordination type is SW_ALL or HW_ALL,
1024 * it is necessary to call it for every affected cpu. Otherwise
1025 * it can be called only for the cpu pointed by pr.
1026 */
1027 if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
1028 set_cpus_allowed(current, cpumask_of_cpu(pr->id));
1029 ret = p_throttling->acpi_processor_set_throttling(pr,
1030 t_state.target_state);
1031 } else {
1032 /*
1033 * When the T-state coordination is SW_ALL or HW_ALL,
1034 * it is necessary to set T-state for every affected
1035 * cpus.
1036 */
1037 for_each_cpu_mask(i, online_throttling_cpus) {
1038 match_pr = processors[i];
1039 /*
1040 * If the pointer is invalid, we will report the
1041 * error message and continue.
1042 */
1043 if (!match_pr) {
1044 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1045 "Invalid Pointer for CPU %d\n", i));
1046 continue;
1047 }
1048 /*
1049 * If the throttling control is unsupported on CPU i,
1050 * we will report the error message and continue.
1051 */
1052 if (!match_pr->flags.throttling) {
1053 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1054 "Throttling Controll is unsupported "
1055 "on CPU %d\n", i));
1056 continue;
1057 }
1058 t_state.cpu = i;
1059 set_cpus_allowed(current, cpumask_of_cpu(i));
1060 ret = match_pr->throttling.
1061 acpi_processor_set_throttling(
1062 match_pr, t_state.target_state);
1063 }
1064 }
1065 /*
1066 * After the set_throttling is called, the
1067 * throttling notifier is called for every
1068 * affected cpu to update the T-states.
1069 * The notifier event is THROTTLING_POSTCHANGE
1070 */
1071 for_each_cpu_mask(i, online_throttling_cpus) {
1072 t_state.cpu = i;
1073 acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
1074 &t_state);
1075 }
752 /* restore the previous state */ 1076 /* restore the previous state */
753 set_cpus_allowed(current, saved_mask); 1077 set_cpus_allowed(current, saved_mask);
754 return ret; 1078 return ret;
@@ -757,6 +1081,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
757int acpi_processor_get_throttling_info(struct acpi_processor *pr) 1081int acpi_processor_get_throttling_info(struct acpi_processor *pr)
758{ 1082{
759 int result = 0; 1083 int result = 0;
1084 struct acpi_processor_throttling *pthrottling;
760 1085
761 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 1086 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
762 "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", 1087 "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
@@ -788,7 +1113,16 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
788 &acpi_processor_set_throttling_ptc; 1113 &acpi_processor_set_throttling_ptc;
789 } 1114 }
790 1115
791 acpi_processor_get_tsd(pr); 1116 /*
1117 * If TSD package for one CPU can't be parsed successfully, it means
1118 * that this CPU will have no coordination with other CPUs.
1119 */
1120 if (acpi_processor_get_tsd(pr)) {
1121 pthrottling = &pr->throttling;
1122 pthrottling->tsd_valid_flag = 0;
1123 cpu_set(pr->id, pthrottling->shared_cpu_map);
1124 pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
1125 }
792 1126
793 /* 1127 /*
794 * PIIX4 Errata: We don't support throttling on the original PIIX4. 1128 * PIIX4 Errata: We don't support throttling on the original PIIX4.
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index d9d531cce27f..c7b0aa52dd23 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -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 */
947static int acpi_dock_match(struct acpi_device *device)
948{
949 acpi_handle tmp;
950 return acpi_get_handle(device->handle, "_DCK", &tmp);
951}
952
944static void acpi_device_set_id(struct acpi_device *device, 953static 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
1083static int 1129static int
1130acpi_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
1143static int
1084acpi_add_single_object(struct acpi_device **child, 1144acpi_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) =
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 485de1347075..293a1cbb47c0 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -170,7 +170,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)
170 /* Reprogram control registers and execute _BFS */ 170 /* Reprogram control registers and execute _BFS */
171 acpi_leave_sleep_state_prep(acpi_state); 171 acpi_leave_sleep_state_prep(acpi_state);
172 172
173 /* ACPI 3.0 specs (P62) says that it's the responsabilty 173 /* ACPI 3.0 specs (P62) says that it's the responsibility
174 * of the OSPM to clear the status bit [ implying that the 174 * of the OSPM to clear the status bit [ implying that the
175 * POWER_BUTTON event should not reach userspace ] 175 * POWER_BUTTON event should not reach userspace ]
176 */ 176 */
@@ -472,11 +472,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
472 if (acpi_target_sleep_state == ACPI_STATE_S0 || 472 if (acpi_target_sleep_state == ACPI_STATE_S0 ||
473 (wake && adev->wakeup.state.enabled && 473 (wake && adev->wakeup.state.enabled &&
474 adev->wakeup.sleep_state <= acpi_target_sleep_state)) { 474 adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
475 acpi_status status;
476
475 acpi_method[3] = 'W'; 477 acpi_method[3] = 'W';
476 acpi_evaluate_integer(handle, acpi_method, NULL, &d_max); 478 status = acpi_evaluate_integer(handle, acpi_method, NULL,
477 /* Sanity check */ 479 &d_max);
478 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 */
479 d_min = d_max; 487 d_min = d_max;
488 }
480 } 489 }
481 490
482 if (d_min_p) 491 if (d_min_p)
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/system.c b/drivers/acpi/system.c
index 5ffe0ea18967..ce881713f7a6 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -40,6 +40,8 @@ ACPI_MODULE_NAME("system");
40#define ACPI_SYSTEM_CLASS "system" 40#define ACPI_SYSTEM_CLASS "system"
41#define ACPI_SYSTEM_DEVICE_NAME "System" 41#define ACPI_SYSTEM_DEVICE_NAME "System"
42 42
43u32 acpi_irq_handled;
44
43/* 45/*
44 * Make ACPICA version work as module param 46 * Make ACPICA version work as module param
45 */ 47 */
@@ -166,6 +168,212 @@ static int acpi_system_sysfs_init(void)
166 return 0; 168 return 0;
167} 169}
168 170
171/*
172 * Detailed ACPI IRQ counters in /sys/firmware/acpi/interrupts/
173 * See Documentation/ABI/testing/sysfs-firmware-acpi
174 */
175
176#define COUNT_GPE 0
177#define COUNT_SCI 1 /* acpi_irq_handled */
178#define COUNT_ERROR 2 /* other */
179#define NUM_COUNTERS_EXTRA 3
180
181static u32 *all_counters;
182static u32 num_gpes;
183static u32 num_counters;
184static struct attribute **all_attrs;
185static u32 acpi_gpe_count;
186
187static struct attribute_group interrupt_stats_attr_group = {
188 .name = "interrupts",
189};
190static struct kobj_attribute *counter_attrs;
191
192static int count_num_gpes(void)
193{
194 int count = 0;
195 struct acpi_gpe_xrupt_info *gpe_xrupt_info;
196 struct acpi_gpe_block_info *gpe_block;
197 acpi_cpu_flags flags;
198
199 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
200
201 gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
202 while (gpe_xrupt_info) {
203 gpe_block = gpe_xrupt_info->gpe_block_list_head;
204 while (gpe_block) {
205 count += gpe_block->register_count *
206 ACPI_GPE_REGISTER_WIDTH;
207 gpe_block = gpe_block->next;
208 }
209 gpe_xrupt_info = gpe_xrupt_info->next;
210 }
211 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
212
213 return count;
214}
215
216static void delete_gpe_attr_array(void)
217{
218 u32 *tmp = all_counters;
219
220 all_counters = NULL;
221 kfree(tmp);
222
223 if (counter_attrs) {
224 int i;
225
226 for (i = 0; i < num_gpes; i++)
227 kfree(counter_attrs[i].attr.name);
228
229 kfree(counter_attrs);
230 }
231 kfree(all_attrs);
232
233 return;
234}
235
236void acpi_os_gpe_count(u32 gpe_number)
237{
238 acpi_gpe_count++;
239
240 if (!all_counters)
241 return;
242
243 if (gpe_number < num_gpes)
244 all_counters[gpe_number]++;
245 else
246 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
247
248 return;
249}
250
251void acpi_os_fixed_event_count(u32 event_number)
252{
253 if (!all_counters)
254 return;
255
256 if (event_number < ACPI_NUM_FIXED_EVENTS)
257 all_counters[num_gpes + event_number]++;
258 else
259 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
260
261 return;
262}
263
264static ssize_t counter_show(struct kobject *kobj,
265 struct kobj_attribute *attr, char *buf)
266{
267 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI] =
268 acpi_irq_handled;
269 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE] =
270 acpi_gpe_count;
271
272 return sprintf(buf, "%d\n", all_counters[attr - counter_attrs]);
273}
274
275/*
276 * counter_set() sets the specified counter.
277 * setting the total "sci" file to any value clears all counters.
278 */
279static ssize_t counter_set(struct kobject *kobj,
280 struct kobj_attribute *attr, const char *buf, size_t size)
281{
282 int index = attr - counter_attrs;
283
284 if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
285 int i;
286 for (i = 0; i < num_counters; ++i)
287 all_counters[i] = 0;
288 acpi_gpe_count = 0;
289 acpi_irq_handled = 0;
290
291 } else
292 all_counters[index] = strtoul(buf, NULL, 0);
293
294 return size;
295}
296
297void acpi_irq_stats_init(void)
298{
299 int i;
300
301 if (all_counters)
302 return;
303
304 num_gpes = count_num_gpes();
305 num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA;
306
307 all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1),
308 GFP_KERNEL);
309 if (all_attrs == NULL)
310 return;
311
312 all_counters = kzalloc(sizeof(u32) * (num_counters), GFP_KERNEL);
313 if (all_counters == NULL)
314 goto fail;
315
316 counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters),
317 GFP_KERNEL);
318 if (counter_attrs == NULL)
319 goto fail;
320
321 for (i = 0; i < num_counters; ++i) {
322 char buffer[10];
323 char *name;
324
325 if (i < num_gpes)
326 sprintf(buffer, "gpe%02X", i);
327 else if (i == num_gpes + ACPI_EVENT_PMTIMER)
328 sprintf(buffer, "ff_pmtimer");
329 else if (i == num_gpes + ACPI_EVENT_GLOBAL)
330 sprintf(buffer, "ff_gbl_lock");
331 else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON)
332 sprintf(buffer, "ff_pwr_btn");
333 else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON)
334 sprintf(buffer, "ff_slp_btn");
335 else if (i == num_gpes + ACPI_EVENT_RTC)
336 sprintf(buffer, "ff_rt_clk");
337 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE)
338 sprintf(buffer, "gpe_all");
339 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI)
340 sprintf(buffer, "sci");
341 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR)
342 sprintf(buffer, "error");
343 else
344 sprintf(buffer, "bug%02X", i);
345
346 name = kzalloc(strlen(buffer) + 1, GFP_KERNEL);
347 if (name == NULL)
348 goto fail;
349 strncpy(name, buffer, strlen(buffer) + 1);
350
351 counter_attrs[i].attr.name = name;
352 counter_attrs[i].attr.mode = 0644;
353 counter_attrs[i].show = counter_show;
354 counter_attrs[i].store = counter_set;
355
356 all_attrs[i] = &counter_attrs[i].attr;
357 }
358
359 interrupt_stats_attr_group.attrs = all_attrs;
360 sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group);
361 return;
362
363fail:
364 delete_gpe_attr_array();
365 return;
366}
367
368static void __exit interrupt_stats_exit(void)
369{
370 sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group);
371
372 delete_gpe_attr_array();
373
374 return;
375}
376
169/* -------------------------------------------------------------------------- 377/* --------------------------------------------------------------------------
170 FS Interface (/proc) 378 FS Interface (/proc)
171 -------------------------------------------------------------------------- */ 379 -------------------------------------------------------------------------- */
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
5obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o 5obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
6 6
7EXTRA_CFLAGS += $(ACPI_CFLAGS) 7EXTRA_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
222ACPI_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..8d4b79b4f933 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -43,7 +43,7 @@
43#include <linux/seq_file.h> 43#include <linux/seq_file.h>
44#include <linux/reboot.h> 44#include <linux/reboot.h>
45#include <asm/uaccess.h> 45#include <asm/uaccess.h>
46 46#include <linux/thermal.h>
47#include <acpi/acpi_bus.h> 47#include <acpi/acpi_bus.h>
48#include <acpi/acpi_drivers.h> 48#include <acpi/acpi_drivers.h>
49 49
@@ -65,9 +65,6 @@
65#define ACPI_THERMAL_MAX_ACTIVE 10 65#define ACPI_THERMAL_MAX_ACTIVE 10
66#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 66#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
67 67
68#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
69#define CELSIUS_TO_KELVIN(t) ((t+273)*10)
70
71#define _COMPONENT ACPI_THERMAL_COMPONENT 68#define _COMPONENT ACPI_THERMAL_COMPONENT
72ACPI_MODULE_NAME("thermal"); 69ACPI_MODULE_NAME("thermal");
73 70
@@ -195,6 +192,8 @@ struct acpi_thermal {
195 struct acpi_thermal_trips trips; 192 struct acpi_thermal_trips trips;
196 struct acpi_handle_list devices; 193 struct acpi_handle_list devices;
197 struct timer_list timer; 194 struct timer_list timer;
195 struct thermal_zone_device *thermal_zone;
196 int tz_enabled;
198 struct mutex lock; 197 struct mutex lock;
199}; 198};
200 199
@@ -321,178 +320,226 @@ static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
321 return 0; 320 return 0;
322} 321}
323 322
324static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) 323#define ACPI_TRIPS_CRITICAL 0x01
325{ 324#define ACPI_TRIPS_HOT 0x02
326 acpi_status status = AE_OK; 325#define ACPI_TRIPS_PASSIVE 0x04
327 int i = 0; 326#define ACPI_TRIPS_ACTIVE 0x08
327#define ACPI_TRIPS_DEVICES 0x10
328 328
329#define ACPI_TRIPS_REFRESH_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
330#define ACPI_TRIPS_REFRESH_DEVICES ACPI_TRIPS_DEVICES
329 331
330 if (!tz) 332#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
331 return -EINVAL; 333 ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \
334 ACPI_TRIPS_DEVICES)
332 335
333 /* Critical Shutdown (required) */ 336/*
334 337 * This exception is thrown out in two cases:
335 status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, 338 * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
336 &tz->trips.critical.temperature); 339 * when re-evaluating the AML code.
337 if (ACPI_FAILURE(status)) { 340 * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
338 tz->trips.critical.flags.valid = 0; 341 * We need to re-bind the cooling devices of a thermal zone when this occurs.
339 ACPI_EXCEPTION((AE_INFO, status, "No critical threshold")); 342 */
340 return -ENODEV; 343#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str) \
341 } else { 344do { \
342 tz->trips.critical.flags.valid = 1; 345 if (flags != ACPI_TRIPS_INIT) \
343 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 346 ACPI_EXCEPTION((AE_INFO, AE_ERROR, \
344 "Found critical threshold [%lu]\n", 347 "ACPI thermal trip point %s changed\n" \
345 tz->trips.critical.temperature)); 348 "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \
346 } 349} while (0)
350
351static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
352{
353 acpi_status status = AE_OK;
354 struct acpi_handle_list devices;
355 int valid = 0;
356 int i;
347 357
348 if (tz->trips.critical.flags.valid == 1) { 358 /* Critical Shutdown (required) */
349 if (crt == -1) { 359 if (flag & ACPI_TRIPS_CRITICAL) {
360 status = acpi_evaluate_integer(tz->device->handle,
361 "_CRT", NULL, &tz->trips.critical.temperature);
362 if (ACPI_FAILURE(status)) {
350 tz->trips.critical.flags.valid = 0; 363 tz->trips.critical.flags.valid = 0;
351 } else if (crt > 0) { 364 ACPI_EXCEPTION((AE_INFO, status,
352 unsigned long crt_k = CELSIUS_TO_KELVIN(crt); 365 "No critical threshold"));
353 366 return -ENODEV;
354 /* 367 } else {
355 * Allow override to lower critical threshold 368 tz->trips.critical.flags.valid = 1;
356 */ 369 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
357 if (crt_k < tz->trips.critical.temperature) 370 "Found critical threshold [%lu]\n",
358 tz->trips.critical.temperature = crt_k; 371 tz->trips.critical.temperature));
372 }
373 if (tz->trips.critical.flags.valid == 1) {
374 if (crt == -1) {
375 tz->trips.critical.flags.valid = 0;
376 } else if (crt > 0) {
377 unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
378 /*
379 * Allow override to lower critical threshold
380 */
381 if (crt_k < tz->trips.critical.temperature)
382 tz->trips.critical.temperature = crt_k;
383 }
359 } 384 }
360 } 385 }
361 386
362 /* Critical Sleep (optional) */ 387 /* Critical Sleep (optional) */
363 388 if (flag & ACPI_TRIPS_HOT) {
364 status =
365 acpi_evaluate_integer(tz->device->handle, "_HOT", NULL,
366 &tz->trips.hot.temperature);
367 if (ACPI_FAILURE(status)) {
368 tz->trips.hot.flags.valid = 0;
369 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
370 } else {
371 tz->trips.hot.flags.valid = 1;
372 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n",
373 tz->trips.hot.temperature));
374 }
375
376 /* Passive: Processors (optional) */
377
378 if (psv == -1) {
379 status = AE_SUPPORT;
380 } else if (psv > 0) {
381 tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
382 status = AE_OK;
383 } else {
384 status = acpi_evaluate_integer(tz->device->handle, 389 status = acpi_evaluate_integer(tz->device->handle,
385 "_PSV", NULL, &tz->trips.passive.temperature); 390 "_HOT", NULL, &tz->trips.hot.temperature);
391 if (ACPI_FAILURE(status)) {
392 tz->trips.hot.flags.valid = 0;
393 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
394 "No hot threshold\n"));
395 } else {
396 tz->trips.hot.flags.valid = 1;
397 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
398 "Found hot threshold [%lu]\n",
399 tz->trips.critical.temperature));
400 }
386 } 401 }
387 402
388 if (ACPI_FAILURE(status)) { 403 /* Passive (optional) */
389 tz->trips.passive.flags.valid = 0; 404 if (flag & ACPI_TRIPS_PASSIVE) {
390 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n")); 405 valid = tz->trips.passive.flags.valid;
391 } else { 406 if (psv == -1) {
392 tz->trips.passive.flags.valid = 1; 407 status = AE_SUPPORT;
393 408 } else if (psv > 0) {
394 status = 409 tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
395 acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, 410 status = AE_OK;
396 &tz->trips.passive.tc1); 411 } else {
397 if (ACPI_FAILURE(status)) 412 status = acpi_evaluate_integer(tz->device->handle,
398 tz->trips.passive.flags.valid = 0; 413 "_PSV", NULL, &tz->trips.passive.temperature);
399 414 }
400 status =
401 acpi_evaluate_integer(tz->device->handle, "_TC2", NULL,
402 &tz->trips.passive.tc2);
403 if (ACPI_FAILURE(status))
404 tz->trips.passive.flags.valid = 0;
405 415
406 status =
407 acpi_evaluate_integer(tz->device->handle, "_TSP", NULL,
408 &tz->trips.passive.tsp);
409 if (ACPI_FAILURE(status)) 416 if (ACPI_FAILURE(status))
410 tz->trips.passive.flags.valid = 0; 417 tz->trips.passive.flags.valid = 0;
411 418 else {
412 status = 419 tz->trips.passive.flags.valid = 1;
413 acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, 420 if (flag == ACPI_TRIPS_INIT) {
414 &tz->trips.passive.devices); 421 status = acpi_evaluate_integer(
422 tz->device->handle, "_TC1",
423 NULL, &tz->trips.passive.tc1);
424 if (ACPI_FAILURE(status))
425 tz->trips.passive.flags.valid = 0;
426 status = acpi_evaluate_integer(
427 tz->device->handle, "_TC2",
428 NULL, &tz->trips.passive.tc2);
429 if (ACPI_FAILURE(status))
430 tz->trips.passive.flags.valid = 0;
431 status = acpi_evaluate_integer(
432 tz->device->handle, "_TSP",
433 NULL, &tz->trips.passive.tsp);
434 if (ACPI_FAILURE(status))
435 tz->trips.passive.flags.valid = 0;
436 }
437 }
438 }
439 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
440 memset(&devices, 0, sizeof(struct acpi_handle_list));
441 status = acpi_evaluate_reference(tz->device->handle, "_PSL",
442 NULL, &devices);
415 if (ACPI_FAILURE(status)) 443 if (ACPI_FAILURE(status))
416 tz->trips.passive.flags.valid = 0; 444 tz->trips.passive.flags.valid = 0;
417
418 if (!tz->trips.passive.flags.valid)
419 printk(KERN_WARNING PREFIX "Invalid passive threshold\n");
420 else 445 else
421 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 446 tz->trips.passive.flags.valid = 1;
422 "Found passive threshold [%lu]\n",
423 tz->trips.passive.temperature));
424 }
425 447
426 /* Active: Fans, etc. (optional) */ 448 if (memcmp(&tz->trips.passive.devices, &devices,
449 sizeof(struct acpi_handle_list))) {
450 memcpy(&tz->trips.passive.devices, &devices,
451 sizeof(struct acpi_handle_list));
452 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
453 }
454 }
455 if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
456 if (valid != tz->trips.passive.flags.valid)
457 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
458 }
427 459
460 /* Active (optional) */
428 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 461 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
429
430 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; 462 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
463 valid = tz->trips.active[i].flags.valid;
431 464
432 if (act == -1) 465 if (act == -1)
433 break; /* disable all active trip points */ 466 break; /* disable all active trip points */
434 467
435 status = acpi_evaluate_integer(tz->device->handle, 468 if (flag & ACPI_TRIPS_ACTIVE) {
436 name, NULL, &tz->trips.active[i].temperature); 469 status = acpi_evaluate_integer(tz->device->handle,
437 470 name, NULL, &tz->trips.active[i].temperature);
438 if (ACPI_FAILURE(status)) { 471 if (ACPI_FAILURE(status)) {
439 if (i == 0) /* no active trip points */ 472 tz->trips.active[i].flags.valid = 0;
473 if (i == 0)
474 break;
475 if (act <= 0)
476 break;
477 if (i == 1)
478 tz->trips.active[0].temperature =
479 CELSIUS_TO_KELVIN(act);
480 else
481 /*
482 * Don't allow override higher than
483 * the next higher trip point
484 */
485 tz->trips.active[i - 1].temperature =
486 (tz->trips.active[i - 2].temperature <
487 CELSIUS_TO_KELVIN(act) ?
488 tz->trips.active[i - 2].temperature :
489 CELSIUS_TO_KELVIN(act));
440 break; 490 break;
441 if (act <= 0) /* no override requested */ 491 } else
442 break; 492 tz->trips.active[i].flags.valid = 1;
443 if (i == 1) { /* 1 trip point */
444 tz->trips.active[0].temperature =
445 CELSIUS_TO_KELVIN(act);
446 } else { /* multiple trips */
447 /*
448 * Don't allow override higher than
449 * the next higher trip point
450 */
451 tz->trips.active[i - 1].temperature =
452 (tz->trips.active[i - 2].temperature <
453 CELSIUS_TO_KELVIN(act) ?
454 tz->trips.active[i - 2].temperature :
455 CELSIUS_TO_KELVIN(act));
456 }
457 break;
458 } 493 }
459 494
460 name[2] = 'L'; 495 name[2] = 'L';
461 status = 496 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
462 acpi_evaluate_reference(tz->device->handle, name, NULL, 497 memset(&devices, 0, sizeof(struct acpi_handle_list));
463 &tz->trips.active[i].devices); 498 status = acpi_evaluate_reference(tz->device->handle,
464 if (ACPI_SUCCESS(status)) { 499 name, NULL, &devices);
465 tz->trips.active[i].flags.valid = 1; 500 if (ACPI_FAILURE(status))
466 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 501 tz->trips.active[i].flags.valid = 0;
467 "Found active threshold [%d]:[%lu]\n", 502 else
468 i, tz->trips.active[i].temperature)); 503 tz->trips.active[i].flags.valid = 1;
469 } else 504
470 ACPI_EXCEPTION((AE_INFO, status, 505 if (memcmp(&tz->trips.active[i].devices, &devices,
471 "Invalid active threshold [%d]", i)); 506 sizeof(struct acpi_handle_list))) {
507 memcpy(&tz->trips.active[i].devices, &devices,
508 sizeof(struct acpi_handle_list));
509 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
510 }
511 }
512 if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
513 if (valid != tz->trips.active[i].flags.valid)
514 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
515
516 if (!tz->trips.active[i].flags.valid)
517 break;
518 }
519
520 if (flag & ACPI_TRIPS_DEVICES) {
521 memset(&devices, 0, sizeof(struct acpi_handle_list));
522 status = acpi_evaluate_reference(tz->device->handle, "_TZD",
523 NULL, &devices);
524 if (memcmp(&tz->devices, &devices,
525 sizeof(struct acpi_handle_list))) {
526 memcpy(&tz->devices, &devices,
527 sizeof(struct acpi_handle_list));
528 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
529 }
472 } 530 }
473 531
474 return 0; 532 return 0;
475} 533}
476 534
477static int acpi_thermal_get_devices(struct acpi_thermal *tz) 535static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
478{ 536{
479 acpi_status status = AE_OK; 537 return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
480
481
482 if (!tz)
483 return -EINVAL;
484
485 status =
486 acpi_evaluate_reference(tz->device->handle, "_TZD", NULL, &tz->devices);
487 if (ACPI_FAILURE(status))
488 return -ENODEV;
489
490 return 0;
491} 538}
492 539
493static int acpi_thermal_critical(struct acpi_thermal *tz) 540static int acpi_thermal_critical(struct acpi_thermal *tz)
494{ 541{
495 if (!tz || !tz->trips.critical.flags.valid || nocrt) 542 if (!tz || !tz->trips.critical.flags.valid)
496 return -EINVAL; 543 return -EINVAL;
497 544
498 if (tz->temperature >= tz->trips.critical.temperature) { 545 if (tz->temperature >= tz->trips.critical.temperature) {
@@ -501,9 +548,6 @@ static int acpi_thermal_critical(struct acpi_thermal *tz)
501 } else if (tz->trips.critical.flags.enabled) 548 } else if (tz->trips.critical.flags.enabled)
502 tz->trips.critical.flags.enabled = 0; 549 tz->trips.critical.flags.enabled = 0;
503 550
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, 551 acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
508 tz->trips.critical.flags.enabled); 552 tz->trips.critical.flags.enabled);
509 acpi_bus_generate_netlink_event(tz->device->pnp.device_class, 553 acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
@@ -511,14 +555,20 @@ static int acpi_thermal_critical(struct acpi_thermal *tz)
511 ACPI_THERMAL_NOTIFY_CRITICAL, 555 ACPI_THERMAL_NOTIFY_CRITICAL,
512 tz->trips.critical.flags.enabled); 556 tz->trips.critical.flags.enabled);
513 557
514 orderly_poweroff(true); 558 /* take no action if nocrt is set */
559 if(!nocrt) {
560 printk(KERN_EMERG
561 "Critical temperature reached (%ld C), shutting down.\n",
562 KELVIN_TO_CELSIUS(tz->temperature));
563 orderly_poweroff(true);
564 }
515 565
516 return 0; 566 return 0;
517} 567}
518 568
519static int acpi_thermal_hot(struct acpi_thermal *tz) 569static int acpi_thermal_hot(struct acpi_thermal *tz)
520{ 570{
521 if (!tz || !tz->trips.hot.flags.valid || nocrt) 571 if (!tz || !tz->trips.hot.flags.valid)
522 return -EINVAL; 572 return -EINVAL;
523 573
524 if (tz->temperature >= tz->trips.hot.temperature) { 574 if (tz->temperature >= tz->trips.hot.temperature) {
@@ -534,7 +584,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz)
534 ACPI_THERMAL_NOTIFY_HOT, 584 ACPI_THERMAL_NOTIFY_HOT,
535 tz->trips.hot.flags.enabled); 585 tz->trips.hot.flags.enabled);
536 586
537 /* TBD: Call user-mode "sleep(S4)" function */ 587 /* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */
538 588
539 return 0; 589 return 0;
540} 590}
@@ -732,6 +782,9 @@ static void acpi_thermal_check(void *data)
732 if (result) 782 if (result)
733 goto unlock; 783 goto unlock;
734 784
785 if (!tz->tz_enabled)
786 goto unlock;
787
735 memset(&tz->state, 0, sizeof(tz->state)); 788 memset(&tz->state, 0, sizeof(tz->state));
736 789
737 /* 790 /*
@@ -825,6 +878,290 @@ static void acpi_thermal_check(void *data)
825 mutex_unlock(&tz->lock); 878 mutex_unlock(&tz->lock);
826} 879}
827 880
881/* sys I/F for generic thermal sysfs support */
882static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
883{
884 struct acpi_thermal *tz = thermal->devdata;
885
886 if (!tz)
887 return -EINVAL;
888
889 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(tz->temperature));
890}
891
892static const char enabled[] = "kernel";
893static const char disabled[] = "user";
894static int thermal_get_mode(struct thermal_zone_device *thermal,
895 char *buf)
896{
897 struct acpi_thermal *tz = thermal->devdata;
898
899 if (!tz)
900 return -EINVAL;
901
902 return sprintf(buf, "%s\n", tz->tz_enabled ?
903 enabled : disabled);
904}
905
906static int thermal_set_mode(struct thermal_zone_device *thermal,
907 const char *buf)
908{
909 struct acpi_thermal *tz = thermal->devdata;
910 int enable;
911
912 if (!tz)
913 return -EINVAL;
914
915 /*
916 * enable/disable thermal management from ACPI thermal driver
917 */
918 if (!strncmp(buf, enabled, sizeof enabled - 1))
919 enable = 1;
920 else if (!strncmp(buf, disabled, sizeof disabled - 1))
921 enable = 0;
922 else
923 return -EINVAL;
924
925 if (enable != tz->tz_enabled) {
926 tz->tz_enabled = enable;
927 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
928 "%s ACPI thermal control\n",
929 tz->tz_enabled ? enabled : disabled));
930 acpi_thermal_check(tz);
931 }
932 return 0;
933}
934
935static int thermal_get_trip_type(struct thermal_zone_device *thermal,
936 int trip, char *buf)
937{
938 struct acpi_thermal *tz = thermal->devdata;
939 int i;
940
941 if (!tz || trip < 0)
942 return -EINVAL;
943
944 if (tz->trips.critical.flags.valid) {
945 if (!trip)
946 return sprintf(buf, "critical\n");
947 trip--;
948 }
949
950 if (tz->trips.hot.flags.valid) {
951 if (!trip)
952 return sprintf(buf, "hot\n");
953 trip--;
954 }
955
956 if (tz->trips.passive.flags.valid) {
957 if (!trip)
958 return sprintf(buf, "passive\n");
959 trip--;
960 }
961
962 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
963 tz->trips.active[i].flags.valid; i++) {
964 if (!trip)
965 return sprintf(buf, "active%d\n", i);
966 trip--;
967 }
968
969 return -EINVAL;
970}
971
972static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
973 int trip, char *buf)
974{
975 struct acpi_thermal *tz = thermal->devdata;
976 int i;
977
978 if (!tz || trip < 0)
979 return -EINVAL;
980
981 if (tz->trips.critical.flags.valid) {
982 if (!trip)
983 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
984 tz->trips.critical.temperature));
985 trip--;
986 }
987
988 if (tz->trips.hot.flags.valid) {
989 if (!trip)
990 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
991 tz->trips.hot.temperature));
992 trip--;
993 }
994
995 if (tz->trips.passive.flags.valid) {
996 if (!trip)
997 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
998 tz->trips.passive.temperature));
999 trip--;
1000 }
1001
1002 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
1003 tz->trips.active[i].flags.valid; i++) {
1004 if (!trip)
1005 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
1006 tz->trips.active[i].temperature));
1007 trip--;
1008 }
1009
1010 return -EINVAL;
1011}
1012
1013typedef int (*cb)(struct thermal_zone_device *, int,
1014 struct thermal_cooling_device *);
1015static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
1016 struct thermal_cooling_device *cdev,
1017 cb action)
1018{
1019 struct acpi_device *device = cdev->devdata;
1020 struct acpi_thermal *tz = thermal->devdata;
1021 struct acpi_device *dev;
1022 acpi_status status;
1023 acpi_handle handle;
1024 int i;
1025 int j;
1026 int trip = -1;
1027 int result = 0;
1028
1029 if (tz->trips.critical.flags.valid)
1030 trip++;
1031
1032 if (tz->trips.hot.flags.valid)
1033 trip++;
1034
1035 if (tz->trips.passive.flags.valid) {
1036 trip++;
1037 for (i = 0; i < tz->trips.passive.devices.count;
1038 i++) {
1039 handle = tz->trips.passive.devices.handles[i];
1040 status = acpi_bus_get_device(handle, &dev);
1041 if (ACPI_SUCCESS(status) && (dev == device)) {
1042 result = action(thermal, trip, cdev);
1043 if (result)
1044 goto failed;
1045 }
1046 }
1047 }
1048
1049 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1050 if (!tz->trips.active[i].flags.valid)
1051 break;
1052 trip++;
1053 for (j = 0;
1054 j < tz->trips.active[i].devices.count;
1055 j++) {
1056 handle = tz->trips.active[i].devices.handles[j];
1057 status = acpi_bus_get_device(handle, &dev);
1058 if (ACPI_SUCCESS(status) && (dev == device)) {
1059 result = action(thermal, trip, cdev);
1060 if (result)
1061 goto failed;
1062 }
1063 }
1064 }
1065
1066 for (i = 0; i < tz->devices.count; i++) {
1067 handle = tz->devices.handles[i];
1068 status = acpi_bus_get_device(handle, &dev);
1069 if (ACPI_SUCCESS(status) && (dev == device)) {
1070 result = action(thermal, -1, cdev);
1071 if (result)
1072 goto failed;
1073 }
1074 }
1075
1076failed:
1077 return result;
1078}
1079
1080static int
1081acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
1082 struct thermal_cooling_device *cdev)
1083{
1084 return acpi_thermal_cooling_device_cb(thermal, cdev,
1085 thermal_zone_bind_cooling_device);
1086}
1087
1088static int
1089acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
1090 struct thermal_cooling_device *cdev)
1091{
1092 return acpi_thermal_cooling_device_cb(thermal, cdev,
1093 thermal_zone_unbind_cooling_device);
1094}
1095
1096static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
1097 .bind = acpi_thermal_bind_cooling_device,
1098 .unbind = acpi_thermal_unbind_cooling_device,
1099 .get_temp = thermal_get_temp,
1100 .get_mode = thermal_get_mode,
1101 .set_mode = thermal_set_mode,
1102 .get_trip_type = thermal_get_trip_type,
1103 .get_trip_temp = thermal_get_trip_temp,
1104};
1105
1106static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
1107{
1108 int trips = 0;
1109 int result;
1110 acpi_status status;
1111 int i;
1112
1113 if (tz->trips.critical.flags.valid)
1114 trips++;
1115
1116 if (tz->trips.hot.flags.valid)
1117 trips++;
1118
1119 if (tz->trips.passive.flags.valid)
1120 trips++;
1121
1122 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
1123 tz->trips.active[i].flags.valid; i++, trips++);
1124 tz->thermal_zone = thermal_zone_device_register("ACPI thermal zone",
1125 trips, tz, &acpi_thermal_zone_ops);
1126 if (!tz->thermal_zone)
1127 return -ENODEV;
1128
1129 result = sysfs_create_link(&tz->device->dev.kobj,
1130 &tz->thermal_zone->device.kobj, "thermal_zone");
1131 if (result)
1132 return result;
1133
1134 result = sysfs_create_link(&tz->thermal_zone->device.kobj,
1135 &tz->device->dev.kobj, "device");
1136 if (result)
1137 return result;
1138
1139 status = acpi_attach_data(tz->device->handle,
1140 acpi_bus_private_data_handler,
1141 tz->thermal_zone);
1142 if (ACPI_FAILURE(status)) {
1143 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1144 "Error attaching device data\n"));
1145 return -ENODEV;
1146 }
1147
1148 tz->tz_enabled = 1;
1149
1150 printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n",
1151 tz->device->dev.bus_id, tz->thermal_zone->id);
1152 return 0;
1153}
1154
1155static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
1156{
1157 sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
1158 sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
1159 thermal_zone_device_unregister(tz->thermal_zone);
1160 tz->thermal_zone = NULL;
1161 acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler);
1162}
1163
1164
828/* -------------------------------------------------------------------------- 1165/* --------------------------------------------------------------------------
829 FS Interface (/proc) 1166 FS Interface (/proc)
830 -------------------------------------------------------------------------- */ 1167 -------------------------------------------------------------------------- */
@@ -1181,15 +1518,15 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
1181 acpi_thermal_check(tz); 1518 acpi_thermal_check(tz);
1182 break; 1519 break;
1183 case ACPI_THERMAL_NOTIFY_THRESHOLDS: 1520 case ACPI_THERMAL_NOTIFY_THRESHOLDS:
1184 acpi_thermal_get_trip_points(tz); 1521 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
1185 acpi_thermal_check(tz); 1522 acpi_thermal_check(tz);
1186 acpi_bus_generate_proc_event(device, event, 0); 1523 acpi_bus_generate_proc_event(device, event, 0);
1187 acpi_bus_generate_netlink_event(device->pnp.device_class, 1524 acpi_bus_generate_netlink_event(device->pnp.device_class,
1188 device->dev.bus_id, event, 0); 1525 device->dev.bus_id, event, 0);
1189 break; 1526 break;
1190 case ACPI_THERMAL_NOTIFY_DEVICES: 1527 case ACPI_THERMAL_NOTIFY_DEVICES:
1191 if (tz->flags.devices) 1528 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
1192 acpi_thermal_get_devices(tz); 1529 acpi_thermal_check(tz);
1193 acpi_bus_generate_proc_event(device, event, 0); 1530 acpi_bus_generate_proc_event(device, event, 0);
1194 acpi_bus_generate_netlink_event(device->pnp.device_class, 1531 acpi_bus_generate_netlink_event(device->pnp.device_class,
1195 device->dev.bus_id, event, 0); 1532 device->dev.bus_id, event, 0);
@@ -1232,11 +1569,6 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
1232 else 1569 else
1233 acpi_thermal_get_polling_frequency(tz); 1570 acpi_thermal_get_polling_frequency(tz);
1234 1571
1235 /* Get devices in this thermal zone [_TZD] (optional) */
1236 result = acpi_thermal_get_devices(tz);
1237 if (!result)
1238 tz->flags.devices = 1;
1239
1240 return 0; 1572 return 0;
1241} 1573}
1242 1574
@@ -1260,13 +1592,19 @@ static int acpi_thermal_add(struct acpi_device *device)
1260 strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); 1592 strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
1261 acpi_driver_data(device) = tz; 1593 acpi_driver_data(device) = tz;
1262 mutex_init(&tz->lock); 1594 mutex_init(&tz->lock);
1595
1596
1263 result = acpi_thermal_get_info(tz); 1597 result = acpi_thermal_get_info(tz);
1264 if (result) 1598 if (result)
1265 goto end; 1599 goto free_memory;
1600
1601 result = acpi_thermal_register_thermal_zone(tz);
1602 if (result)
1603 goto free_memory;
1266 1604
1267 result = acpi_thermal_add_fs(device); 1605 result = acpi_thermal_add_fs(device);
1268 if (result) 1606 if (result)
1269 goto end; 1607 goto unregister_thermal_zone;
1270 1608
1271 init_timer(&tz->timer); 1609 init_timer(&tz->timer);
1272 1610
@@ -1277,19 +1615,21 @@ static int acpi_thermal_add(struct acpi_device *device)
1277 acpi_thermal_notify, tz); 1615 acpi_thermal_notify, tz);
1278 if (ACPI_FAILURE(status)) { 1616 if (ACPI_FAILURE(status)) {
1279 result = -ENODEV; 1617 result = -ENODEV;
1280 goto end; 1618 goto remove_fs;
1281 } 1619 }
1282 1620
1283 printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", 1621 printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
1284 acpi_device_name(device), acpi_device_bid(device), 1622 acpi_device_name(device), acpi_device_bid(device),
1285 KELVIN_TO_CELSIUS(tz->temperature)); 1623 KELVIN_TO_CELSIUS(tz->temperature));
1624 goto end;
1286 1625
1287 end: 1626remove_fs:
1288 if (result) { 1627 acpi_thermal_remove_fs(device);
1289 acpi_thermal_remove_fs(device); 1628unregister_thermal_zone:
1290 kfree(tz); 1629 thermal_zone_device_unregister(tz->thermal_zone);
1291 } 1630free_memory:
1292 1631 kfree(tz);
1632end:
1293 return result; 1633 return result;
1294} 1634}
1295 1635
@@ -1329,6 +1669,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
1329 } 1669 }
1330 1670
1331 acpi_thermal_remove_fs(device); 1671 acpi_thermal_remove_fs(device);
1672 acpi_thermal_unregister_thermal_zone(tz);
1332 mutex_destroy(&tz->lock); 1673 mutex_destroy(&tz->lock);
1333 kfree(tz); 1674 kfree(tz);
1334 return 0; 1675 return 0;
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index 93ea8290b4f7..630c9a2c5b7b 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -671,7 +671,6 @@ void acpi_ut_init_globals(void)
671 671
672 /* GPE support */ 672 /* GPE support */
673 673
674 acpi_gpe_count = 0;
675 acpi_gbl_gpe_xrupt_list_head = NULL; 674 acpi_gbl_gpe_xrupt_list_head = NULL;
676 acpi_gbl_gpe_fadt_blocks[0] = NULL; 675 acpi_gbl_gpe_fadt_blocks[0] = NULL;
677 acpi_gbl_gpe_fadt_blocks[1] = NULL; 676 acpi_gbl_gpe_fadt_blocks[1] = NULL;
@@ -735,4 +734,3 @@ void acpi_ut_init_globals(void)
735 734
736ACPI_EXPORT_SYMBOL(acpi_dbg_level) 735ACPI_EXPORT_SYMBOL(acpi_dbg_level)
737 ACPI_EXPORT_SYMBOL(acpi_dbg_layer) 736 ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
738 ACPI_EXPORT_SYMBOL(acpi_gpe_count)
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index bd77e81e81c1..7f714fa2a454 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -34,6 +34,7 @@
34#include <linux/seq_file.h> 34#include <linux/seq_file.h>
35#include <linux/input.h> 35#include <linux/input.h>
36#include <linux/backlight.h> 36#include <linux/backlight.h>
37#include <linux/thermal.h>
37#include <linux/video_output.h> 38#include <linux/video_output.h>
38#include <asm/uaccess.h> 39#include <asm/uaccess.h>
39 40
@@ -72,8 +73,12 @@ MODULE_AUTHOR("Bruno Ducrot");
72MODULE_DESCRIPTION("ACPI Video Driver"); 73MODULE_DESCRIPTION("ACPI Video Driver");
73MODULE_LICENSE("GPL"); 74MODULE_LICENSE("GPL");
74 75
76static int brightness_switch_enabled = 1;
77module_param(brightness_switch_enabled, bool, 0644);
78
75static int acpi_video_bus_add(struct acpi_device *device); 79static int acpi_video_bus_add(struct acpi_device *device);
76static int acpi_video_bus_remove(struct acpi_device *device, int type); 80static int acpi_video_bus_remove(struct acpi_device *device, int type);
81static int acpi_video_resume(struct acpi_device *device);
77 82
78static const struct acpi_device_id video_device_ids[] = { 83static const struct acpi_device_id video_device_ids[] = {
79 {ACPI_VIDEO_HID, 0}, 84 {ACPI_VIDEO_HID, 0},
@@ -88,6 +93,7 @@ static struct acpi_driver acpi_video_bus = {
88 .ops = { 93 .ops = {
89 .add = acpi_video_bus_add, 94 .add = acpi_video_bus_add,
90 .remove = acpi_video_bus_remove, 95 .remove = acpi_video_bus_remove,
96 .resume = acpi_video_resume,
91 }, 97 },
92}; 98};
93 99
@@ -179,6 +185,7 @@ struct acpi_video_device {
179 struct acpi_device *dev; 185 struct acpi_device *dev;
180 struct acpi_video_device_brightness *brightness; 186 struct acpi_video_device_brightness *brightness;
181 struct backlight_device *backlight; 187 struct backlight_device *backlight;
188 struct thermal_cooling_device *cdev;
182 struct output_device *output_dev; 189 struct output_device *output_dev;
183}; 190};
184 191
@@ -273,7 +280,6 @@ static void acpi_video_device_rebind(struct acpi_video_bus *video);
273static void acpi_video_device_bind(struct acpi_video_bus *video, 280static void acpi_video_device_bind(struct acpi_video_bus *video,
274 struct acpi_video_device *device); 281 struct acpi_video_device *device);
275static int acpi_video_device_enumerate(struct acpi_video_bus *video); 282static int acpi_video_device_enumerate(struct acpi_video_bus *video);
276static int acpi_video_switch_output(struct acpi_video_bus *video, int event);
277static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, 283static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
278 int level); 284 int level);
279static int acpi_video_device_lcd_get_level_current( 285static int acpi_video_device_lcd_get_level_current(
@@ -292,18 +298,26 @@ static int acpi_video_device_set_state(struct acpi_video_device *device, int sta
292static int acpi_video_get_brightness(struct backlight_device *bd) 298static int acpi_video_get_brightness(struct backlight_device *bd)
293{ 299{
294 unsigned long cur_level; 300 unsigned long cur_level;
301 int i;
295 struct acpi_video_device *vd = 302 struct acpi_video_device *vd =
296 (struct acpi_video_device *)bl_get_data(bd); 303 (struct acpi_video_device *)bl_get_data(bd);
297 acpi_video_device_lcd_get_level_current(vd, &cur_level); 304 acpi_video_device_lcd_get_level_current(vd, &cur_level);
298 return (int) cur_level; 305 for (i = 2; i < vd->brightness->count; i++) {
306 if (vd->brightness->levels[i] == cur_level)
307 /* The first two entries are special - see page 575
308 of the ACPI spec 3.0 */
309 return i-2;
310 }
311 return 0;
299} 312}
300 313
301static int acpi_video_set_brightness(struct backlight_device *bd) 314static int acpi_video_set_brightness(struct backlight_device *bd)
302{ 315{
303 int request_level = bd->props.brightness; 316 int request_level = bd->props.brightness+2;
304 struct acpi_video_device *vd = 317 struct acpi_video_device *vd =
305 (struct acpi_video_device *)bl_get_data(bd); 318 (struct acpi_video_device *)bl_get_data(bd);
306 acpi_video_device_lcd_set_level(vd, request_level); 319 acpi_video_device_lcd_set_level(vd,
320 vd->brightness->levels[request_level]);
307 return 0; 321 return 0;
308} 322}
309 323
@@ -334,6 +348,54 @@ static struct output_properties acpi_output_properties = {
334 .set_state = acpi_video_output_set, 348 .set_state = acpi_video_output_set,
335 .get_status = acpi_video_output_get, 349 .get_status = acpi_video_output_get,
336}; 350};
351
352
353/* thermal cooling device callbacks */
354static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf)
355{
356 struct acpi_device *device = cdev->devdata;
357 struct acpi_video_device *video = acpi_driver_data(device);
358
359 return sprintf(buf, "%d\n", video->brightness->count - 3);
360}
361
362static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
363{
364 struct acpi_device *device = cdev->devdata;
365 struct acpi_video_device *video = acpi_driver_data(device);
366 unsigned long level;
367 int state;
368
369 acpi_video_device_lcd_get_level_current(video, &level);
370 for (state = 2; state < video->brightness->count; state++)
371 if (level == video->brightness->levels[state])
372 return sprintf(buf, "%d\n",
373 video->brightness->count - state - 1);
374
375 return -EINVAL;
376}
377
378static int
379video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
380{
381 struct acpi_device *device = cdev->devdata;
382 struct acpi_video_device *video = acpi_driver_data(device);
383 int level;
384
385 if ( state >= video->brightness->count - 2)
386 return -EINVAL;
387
388 state = video->brightness->count - state;
389 level = video->brightness->levels[state -1];
390 return acpi_video_device_lcd_set_level(video, level);
391}
392
393static struct thermal_cooling_device_ops video_cooling_ops = {
394 .get_max_state = video_get_max_state,
395 .get_cur_state = video_get_cur_state,
396 .set_cur_state = video_set_cur_state,
397};
398
337/* -------------------------------------------------------------------------- 399/* --------------------------------------------------------------------------
338 Video Management 400 Video Management
339 -------------------------------------------------------------------------- */ 401 -------------------------------------------------------------------------- */
@@ -652,7 +714,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
652 kfree(obj); 714 kfree(obj);
653 715
654 if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ 716 if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
655 unsigned long tmp; 717 int result;
656 static int count = 0; 718 static int count = 0;
657 char *name; 719 char *name;
658 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); 720 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
@@ -660,14 +722,30 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
660 return; 722 return;
661 723
662 sprintf(name, "acpi_video%d", count++); 724 sprintf(name, "acpi_video%d", count++);
663 acpi_video_device_lcd_get_level_current(device, &tmp);
664 device->backlight = backlight_device_register(name, 725 device->backlight = backlight_device_register(name,
665 NULL, device, &acpi_backlight_ops); 726 NULL, device, &acpi_backlight_ops);
666 device->backlight->props.max_brightness = max_level; 727 device->backlight->props.max_brightness = device->brightness->count-3;
667 device->backlight->props.brightness = (int)tmp; 728 device->backlight->props.brightness = acpi_video_get_brightness(device->backlight);
668 backlight_update_status(device->backlight); 729 backlight_update_status(device->backlight);
669
670 kfree(name); 730 kfree(name);
731
732 device->cdev = thermal_cooling_device_register("LCD",
733 device->dev, &video_cooling_ops);
734 if (device->cdev) {
735 printk(KERN_INFO PREFIX
736 "%s is registered as cooling_device%d\n",
737 device->dev->dev.bus_id, device->cdev->id);
738 result = sysfs_create_link(&device->dev->dev.kobj,
739 &device->cdev->device.kobj,
740 "thermal_cooling");
741 if (result)
742 printk(KERN_ERR PREFIX "Create sysfs link\n");
743 result = sysfs_create_link(&device->cdev->device.kobj,
744 &device->dev->dev.kobj,
745 "device");
746 if (result)
747 printk(KERN_ERR PREFIX "Create sysfs link\n");
748 }
671 } 749 }
672 if (device->cap._DCS && device->cap._DSS){ 750 if (device->cap._DCS && device->cap._DSS){
673 static int count = 0; 751 static int count = 0;
@@ -726,11 +804,40 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
726static int acpi_video_bus_check(struct acpi_video_bus *video) 804static int acpi_video_bus_check(struct acpi_video_bus *video)
727{ 805{
728 acpi_status status = -ENOENT; 806 acpi_status status = -ENOENT;
729 807 long device_id;
808 struct device *dev;
809 struct acpi_device *device;
730 810
731 if (!video) 811 if (!video)
732 return -EINVAL; 812 return -EINVAL;
733 813
814 device = video->device;
815
816 status =
817 acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
818
819 if (!ACPI_SUCCESS(status))
820 return -ENODEV;
821
822 /* We need to attempt to determine whether the _ADR refers to a
823 PCI device or not. There's no terribly good way to do this,
824 so the best we can hope for is to assume that there'll never
825 be a video device in the host bridge */
826 if (device_id >= 0x10000) {
827 /* It looks like a PCI device. Does it exist? */
828 dev = acpi_get_physical_device(device->handle);
829 } else {
830 /* It doesn't look like a PCI device. Does its parent
831 exist? */
832 acpi_handle phandle;
833 if (acpi_get_parent(device->handle, &phandle))
834 return -ENODEV;
835 dev = acpi_get_physical_device(phandle);
836 }
837 if (!dev)
838 return -ENODEV;
839 put_device(dev);
840
734 /* Since there is no HID, CID and so on for VGA driver, we have 841 /* Since there is no HID, CID and so on for VGA driver, we have
735 * to check well known required nodes. 842 * to check well known required nodes.
736 */ 843 */
@@ -1256,8 +1363,37 @@ acpi_video_bus_write_DOS(struct file *file,
1256 1363
1257static int acpi_video_bus_add_fs(struct acpi_device *device) 1364static int acpi_video_bus_add_fs(struct acpi_device *device)
1258{ 1365{
1366 long device_id;
1367 int status;
1259 struct proc_dir_entry *entry = NULL; 1368 struct proc_dir_entry *entry = NULL;
1260 struct acpi_video_bus *video; 1369 struct acpi_video_bus *video;
1370 struct device *dev;
1371
1372 status =
1373 acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
1374
1375 if (!ACPI_SUCCESS(status))
1376 return -ENODEV;
1377
1378 /* We need to attempt to determine whether the _ADR refers to a
1379 PCI device or not. There's no terribly good way to do this,
1380 so the best we can hope for is to assume that there'll never
1381 be a video device in the host bridge */
1382 if (device_id >= 0x10000) {
1383 /* It looks like a PCI device. Does it exist? */
1384 dev = acpi_get_physical_device(device->handle);
1385 } else {
1386 /* It doesn't look like a PCI device. Does its parent
1387 exist? */
1388 acpi_handle phandle;
1389 if (acpi_get_parent(device->handle, &phandle))
1390 return -ENODEV;
1391 dev = acpi_get_physical_device(phandle);
1392 }
1393 if (!dev)
1394 return -ENODEV;
1395 put_device(dev);
1396
1261 1397
1262 1398
1263 video = acpi_driver_data(device); 1399 video = acpi_driver_data(device);
@@ -1580,64 +1716,6 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
1580 return status; 1716 return status;
1581} 1717}
1582 1718
1583/*
1584 * Arg:
1585 * video : video bus device
1586 * event : notify event
1587 *
1588 * Return:
1589 * < 0 : error
1590 *
1591 * 1. Find out the current active output device.
1592 * 2. Identify the next output device to switch to.
1593 * 3. call _DSS to do actual switch.
1594 */
1595
1596static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
1597{
1598 struct list_head *node;
1599 struct acpi_video_device *dev = NULL;
1600 struct acpi_video_device *dev_next = NULL;
1601 struct acpi_video_device *dev_prev = NULL;
1602 unsigned long state;
1603 int status = 0;
1604
1605 mutex_lock(&video->device_list_lock);
1606
1607 list_for_each(node, &video->video_device_list) {
1608 dev = container_of(node, struct acpi_video_device, entry);
1609 status = acpi_video_device_get_state(dev, &state);
1610 if (state & 0x2) {
1611 dev_next = container_of(node->next,
1612 struct acpi_video_device, entry);
1613 dev_prev = container_of(node->prev,
1614 struct acpi_video_device, entry);
1615 goto out;
1616 }
1617 }
1618
1619 dev_next = container_of(node->next, struct acpi_video_device, entry);
1620 dev_prev = container_of(node->prev, struct acpi_video_device, entry);
1621
1622 out:
1623 mutex_unlock(&video->device_list_lock);
1624
1625 switch (event) {
1626 case ACPI_VIDEO_NOTIFY_CYCLE:
1627 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
1628 acpi_video_device_set_state(dev, 0);
1629 acpi_video_device_set_state(dev_next, 0x80000001);
1630 break;
1631 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
1632 acpi_video_device_set_state(dev, 0);
1633 acpi_video_device_set_state(dev_prev, 0x80000001);
1634 default:
1635 break;
1636 }
1637
1638 return status;
1639}
1640
1641static int 1719static int
1642acpi_video_get_next_level(struct acpi_video_device *device, 1720acpi_video_get_next_level(struct acpi_video_device *device,
1643 u32 level_current, u32 event) 1721 u32 level_current, u32 event)
@@ -1729,6 +1807,14 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
1729 ACPI_DEVICE_NOTIFY, 1807 ACPI_DEVICE_NOTIFY,
1730 acpi_video_device_notify); 1808 acpi_video_device_notify);
1731 backlight_device_unregister(device->backlight); 1809 backlight_device_unregister(device->backlight);
1810 if (device->cdev) {
1811 sysfs_remove_link(&device->dev->dev.kobj,
1812 "thermal_cooling");
1813 sysfs_remove_link(&device->cdev->device.kobj,
1814 "device");
1815 thermal_cooling_device_unregister(device->cdev);
1816 device->cdev = NULL;
1817 }
1732 video_output_unregister(device->output_dev); 1818 video_output_unregister(device->output_dev);
1733 1819
1734 return 0; 1820 return 0;
@@ -1797,23 +1883,19 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
1797 * connector. */ 1883 * connector. */
1798 acpi_video_device_enumerate(video); 1884 acpi_video_device_enumerate(video);
1799 acpi_video_device_rebind(video); 1885 acpi_video_device_rebind(video);
1800 acpi_video_switch_output(video, event);
1801 acpi_bus_generate_proc_event(device, event, 0); 1886 acpi_bus_generate_proc_event(device, event, 0);
1802 keycode = KEY_SWITCHVIDEOMODE; 1887 keycode = KEY_SWITCHVIDEOMODE;
1803 break; 1888 break;
1804 1889
1805 case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ 1890 case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */
1806 acpi_video_switch_output(video, event);
1807 acpi_bus_generate_proc_event(device, event, 0); 1891 acpi_bus_generate_proc_event(device, event, 0);
1808 keycode = KEY_SWITCHVIDEOMODE; 1892 keycode = KEY_SWITCHVIDEOMODE;
1809 break; 1893 break;
1810 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ 1894 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
1811 acpi_video_switch_output(video, event);
1812 acpi_bus_generate_proc_event(device, event, 0); 1895 acpi_bus_generate_proc_event(device, event, 0);
1813 keycode = KEY_VIDEO_NEXT; 1896 keycode = KEY_VIDEO_NEXT;
1814 break; 1897 break;
1815 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ 1898 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
1816 acpi_video_switch_output(video, event);
1817 acpi_bus_generate_proc_event(device, event, 0); 1899 acpi_bus_generate_proc_event(device, event, 0);
1818 keycode = KEY_VIDEO_PREV; 1900 keycode = KEY_VIDEO_PREV;
1819 break; 1901 break;
@@ -1825,6 +1907,7 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
1825 break; 1907 break;
1826 } 1908 }
1827 1909
1910 acpi_notifier_call_chain(device, event, 0);
1828 input_report_key(input, keycode, 1); 1911 input_report_key(input, keycode, 1);
1829 input_sync(input); 1912 input_sync(input);
1830 input_report_key(input, keycode, 0); 1913 input_report_key(input, keycode, 0);
@@ -1850,27 +1933,32 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
1850 1933
1851 switch (event) { 1934 switch (event) {
1852 case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ 1935 case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
1853 acpi_video_switch_brightness(video_device, event); 1936 if (brightness_switch_enabled)
1937 acpi_video_switch_brightness(video_device, event);
1854 acpi_bus_generate_proc_event(device, event, 0); 1938 acpi_bus_generate_proc_event(device, event, 0);
1855 keycode = KEY_BRIGHTNESS_CYCLE; 1939 keycode = KEY_BRIGHTNESS_CYCLE;
1856 break; 1940 break;
1857 case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ 1941 case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
1858 acpi_video_switch_brightness(video_device, event); 1942 if (brightness_switch_enabled)
1943 acpi_video_switch_brightness(video_device, event);
1859 acpi_bus_generate_proc_event(device, event, 0); 1944 acpi_bus_generate_proc_event(device, event, 0);
1860 keycode = KEY_BRIGHTNESSUP; 1945 keycode = KEY_BRIGHTNESSUP;
1861 break; 1946 break;
1862 case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ 1947 case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
1863 acpi_video_switch_brightness(video_device, event); 1948 if (brightness_switch_enabled)
1949 acpi_video_switch_brightness(video_device, event);
1864 acpi_bus_generate_proc_event(device, event, 0); 1950 acpi_bus_generate_proc_event(device, event, 0);
1865 keycode = KEY_BRIGHTNESSDOWN; 1951 keycode = KEY_BRIGHTNESSDOWN;
1866 break; 1952 break;
1867 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ 1953 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
1868 acpi_video_switch_brightness(video_device, event); 1954 if (brightness_switch_enabled)
1955 acpi_video_switch_brightness(video_device, event);
1869 acpi_bus_generate_proc_event(device, event, 0); 1956 acpi_bus_generate_proc_event(device, event, 0);
1870 keycode = KEY_BRIGHTNESS_ZERO; 1957 keycode = KEY_BRIGHTNESS_ZERO;
1871 break; 1958 break;
1872 case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ 1959 case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
1873 acpi_video_switch_brightness(video_device, event); 1960 if (brightness_switch_enabled)
1961 acpi_video_switch_brightness(video_device, event);
1874 acpi_bus_generate_proc_event(device, event, 0); 1962 acpi_bus_generate_proc_event(device, event, 0);
1875 keycode = KEY_DISPLAY_OFF; 1963 keycode = KEY_DISPLAY_OFF;
1876 break; 1964 break;
@@ -1881,6 +1969,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
1881 break; 1969 break;
1882 } 1970 }
1883 1971
1972 acpi_notifier_call_chain(device, event, 0);
1884 input_report_key(input, keycode, 1); 1973 input_report_key(input, keycode, 1);
1885 input_sync(input); 1974 input_sync(input);
1886 input_report_key(input, keycode, 0); 1975 input_report_key(input, keycode, 0);
@@ -1890,6 +1979,25 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
1890} 1979}
1891 1980
1892static int instance; 1981static int instance;
1982static int acpi_video_resume(struct acpi_device *device)
1983{
1984 struct acpi_video_bus *video;
1985 struct acpi_video_device *video_device;
1986 int i;
1987
1988 if (!device || !acpi_driver_data(device))
1989 return -EINVAL;
1990
1991 video = acpi_driver_data(device);
1992
1993 for (i = 0; i < video->attached_count; i++) {
1994 video_device = video->attached_array[i].bind_info;
1995 if (video_device && video_device->backlight)
1996 acpi_video_set_brightness(video_device->backlight);
1997 }
1998 return AE_OK;
1999}
2000
1893static int acpi_video_bus_add(struct acpi_device *device) 2001static int acpi_video_bus_add(struct acpi_device *device)
1894{ 2002{
1895 acpi_status status; 2003 acpi_status status;
diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c
new file mode 100644
index 000000000000..36b84ab418dd
--- /dev/null
+++ b/drivers/acpi/wmi.c
@@ -0,0 +1,710 @@
1/*
2 * ACPI-WMI mapping driver
3 *
4 * Copyright (C) 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk>
5 *
6 * GUID parsing code from ldm.c is:
7 * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
8 * Copyright (c) 2001-2007 Anton Altaparmakov
9 * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
10 *
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or (at
16 * your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 *
27 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 */
29
30#include <linux/kernel.h>
31#include <linux/init.h>
32#include <linux/types.h>
33#include <linux/list.h>
34#include <linux/acpi.h>
35#include <acpi/acpi_bus.h>
36#include <acpi/acpi_drivers.h>
37
38ACPI_MODULE_NAME("wmi");
39MODULE_AUTHOR("Carlos Corbacho");
40MODULE_DESCRIPTION("ACPI-WMI Mapping Driver");
41MODULE_LICENSE("GPL");
42
43#define ACPI_WMI_CLASS "wmi"
44
45#undef PREFIX
46#define PREFIX "ACPI: WMI: "
47
48static DEFINE_MUTEX(wmi_data_lock);
49
50struct guid_block {
51 char guid[16];
52 union {
53 char object_id[2];
54 struct {
55 unsigned char notify_id;
56 unsigned char reserved;
57 };
58 };
59 u8 instance_count;
60 u8 flags;
61};
62
63struct wmi_block {
64 struct list_head list;
65 struct guid_block gblock;
66 acpi_handle handle;
67 wmi_notify_handler handler;
68 void *handler_data;
69};
70
71static struct wmi_block wmi_blocks;
72
73/*
74 * If the GUID data block is marked as expensive, we must enable and
75 * explicitily disable data collection.
76 */
77#define ACPI_WMI_EXPENSIVE 0x1
78#define ACPI_WMI_METHOD 0x2 /* GUID is a method */
79#define ACPI_WMI_STRING 0x4 /* GUID takes & returns a string */
80#define ACPI_WMI_EVENT 0x8 /* GUID is an event */
81
82static int acpi_wmi_remove(struct acpi_device *device, int type);
83static int acpi_wmi_add(struct acpi_device *device);
84
85static const struct acpi_device_id wmi_device_ids[] = {
86 {"PNP0C14", 0},
87 {"pnp0c14", 0},
88 {"", 0},
89};
90MODULE_DEVICE_TABLE(acpi, wmi_device_ids);
91
92static struct acpi_driver acpi_wmi_driver = {
93 .name = "wmi",
94 .class = ACPI_WMI_CLASS,
95 .ids = wmi_device_ids,
96 .ops = {
97 .add = acpi_wmi_add,
98 .remove = acpi_wmi_remove,
99 },
100};
101
102/*
103 * GUID parsing functions
104 */
105
106/**
107 * wmi_parse_hexbyte - Convert a ASCII hex number to a byte
108 * @src: Pointer to at least 2 characters to convert.
109 *
110 * Convert a two character ASCII hex string to a number.
111 *
112 * Return: 0-255 Success, the byte was parsed correctly
113 * -1 Error, an invalid character was supplied
114 */
115static int wmi_parse_hexbyte(const u8 *src)
116{
117 unsigned int x; /* For correct wrapping */
118 int h;
119
120 /* high part */
121 x = src[0];
122 if (x - '0' <= '9' - '0') {
123 h = x - '0';
124 } else if (x - 'a' <= 'f' - 'a') {
125 h = x - 'a' + 10;
126 } else if (x - 'A' <= 'F' - 'A') {
127 h = x - 'A' + 10;
128 } else {
129 return -1;
130 }
131 h <<= 4;
132
133 /* low part */
134 x = src[1];
135 if (x - '0' <= '9' - '0')
136 return h | (x - '0');
137 if (x - 'a' <= 'f' - 'a')
138 return h | (x - 'a' + 10);
139 if (x - 'A' <= 'F' - 'A')
140 return h | (x - 'A' + 10);
141 return -1;
142}
143
144/**
145 * wmi_swap_bytes - Rearrange GUID bytes to match GUID binary
146 * @src: Memory block holding binary GUID (16 bytes)
147 * @dest: Memory block to hold byte swapped binary GUID (16 bytes)
148 *
149 * Byte swap a binary GUID to match it's real GUID value
150 */
151static void wmi_swap_bytes(u8 *src, u8 *dest)
152{
153 int i;
154
155 for (i = 0; i <= 3; i++)
156 memcpy(dest + i, src + (3 - i), 1);
157
158 for (i = 0; i <= 1; i++)
159 memcpy(dest + 4 + i, src + (5 - i), 1);
160
161 for (i = 0; i <= 1; i++)
162 memcpy(dest + 6 + i, src + (7 - i), 1);
163
164 memcpy(dest + 8, src + 8, 8);
165}
166
167/**
168 * wmi_parse_guid - Convert GUID from ASCII to binary
169 * @src: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
170 * @dest: Memory block to hold binary GUID (16 bytes)
171 *
172 * N.B. The GUID need not be NULL terminated.
173 *
174 * Return: 'true' @dest contains binary GUID
175 * 'false' @dest contents are undefined
176 */
177static bool wmi_parse_guid(const u8 *src, u8 *dest)
178{
179 static const int size[] = { 4, 2, 2, 2, 6 };
180 int i, j, v;
181
182 if (src[8] != '-' || src[13] != '-' ||
183 src[18] != '-' || src[23] != '-')
184 return false;
185
186 for (j = 0; j < 5; j++, src++) {
187 for (i = 0; i < size[j]; i++, src += 2, *dest++ = v) {
188 v = wmi_parse_hexbyte(src);
189 if (v < 0)
190 return false;
191 }
192 }
193
194 return true;
195}
196
197static bool find_guid(const char *guid_string, struct wmi_block **out)
198{
199 char tmp[16], guid_input[16];
200 struct wmi_block *wblock;
201 struct guid_block *block;
202 struct list_head *p;
203
204 wmi_parse_guid(guid_string, tmp);
205 wmi_swap_bytes(tmp, guid_input);
206
207 list_for_each(p, &wmi_blocks.list) {
208 wblock = list_entry(p, struct wmi_block, list);
209 block = &wblock->gblock;
210
211 if (memcmp(block->guid, guid_input, 16) == 0) {
212 if (out)
213 *out = wblock;
214 return 1;
215 }
216 }
217 return 0;
218}
219
220/*
221 * Exported WMI functions
222 */
223/**
224 * wmi_evaluate_method - Evaluate a WMI method
225 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
226 * @instance: Instance index
227 * @method_id: Method ID to call
228 * &in: Buffer containing input for the method call
229 * &out: Empty buffer to return the method results
230 *
231 * Call an ACPI-WMI method
232 */
233acpi_status wmi_evaluate_method(const char *guid_string, u8 instance,
234u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
235{
236 struct guid_block *block = NULL;
237 struct wmi_block *wblock = NULL;
238 acpi_handle handle;
239 acpi_status status;
240 struct acpi_object_list input;
241 union acpi_object params[3];
242 char method[4] = "WM";
243
244 if (!find_guid(guid_string, &wblock))
245 return AE_BAD_ADDRESS;
246
247 block = &wblock->gblock;
248 handle = wblock->handle;
249
250 if (!block->flags & ACPI_WMI_METHOD)
251 return AE_BAD_DATA;
252
253 if (block->instance_count < instance)
254 return AE_BAD_PARAMETER;
255
256 input.count = 2;
257 input.pointer = params;
258 params[0].type = ACPI_TYPE_INTEGER;
259 params[0].integer.value = instance;
260 params[1].type = ACPI_TYPE_INTEGER;
261 params[1].integer.value = method_id;
262
263 if (in) {
264 input.count = 3;
265
266 if (block->flags & ACPI_WMI_STRING) {
267 params[2].type = ACPI_TYPE_STRING;
268 } else {
269 params[2].type = ACPI_TYPE_BUFFER;
270 }
271 params[2].buffer.length = in->length;
272 params[2].buffer.pointer = in->pointer;
273 }
274
275 strncat(method, block->object_id, 2);
276
277 status = acpi_evaluate_object(handle, method, &input, out);
278
279 return status;
280}
281EXPORT_SYMBOL_GPL(wmi_evaluate_method);
282
283/**
284 * wmi_query_block - Return contents of a WMI block
285 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
286 * @instance: Instance index
287 * &out: Empty buffer to return the contents of the data block to
288 *
289 * Return the contents of an ACPI-WMI data block to a buffer
290 */
291acpi_status wmi_query_block(const char *guid_string, u8 instance,
292struct acpi_buffer *out)
293{
294 struct guid_block *block = NULL;
295 struct wmi_block *wblock = NULL;
296 acpi_handle handle;
297 acpi_status status, wc_status = AE_ERROR;
298 struct acpi_object_list input, wc_input;
299 union acpi_object wc_params[1], wq_params[1];
300 char method[4];
301 char wc_method[4] = "WC";
302
303 if (!guid_string || !out)
304 return AE_BAD_PARAMETER;
305
306 if (!find_guid(guid_string, &wblock))
307 return AE_BAD_ADDRESS;
308
309 block = &wblock->gblock;
310 handle = wblock->handle;
311
312 if (block->instance_count < instance)
313 return AE_BAD_PARAMETER;
314
315 /* Check GUID is a data block */
316 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
317 return AE_BAD_ADDRESS;
318
319 input.count = 1;
320 input.pointer = wq_params;
321 wq_params[0].type = ACPI_TYPE_INTEGER;
322 wq_params[0].integer.value = instance;
323
324 /*
325 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to
326 * enable collection.
327 */
328 if (block->flags & ACPI_WMI_EXPENSIVE) {
329 wc_input.count = 1;
330 wc_input.pointer = wc_params;
331 wc_params[0].type = ACPI_TYPE_INTEGER;
332 wc_params[0].integer.value = 1;
333
334 strncat(wc_method, block->object_id, 2);
335
336 /*
337 * Some GUIDs break the specification by declaring themselves
338 * expensive, but have no corresponding WCxx method. So we
339 * should not fail if this happens.
340 */
341 wc_status = acpi_evaluate_object(handle, wc_method,
342 &wc_input, NULL);
343 }
344
345 strcpy(method, "WQ");
346 strncat(method, block->object_id, 2);
347
348 status = acpi_evaluate_object(handle, method, NULL, out);
349
350 /*
351 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
352 * the WQxx method failed - we should disable collection anyway.
353 */
354 if ((block->flags & ACPI_WMI_EXPENSIVE) && wc_status) {
355 wc_params[0].integer.value = 0;
356 status = acpi_evaluate_object(handle,
357 wc_method, &wc_input, NULL);
358 }
359
360 return status;
361}
362EXPORT_SYMBOL_GPL(wmi_query_block);
363
364/**
365 * wmi_set_block - Write to a WMI block
366 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
367 * @instance: Instance index
368 * &in: Buffer containing new values for the data block
369 *
370 * Write the contents of the input buffer to an ACPI-WMI data block
371 */
372acpi_status wmi_set_block(const char *guid_string, u8 instance,
373const struct acpi_buffer *in)
374{
375 struct guid_block *block = NULL;
376 struct wmi_block *wblock = NULL;
377 acpi_handle handle;
378 struct acpi_object_list input;
379 union acpi_object params[2];
380 char method[4] = "WS";
381
382 if (!guid_string || !in)
383 return AE_BAD_DATA;
384
385 if (!find_guid(guid_string, &wblock))
386 return AE_BAD_ADDRESS;
387
388 block = &wblock->gblock;
389 handle = wblock->handle;
390
391 if (block->instance_count < instance)
392 return AE_BAD_PARAMETER;
393
394 /* Check GUID is a data block */
395 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
396 return AE_BAD_ADDRESS;
397
398 input.count = 2;
399 input.pointer = params;
400 params[0].type = ACPI_TYPE_INTEGER;
401 params[0].integer.value = instance;
402
403 if (block->flags & ACPI_WMI_STRING) {
404 params[1].type = ACPI_TYPE_STRING;
405 } else {
406 params[1].type = ACPI_TYPE_BUFFER;
407 }
408 params[1].buffer.length = in->length;
409 params[1].buffer.pointer = in->pointer;
410
411 strncat(method, block->object_id, 2);
412
413 return acpi_evaluate_object(handle, method, &input, NULL);
414}
415EXPORT_SYMBOL_GPL(wmi_set_block);
416
417/**
418 * wmi_install_notify_handler - Register handler for WMI events
419 * @handler: Function to handle notifications
420 * @data: Data to be returned to handler when event is fired
421 *
422 * Register a handler for events sent to the ACPI-WMI mapper device.
423 */
424acpi_status wmi_install_notify_handler(const char *guid,
425wmi_notify_handler handler, void *data)
426{
427 struct wmi_block *block;
428
429 if (!guid || !handler)
430 return AE_BAD_PARAMETER;
431
432 find_guid(guid, &block);
433 if (!block)
434 return AE_NOT_EXIST;
435
436 if (block->handler)
437 return AE_ALREADY_ACQUIRED;
438
439 block->handler = handler;
440 block->handler_data = data;
441
442 return AE_OK;
443}
444EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
445
446/**
447 * wmi_uninstall_notify_handler - Unregister handler for WMI events
448 *
449 * Unregister handler for events sent to the ACPI-WMI mapper device.
450 */
451acpi_status wmi_remove_notify_handler(const char *guid)
452{
453 struct wmi_block *block;
454
455 if (!guid)
456 return AE_BAD_PARAMETER;
457
458 find_guid(guid, &block);
459 if (!block)
460 return AE_NOT_EXIST;
461
462 if (!block->handler)
463 return AE_NULL_ENTRY;
464
465 block->handler = NULL;
466 block->handler_data = NULL;
467
468 return AE_OK;
469}
470EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
471
472/**
473 * wmi_get_event_data - Get WMI data associated with an event
474 *
475 * @event - Event to find
476 * &out - Buffer to hold event data
477 *
478 * Returns extra data associated with an event in WMI.
479 */
480acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
481{
482 struct acpi_object_list input;
483 union acpi_object params[1];
484 struct guid_block *gblock;
485 struct wmi_block *wblock;
486 struct list_head *p;
487
488 input.count = 1;
489 input.pointer = params;
490 params[0].type = ACPI_TYPE_INTEGER;
491 params[0].integer.value = event;
492
493 list_for_each(p, &wmi_blocks.list) {
494 wblock = list_entry(p, struct wmi_block, list);
495 gblock = &wblock->gblock;
496
497 if ((gblock->flags & ACPI_WMI_EVENT) &&
498 (gblock->notify_id == event))
499 return acpi_evaluate_object(wblock->handle, "_WED",
500 &input, out);
501 }
502
503 return AE_NOT_FOUND;
504}
505EXPORT_SYMBOL_GPL(wmi_get_event_data);
506
507/**
508 * wmi_has_guid - Check if a GUID is available
509 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
510 *
511 * Check if a given GUID is defined by _WDG
512 */
513bool wmi_has_guid(const char *guid_string)
514{
515 return find_guid(guid_string, NULL);
516}
517EXPORT_SYMBOL_GPL(wmi_has_guid);
518
519/*
520 * Parse the _WDG method for the GUID data blocks
521 */
522static __init acpi_status parse_wdg(acpi_handle handle)
523{
524 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
525 union acpi_object *obj;
526 struct guid_block *gblock;
527 struct wmi_block *wblock;
528 acpi_status status;
529 u32 i, total;
530
531 status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
532
533 if (ACPI_FAILURE(status))
534 return status;
535
536 obj = (union acpi_object *) out.pointer;
537
538 if (obj->type != ACPI_TYPE_BUFFER)
539 return AE_ERROR;
540
541 total = obj->buffer.length / sizeof(struct guid_block);
542
543 gblock = kzalloc(obj->buffer.length, GFP_KERNEL);
544 if (!gblock)
545 return AE_NO_MEMORY;
546
547 memcpy(gblock, obj->buffer.pointer, obj->buffer.length);
548
549 for (i = 0; i < total; i++) {
550 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
551 if (!wblock)
552 return AE_NO_MEMORY;
553
554 wblock->gblock = gblock[i];
555 wblock->handle = handle;
556 list_add_tail(&wblock->list, &wmi_blocks.list);
557 }
558
559 kfree(out.pointer);
560 kfree(gblock);
561
562 return status;
563}
564
565/*
566 * WMI can have EmbeddedControl access regions. In which case, we just want to
567 * hand these off to the EC driver.
568 */
569static acpi_status
570acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
571 u32 bits, acpi_integer * value,
572 void *handler_context, void *region_context)
573{
574 int result = 0, i = 0;
575 u8 temp = 0;
576
577 if ((address > 0xFF) || !value)
578 return AE_BAD_PARAMETER;
579
580 if (function != ACPI_READ && function != ACPI_WRITE)
581 return AE_BAD_PARAMETER;
582
583 if (bits != 8)
584 return AE_BAD_PARAMETER;
585
586 if (function == ACPI_READ) {
587 result = ec_read(address, &temp);
588 (*value) |= ((acpi_integer)temp) << i;
589 } else {
590 temp = 0xff & ((*value) >> i);
591 result = ec_write(address, temp);
592 }
593
594 switch (result) {
595 case -EINVAL:
596 return AE_BAD_PARAMETER;
597 break;
598 case -ENODEV:
599 return AE_NOT_FOUND;
600 break;
601 case -ETIME:
602 return AE_TIME;
603 break;
604 default:
605 return AE_OK;
606 }
607}
608
609static void acpi_wmi_notify(acpi_handle handle, u32 event, void *data)
610{
611 struct guid_block *block;
612 struct wmi_block *wblock;
613 struct list_head *p;
614 struct acpi_device *device = data;
615
616 list_for_each(p, &wmi_blocks.list) {
617 wblock = list_entry(p, struct wmi_block, list);
618 block = &wblock->gblock;
619
620 if ((block->flags & ACPI_WMI_EVENT) &&
621 (block->notify_id == event)) {
622 if (wblock->handler)
623 wblock->handler(event, wblock->handler_data);
624
625 acpi_bus_generate_netlink_event(
626 device->pnp.device_class, device->dev.bus_id,
627 event, 0);
628 break;
629 }
630 }
631}
632
633static int acpi_wmi_remove(struct acpi_device *device, int type)
634{
635 acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
636 acpi_wmi_notify);
637
638 acpi_remove_address_space_handler(device->handle,
639 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
640
641 return 0;
642}
643
644static int __init acpi_wmi_add(struct acpi_device *device)
645{
646 acpi_status status;
647 int result = 0;
648
649 status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
650 acpi_wmi_notify, device);
651 if (ACPI_FAILURE(status)) {
652 printk(KERN_ERR PREFIX "Error installing notify handler\n");
653 return -ENODEV;
654 }
655
656 status = acpi_install_address_space_handler(device->handle,
657 ACPI_ADR_SPACE_EC,
658 &acpi_wmi_ec_space_handler,
659 NULL, NULL);
660 if (ACPI_FAILURE(status))
661 return -ENODEV;
662
663 status = parse_wdg(device->handle);
664 if (ACPI_FAILURE(status)) {
665 printk(KERN_ERR PREFIX "Error installing EC region handler\n");
666 return -ENODEV;
667 }
668
669 return result;
670}
671
672static int __init acpi_wmi_init(void)
673{
674 acpi_status result;
675
676 if (acpi_disabled)
677 return -ENODEV;
678
679 INIT_LIST_HEAD(&wmi_blocks.list);
680
681 result = acpi_bus_register_driver(&acpi_wmi_driver);
682
683 if (result < 0) {
684 printk(KERN_INFO PREFIX "Error loading mapper\n");
685 } else {
686 printk(KERN_INFO PREFIX "Mapper loaded\n");
687 }
688
689 return result;
690}
691
692static void __exit acpi_wmi_exit(void)
693{
694 struct list_head *p, *tmp;
695 struct wmi_block *wblock;
696
697 acpi_bus_unregister_driver(&acpi_wmi_driver);
698
699 list_for_each_safe(p, tmp, &wmi_blocks.list) {
700 wblock = list_entry(p, struct wmi_block, list);
701
702 list_del(p);
703 kfree(wblock);
704 }
705
706 printk(KERN_INFO PREFIX "Mapper unloaded\n");
707}
708
709subsys_initcall(acpi_wmi_init);
710module_exit(acpi_wmi_exit);