aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig40
-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.c10
-rw-r--r--drivers/acpi/blacklist.c58
-rw-r--r--drivers/acpi/bus.c26
-rw-r--r--drivers/acpi/debug.c57
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c4
-rw-r--r--drivers/acpi/dock.c14
-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/glue.c4
-rw-r--r--drivers/acpi/hardware/hwsleep.c2
-rw-r--r--drivers/acpi/namespace/nsxfeval.c10
-rw-r--r--drivers/acpi/numa.c3
-rw-r--r--drivers/acpi/osl.c372
-rw-r--r--drivers/acpi/pci_bind.c4
-rw-r--r--drivers/acpi/pci_irq.c7
-rw-r--r--drivers/acpi/pci_link.c2
-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/sbs.c2
-rw-r--r--drivers/acpi/sbshc.c4
-rw-r--r--drivers/acpi/scan.c110
-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
41 files changed, 2974 insertions, 489 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ccf6ea95f68..7ef172c2a1d 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -68,26 +68,28 @@ config ACPI_PROCFS
68 68
69 Say N to delete /proc/acpi/ files that have moved to /sys/ 69 Say N to delete /proc/acpi/ files that have moved to /sys/
70config ACPI_PROCFS_POWER 70config ACPI_PROCFS_POWER
71 bool "Deprecated power /proc/acpi folders" 71 bool "Deprecated power /proc/acpi directories"
72 depends on PROC_FS 72 depends on PROC_FS
73 default y 73 default y
74 ---help--- 74 ---help---
75 For backwards compatibility, this option allows 75 For backwards compatibility, this option allows
76 deprecated power /proc/acpi/ folders to exist, even when 76 deprecated power /proc/acpi/ directories to exist, even when
77 they have been replaced by functions in /sys. 77 they have been replaced by functions in /sys.
78 The deprecated folders (and their replacements) include: 78 The deprecated directories (and their replacements) include:
79 /proc/acpi/battery/* (/sys/class/power_supply/*) 79 /proc/acpi/battery/* (/sys/class/power_supply/*)
80 /proc/acpi/ac_adapter/* (sys/class/power_supply/*) 80 /proc/acpi/ac_adapter/* (sys/class/power_supply/*)
81 This option has no effect on /proc/acpi/ folders 81 This option has no effect on /proc/acpi/ directories
82 and functions, which do not yet exist in /sys 82 and functions, which do not yet exist in /sys
83 83
84 Say N to delete power /proc/acpi/ folders that have moved to /sys/ 84 Say N to delete power /proc/acpi/ directories that have moved to /sys/
85
85config ACPI_SYSFS_POWER 86config ACPI_SYSFS_POWER
86 bool "Future power /sys interface" 87 bool "Future power /sys interface"
87 select POWER_SUPPLY 88 select POWER_SUPPLY
88 default y 89 default y
89 ---help--- 90 ---help---
90 Say N to disable power /sys interface 91 Say N to disable power /sys interface
92
91config ACPI_PROC_EVENT 93config ACPI_PROC_EVENT
92 bool "Deprecated /proc/acpi/event support" 94 bool "Deprecated /proc/acpi/event support"
93 depends on PROC_FS 95 depends on PROC_FS
@@ -186,6 +188,7 @@ config ACPI_HOTPLUG_CPU
186config ACPI_THERMAL 188config ACPI_THERMAL
187 tristate "Thermal Zone" 189 tristate "Thermal Zone"
188 depends on ACPI_PROCESSOR 190 depends on ACPI_PROCESSOR
191 select THERMAL
189 default y 192 default y
190 help 193 help
191 This driver adds support for ACPI thermal zones. Most mobile and 194 This driver adds support for ACPI thermal zones. Most mobile and
@@ -199,6 +202,16 @@ config ACPI_NUMA
199 depends on (X86 || IA64) 202 depends on (X86 || IA64)
200 default y if IA64_GENERIC || IA64_SGI_SN2 203 default y if IA64_GENERIC || IA64_SGI_SN2
201 204
205config ACPI_WMI
206 tristate "WMI (EXPERIMENTAL)"
207 depends on EXPERIMENTAL
208 help
209 This driver adds support for the ACPI-WMI mapper device (PNP0C14)
210 found on some systems.
211
212 NOTE: You will need another driver or userspace application on top of
213 this to actually use anything defined in the ACPI-WMI mapper.
214
202config ACPI_ASUS 215config ACPI_ASUS
203 tristate "ASUS/Medion Laptop Extras" 216 tristate "ASUS/Medion Laptop Extras"
204 depends on X86 217 depends on X86
@@ -263,8 +276,10 @@ config ACPI_CUSTOM_DSDT
263 depends on !STANDALONE 276 depends on !STANDALONE
264 default n 277 default n
265 help 278 help
266 This option is to load a custom ACPI DSDT 279 This option supports a custom DSDT by linking it into the kernel.
267 If you don't know what that is, say N. 280 See Documentation/acpi/dsdt-override.txt
281
282 If unsure, say N.
268 283
269config ACPI_CUSTOM_DSDT_FILE 284config ACPI_CUSTOM_DSDT_FILE
270 string "Custom DSDT Table file to include" 285 string "Custom DSDT Table file to include"
@@ -274,6 +289,17 @@ config ACPI_CUSTOM_DSDT_FILE
274 Enter the full path name to the file which includes the AmlCode 289 Enter the full path name to the file which includes the AmlCode
275 declaration. 290 declaration.
276 291
292config ACPI_CUSTOM_DSDT_INITRD
293 bool "Read Custom DSDT from initramfs"
294 depends on BLK_DEV_INITRD
295 default n
296 help
297 This option supports a custom DSDT by optionally loading it from initrd.
298 See Documentation/acpi/dsdt-override.txt
299
300 If you are not using this feature now, but may use it later,
301 it is safe to say Y here.
302
277config ACPI_BLACKLIST_YEAR 303config ACPI_BLACKLIST_YEAR
278 int "Disable ACPI for systems before Jan 1st this year" if X86_32 304 int "Disable ACPI for systems before Jan 1st this year" if X86_32
279 default 0 305 default 0
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 456446f9007..f29812a8653 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 d915fec9bf6..d25ef961415 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 c4a769d1ba8..f6215e80980 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 6daf6088ac8..1fa86811b8e 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;
@@ -128,7 +134,7 @@ static ssize_t show_present(struct device *dev,
128 return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay)); 134 return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay));
129 135
130} 136}
131DEVICE_ATTR(present, S_IRUGO, show_present, NULL); 137static DEVICE_ATTR(present, S_IRUGO, show_present, NULL);
132 138
133/* 139/*
134 * write_eject - write method for "eject" file in sysfs 140 * write_eject - write method for "eject" file in sysfs
@@ -144,7 +150,7 @@ static ssize_t write_eject(struct device *dev, struct device_attribute *attr,
144 eject_device(bay->handle); 150 eject_device(bay->handle);
145 return count; 151 return count;
146} 152}
147DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject); 153static DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject);
148 154
149/** 155/**
150 * is_ata - see if a device is an ata device 156 * is_ata - see if a device is an ata device
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 8809654d6cc..6dbaa2d15fe 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 1b4cf984b08..8b0d4b7d188 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 -------------------------------------------------------------------------- */
@@ -366,7 +391,6 @@ int acpi_bus_receive_event(struct acpi_bus_event *event)
366 return 0; 391 return 0;
367} 392}
368 393
369EXPORT_SYMBOL(acpi_bus_receive_event);
370#endif /* CONFIG_ACPI_PROC_EVENT */ 394#endif /* CONFIG_ACPI_PROC_EVENT */
371 395
372/* -------------------------------------------------------------------------- 396/* --------------------------------------------------------------------------
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index bf513e07b77..6df564f4ca6 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/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index fc9da4879cb..f501e083aac 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -359,7 +359,9 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
359 359
360 status = acpi_os_validate_address(obj_desc->region.space_id, 360 status = acpi_os_validate_address(obj_desc->region.space_id,
361 obj_desc->region.address, 361 obj_desc->region.address,
362 (acpi_size) obj_desc->region.length); 362 (acpi_size) obj_desc->region.length,
363 acpi_ut_get_node_name(node));
364
363 if (ACPI_FAILURE(status)) { 365 if (ACPI_FAILURE(status)) {
364 /* 366 /*
365 * Invalid address/length. We will emit an error message and mark 367 * Invalid address/length. We will emit an error message and mark
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 1dabdf4c07b..307cef65c24 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;
@@ -680,7 +686,7 @@ static ssize_t show_docked(struct device *dev,
680 return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station)); 686 return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
681 687
682} 688}
683DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); 689static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
684 690
685/* 691/*
686 * show_flags - read method for flags file in sysfs 692 * show_flags - read method for flags file in sysfs
@@ -691,7 +697,7 @@ static ssize_t show_flags(struct device *dev,
691 return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); 697 return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
692 698
693} 699}
694DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL); 700static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
695 701
696/* 702/*
697 * write_undock - write method for "undock" file in sysfs 703 * write_undock - write method for "undock" file in sysfs
@@ -707,7 +713,7 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
707 ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST); 713 ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
708 return ret ? ret: count; 714 return ret ? ret: count;
709} 715}
710DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); 716static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
711 717
712/* 718/*
713 * show_dock_uid - read method for "uid" file in sysfs 719 * show_dock_uid - read method for "uid" file in sysfs
@@ -723,7 +729,7 @@ static ssize_t show_dock_uid(struct device *dev,
723 729
724 return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf); 730 return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
725} 731}
726DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); 732static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
727 733
728/** 734/**
729 * dock_add - add a new dock station 735 * dock_add - add a new dock station
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 987b967c746..7222a18a031 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 5c95863f8fa..5479dc0eeee 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 e41287815ea..3048801a37b 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 e22f4a973c0..0dadd2adc80 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 a6e149d692c..48cb705b274 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/glue.c b/drivers/acpi/glue.c
index 4893e256e39..eda0978b57c 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -36,8 +36,6 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
36 return -ENODEV; 36 return -ENODEV;
37} 37}
38 38
39EXPORT_SYMBOL(register_acpi_bus_type);
40
41int unregister_acpi_bus_type(struct acpi_bus_type *type) 39int unregister_acpi_bus_type(struct acpi_bus_type *type)
42{ 40{
43 if (acpi_disabled) 41 if (acpi_disabled)
@@ -53,8 +51,6 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
53 return -ENODEV; 51 return -ENODEV;
54} 52}
55 53
56EXPORT_SYMBOL(unregister_acpi_bus_type);
57
58static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) 54static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
59{ 55{
60 struct acpi_bus_type *tmp, *ret = NULL; 56 struct acpi_bus_type *tmp, *ret = NULL;
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index fd1c4ba6336..058d0be5cbe 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 f39fbc6b923..b92133faf5b 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/numa.c b/drivers/acpi/numa.c
index 0822d9fc1cb..5d59cb33b1a 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -78,6 +78,7 @@ int acpi_map_pxm_to_node(int pxm)
78 return node; 78 return node;
79} 79}
80 80
81#if 0
81void __cpuinit acpi_unmap_pxm_to_node(int node) 82void __cpuinit acpi_unmap_pxm_to_node(int node)
82{ 83{
83 int pxm = node_to_pxm_map[node]; 84 int pxm = node_to_pxm_map[node];
@@ -85,6 +86,7 @@ void __cpuinit acpi_unmap_pxm_to_node(int node)
85 node_to_pxm_map[node] = PXM_INVAL; 86 node_to_pxm_map[node] = PXM_INVAL;
86 node_clear(node, nodes_found_map); 87 node_clear(node, nodes_found_map);
87} 88}
89#endif /* 0 */
88 90
89static void __init 91static void __init
90acpi_table_print_srat_entry(struct acpi_subtable_header *header) 92acpi_table_print_srat_entry(struct acpi_subtable_header *header)
@@ -247,7 +249,6 @@ int acpi_get_pxm(acpi_handle h)
247 } while (ACPI_SUCCESS(status)); 249 } while (ACPI_SUCCESS(status));
248 return -1; 250 return -1;
249} 251}
250EXPORT_SYMBOL(acpi_get_pxm);
251 252
252int acpi_get_node(acpi_handle *handle) 253int acpi_get_node(acpi_handle *handle)
253{ 254{
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index e53fb516f9d..27ccd68b8f4 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -44,6 +44,8 @@
44#include <asm/uaccess.h> 44#include <asm/uaccess.h>
45 45
46#include <linux/efi.h> 46#include <linux/efi.h>
47#include <linux/ioport.h>
48#include <linux/list.h>
47 49
48#define _COMPONENT ACPI_OS_SERVICES 50#define _COMPONENT ACPI_OS_SERVICES
49ACPI_MODULE_NAME("osl"); 51ACPI_MODULE_NAME("osl");
@@ -74,9 +76,25 @@ static void *acpi_irq_context;
74static struct workqueue_struct *kacpid_wq; 76static struct workqueue_struct *kacpid_wq;
75static struct workqueue_struct *kacpi_notify_wq; 77static struct workqueue_struct *kacpi_notify_wq;
76 78
79struct acpi_res_list {
80 resource_size_t start;
81 resource_size_t end;
82 acpi_adr_space_type resource_type; /* IO port, System memory, ...*/
83 char name[5]; /* only can have a length of 4 chars, make use of this
84 one instead of res->name, no need to kalloc then */
85 struct list_head resource_list;
86};
87
88static LIST_HEAD(resource_list_head);
89static DEFINE_SPINLOCK(acpi_res_lock);
90
77#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ 91#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
78static char osi_additional_string[OSI_STRING_LENGTH_MAX]; 92static char osi_additional_string[OSI_STRING_LENGTH_MAX];
79 93
94#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
95static int acpi_no_initrd_override;
96#endif
97
80/* 98/*
81 * "Ode to _OSI(Linux)" 99 * "Ode to _OSI(Linux)"
82 * 100 *
@@ -120,7 +138,7 @@ static char osi_additional_string[OSI_STRING_LENGTH_MAX];
120 */ 138 */
121#define OSI_LINUX_ENABLE 0 139#define OSI_LINUX_ENABLE 0
122 140
123struct osi_linux { 141static struct osi_linux {
124 unsigned int enable:1; 142 unsigned int enable:1;
125 unsigned int dmi:1; 143 unsigned int dmi:1;
126 unsigned int cmdline:1; 144 unsigned int cmdline:1;
@@ -219,8 +237,6 @@ void acpi_os_printf(const char *fmt, ...)
219 va_end(args); 237 va_end(args);
220} 238}
221 239
222EXPORT_SYMBOL(acpi_os_printf);
223
224void acpi_os_vprintf(const char *fmt, va_list args) 240void acpi_os_vprintf(const char *fmt, va_list args)
225{ 241{
226 static char buffer[512]; 242 static char buffer[512];
@@ -250,11 +266,16 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
250 "System description tables not found\n"); 266 "System description tables not found\n");
251 return 0; 267 return 0;
252 } 268 }
253 } else 269 } else {
254 return acpi_find_rsdp(); 270 acpi_physical_address pa = 0;
271
272 acpi_find_root_pointer(&pa);
273 return pa;
274 }
255} 275}
256 276
257void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) 277void __iomem *__init_refok
278acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
258{ 279{
259 if (phys > ULONG_MAX) { 280 if (phys > ULONG_MAX) {
260 printk(KERN_ERR PREFIX "Cannot map memory that high\n"); 281 printk(KERN_ERR PREFIX "Cannot map memory that high\n");
@@ -312,6 +333,67 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
312 return AE_OK; 333 return AE_OK;
313} 334}
314 335
336#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
337struct acpi_table_header *acpi_find_dsdt_initrd(void)
338{
339 struct file *firmware_file;
340 mm_segment_t oldfs;
341 unsigned long len, len2;
342 struct acpi_table_header *dsdt_buffer, *ret = NULL;
343 struct kstat stat;
344 char *ramfs_dsdt_name = "/DSDT.aml";
345
346 printk(KERN_INFO PREFIX "Checking initramfs for custom DSDT");
347
348 /*
349 * Never do this at home, only the user-space is allowed to open a file.
350 * The clean way would be to use the firmware loader.
351 * But this code must be run before there is any userspace available.
352 * A static/init firmware infrastructure doesn't exist yet...
353 */
354 if (vfs_stat(ramfs_dsdt_name, &stat) < 0)
355 return ret;
356
357 len = stat.size;
358 /* check especially against empty files */
359 if (len <= 4) {
360 printk(KERN_ERR PREFIX "Failed: DSDT only %lu bytes.\n", len);
361 return ret;
362 }
363
364 firmware_file = filp_open(ramfs_dsdt_name, O_RDONLY, 0);
365 if (IS_ERR(firmware_file)) {
366 printk(KERN_ERR PREFIX "Failed to open %s.\n", ramfs_dsdt_name);
367 return ret;
368 }
369
370 dsdt_buffer = kmalloc(len, GFP_ATOMIC);
371 if (!dsdt_buffer) {
372 printk(KERN_ERR PREFIX "Failed to allocate %lu bytes.\n", len);
373 goto err;
374 }
375
376 oldfs = get_fs();
377 set_fs(KERNEL_DS);
378 len2 = vfs_read(firmware_file, (char __user *)dsdt_buffer, len,
379 &firmware_file->f_pos);
380 set_fs(oldfs);
381 if (len2 < len) {
382 printk(KERN_ERR PREFIX "Failed to read %lu bytes from %s.\n",
383 len, ramfs_dsdt_name);
384 ACPI_FREE(dsdt_buffer);
385 goto err;
386 }
387
388 printk(KERN_INFO PREFIX "Found %lu byte DSDT in %s.\n",
389 len, ramfs_dsdt_name);
390 ret = dsdt_buffer;
391err:
392 filp_close(firmware_file, NULL);
393 return ret;
394}
395#endif
396
315acpi_status 397acpi_status
316acpi_os_table_override(struct acpi_table_header * existing_table, 398acpi_os_table_override(struct acpi_table_header * existing_table,
317 struct acpi_table_header ** new_table) 399 struct acpi_table_header ** new_table)
@@ -319,20 +401,52 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
319 if (!existing_table || !new_table) 401 if (!existing_table || !new_table)
320 return AE_BAD_PARAMETER; 402 return AE_BAD_PARAMETER;
321 403
404 *new_table = NULL;
405
322#ifdef CONFIG_ACPI_CUSTOM_DSDT 406#ifdef CONFIG_ACPI_CUSTOM_DSDT
323 if (strncmp(existing_table->signature, "DSDT", 4) == 0) 407 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
324 *new_table = (struct acpi_table_header *)AmlCode; 408 *new_table = (struct acpi_table_header *)AmlCode;
325 else
326 *new_table = NULL;
327#else
328 *new_table = NULL;
329#endif 409#endif
410#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
411 if ((strncmp(existing_table->signature, "DSDT", 4) == 0) &&
412 !acpi_no_initrd_override) {
413 struct acpi_table_header *initrd_table;
414
415 initrd_table = acpi_find_dsdt_initrd();
416 if (initrd_table)
417 *new_table = initrd_table;
418 }
419#endif
420 if (*new_table != NULL) {
421 printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
422 "this is unsafe: tainting kernel\n",
423 existing_table->signature,
424 existing_table->oem_table_id);
425 add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
426 }
330 return AE_OK; 427 return AE_OK;
331} 428}
332 429
430#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
431int __init acpi_no_initrd_override_setup(char *s)
432{
433 acpi_no_initrd_override = 1;
434 return 1;
435}
436__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup);
437#endif
438
333static irqreturn_t acpi_irq(int irq, void *dev_id) 439static irqreturn_t acpi_irq(int irq, void *dev_id)
334{ 440{
335 return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; 441 u32 handled;
442
443 handled = (*acpi_irq_handler) (acpi_irq_context);
444
445 if (handled) {
446 acpi_irq_handled++;
447 return IRQ_HANDLED;
448 } else
449 return IRQ_NONE;
336} 450}
337 451
338acpi_status 452acpi_status
@@ -341,6 +455,8 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
341{ 455{
342 unsigned int irq; 456 unsigned int irq;
343 457
458 acpi_irq_stats_init();
459
344 /* 460 /*
345 * Ignore the GSI from the core, and use the value in our copy of the 461 * Ignore the GSI from the core, and use the value in our copy of the
346 * FADT. It may not be the same if an interrupt source override exists 462 * FADT. It may not be the same if an interrupt source override exists
@@ -384,8 +500,6 @@ void acpi_os_sleep(acpi_integer ms)
384 schedule_timeout_interruptible(msecs_to_jiffies(ms)); 500 schedule_timeout_interruptible(msecs_to_jiffies(ms));
385} 501}
386 502
387EXPORT_SYMBOL(acpi_os_sleep);
388
389void acpi_os_stall(u32 us) 503void acpi_os_stall(u32 us)
390{ 504{
391 while (us) { 505 while (us) {
@@ -399,8 +513,6 @@ void acpi_os_stall(u32 us)
399 } 513 }
400} 514}
401 515
402EXPORT_SYMBOL(acpi_os_stall);
403
404/* 516/*
405 * Support ACPI 3.0 AML Timer operand 517 * Support ACPI 3.0 AML Timer operand
406 * Returns 64-bit free-running, monotonically increasing timer 518 * Returns 64-bit free-running, monotonically increasing timer
@@ -550,8 +662,6 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
550 return (result ? AE_ERROR : AE_OK); 662 return (result ? AE_ERROR : AE_OK);
551} 663}
552 664
553EXPORT_SYMBOL(acpi_os_read_pci_configuration);
554
555acpi_status 665acpi_status
556acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, 666acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
557 acpi_integer value, u32 width) 667 acpi_integer value, u32 width)
@@ -661,25 +771,6 @@ static void acpi_os_execute_deferred(struct work_struct *work)
661 dpc->function(dpc->context); 771 dpc->function(dpc->context);
662 kfree(dpc); 772 kfree(dpc);
663 773
664 /* Yield cpu to notify thread */
665 cond_resched();
666
667 return;
668}
669
670static void acpi_os_execute_notify(struct work_struct *work)
671{
672 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
673
674 if (!dpc) {
675 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
676 return;
677 }
678
679 dpc->function(dpc->context);
680
681 kfree(dpc);
682
683 return; 774 return;
684} 775}
685 776
@@ -703,7 +794,7 @@ acpi_status acpi_os_execute(acpi_execute_type type,
703{ 794{
704 acpi_status status = AE_OK; 795 acpi_status status = AE_OK;
705 struct acpi_os_dpc *dpc; 796 struct acpi_os_dpc *dpc;
706 797 struct workqueue_struct *queue;
707 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 798 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
708 "Scheduling function [%p(%p)] for deferred execution.\n", 799 "Scheduling function [%p(%p)] for deferred execution.\n",
709 function, context)); 800 function, context));
@@ -727,20 +818,13 @@ acpi_status acpi_os_execute(acpi_execute_type type,
727 dpc->function = function; 818 dpc->function = function;
728 dpc->context = context; 819 dpc->context = context;
729 820
730 if (type == OSL_NOTIFY_HANDLER) { 821 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
731 INIT_WORK(&dpc->work, acpi_os_execute_notify); 822 queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq;
732 if (!queue_work(kacpi_notify_wq, &dpc->work)) { 823 if (!queue_work(queue, &dpc->work)) {
733 status = AE_ERROR; 824 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
734 kfree(dpc); 825 "Call to queue_work() failed.\n"));
735 } 826 status = AE_ERROR;
736 } else { 827 kfree(dpc);
737 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
738 if (!queue_work(kacpid_wq, &dpc->work)) {
739 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
740 "Call to queue_work() failed.\n"));
741 status = AE_ERROR;
742 kfree(dpc);
743 }
744 } 828 }
745 return_ACPI_STATUS(status); 829 return_ACPI_STATUS(status);
746} 830}
@@ -793,8 +877,6 @@ acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
793 return AE_OK; 877 return AE_OK;
794} 878}
795 879
796EXPORT_SYMBOL(acpi_os_create_semaphore);
797
798/* 880/*
799 * TODO: A better way to delete semaphores? Linux doesn't have a 881 * TODO: A better way to delete semaphores? Linux doesn't have a
800 * 'delete_semaphore()' function -- may result in an invalid 882 * 'delete_semaphore()' function -- may result in an invalid
@@ -818,8 +900,6 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
818 return AE_OK; 900 return AE_OK;
819} 901}
820 902
821EXPORT_SYMBOL(acpi_os_delete_semaphore);
822
823/* 903/*
824 * TODO: The kernel doesn't have a 'down_timeout' function -- had to 904 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
825 * improvise. The process is to sleep for one scheduler quantum 905 * improvise. The process is to sleep for one scheduler quantum
@@ -912,8 +992,6 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
912 return status; 992 return status;
913} 993}
914 994
915EXPORT_SYMBOL(acpi_os_wait_semaphore);
916
917/* 995/*
918 * TODO: Support for units > 1? 996 * TODO: Support for units > 1?
919 */ 997 */
@@ -936,8 +1014,6 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
936 return AE_OK; 1014 return AE_OK;
937} 1015}
938 1016
939EXPORT_SYMBOL(acpi_os_signal_semaphore);
940
941#ifdef ACPI_FUTURE_USAGE 1017#ifdef ACPI_FUTURE_USAGE
942u32 acpi_os_get_line(char *buffer) 1018u32 acpi_os_get_line(char *buffer)
943{ 1019{
@@ -981,8 +1057,6 @@ acpi_status acpi_os_signal(u32 function, void *info)
981 return AE_OK; 1057 return AE_OK;
982} 1058}
983 1059
984EXPORT_SYMBOL(acpi_os_signal);
985
986static int __init acpi_os_name_setup(char *str) 1060static int __init acpi_os_name_setup(char *str)
987{ 1061{
988 char *p = acpi_os_name; 1062 char *p = acpi_os_name;
@@ -1102,6 +1176,128 @@ static int __init acpi_wake_gpes_always_on_setup(char *str)
1102 1176
1103__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); 1177__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
1104 1178
1179/* Check of resource interference between native drivers and ACPI
1180 * OperationRegions (SystemIO and System Memory only).
1181 * IO ports and memory declared in ACPI might be used by the ACPI subsystem
1182 * in arbitrary AML code and can interfere with legacy drivers.
1183 * acpi_enforce_resources= can be set to:
1184 *
1185 * - strict (2)
1186 * -> further driver trying to access the resources will not load
1187 * - lax (default) (1)
1188 * -> further driver trying to access the resources will load, but you
1189 * get a system message that something might go wrong...
1190 *
1191 * - no (0)
1192 * -> ACPI Operation Region resources will not be registered
1193 *
1194 */
1195#define ENFORCE_RESOURCES_STRICT 2
1196#define ENFORCE_RESOURCES_LAX 1
1197#define ENFORCE_RESOURCES_NO 0
1198
1199static unsigned int acpi_enforce_resources = ENFORCE_RESOURCES_LAX;
1200
1201static int __init acpi_enforce_resources_setup(char *str)
1202{
1203 if (str == NULL || *str == '\0')
1204 return 0;
1205
1206 if (!strcmp("strict", str))
1207 acpi_enforce_resources = ENFORCE_RESOURCES_STRICT;
1208 else if (!strcmp("lax", str))
1209 acpi_enforce_resources = ENFORCE_RESOURCES_LAX;
1210 else if (!strcmp("no", str))
1211 acpi_enforce_resources = ENFORCE_RESOURCES_NO;
1212
1213 return 1;
1214}
1215
1216__setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
1217
1218/* Check for resource conflicts between ACPI OperationRegions and native
1219 * drivers */
1220int acpi_check_resource_conflict(struct resource *res)
1221{
1222 struct acpi_res_list *res_list_elem;
1223 int ioport;
1224 int clash = 0;
1225
1226 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1227 return 0;
1228 if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM))
1229 return 0;
1230
1231 ioport = res->flags & IORESOURCE_IO;
1232
1233 spin_lock(&acpi_res_lock);
1234 list_for_each_entry(res_list_elem, &resource_list_head,
1235 resource_list) {
1236 if (ioport && (res_list_elem->resource_type
1237 != ACPI_ADR_SPACE_SYSTEM_IO))
1238 continue;
1239 if (!ioport && (res_list_elem->resource_type
1240 != ACPI_ADR_SPACE_SYSTEM_MEMORY))
1241 continue;
1242
1243 if (res->end < res_list_elem->start
1244 || res_list_elem->end < res->start)
1245 continue;
1246 clash = 1;
1247 break;
1248 }
1249 spin_unlock(&acpi_res_lock);
1250
1251 if (clash) {
1252 if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
1253 printk(KERN_INFO "%sACPI: %s resource %s [0x%llx-0x%llx]"
1254 " conflicts with ACPI region %s"
1255 " [0x%llx-0x%llx]\n",
1256 acpi_enforce_resources == ENFORCE_RESOURCES_LAX
1257 ? KERN_WARNING : KERN_ERR,
1258 ioport ? "I/O" : "Memory", res->name,
1259 (long long) res->start, (long long) res->end,
1260 res_list_elem->name,
1261 (long long) res_list_elem->start,
1262 (long long) res_list_elem->end);
1263 printk(KERN_INFO "ACPI: Device needs an ACPI driver\n");
1264 }
1265 if (acpi_enforce_resources == ENFORCE_RESOURCES_STRICT)
1266 return -EBUSY;
1267 }
1268 return 0;
1269}
1270EXPORT_SYMBOL(acpi_check_resource_conflict);
1271
1272int acpi_check_region(resource_size_t start, resource_size_t n,
1273 const char *name)
1274{
1275 struct resource res = {
1276 .start = start,
1277 .end = start + n - 1,
1278 .name = name,
1279 .flags = IORESOURCE_IO,
1280 };
1281
1282 return acpi_check_resource_conflict(&res);
1283}
1284EXPORT_SYMBOL(acpi_check_region);
1285
1286int acpi_check_mem_region(resource_size_t start, resource_size_t n,
1287 const char *name)
1288{
1289 struct resource res = {
1290 .start = start,
1291 .end = start + n - 1,
1292 .name = name,
1293 .flags = IORESOURCE_MEM,
1294 };
1295
1296 return acpi_check_resource_conflict(&res);
1297
1298}
1299EXPORT_SYMBOL(acpi_check_mem_region);
1300
1105/* 1301/*
1106 * Acquire a spinlock. 1302 * Acquire a spinlock.
1107 * 1303 *
@@ -1213,24 +1409,24 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
1213 * 1409 *
1214 * Returns 0 on success 1410 * Returns 0 on success
1215 */ 1411 */
1216int acpi_dmi_dump(void) 1412static int acpi_dmi_dump(void)
1217{ 1413{
1218 1414
1219 if (!dmi_available) 1415 if (!dmi_available)
1220 return -1; 1416 return -1;
1221 1417
1222 printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n", 1418 printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
1223 dmi_get_slot(DMI_SYS_VENDOR)); 1419 dmi_get_system_info(DMI_SYS_VENDOR));
1224 printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n", 1420 printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
1225 dmi_get_slot(DMI_PRODUCT_NAME)); 1421 dmi_get_system_info(DMI_PRODUCT_NAME));
1226 printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n", 1422 printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
1227 dmi_get_slot(DMI_PRODUCT_VERSION)); 1423 dmi_get_system_info(DMI_PRODUCT_VERSION));
1228 printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n", 1424 printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
1229 dmi_get_slot(DMI_BOARD_NAME)); 1425 dmi_get_system_info(DMI_BOARD_NAME));
1230 printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n", 1426 printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
1231 dmi_get_slot(DMI_BIOS_VENDOR)); 1427 dmi_get_system_info(DMI_BIOS_VENDOR));
1232 printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n", 1428 printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
1233 dmi_get_slot(DMI_BIOS_DATE)); 1429 dmi_get_system_info(DMI_BIOS_DATE));
1234 1430
1235 return 0; 1431 return 0;
1236} 1432}
@@ -1303,10 +1499,46 @@ acpi_status
1303acpi_os_validate_address ( 1499acpi_os_validate_address (
1304 u8 space_id, 1500 u8 space_id,
1305 acpi_physical_address address, 1501 acpi_physical_address address,
1306 acpi_size length) 1502 acpi_size length,
1503 char *name)
1307{ 1504{
1505 struct acpi_res_list *res;
1506 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1507 return AE_OK;
1308 1508
1309 return AE_OK; 1509 switch (space_id) {
1510 case ACPI_ADR_SPACE_SYSTEM_IO:
1511 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1512 /* Only interference checks against SystemIO and SytemMemory
1513 are needed */
1514 res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL);
1515 if (!res)
1516 return AE_OK;
1517 /* ACPI names are fixed to 4 bytes, still better use strlcpy */
1518 strlcpy(res->name, name, 5);
1519 res->start = address;
1520 res->end = address + length - 1;
1521 res->resource_type = space_id;
1522 spin_lock(&acpi_res_lock);
1523 list_add(&res->resource_list, &resource_list_head);
1524 spin_unlock(&acpi_res_lock);
1525 pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, "
1526 "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
1527 ? "SystemIO" : "System Memory",
1528 (unsigned long long)res->start,
1529 (unsigned long long)res->end,
1530 res->name);
1531 break;
1532 case ACPI_ADR_SPACE_PCI_CONFIG:
1533 case ACPI_ADR_SPACE_EC:
1534 case ACPI_ADR_SPACE_SMBUS:
1535 case ACPI_ADR_SPACE_CMOS:
1536 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1537 case ACPI_ADR_SPACE_DATA_TABLE:
1538 case ACPI_ADR_SPACE_FIXED_HARDWARE:
1539 break;
1540 }
1541 return AE_OK;
1310} 1542}
1311 1543
1312#endif 1544#endif
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 388300de005..4b252ea0e95 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -44,6 +44,8 @@ struct acpi_pci_data {
44 struct pci_dev *dev; 44 struct pci_dev *dev;
45}; 45};
46 46
47static int acpi_pci_unbind(struct acpi_device *device);
48
47static void acpi_pci_data_handler(acpi_handle handle, u32 function, 49static void acpi_pci_data_handler(acpi_handle handle, u32 function,
48 void *context) 50 void *context)
49{ 51{
@@ -267,7 +269,7 @@ int acpi_pci_bind(struct acpi_device *device)
267 return result; 269 return result;
268} 270}
269 271
270int acpi_pci_unbind(struct acpi_device *device) 272static int acpi_pci_unbind(struct acpi_device *device)
271{ 273{
272 int result = 0; 274 int result = 0;
273 acpi_status status = AE_OK; 275 acpi_status status = AE_OK;
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 62010c2481b..7f19859580c 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)
@@ -478,8 +475,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
478 return 0; 475 return 0;
479} 476}
480 477
481EXPORT_SYMBOL(acpi_pci_irq_enable);
482
483/* FIXME: implement x86/x86_64 version */ 478/* FIXME: implement x86/x86_64 version */
484void __attribute__ ((weak)) acpi_unregister_gsi(u32 i) 479void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
485{ 480{
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 5400ea173f6..233c40c5168 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -95,7 +95,7 @@ static struct {
95 int count; 95 int count;
96 struct list_head entries; 96 struct list_head entries;
97} acpi_link; 97} acpi_link;
98DEFINE_MUTEX(acpi_link_lock); 98static DEFINE_MUTEX(acpi_link_lock);
99 99
100/* -------------------------------------------------------------------------- 100/* --------------------------------------------------------------------------
101 PCI Link Device Management 101 PCI Link Device Management
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index af1769a20c7..76bf6d90c70 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 e48ee4f8749..75ccf5d18bf 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 199ea214615..32003fdc91e 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 463b0247cbc..f32010bee4d 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 06e6f3fb882..9cb43f52f7b 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 1685b40abda..1b8e592a824 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/sbs.c b/drivers/acpi/sbs.c
index f136c7d3b3c..1194105cc3c 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -888,7 +888,7 @@ static void acpi_charger_remove(struct acpi_sbs *sbs)
888#endif 888#endif
889} 889}
890 890
891void acpi_sbs_callback(void *context) 891static void acpi_sbs_callback(void *context)
892{ 892{
893 int id; 893 int id;
894 struct acpi_sbs *sbs = context; 894 struct acpi_sbs *sbs = context;
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index fd40b6a1d63..ae9a90438e2 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -111,8 +111,8 @@ static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
111 return -ETIME; 111 return -ETIME;
112} 112}
113 113
114int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, u8 address, 114static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
115 u8 command, u8 *data, u8 length) 115 u8 address, u8 command, u8 *data, u8 length)
116{ 116{
117 int ret = -EFAULT, i; 117 int ret = -EFAULT, i;
118 u8 temp, sz = 0; 118 u8 temp, sz = 0;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index d9d531cce27..3fac011f9cf 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -59,7 +59,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
59 count = snprintf(&modalias[len], size, "%s:", 59 count = snprintf(&modalias[len], size, "%s:",
60 cid_list->id[i].value); 60 cid_list->id[i].value);
61 if (count < 0 || count >= size) { 61 if (count < 0 || count >= size) {
62 printk(KERN_ERR "acpi: %s cid[%i] exceeds event buffer size", 62 printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size",
63 acpi_dev->pnp.device_name, i); 63 acpi_dev->pnp.device_name, i);
64 break; 64 break;
65 } 65 }
@@ -453,7 +453,7 @@ static int acpi_device_register(struct acpi_device *device,
453 device->dev.release = &acpi_device_release; 453 device->dev.release = &acpi_device_release;
454 result = device_add(&device->dev); 454 result = device_add(&device->dev);
455 if(result) { 455 if(result) {
456 printk("Error adding device %s", device->dev.bus_id); 456 printk(KERN_ERR PREFIX "Error adding device %s", device->dev.bus_id);
457 goto end; 457 goto end;
458 } 458 }
459 459
@@ -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,13 +959,14 @@ 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) {
956 case ACPI_BUS_TYPE_DEVICE: 966 case ACPI_BUS_TYPE_DEVICE:
957 status = acpi_get_object_info(handle, &buffer); 967 status = acpi_get_object_info(handle, &buffer);
958 if (ACPI_FAILURE(status)) { 968 if (ACPI_FAILURE(status)) {
959 printk("%s: Error reading device info\n", __FUNCTION__); 969 printk(KERN_ERR PREFIX "%s: Error reading device info\n", __FUNCTION__);
960 return; 970 return;
961 } 971 }
962 972
@@ -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,12 +1034,45 @@ 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
1029 printk(KERN_ERR "Memory allocation error\n"); 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
1075 printk(KERN_ERR PREFIX "Memory allocation error\n");
1030 } 1076 }
1031 1077
1032 kfree(buffer.pointer); 1078 kfree(buffer.pointer);
@@ -1050,7 +1096,7 @@ static int acpi_device_set_context(struct acpi_device *device, int type)
1050 acpi_bus_data_handler, device); 1096 acpi_bus_data_handler, device);
1051 1097
1052 if (ACPI_FAILURE(status)) { 1098 if (ACPI_FAILURE(status)) {
1053 printk("Error attaching device data\n"); 1099 printk(KERN_ERR PREFIX "Error attaching device data\n");
1054 result = -ENODEV; 1100 result = -ENODEV;
1055 } 1101 }
1056 } 1102 }
@@ -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 485de134707..293a1cbb47c 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 1538355c266..f8df5217d47 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 5ffe0ea1896..55cf4c05bb7 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 if (!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 0a7d7afac25..7385efa6162 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 cf8fa514189..9ecb4b6c1e7 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 5f79b445121..8d4b79b4f93 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 93ea8290b4f..630c9a2c5b7 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 bd77e81e81c..7f714fa2a45 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 00000000000..36b84ab418d
--- /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);